WvStreams
|
00001 /* 00002 * Worldvisions Weaver Software: 00003 * Copyright (C) 1997-2002 Net Integration Technologies, Inc. 00004 * 00005 * WvIPFirewall is an extremely simple hackish class that handles the Linux 00006 * 2.4 "iptables" firewall. See wvipfirewall.h. 00007 */ 00008 #include "wvipfirewall.h" 00009 #include "wvinterface.h" 00010 #include <unistd.h> 00011 00012 00013 bool WvIPFirewall::enable = false, WvIPFirewall::ignore_errors = true; 00014 00015 00016 WvIPFirewall::WvIPFirewall() : log("Firewall", WvLog::Debug2) 00017 { 00018 // don't change any firewall rules here! Remember that there may be 00019 // more than one instance of the firewall object. 00020 } 00021 00022 00023 WvIPFirewall::~WvIPFirewall() 00024 { 00025 zap(); 00026 } 00027 00028 00029 WvString WvIPFirewall::port_command(const char *cmd, const char *proto, 00030 const WvIPPortAddr &addr) 00031 { 00032 WvIPAddr ad(addr), none; 00033 00034 return WvString("iptables %s Services -j ACCEPT -p %s " 00035 "%s --dport %s " 00036 "%s", 00037 cmd, proto, 00038 ad == none ? WvString("") : WvString("-d %s", ad), 00039 addr.port, 00040 shutup()); 00041 } 00042 00043 00044 WvString WvIPFirewall::redir_command(const char *cmd, const WvIPPortAddr &src, 00045 int dstport) 00046 { 00047 WvIPAddr ad(src), none; 00048 00049 return WvString("iptables -t nat %s TProxy " 00050 "-p tcp %s --dport %s " 00051 "-j REDIRECT --to-ports %s " 00052 "%s", 00053 cmd, 00054 ad == none ? WvString("") : WvString("-d %s", ad), 00055 src.port, dstport, 00056 shutup()); 00057 } 00058 00059 WvString WvIPFirewall::forward_command(const char *cmd, 00060 const char *proto, 00061 const WvIPPortAddr &src, 00062 const WvIPPortAddr &dst, bool snat) 00063 { 00064 WvIPAddr srcaddr(src), dstaddr(dst), zero; 00065 WvString haveiface(""), haveoface(""); 00066 if (!(srcaddr == zero)) 00067 { 00068 haveiface.append("-d "); 00069 haveiface.append((WvString)srcaddr); 00070 } 00071 00072 WvString retval; 00073 00074 if ((dst == WvIPAddr("127.0.0.1")) || (dst == zero)) 00075 { 00076 retval.append("iptables -t nat %s FASTFORWARD -p %s --dport %s %s " 00077 "-j REDIRECT --to-port %s %s \n", 00078 cmd, proto, src.port, haveiface, dst.port, shutup()); 00079 } 00080 else 00081 { 00082 haveoface.append("-d "); 00083 haveoface.append((WvString)dstaddr); 00084 00085 retval.append("iptables -t nat %s FASTFORWARD -p %s --dport %s %s " 00086 "-j DNAT --to-destination %s " 00087 "%s \n", cmd, proto, src.port, haveiface, dst, shutup()); 00088 } 00089 00090 // FA57 is leet-speak for FAST, which is short for FASTFORWARD --adewhurst 00091 // FA58 is FA57+1. Nothing creative sprang to mind. --adewhurst 00092 // 00093 // We need this to mark the packet as it comes in so that we allow the 00094 // FastForward-ed packets to bypass the firewall (FA57). 00095 // 00096 // If we mark the packet with FA58, that means it gets masqueraded before 00097 // leaving, which may be useful to work around some network configuratios. 00098 retval.append("iptables -t mangle %s FASTFORWARD -p %s --dport %s " 00099 "-j MARK --set-mark %s %s %s\n", cmd, proto, src.port, 00100 snat ? "0xFA58" : "0xFA57", haveiface, shutup()); 00101 00102 // Don't open the port completely; just open it for the forwarded packets 00103 retval.append("iptables %s FFASTFORWARD -j ACCEPT -p %s " 00104 "--dport %s -m mark --mark %s %s %s\n", cmd, proto, dst.port, 00105 snat ? "0xFA58" : "0xFA57", haveoface, shutup()); 00106 00107 return retval; 00108 } 00109 00110 WvString WvIPFirewall::redir_port_range_command(const char *cmd, 00111 const WvIPPortAddr &src_min, const WvIPPortAddr &src_max, int dstport) 00112 { 00113 WvIPAddr ad(src_min), none; 00114 00115 return WvString("iptables -t nat %s TProxy " 00116 "-p tcp %s --dport %s:%s " 00117 "-j REDIRECT --to-ports %s " 00118 "%s", 00119 cmd, 00120 ad == none ? WvString("") : WvString("-d %s", ad), 00121 src_min.port == 0? WvString(""): WvString(src_min.port), 00122 src_max.port == 0? WvString(""): WvString(src_max.port), 00123 dstport, 00124 shutup()); 00125 } 00126 00127 WvString WvIPFirewall::redir_all_command(const char *cmd, int dstport) 00128 { 00129 return WvString("iptables -t nat %s TProxy " 00130 "-p tcp " 00131 "-j REDIRECT --to-ports %s " 00132 "%s", 00133 cmd, 00134 dstport, 00135 shutup()); 00136 } 00137 00138 WvString WvIPFirewall::proto_command(const char *cmd, const char *proto) 00139 { 00140 return WvString("iptables %s Services -p %s -j ACCEPT " 00141 "%s", 00142 cmd, proto, shutup()); 00143 } 00144 00145 00146 void WvIPFirewall::add_port(const WvIPPortAddr &addr) 00147 { 00148 addrs.append(new WvIPPortAddr(addr), true); 00149 WvString s(port_command("-A", "tcp", addr)), 00150 s2(port_command("-A", "udp", addr)); 00151 if (enable) 00152 { 00153 system(s); 00154 system(s2); 00155 } 00156 } 00157 00158 00159 // note! This does not remove the address from the list, only the kernel! 00160 void WvIPFirewall::del_port(const WvIPPortAddr &addr) 00161 { 00162 WvIPPortAddrList::Iter i(addrs); 00163 for (i.rewind(); i.next(); ) 00164 { 00165 if (*i == addr) 00166 { 00167 WvString s(port_command("-D", "tcp", addr)), 00168 s2(port_command("-D", "udp", addr)); 00169 if (enable) 00170 { 00171 system(s); 00172 system(s2); 00173 } 00174 return; 00175 } 00176 } 00177 } 00178 00179 void WvIPFirewall::add_forward(const WvIPPortAddr &src, 00180 const WvIPPortAddr &dst, bool snat) 00181 { 00182 ffwds.append(new FFwd(src, dst, snat), true); 00183 WvString s(forward_command("-A", "tcp", src, dst, snat)), 00184 s2(forward_command("-A", "udp", src, dst, snat)); 00185 00186 log("Add Forwards (%s):\n%s\n%s\n", enable, s, s2); 00187 00188 if (enable) 00189 { 00190 system(s); 00191 system(s2); 00192 } 00193 } 00194 00195 void WvIPFirewall::del_forward(const WvIPPortAddr &src, 00196 const WvIPPortAddr &dst, bool snat) 00197 { 00198 FFwdList::Iter i(ffwds); 00199 for (i.rewind(); i.next();) 00200 { 00201 if (i->src == src && i->dst == dst && i->snat == snat) 00202 { 00203 WvString s(forward_command("-D", "tcp", src, dst, snat)), 00204 s2(forward_command("-D", "udp", src, dst, snat)); 00205 00206 log("Delete Forward (%s):\n%s\n%s\n", enable, s, s2); 00207 00208 if (enable) 00209 { 00210 system(s); 00211 system(s2); 00212 } 00213 } 00214 } 00215 } 00216 00217 void WvIPFirewall::add_redir(const WvIPPortAddr &src, int dstport) 00218 { 00219 redirs.append(new Redir(src, dstport), true); 00220 WvString s(redir_command("-A", src, dstport)); 00221 if (enable) system(s); 00222 } 00223 00224 00225 void WvIPFirewall::del_redir(const WvIPPortAddr &src, int dstport) 00226 { 00227 RedirList::Iter i(redirs); 00228 for (i.rewind(); i.next(); ) 00229 { 00230 if (i->src == src && i->dstport == dstport) 00231 { 00232 WvString s(redir_command("-D", src, dstport)); 00233 if (enable) system(s); 00234 return; 00235 } 00236 } 00237 } 00238 00239 void WvIPFirewall::add_redir_all(int dstport) 00240 { 00241 redir_alls.append(new RedirAll(dstport), true); 00242 WvString s(redir_all_command("-A", dstport)); 00243 if (enable) system(s); 00244 } 00245 00246 00247 void WvIPFirewall::del_redir_all(int dstport) 00248 { 00249 RedirAllList::Iter i(redir_alls); 00250 for (i.rewind(); i.next(); ) 00251 { 00252 if (i->dstport == dstport) 00253 { 00254 WvString s(redir_all_command("-D", dstport)); 00255 if (enable) system(s); 00256 return; 00257 } 00258 } 00259 } 00260 00261 void WvIPFirewall::add_redir_port_range(const WvIPPortAddr &src_min, 00262 const WvIPPortAddr &src_max, int dstport) 00263 { 00264 redir_port_ranges.append(new RedirPortRange(src_min, src_max, dstport), true); 00265 WvString s(redir_port_range_command("-A", src_min, src_max, dstport)); 00266 if (enable) system(s); 00267 } 00268 00269 00270 void WvIPFirewall::del_redir_port_range(const WvIPPortAddr &src_min, 00271 const WvIPPortAddr &src_max, int dstport) 00272 { 00273 RedirPortRangeList::Iter i(redir_port_ranges); 00274 for (i.rewind(); i.next(); ) 00275 { 00276 if (i->src_min == src_min && i->src_max == src_max 00277 && i->dstport == dstport) 00278 { 00279 WvString s(redir_port_range_command("-D", src_min, src_max, dstport)); 00280 if (enable) system(s); 00281 return; 00282 } 00283 } 00284 } 00285 00286 00287 void WvIPFirewall::add_proto(WvStringParm proto) 00288 { 00289 protos.append(new WvString(proto), true); 00290 WvString s(proto_command("-A", proto)); 00291 if (enable) system(s); 00292 } 00293 00294 00295 void WvIPFirewall::del_proto(WvStringParm proto) 00296 { 00297 WvStringList::Iter i(protos); 00298 for (i.rewind(); i.next(); ) 00299 { 00300 if (*i == proto) 00301 { 00302 WvString s(proto_command("-D", proto)); 00303 if (enable) system(s); 00304 return; 00305 } 00306 } 00307 } 00308 00309 00310 // clear out our portion of the firewall 00311 void WvIPFirewall::zap() 00312 { 00313 WvIPPortAddrList::Iter i(addrs); 00314 for (i.rewind(); i.next(); ) 00315 { 00316 del_port(*i); 00317 i.xunlink(); 00318 } 00319 00320 FFwdList::Iter ifwd(ffwds); 00321 for (ifwd.rewind(); ifwd.next();) 00322 { 00323 del_forward(ifwd->src, ifwd->dst, ifwd->snat); 00324 ifwd.xunlink(); 00325 } 00326 00327 RedirList::Iter i2(redirs); 00328 for (i2.rewind(); i2.next(); ) 00329 { 00330 del_redir(i2->src, i2->dstport); 00331 i2.xunlink(); 00332 } 00333 00334 RedirAllList::Iter i2_5(redir_alls); 00335 for (i2_5.rewind(); i2_5.next(); ) 00336 { 00337 del_redir_all(i2_5->dstport); 00338 i2_5.xunlink(); 00339 } 00340 00341 RedirPortRangeList::Iter port_range(redir_port_ranges); 00342 for (port_range.rewind(); port_range.next(); ) 00343 { 00344 del_redir_port_range(port_range->src_min, port_range->src_max, 00345 port_range->dstport); 00346 port_range.xunlink(); 00347 } 00348 00349 WvStringList::Iter i3(protos); 00350 for (i3.rewind(); i3.next(); ) 00351 { 00352 del_proto(*i3); 00353 i3.xunlink(); 00354 } 00355 }