WvStreams
wvipfirewall.cc
1/*
2 * Worldvisions Weaver Software:
3 * Copyright (C) 1997-2002 Net Integration Technologies, Inc.
4 *
5 * WvIPFirewall is an extremely simple hackish class that handles the Linux
6 * 2.4 "iptables" firewall. See wvipfirewall.h.
7 */
8#include "wvipfirewall.h"
9#include "wvinterface.h"
10#include <unistd.h>
11
12
13bool WvIPFirewall::enable = false, WvIPFirewall::ignore_errors = true;
14
15
16WvIPFirewall::WvIPFirewall() : log("Firewall", WvLog::Debug2)
17{
18 // don't change any firewall rules here! Remember that there may be
19 // more than one instance of the firewall object.
20}
21
22
23WvIPFirewall::~WvIPFirewall()
24{
25 zap();
26}
27
28
29WvString WvIPFirewall::port_command(const char *cmd, const char *proto,
30 const WvIPPortAddr &addr)
31{
32 WvIPAddr ad(addr), none;
33
34 return WvString("iptables %s Services -j ACCEPT -p %s "
35 "%s --dport %s "
36 "%s",
37 cmd, proto,
38 ad == none ? WvString("") : WvString("-d %s", ad),
39 addr.port,
40 shutup());
41}
42
43
44WvString WvIPFirewall::redir_command(const char *cmd, const WvIPPortAddr &src,
45 int dstport)
46{
47 WvIPAddr ad(src), none;
48
49 return WvString("iptables -t nat %s TProxy "
50 "-p tcp %s --dport %s "
51 "-j REDIRECT --to-ports %s "
52 "%s",
53 cmd,
54 ad == none ? WvString("") : WvString("-d %s", ad),
55 src.port, dstport,
56 shutup());
57}
58
59WvString WvIPFirewall::forward_command(const char *cmd,
60 const char *proto,
61 const WvIPPortAddr &src,
62 const WvIPPortAddr &dst, bool snat)
63{
64 WvIPAddr srcaddr(src), dstaddr(dst), zero;
65 WvString haveiface(""), haveoface("");
66 if (!(srcaddr == zero))
67 {
68 haveiface.append("-d ");
69 haveiface.append((WvString)srcaddr);
70 }
71
72 WvString retval;
73
74 if ((dst == WvIPAddr("127.0.0.1")) || (dst == zero))
75 {
76 retval.append("iptables -t nat %s FASTFORWARD -p %s --dport %s %s "
77 "-j REDIRECT --to-port %s %s \n",
78 cmd, proto, src.port, haveiface, dst.port, shutup());
79 }
80 else
81 {
82 haveoface.append("-d ");
83 haveoface.append((WvString)dstaddr);
84
85 retval.append("iptables -t nat %s FASTFORWARD -p %s --dport %s %s "
86 "-j DNAT --to-destination %s "
87 "%s \n", cmd, proto, src.port, haveiface, dst, shutup());
88 }
89
90 // FA57 is leet-speak for FAST, which is short for FASTFORWARD --adewhurst
91 // FA58 is FA57+1. Nothing creative sprang to mind. --adewhurst
92 //
93 // We need this to mark the packet as it comes in so that we allow the
94 // FastForward-ed packets to bypass the firewall (FA57).
95 //
96 // If we mark the packet with FA58, that means it gets masqueraded before
97 // leaving, which may be useful to work around some network configuratios.
98 retval.append("iptables -t mangle %s FASTFORWARD -p %s --dport %s "
99 "-j MARK --set-mark %s %s %s\n", cmd, proto, src.port,
100 snat ? "0xFA58" : "0xFA57", haveiface, shutup());
101
102 // Don't open the port completely; just open it for the forwarded packets
103 retval.append("iptables %s FFASTFORWARD -j ACCEPT -p %s "
104 "--dport %s -m mark --mark %s %s %s\n", cmd, proto, dst.port,
105 snat ? "0xFA58" : "0xFA57", haveoface, shutup());
106
107 return retval;
108}
109
110WvString WvIPFirewall::redir_port_range_command(const char *cmd,
111 const WvIPPortAddr &src_min, const WvIPPortAddr &src_max, int dstport)
112{
113 WvIPAddr ad(src_min), none;
114
115 return WvString("iptables -t nat %s TProxy "
116 "-p tcp %s --dport %s:%s "
117 "-j REDIRECT --to-ports %s "
118 "%s",
119 cmd,
120 ad == none ? WvString("") : WvString("-d %s", ad),
121 src_min.port == 0? WvString(""): WvString(src_min.port),
122 src_max.port == 0? WvString(""): WvString(src_max.port),
123 dstport,
124 shutup());
125}
126
127WvString WvIPFirewall::redir_all_command(const char *cmd, int dstport)
128{
129 return WvString("iptables -t nat %s TProxy "
130 "-p tcp "
131 "-j REDIRECT --to-ports %s "
132 "%s",
133 cmd,
134 dstport,
135 shutup());
136}
137
138WvString WvIPFirewall::proto_command(const char *cmd, const char *proto)
139{
140 return WvString("iptables %s Services -p %s -j ACCEPT "
141 "%s",
142 cmd, proto, shutup());
143}
144
145
146void WvIPFirewall::add_port(const WvIPPortAddr &addr)
147{
148 addrs.append(new WvIPPortAddr(addr), true);
149 WvString s(port_command("-A", "tcp", addr)),
150 s2(port_command("-A", "udp", addr));
151 if (enable)
152 {
153 system(s);
154 system(s2);
155 }
156}
157
158
159// note! This does not remove the address from the list, only the kernel!
160void WvIPFirewall::del_port(const WvIPPortAddr &addr)
161{
162 WvIPPortAddrList::Iter i(addrs);
163 for (i.rewind(); i.next(); )
164 {
165 if (*i == addr)
166 {
167 WvString s(port_command("-D", "tcp", addr)),
168 s2(port_command("-D", "udp", addr));
169 if (enable)
170 {
171 system(s);
172 system(s2);
173 }
174 return;
175 }
176 }
177}
178
179void WvIPFirewall::add_forward(const WvIPPortAddr &src,
180 const WvIPPortAddr &dst, bool snat)
181{
182 ffwds.append(new FFwd(src, dst, snat), true);
183 WvString s(forward_command("-A", "tcp", src, dst, snat)),
184 s2(forward_command("-A", "udp", src, dst, snat));
185
186 log("Add Forwards (%s):\n%s\n%s\n", enable, s, s2);
187
188 if (enable)
189 {
190 system(s);
191 system(s2);
192 }
193}
194
195void WvIPFirewall::del_forward(const WvIPPortAddr &src,
196 const WvIPPortAddr &dst, bool snat)
197{
198 FFwdList::Iter i(ffwds);
199 for (i.rewind(); i.next();)
200 {
201 if (i->src == src && i->dst == dst && i->snat == snat)
202 {
203 WvString s(forward_command("-D", "tcp", src, dst, snat)),
204 s2(forward_command("-D", "udp", src, dst, snat));
205
206 log("Delete Forward (%s):\n%s\n%s\n", enable, s, s2);
207
208 if (enable)
209 {
210 system(s);
211 system(s2);
212 }
213 }
214 }
215}
216
217void WvIPFirewall::add_redir(const WvIPPortAddr &src, int dstport)
218{
219 redirs.append(new Redir(src, dstport), true);
220 WvString s(redir_command("-A", src, dstport));
221 if (enable) system(s);
222}
223
224
225void WvIPFirewall::del_redir(const WvIPPortAddr &src, int dstport)
226{
227 RedirList::Iter i(redirs);
228 for (i.rewind(); i.next(); )
229 {
230 if (i->src == src && i->dstport == dstport)
231 {
232 WvString s(redir_command("-D", src, dstport));
233 if (enable) system(s);
234 return;
235 }
236 }
237}
238
239void WvIPFirewall::add_redir_all(int dstport)
240{
241 redir_alls.append(new RedirAll(dstport), true);
242 WvString s(redir_all_command("-A", dstport));
243 if (enable) system(s);
244}
245
246
247void WvIPFirewall::del_redir_all(int dstport)
248{
249 RedirAllList::Iter i(redir_alls);
250 for (i.rewind(); i.next(); )
251 {
252 if (i->dstport == dstport)
253 {
254 WvString s(redir_all_command("-D", dstport));
255 if (enable) system(s);
256 return;
257 }
258 }
259}
260
261void WvIPFirewall::add_redir_port_range(const WvIPPortAddr &src_min,
262 const WvIPPortAddr &src_max, int dstport)
263{
264 redir_port_ranges.append(new RedirPortRange(src_min, src_max, dstport), true);
265 WvString s(redir_port_range_command("-A", src_min, src_max, dstport));
266 if (enable) system(s);
267}
268
269
270void WvIPFirewall::del_redir_port_range(const WvIPPortAddr &src_min,
271 const WvIPPortAddr &src_max, int dstport)
272{
273 RedirPortRangeList::Iter i(redir_port_ranges);
274 for (i.rewind(); i.next(); )
275 {
276 if (i->src_min == src_min && i->src_max == src_max
277 && i->dstport == dstport)
278 {
279 WvString s(redir_port_range_command("-D", src_min, src_max, dstport));
280 if (enable) system(s);
281 return;
282 }
283 }
284}
285
286
287void WvIPFirewall::add_proto(WvStringParm proto)
288{
289 protos.append(new WvString(proto), true);
290 WvString s(proto_command("-A", proto));
291 if (enable) system(s);
292}
293
294
295void WvIPFirewall::del_proto(WvStringParm proto)
296{
297 WvStringList::Iter i(protos);
298 for (i.rewind(); i.next(); )
299 {
300 if (*i == proto)
301 {
302 WvString s(proto_command("-D", proto));
303 if (enable) system(s);
304 return;
305 }
306 }
307}
308
309
310// clear out our portion of the firewall
311void WvIPFirewall::zap()
312{
313 WvIPPortAddrList::Iter i(addrs);
314 for (i.rewind(); i.next(); )
315 {
316 del_port(*i);
317 i.xunlink();
318 }
319
320 FFwdList::Iter ifwd(ffwds);
321 for (ifwd.rewind(); ifwd.next();)
322 {
323 del_forward(ifwd->src, ifwd->dst, ifwd->snat);
324 ifwd.xunlink();
325 }
326
327 RedirList::Iter i2(redirs);
328 for (i2.rewind(); i2.next(); )
329 {
330 del_redir(i2->src, i2->dstport);
331 i2.xunlink();
332 }
333
334 RedirAllList::Iter i2_5(redir_alls);
335 for (i2_5.rewind(); i2_5.next(); )
336 {
337 del_redir_all(i2_5->dstport);
338 i2_5.xunlink();
339 }
340
341 RedirPortRangeList::Iter port_range(redir_port_ranges);
342 for (port_range.rewind(); port_range.next(); )
343 {
344 del_redir_port_range(port_range->src_min, port_range->src_max,
345 port_range->dstport);
346 port_range.xunlink();
347 }
348
349 WvStringList::Iter i3(protos);
350 for (i3.rewind(); i3.next(); )
351 {
352 del_proto(*i3);
353 i3.xunlink();
354 }
355}
A WvFastString acts exactly like a WvString, but can take (const char *) strings without needing to a...
Definition wvstring.h:94
An IP address is made up of a "dotted quad" – four decimal numbers in the form www....
Definition wvaddr.h:250
An IP+Port address also includes a port number, with the resulting form www.xxx.yyy....
Definition wvaddr.h:394
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition wvlog.h:57
WvString is an implementation of a simple and efficient printable-string class.
Definition wvstring.h:330