//#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@> int readether(std::vector<std::string> & argv, std::string & args) { std::string localipfile = "/var/smoothwall/red/local-ipaddress"; std::string redfile = "/var/smoothwall/red/iface"; std::string etherfile = "/var/smoothwall/ethernet/settings"; std::string buildit = ""; char between[32] = ""; ConfigVAR ether(etherfile); ConfigSTR localip(localipfile); ConfigSTR rediface(redfile); buildit += args + ","; if (args == "RED") { buildit += rediface.str() + ","; buildit += rediface.str() + ","; buildit += localip.str() + ","; } else { sprintf((char *)between, "%s%s", args.c_str(), "_DEV"); if (ether[(const char *) between] == "") return 0; buildit += ether[(const char *) between] + ","; buildit += ether[(const char *) between] + ","; sprintf((char *)between, "%s%s", args.c_str(), "_ADDRESS"); buildit += ether[(const char *) between] + ","; } sprintf((char *)between, "%s%s", args.c_str(), "_NETMASK"); buildit += ether[(const char *) between] + ","; sprintf((char *)between, "%s%s", args.c_str(), "_BROADCAST"); buildit += ether[(const char *) between] + ","; buildit += "on,on,,\n"; argv.push_back(buildit); return 0; }
//#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@> int ifaliasup(std::vector<std::string> & parameters, std::string & response) { int error = 0; error = wrtaliases (response); if (error) return errrpt(response); std::vector<std::string> argv; std::string cmdprefix = "/var/smoothwall"; std::string varfile = cmdprefix + "/portfw/snort.var"; std::string localipfile = "/var/smoothwall/red/local-ipaddress"; std::string aliasfile = cmdprefix + "/portfw/aliases"; ConfigCSV aliases(aliasfile); ConfigSTR localip(localipfile); std::string::size_type n; char home_net[5000] = ""; char * hnptr = home_net; FILE * varhandle; 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); } std::string homenet = "var HOME_NET [" + localip.str(); response = "Bringing alias interfaces up"; error = errrpt(response); hnptr += sprintf(hnptr, "%s,", homenet.c_str()); for (int line = aliases.first(); line == 0; line = aliases.next()) { std::string f_color = aliases[0]; std::string f_ifalias = aliases[1]; std::string f_ip = aliases[3]; std::string f_net = aliases[4]; std::string f_bcst = aliases[5]; if ((n = f_ifalias.find_first_of(":")) != std::string::npos && aliases[7] == "on") { // Add the alias to HOME_NET if it is enabled and we have room (with // 255 aliases maximum should be less than 4878 plus 28 chars at finish) if ((n = f_color.find("RED")) != std::string::npos) hnptr += sprintf(hnptr, "%s,", f_ip.c_str()); errrpt("bringing up alias (" + f_ifalias + ")"); if (f_ifalias.find_first_of("p") != std::string::npos) error += simplesecuresysteml("/sbin/ifconfig",f_ifalias.c_str(),f_ip.c_str(), "netmask",f_net.c_str(),"up",NULL); else error += simplesecuresysteml("/sbin/ifconfig",f_ifalias.c_str(),f_ip.c_str(), "netmask",f_net.c_str(),"broadcast",f_bcst.c_str(),"up",NULL); } } // backup one space to overwrite the trailing comma hnptr += sprintf(--hnptr, "]\n"); if (!(varhandle = fopen(varfile.c_str(), "w"))) { response = "Abort, could not create or open (" + varfile + ") file"; return errrpt(response); } fputs((char*) home_net, varhandle); fclose(varhandle); errrpt("NOTE: snort should be restarted manually to update its HOME_NET value"); errrpt("NOTE: /etc/snort.conf can be further customized for each scenario"); response = "Successfully brought up alias interfaces."; if (error) response = "Abort while bringing up alias interfaces"; return errrpt(response); }
//#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@#@> 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_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); }