// work form char * int ipbatch(const char *arg) { int rval = 0; if(!strcmp(arg,"commit")) { rval = ipbatch(mybatch); mybatch.clear(); } else mybatch.push_back(std::string(arg)); return rval; }
// or from single strings int ipbatch(const std::string &arg) { int rval = 0; if(arg == "commit") { rval = ipbatch(mybatch); mybatch.clear(); } else mybatch.push_back(arg); return rval; }
int stop_guardian(std::vector<std::string> & parameters, std::string & response) { int error = 0; std::vector<std::string>ipb; response = "Guardian Process Terminated"; killunknownprocess("guardian.pl"); ipbatch(ipb); return 0; }
int set_ipblock(std::vector<std::string> & parameters, std::string & response) { int error = 0; ConfigCSV config("/var/smoothwall/ipblock/config"); std::vector<std::string>ipb; std::string::size_type n; ipb.push_back("iptables -F ipblock"); for (int line = config.first(); line == 0; line = config.next()) { const std::string & remip = config[0]; const std::string & log = config[1]; const std::string & target = config[2]; const std::string & enabled = config[3]; // are we complete? if (remip == "" && enabled != "") break; if ((n = remip.find_first_not_of(IP_NUMBERS)) != std::string::npos) { response = "Bad remote IP: " + remip; error = 1; goto EXIT; } if (!(target == "DROP" || target == "REJECT")) { response = "Bad target: " + target; error = 1; goto EXIT; } if (enabled == "on") { if (log == "on") ipb.push_back("iptables -A ipblock -s " + remip + " -j LOG --log-prefix \"Denied-by-filter:ipblock \""); ipb.push_back("iptables -A ipblock -s " + remip + " -j " + target); } } error = ipbatch(ipb); if (error) { response = "ipbatch failure"; goto EXIT; } response = "Block rules set"; EXIT: return error; }
int start_guardian(std::vector<std::string> & parameters, std::string & response) { int error = 0; std::vector<std::string>ipb; ConfigVAR settings("/var/smoothwall/snort/settings"); if (settings["ENABLE_GUARD"] == "on") { response = "Guardian Process started"; error = simplesecuresysteml("/usr/local/sbin/guardian.pl", NULL, NULL); error = ipbatch(ipb); if (error) response = "Guardian Start Failed!"; else response = "Guardian Start Successful"; } return error; }
int set_timed_access(std::vector<std::string> & parameters, std::string & response) { int error = 0, preStartTime, postStopTime; ConfigVAR settings("/var/smoothwall/timedaccess/settings"); ConfigCSV config("/var/smoothwall/timedaccess/machines"); std::vector<std::string>ipb; std::string::size_type n; std::string daysOfWeek = ""; std::ostringstream ssPreStartHour, ssPreStartMin, ssPostStopHour, ssPostStopMin; // Convert the times to decimal; a day has 1440 minutes (0-1439). preStartTime = (strtol (settings["START_HOUR"].c_str(), NULL, 10)*60 + strtol (settings["START_MIN"].c_str(), NULL, 10)) - 1; postStopTime = (strtol (settings["END_HOUR"].c_str(), NULL, 10)*60 + strtol (settings["END_MIN"].c_str(), NULL, 10)) + 1; // preStartTime and postStopTime are used as end and start times, respectively, // when the start time>00:00 and/or the end time<23:59:59. ssPreStartHour << preStartTime/60; ssPreStartMin << preStartTime%60; ssPostStopHour << postStopTime/60; ssPostStopMin << postStopTime%60; // Send 'em to John ipb.push_back("iptables -F timedaccess\n"); // If enabled, generate the rules if (settings["ENABLE"] == "on") { // Days of the week the rule applies if (settings["DAY_0"] == "on") daysOfWeek += ",Mon"; if (settings["DAY_1"] == "on") daysOfWeek += ",Tue"; if (settings["DAY_2"] == "on") daysOfWeek += ",Wed"; if (settings["DAY_3"] == "on") daysOfWeek += ",Thu"; if (settings["DAY_4"] == "on") daysOfWeek += ",Fri"; if (settings["DAY_5"] == "on") daysOfWeek += ",Sat"; if (settings["DAY_6"] == "on") daysOfWeek += ",Sun"; if (daysOfWeek.length() > 0) { daysOfWeek[0] = ' '; daysOfWeek = " --weekdays" + daysOfWeek; } // For each IP, generate the rules for (int line = config.first(); line == 0; line = config.next()) { const std::string &ip = config[0]; if ((n = ip.find_first_not_of(IP_NUMBERS)) != std::string::npos) { // illegal characters response = "Bad IP: " + ip; error = 1; return error; } if (settings["MODE"] == "ALLOW") { // Allowing if (preStartTime >= 0) { // There is time before the start time ipb.push_back("iptables -A timedaccess -s " + ip + " -m time" + " --kerneltz" + " --timestart 00:00:00" + " --timestop " + ssPreStartHour.str() + ":" + ssPreStartMin.str() + ":59" + daysOfWeek + " -j timedaction"); ipb.push_back("iptables -A timedaccess -d " + ip + " -m time" + " --kerneltz" + " --timestart 00:00:00" + " --timestop " + ssPreStartHour.str() + ":" + ssPreStartMin.str() + ":59" + daysOfWeek + " -j timedaction"); } // The time interval ipb.push_back("iptables -A timedaccess -s " + ip + " -m time" + " --kerneltz" + " --timestart " + settings["START_HOUR"] + ":" + settings["START_MIN"] + ":00" + " --timestop " + settings["END_HOUR"] + ":" + settings["END_MIN"] + ":59" + daysOfWeek + " -j RETURN"); ipb.push_back("iptables -A timedaccess -d " + ip + " -m time" + " --kerneltz" + " --timestart " + settings["START_HOUR"] + ":" + settings["START_MIN"] + ":00" + " --timestop " + settings["END_HOUR"] + ":" + settings["END_MIN"] + ":59" + daysOfWeek + " -j RETURN"); if (postStopTime <= 1439) { // There is time after the stop time ipb.push_back("iptables -A timedaccess -s " + ip + " -m time" + " --kerneltz" + " --timestart " + ssPostStopHour.str() + ":" + ssPostStopMin.str() + ":00" + " --timestop 23:59:59" + daysOfWeek + " -j timedaction"); ipb.push_back("iptables -A timedaccess -d " + ip + " -m time" + " --kerneltz" + " --timestart " + ssPostStopHour.str() + ":" + ssPostStopMin.str() + ":00" + " --timestop 23:59:59" + daysOfWeek + " -j timedaction"); } } else { // Rejecting if (preStartTime >= 0) { // There is time before the start time ipb.push_back("iptables -A timedaccess -s " + ip + " -m time" + " --kerneltz" + " --timestart 00:00:00" + " --timestop " + ssPreStartHour.str() + ":" + ssPreStartMin.str() + ":59" + daysOfWeek + " -j RETURN"); ipb.push_back("iptables -A timedaccess -d " + ip + " -m time" + " --kerneltz" + " --timestart 00:00:00" + " --timestop " + ssPreStartHour.str() + ":" + ssPreStartMin.str() + ":59" + daysOfWeek + " -j RETURN"); } // The time interval ipb.push_back("iptables -A timedaccess -s " + ip + " -m time" + " --kerneltz" + " --timestart " + settings["START_HOUR"] + ":" + settings["START_MIN"] + ":00" + " --timestop " + settings["END_HOUR"] + ":" + settings["END_MIN"] + ":59" + daysOfWeek + " -j timedaction"); ipb.push_back("iptables -A timedaccess -d " + ip + " -m time" + " --kerneltz" + " --timestart " + settings["START_HOUR"] + ":" + settings["START_MIN"] + ":00" + " --timestop " + settings["END_HOUR"] + ":" + settings["END_MIN"] + ":59" + daysOfWeek + " -j timedaction"); if (postStopTime <= 1439) { // There is time after the stop time ipb.push_back("iptables -A timedaccess -s " + ip + " -m time" + " --kerneltz" + " --timestart " + ssPostStopHour.str() + ":" + ssPostStopMin.str() + ":00" + " --timestop 23:59:59" + daysOfWeek + " -j RETURN"); ipb.push_back("iptables -A timedaccess -d " + ip + " -m time" + " --kerneltz" + " --timestart " + ssPostStopHour.str() + ":" + ssPostStopMin.str() + ":00" + " --timestop 23:59:59" + daysOfWeek + " -j RETURN"); } } } } error = ipbatch(ipb); if (error) response = "ipbatch failure when setting chain timedaccess"; else response = "timed access set"; return error; }
//#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@> int set_portfw(std::vector<std::string> & parameters, std::string & response) { int error = 0; std::string::size_type n; std::string::size_type p; std::vector<std::string>ipb; std::string localipfile = "/var/smoothwall/red/local-ipaddress"; std::string ifacefile = "/var/smoothwall/red/iface"; std::string cmdprefix = "/var/smoothwall"; std::string configfile = cmdprefix + "/portfw/config"; std::string aliasfile = cmdprefix + "/portfw/aliases"; std::string sncheckfile = cmdprefix + "/portfw/subcheck"; ConfigSTR localip(localipfile); ConfigSTR red_iface(ifacefile); ConfigCSV fwdconf(configfile); ConfigCSV aliases(aliasfile); ConfigVAR subnetcheck(sncheckfile); std::string greencheck = subnetcheck["GREEN"]; std::string purplecheck = subnetcheck["PURPLE"]; std::string orangecheck = subnetcheck["ORANGE"]; // preset the response to a success, changed only on error, always return zero response = "Port forwarding rules set"; if (localip.str() == "") { response = "Abort, could not open red local IP file (" + localipfile + ")"; return errrpt (response); } if (localip.str().find_first_not_of(IP_NUMBERS) != std::string::npos) { response = "Abort, bad local IP: " + localip.str(); return errrpt (response); } if (red_iface.str() == "") { response = "Abort, could not open red interface file (" + ifacefile + ")"; return errrpt (response); } if (red_iface.str().find_first_not_of(INTERFACE) != std::string::npos) { response = "Abort, bad red interface specifier: " + red_iface.str(); return errrpt (response); } std::string red_if = red_iface.str(); std::string fwdest_out = ""; std::string dest_out = ""; std::string ifc_in_out = ""; std::string ifc_out_out = ""; std::string fwdportdest = ""; std::string srcipmac_out= ""; std::string dport_out = ""; std::string fwdport_out = ""; std::string prot_out = ""; std::string dnat_out = ""; std::string tgt_out = ""; std::string in_dest = ""; bool bounce_type = false; bool forwarding = false; bool translating = false; bool negated_source = false; std::string temp_source = ""; std::string internal_if = ""; std::string conn_green = "0xD0000000"; std::string conn_purple = "0xE0000000"; std::string conn_orange = "0xF0000000"; std::string green_if = ""; std::string green_ifip = ""; std::string orange_if = ""; std::string orange_ifip = ""; std::string purple_if = ""; std::string purple_ifip = ""; /* The mark_mask value can only be used if we switch to CONNMARK tracking std::string mark_mask = "0xFFF00000/"; //=============================================================================> // We use the upper three nybbles of the available CMARK sequence numbers for // identifying the CMARKs associated with Full Firewall Control. Any other // applications using CMARKs must be aware of this, always using a CMARK mask // that is not greater than 0x000FFFFF. Available only if we use CONNMARK //=============================================================================> */ rmdupes (ipb, "iptables -t filter -F portfwf"); // filtering rules (moved stk) rmdupes (ipb, "iptables -t nat -F portfw"); // DNAT forwarding (stk) rmdupes (ipb, "iptables -t mangle -F portfwb"); // MARK bounce & OMask (stk) rmdupes (ipb, "iptables -t nat -F portfw_post"); // SNAT bounce & OMask (add) rmdupes (ipb, "iptables -t filter -F portfwi"); // filter rules for INPUT (add) rmdupes (ipb, "iptables -t filter -F subnetchk");// filter rules FOR/INPUT (add) // ============================================================================> // we allow masking outbound to a red alias by having an association in // the alias file between a single internal IP and the alias interface // ============================================================================> // Here we find the internal interfaces for possible bouncing and create the // rules for masking outbounds to alias interfaces as we read the alias file unsigned int mark_seq = 0x800; for (int line = aliases.first(); line == 0; line = aliases.next()) { char conn_mark[15] = ""; const std::string & f_ifcolor = aliases[0]; const std::string & f_ifalias = aliases[1]; const std::string & f_realif = aliases[2]; const std::string & f_ipaddress = aliases[3]; const std::string & f_addmask = aliases[4]; const std::string & f_enabled = aliases[7]; const std::string & f_mask2add = aliases[9]; std::string scprefixf = "iptables -t filter -A"; std::string sclogpre = " -j LOG --log-prefix ..FFC..not."; std::string sclogpost = ".subnet.."; std::string sclogrej = " -j REJECT"; // Allow DHCP to bypass subnet checking rmdupes (ipb, scprefixf + " subnetchk -p udp --dport 67 -j RETURN"); rmdupes (ipb, scprefixf + " portfwi -j subnetchk"); rmdupes (ipb, scprefixf + " portfwf -j subnetchk"); //============================================================================> // log and reject any packets with a source that is not in the correct // subnet for the interface that received them //===>> To disable: set "(GREEN|PURPLE|ORANGE)=off" in the "sncheckfile" if (f_ifcolor == "GREEN") { green_if = f_realif; green_ifip = f_ipaddress; if (greencheck != "off") { char cidr[5] = ""; sprintf((char*) cidr, "/%d", snet2cidr(f_addmask)); std::string scpostfixl = (" -i " + green_if + " ! -s " + green_ifip + cidr + sclogpre + f_ifcolor + sclogpost); std::string scpostfixr = (" -i " + green_if + " ! -s " + green_ifip + cidr + sclogrej); rmdupes (ipb, scprefixf + " subnetchk" + scpostfixl); rmdupes (ipb, scprefixf + " subnetchk" + scpostfixr); } } if (f_ifcolor == "ORANGE") { orange_if = f_realif; orange_ifip = f_ipaddress; if (orangecheck != "off") { char cidr[5] = ""; sprintf((char*) cidr, "/%d", snet2cidr(f_addmask)); std::string scpostfixl = (" -i " + orange_if + " ! -s " + orange_ifip + cidr + sclogpre + f_ifcolor + sclogpost); std::string scpostfixr = (" -i " + orange_if + " ! -s " + orange_ifip + cidr + sclogrej); rmdupes (ipb, scprefixf + " subnetchk" + scpostfixl); rmdupes (ipb, scprefixf + " subnetchk" + scpostfixr); } } if (f_ifcolor == "PURPLE") { purple_if = f_realif; purple_ifip = f_ipaddress; if (purplecheck != "off") { char cidr[5] = ""; sprintf((char*) cidr, "/%d", snet2cidr(f_addmask)); std::string scpostfixl = (" -i " + purple_if + " ! -s " + purple_ifip + cidr + sclogpre + f_ifcolor + sclogpost); std::string scpostfixr = (" -i " + purple_if + " ! -s " + purple_ifip + cidr + sclogrej); rmdupes (ipb, scprefixf + " subnetchk" + scpostfixl); rmdupes (ipb, scprefixf + " subnetchk" + scpostfixr); } } if (f_mask2add != "" && f_mask2add.find_first_of("/") == std::string::npos && f_ifalias.find_first_of(":") != std::string::npos && f_enabled == "on") //============================================================================> // Make sure we have an alias interface and a single IP to mask { sprintf((char*) conn_mark, "%#010x", (++mark_seq) * 0x100000); conn_mark[10] = 0; rmdupes (ipb, "iptables -t mangle -A portfwb -s " + f_mask2add + " -j MARK --set-mark " + conn_mark); rmdupes (ipb, "iptables -t nat -A portfw_post -o " + red_if + " -s " + f_mask2add + " -m mark --mark " + conn_mark + " -j SNAT --to-source " + f_ipaddress); } if (mark_seq > 0x8FF) { response = "Abort, more than 255 aliases not supported, reduce alias count."; return errrpt (response); } if (error) { response = "Abort in alias file for " + f_ifalias + " interface."; return errrpt (response); } }// <<== End of reading "aliasfile" //=============================================================================> // This is to clean up any previously entered jumps around the proxies, then // we set the jumps around the proxies for any outbound masking to an alias std::string proxy_jmph = "iptables -t nat "; std::string proxy_jmpt = " -m mark --mark 0x80000000/0x80000000 -j RETURN"; // the match mark mask does not correctly mask for some reason // the position of flag and mask might be reversed if (chkproxy()) { rmdupes (ipb, proxy_jmph + "-D jmpim" + proxy_jmpt); rmdupes (ipb, proxy_jmph + "-D jmpp3scan" + proxy_jmpt); rmdupes (ipb, proxy_jmph + "-D jmpsip" + proxy_jmpt); rmdupes (ipb, proxy_jmph + "-D jmpsquid" + proxy_jmpt); } if (mark_seq > 0x800) { rmdupes (ipb, proxy_jmph + "-I jmpim" + proxy_jmpt); rmdupes (ipb, proxy_jmph + "-I jmpp3scan" + proxy_jmpt); rmdupes (ipb, proxy_jmph + "-I jmpsip" + proxy_jmpt); rmdupes (ipb, proxy_jmph + "-I jmpsquid" + proxy_jmpt); } //=============================================================================> // Read the rules, in sequence from "configfile" and build for (int line = fwdconf.first(); line == 0; line = fwdconf.next()) { const std::string & f_input = fwdconf[1]; const std::string & f_source = fwdconf[2]; const std::string & f_dport = fwdconf[3]; const std::string & f_output = fwdconf[4]; const std::string & f_fwdest = fwdconf[5]; const std::string & f_fwdport = fwdconf[6]; const std::string & f_proto = fwdconf[7]; const std::string & f_action = fwdconf[8]; const std::string & f_enabled = fwdconf[9]; if (f_input.find_first_not_of(INTERFACE) != std::string::npos && (f_input.find_first_not_of(INTERFACE_ALIAS) != std::string::npos) && f_input != "any") { response = "Abort, bad input interface: (" + f_input + ") rule number " + fwdconf[0]; return errrpt (response); } if (f_output.find_first_not_of(INTERFACE) != std::string::npos && (f_output.find_first_not_of(INTERFACE_ALIAS) != std::string::npos) && f_output != "any") { response = "Abort, bad output interface: " + f_output + " rule number " + fwdconf[0]; return errrpt (response); } if (f_proto.find_first_not_of(NUMBERS) != std::string::npos && f_proto != "all") { response = "Abort, bad protocol: (" + f_proto + ") rule number " + fwdconf[0]; return errrpt (response); } if (f_dport.find_first_not_of(NUMBERS_COLON) != std::string::npos) { response = "Abort, bad initial destination port: (" + f_dport + ") rule number " + fwdconf[0]; return errrpt (response); } // First operation is to remove negation, if present negated_source = false; if ((p = f_source.find_first_of("! ")) != std::string::npos && (n = f_source.find_first_not_of("! ")) != std::string::npos) { negated_source = true; temp_source = f_source; temp_source = temp_source.erase(p, n - p); } else temp_source = f_source; if (temp_source.find_first_not_of(IP_NUMBERS) != std::string::npos && temp_source.find_first_not_of(MAC_HEX) != std::string::npos) { response = "Abort, bad source IP or MAC: (" + f_source + ") rule number " + fwdconf[0]; return errrpt (response); } if (f_fwdest.find_first_not_of(IP_NUMBERS) != std::string::npos) { response = "Abort, bad new destination IP: (" + f_fwdest + ") rule number " + fwdconf[0]; return errrpt (response); } if (f_fwdport.find_first_not_of(NUMBERS_COLON) != std::string::npos) { response = "Abort, bad new destination port: (" + f_fwdport + ") rule number " + fwdconf[0]; return errrpt (response); } if (f_action != "REJECT" && f_action != "RETURN" && f_action != "ACCEPT" && f_action != "DROP" && f_action != "LOG") { response = "Abort, bad action: (" + f_action + ") rule number " + fwdconf[0]; return errrpt (response); } if (f_enabled == "on") { // ==========================================================================> // we allow red bouncing by specifying that it comes from * interface // because bouncing requires that DNAT and SNAT be done on the packets // specifying an interface on bounces is not possible, the source is the // destination for bounces, if the source must be limited on bounces, // use an IP limitation // ==========================================================================> // Here we create the source strings, or leave null if unused forwarding = false; in_dest = ""; if (f_input.find(red_if) != std::string::npos) { if (f_proto == "1" || f_proto == "6" || f_proto == "17" || f_proto == "47" || f_proto == "50" || f_proto == "51") { forwarding = true; // ICMP:1 TCP:6 UDP:17 GRE:47 ESP:50 AH:51 <---Forwarded protocols in_dest = localip.str(); // default IP for the actual red interface, changed only for aliases // If it is an alias if (f_input.find(":") != std::string::npos) { for (int line = aliases.first(); line == 0; line = aliases.next()) // forwarding from the red interface we need to find the IP { const std::string & f_ifalias = aliases[1]; const std::string & f_ipaddress = aliases[3]; if ((f_input == f_ifalias && aliases[7] == "on")) in_dest = f_ipaddress; } } if (in_dest.find_first_not_of(IP_NUMBERS) != std::string::npos && in_dest.find_first_of("/") != std::string::npos) { response = "Abort, could not find match for interface (" + f_input + ") and IP (" + in_dest + ") to construct a forwarding rule in rule number " + fwdconf[0]; return errrpt (response); } } // <<== End of protocol } // <<== End of Red IF ifc_in_out = ""; if (f_input != "any" && ! forwarding) // If it is not "any" and not being forwarded set the input interface { ifc_in_out = f_input; // If it is an alias interface, truncate the string starting with the colon if ((n = ifc_in_out.find_first_of(":")) != std::string::npos) ifc_in_out.erase(n, 4); ifc_in_out = " -i " + ifc_in_out; } ifc_out_out = ""; if (f_output != "any" && f_output != "") { ifc_out_out = f_output; if ((n = ifc_out_out.find_first_of(":")) != std::string::npos) ifc_out_out.erase(n, 4); ifc_out_out = " -o " + ifc_out_out; } prot_out = ""; if (f_proto != "all" && f_proto != "") prot_out = " -p " + f_proto; dest_out = ""; if (in_dest != "") dest_out = " -d " + in_dest; dport_out = ""; if (f_dport != "0" && f_dport != "") dport_out = " --dport " + f_dport; translating = false; fwdport_out = ""; fwdportdest = ""; if (f_fwdport != "0" && f_fwdport != "") { translating = true; fwdport_out = " --dport " + f_fwdport; fwdportdest = f_fwdport; if ((n = fwdportdest.find_first_of(":")) != std::string::npos) fwdportdest.replace(n, 1, "-"); fwdportdest = ":" + fwdportdest; } fwdest_out = ""; dnat_out = ""; if (translating || forwarding) { if (f_fwdest != "" && f_fwdest.find_first_of("/") == std::string::npos) // an IP is being forwarded, but we must have a destination IP to // forward to for DNAT to be sensible { fwdest_out = " -d " + f_fwdest; dnat_out = " -j DNAT --to-destination " + f_fwdest + fwdportdest; } // If we expected to build a DNAT rule and failed, the IP is not singular if (dnat_out == "") { response = "Abort, bad new destination IP (" + f_fwdest + "), must be single IP in rule number " + fwdconf[0]; return errrpt (response); } // translation requires the same IP in the DNAT initial destination if (! forwarding) dest_out = fwdest_out; } srcipmac_out = ""; if (temp_source.find_first_not_of(IP_NUMBERS) == std::string::npos) { srcipmac_out = " -s " + temp_source; } if (temp_source.find_first_not_of(MAC_HEX) == std::string::npos) { srcipmac_out = " -m mac --mac-source " + temp_source; } // must be a space between "!" and the descriptor if (negated_source) srcipmac_out = " ! " + srcipmac_out; tgt_out = " -j " + f_action; if (f_action == "LOG") tgt_out = " -j LOG --log-prefix ..FFC.."; // if we aren't going to DNAT we still need some information in portfwf if (! translating && dport_out != "") fwdport_out = dport_out; if (dnat_out == "" && f_fwdest != "") fwdest_out = " -d " + f_fwdest; // ==========================================================================> // Here we get down to the business of creating the rules from the strings if (forwarding || translating) rmdupes (ipb, "iptables -t nat -A portfw " + ifc_in_out + prot_out + srcipmac_out + dest_out + dport_out + dnat_out); rmdupes (ipb, "iptables -t filter -A portfwf -m state --state NEW" + ifc_out_out + prot_out + srcipmac_out + fwdest_out + fwdport_out + tgt_out); // In the INPUT chain we should not ACCEPT since EXTACCESS should be the // source for that type of rule, and only process rules that are not // forwarding or translating rules, meaning no specific output interface if (tgt_out == " -j ACCEPT") tgt_out = " -j RETURN"; // Note: If the destination interface is specified then we don't create // a rule. This allows the proxies to bypass a block rule for outbounds // which may be blocked by an additional specific rule with the Any // interface specified. Another option explored was to skip only ACCEPT // rules, but that has limited usability as well. if (ifc_out_out == "") rmdupes (ipb, "iptables -t filter -A portfwi -m state --state NEW" + ifc_in_out + prot_out + srcipmac_out + dport_out + tgt_out); // ==========================================================================> // Here we create rules for bouncing if the input interface is null and // there has been a DNAT for the red interface, we skip translating DNAT if (forwarding) { std::string forward_pre = "iptables -t mangle -A portfwb -i "; std::string forward_post = " -j MARK --set-mark "; if (green_if != "") rmdupes (ipb, forward_pre + green_if + dest_out + forward_post + conn_green); if (purple_if != "") rmdupes (ipb, forward_pre + purple_if + dest_out + forward_post + conn_purple); if (orange_if != "") rmdupes (ipb, forward_pre + orange_if + dest_out + forward_post + conn_orange); bounce_type = true; } }// <<==== End of enabled }// <<==== End of reading portfw/config file //=============================================================================> // The rules have been created, now we need to allow bounces, if we are doing // any portforwarding that allows bouncing if (bounce_type) { // We only need to SNAT those packets that came in the same interface that // they are going out on to ensure the return path is through the interface std::string pfw_post_pre = "iptables -t nat -A portfw_post -m mark --mark "; std::string pfw_post_post = " -j SNAT --to-source "; if (green_if != "") rmdupes (ipb, pfw_post_pre + conn_green + " -o " + green_if + pfw_post_post + green_ifip); if (purple_if != "") rmdupes (ipb, pfw_post_pre + conn_purple + " -o " + purple_if + pfw_post_post + purple_ifip); if (orange_if != "") rmdupes (ipb, pfw_post_pre + conn_orange + " -o " + orange_if + pfw_post_post + orange_ifip); } //=============================================================================> // Pass the built up vector of strings to ipbatch to build IPTables entries error = ipbatch(ipb); if (error) response = "Abort flushing rules to IPTables"; return errrpt (response); }
//#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@> int set_xtaccess(std::vector<std::string> & parameters, std::string & response) { std::string ifacefile = "/var/smoothwall/red/iface"; std::string cmdprefix = "/var/smoothwall"; std::string configfile = cmdprefix + "/xtaccess/config"; std::string aliasfile = cmdprefix + "/portfw/aliases"; ConfigSTR ifacef(ifacefile); ConfigCSV config(configfile); ConfigCSV aliases(aliasfile); std::vector<std::string> ipb; std::string red_ip = ""; std::string iface = ifacef.str(); std::string destination = ""; std::string dport_out = ""; int error = 0; // preset the response to a success, changed only on error, always return zero response = "External Access Rules set"; if (ifacef.str() == "") { response = "Abort, could not open red local interface file (" + ifacefile + ")"; return errrpt (response); } if (iface.find_first_not_of(INTERFACE) != std::string::npos) { response = "Abort, bad interface: " + iface; return errrpt (response); } rmdupes(ipb, "iptables -t filter -F xtaccess"); rmdupes(ipb, "iptables -t nat -F portfw_pre"); //=============================================================================> // Any destination IP that is local and not forwarded goes to us through INPUT for (int line = config.first(); line == 0; line = config.next()) { const std::string & alias = config[0]; const std::string & protocol = config[1]; const std::string & remip = config[2]; const std::string & locport = config[3]; const std::string & enabled = config[4]; if (protocol.find_first_not_of(NUMBERS) != std::string::npos) { response = "Abort, bad protocol: " + protocol; return errrpt (response); } if (remip.find_first_not_of(IP_NUMBERS) != std::string::npos) { response = "Abort, bad remote IP: " + remip; return errrpt (response); } if (locport.find_first_not_of(NUMBERS_COLON) != std::string::npos) { response = "Abort, bad port: " + locport; return errrpt (response); } dport_out = ""; if (locport != "0" && locport != "") dport_out = " --dport " + locport; red_ip = ""; for (int aline = aliases.first(); aline == 0; aline = aliases.next()) // we need to find the alias IP of the red interface { const std::string & f_ifalias = aliases[1]; const std::string & f_ipaddress = aliases[3]; if (alias == f_ifalias) { red_ip = f_ipaddress; break; } } if (red_ip == "") { response = "Abort, could not find an alias match in (" + configfile + ") with (" + aliasfile + ") for an IP in the XTAccess rule"; return errrpt(response); } destination = " -d " + red_ip; //============================================================================> // This only creates the rules if they are present and enabled, the alias // may be disabled which would make the rule ineffective since the IP would // not be present in ifconfig if (enabled == "on") { rmdupes(ipb, "iptables -t filter -A xtaccess -i " + iface + " -d " + red_ip + " -p " + protocol + dport_out + " -s " + remip + " -j ACCEPT"); } } error = ipbatch(ipb); if (error) response = "ipbatch failure"; return errrpt (response); }
int set_xtaccess(std::vector<std::string> & parameters, std::string & response) { int error = 0; ConfigSTR ifacef("/var/smoothwall/red/iface"); ConfigCSV config("/var/smoothwall/xtaccess/config"); std::vector<std::string>ipb; std::string::size_type n; std::string iface = ifacef.str(); if (iface.substr(0, 3) == "ppp" || iface.substr(0, 4) == "ippp") iface = ""; // ignore ppp if (iface != "" && ((n = iface.find_first_not_of(LETTERS_NUMBERS)) != std::string::npos)) { response = "Bad iface: " + iface; error = 1; goto EXIT; } ipb.push_back("iptables -F xtaccess"); for (int line = config.first(); line == 0; line = config.next()) { const std::string & protocol = config[0]; const std::string & remip = config[1]; const std::string & locport = config[2]; const std::string & enabled = config[3]; // are we complete? if (protocol == "" || remip == "" || locport == "" || enabled == "") break; if ((n = protocol.find_first_not_of(LETTERS)) != std::string::npos) { response = "Bad protocol: " + protocol; error = 1; goto EXIT; } if ((n = remip.find_first_not_of(IP_NUMBERS)) != std::string::npos) { response = "Bad remote IP: " + remip; error = 1; goto EXIT; } if ((n = locport.find_first_not_of(NUMBERS_COLON)) != std::string::npos) { response = "Bad port: " + locport; error = 1; goto EXIT; } if (enabled == "on") { ipb.push_back("iptables -A xtaccess -i ppp0 -p " + protocol + " -s " + remip + " --destination-port " + locport + " -j ACCEPT"); ipb.push_back("iptables -A xtaccess -i ippp0 -p " + protocol + " -s " + remip + " --destination-port " + locport + " -j ACCEPT"); if (iface != "") { ipb.push_back("iptables -A xtaccess -i " + iface + " -p " + protocol + " -s " + remip + " --destination-port " + locport + " -j ACCEPT"); } } } error = ipbatch(ipb); if (error) response = "ipbatch failure"; else response = "xtaccess set"; EXIT: return error; }
int set_internal(std::vector<std::string> & parameters, std::string & response) { int error = 0; ConfigCSV config("/var/smoothwall/dmzholes/config"); std::vector<std::string>ipb; std::string::size_type n; load_portlist(); ipb.push_back("iptables -F dmzholes"); for (int line = config.first(); line == 0; line = config.next()) { const std::string & protocol = config[0]; const std::string & locip = config[1]; const std::string & remip = config[2]; const std::string & remport = config[3]; const std::string & enabled = config[4]; // are we complete? if (protocol == "" || locip == "" || remip == "" || remport == "" || enabled == "") continue; if ((n = protocol.find_first_not_of(LETTERS)) != std::string::npos) { response = "Bad protocol: " + protocol; error = 1; return error; } if ((n = locip.find_first_not_of(IP_NUMBERS)) != std::string::npos) { response = "Bad local IP: " + locip; error = 1; return error; } if ((n = remip.find_first_not_of(IP_NUMBERS)) != std::string::npos) { response = "Bad remote IP: " + remip; error = 1; return error; } if (enabled == "on") { if ((n = remport.find_first_not_of(NUMBERS_COLON)) != std::string::npos) { if (portlist[remport.c_str()].size() > 0) { /* it's a mapped port! */ std::vector<std::string> & vect = portlist[remport.c_str()]; for (std::vector<std::string>::iterator i = vect.begin(); i != vect.end(); i++) { std::string nport = *i; ipb.push_back("iptables -A dmzholes -m state --state NEW -p " + protocol + " -s " + locip + " -d " + remip + " --dport " + nport + " -j ACCEPT"); } } else { response = "Bad remote port: " + remport; error = 1; return error; } } else ipb.push_back("iptables -A dmzholes -m state --state NEW -p " + protocol + " -s " + locip + " -d " + remip + " --dport " + remport + " -j ACCEPT"); } } error = ipbatch(ipb); if (error) response = "ipbatch failure"; else response = "DMZ Holes set"; return (error); }
int set_outgoing(std::vector<std::string> & parameters, std::string & response) { int error = 0; ConfigVAR settings("/var/smoothwall/outgoing/settings"); ConfigCSV config("/var/smoothwall/outgoing/config"); ConfigCSV machineconfig("/var/smoothwall/outgoing/machineconfig"); std::vector<std::string>ipb; std::string::size_type n; load_portlist(); ipb.push_back("iptables -F outgreen\n"); ipb.push_back("iptables -F outorange"); ipb.push_back("iptables -F outpurple"); for (int line = config.first(); line == 0; line = config.next()) { const std::string & colour = config[0]; const std::string & enabled = config[1]; const std::string & port = config[2]; // are we complete? if (colour == "" || port == "" || enabled == "") continue; if (!(colour == "GREEN" || colour == "ORANGE" || colour == "PURPLE")) { response = "Bad colour: " + colour; error = 1; return error; } std::string chain = "out" + colour; std::transform(chain.begin(), chain.end(), chain.begin(), tolower); std::string action = settings[colour.c_str()]; if (action == "") action = "REJECT"; if (enabled == "on") { if ((n = port.find_first_not_of(NUMBERS_COLON)) != std::string::npos) { if (portlist[port.c_str()].size() > 0) { /* it's a mapped port! */ std::vector<std::string> & vect = portlist[port.c_str()]; for (std::vector<std::string>::iterator i = vect.begin(); i != vect.end(); i++) { std::string nport = *i; ipb.push_back("iptables -A " + chain + " -p tcp --dport " + nport + " -j " + action); ipb.push_back("iptables -A " + chain + " -p udp --dport " + nport + " -j " + action); } } else { response = "Bad port: " + port; error = 1; return error; } } else { ipb.push_back("iptables -A " + chain + " -p tcp --dport " + port + " -j " + action); ipb.push_back("iptables -A " + chain + " -p udp --dport " + port + " -j " + action); } } } if (settings["GREEN"] != "ACCEPT") ipb.push_back("iptables -A outgreen -j ACCEPT"); if (settings["ORANGE"] != "ACCEPT") ipb.push_back("iptables -A outorange -j ACCEPT"); if (settings["PURPLE"] != "ACCEPT") ipb.push_back("iptables -A outpurple -j ACCEPT"); ipb.push_back("iptables -F allows"); for (int line = machineconfig.first(); line == 0; line = machineconfig.next()) { const std::string & ip = machineconfig[0]; const std::string & enabled = machineconfig[1]; // are we complete? if (ip == "" || enabled == "") continue; if ((n = ip.find_first_not_of(IP_NUMBERS)) != std::string::npos) { response = "Bad IP: " + ip; error = 1; return error; } if (enabled == "on") ipb.push_back("iptables -A allows -s " + ip + " -j ACCEPT"); } error = ipbatch(ipb); if (error) response = "ipbatch failure"; else response = "Outbound ports set"; return error; }
int set_incoming(std::vector<std::string> & parameters, std::string & response) { int error = 0; std::string::size_type n; std::vector<std::string>ipbfilter; std::vector<std::string>ipbnat; std::vector<std::string>ipbmangle; ConfigSTR localip("/var/smoothwall/red/local-ipaddress"); ConfigSTR iface("/var/smoothwall/red/iface"); ConfigCSV fwdfile("/var/smoothwall/portfw/config"); ConfigVAR ethernet("/var/smoothwall/ethernet/settings"); if ((error = (localip.str() == ""))) { response = "Couldn't open local IP file"; return error; } // carry on if ((n = localip.str().find_first_not_of(IP_NUMBERS)) != std::string::npos) { // illegal characters response = "Bad local IP: " + localip.str(); error = 1; return error; } if ((error = (iface.str() == ""))) { response = "Couldn't open iface file"; return error; } // carry on if ((n = iface.str().find_first_not_of(LETTERS_NUMBERS)) != std::string::npos) { // illegal characters response = "Bad iface: " + iface.str(); error = 1; return error; } ipbfilter.push_back("iptables -t filter -F portfwf"); ipbnat.push_back("iptables -t nat -F portfw"); ipbmangle.push_back("iptables -t mangle -F portfwb"); // iterate the CSV for (int line = fwdfile.first(); line == 0; line = fwdfile.next()) { std::string remdouble; const std::string & protocol = fwdfile[0]; const std::string & extip = fwdfile[1]; const std::string & locport = fwdfile[2]; const std::string & remip = fwdfile[3]; // this last one want to change maybe std::string remport = fwdfile[4]; const std::string & enabled = fwdfile[5]; if ((n = protocol.find_first_not_of(LETTERS)) != std::string::npos) { response = "Bad protocol: " + protocol; error = 1; return error; } if ((n = extip.find_first_not_of(IP_NUMBERS)) != std::string::npos) { response = "Bad external IP: " + extip; error = 1; return error; } if ((n = locport.find_first_not_of(NUMBERS_COLON)) != std::string::npos) { response = "Bad local port: " + locport; error = 1; return error; } if ((n = remip.find_first_not_of(IP_NUMBERS)) != std::string::npos) { response = "Bad remote IP: " + remip; error = 1; return error; } if ((n = remport.find_first_not_of(NUMBERS)) != std::string::npos) { response = "Bad remote port: " + remport; error = 1; return error; } if (enabled == "on") { if (remport == "0") remport = locport; // if locport does not have : or originally remport not zero if(locport.find_first_of(":") == std::string::npos || fwdfile[4] != "0") remdouble = remip + ":" + remport; else remdouble = remip; ipbfilter.push_back("iptables -t filter -A portfwf -m state --state NEW -p " + protocol + " -s " + extip + " -d " + remip + " --dport " + remport + " -j ACCEPT"); ipbnat.push_back("iptables -t nat -A portfw -p " + protocol + " -s " + extip + " -d " + localip.str() + " --dport " + locport + " -j DNAT --to " + remdouble); } } /* Rules to detect bouncing port forwarding */ int mark = 0; std::string insideinterface; while (mark++ < 3) { switch (mark) { case 1: insideinterface = ethernet["GREEN_DEV"]; break; case 2: insideinterface = ethernet["ORANGE_DEV"]; break; case 3: insideinterface = ethernet["PURPLE_DEV"]; break; default: break; } if (insideinterface != "") { ipbmangle.push_back("iptables -t mangle -A portfwb -i " + insideinterface + " -d " + localip.str() + " -j MARK --set-mark " + stringprintf("%d", mark)); } } error = ipbatch(ipbfilter); if (error) { response = "ipbatch failure (filter)"; return error; } error = ipbatch(ipbnat); if (error) { response = "ipbatch failure (nat)"; return error; } error = ipbatch(ipbmangle); if (error) { response = "ipbatch failure (mangle)"; return error; } response = "Portfw rules set"; return (error); }