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 
13 bool WvIPFirewall::enable = false, WvIPFirewall::ignore_errors = true;
14 
15 
16 WvIPFirewall::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 
23 WvIPFirewall::~WvIPFirewall()
24 {
25  zap();
26 }
27 
28 
29 WvString 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 
44 WvString 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 
59 WvString 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 
110 WvString 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 
127 WvString 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 
138 WvString 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 
146 void 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!
160 void 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 
179 void 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 
195 void 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 
217 void 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 
225 void 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 
239 void 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 
247 void 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 
261 void 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 
270 void 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 
287 void 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 
295 void 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
311 void 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 }
WvString
WvString is an implementation of a simple and efficient printable-string class.
Definition: wvstring.h:329
WvLog
A WvLog stream accepts log messages from applications and forwards them to all registered WvLogRcv's.
Definition: wvlog.h:56
WvIPPortAddr
An IP+Port address also includes a port number, with the resulting form www.xxx.yyy....
Definition: wvaddr.h:393
WvIPAddr
An IP address is made up of a "dotted quad" – four decimal numbers in the form www....
Definition: wvaddr.h:249