01/02/2005

"that doesn't make me amiable, it makes me stupid"

This is the fourth in a series of back-dated site updates that have only just been published

firewalling and traffic shaping

Okay so like I said last time I had decided to write an init script for setting up iptables since the one that came with the package was now deprecated. I also thought, if I do this for iptables I might as well do traffic shaping with tc at the same time, I've got all the kernel modules and how hard can it be?

Anyway so firstly lets do iptables. There's three tables you have to worry about. They are named filter, nat and mangle. Then, there are five places, called hooks, where the kernel's networking code gives packets to iptables (well, more strictly, to netfilter) to process. These are called PREROUTING, INPUT, FORWARD, OUTPUT, and POSTROUTING. For each table, when a packet reaches a given hook, the corresponding chain of rules attached to that hook is called to process the packet.

The tables seem to exist to conceptually separate iptables rules into known tasks. Some tables don't even have chains on all hooks, and only specific types of rule are allowed into each table. For example, the filter table only has chains at the INPUT, OUTPUT and FORWARD hooks. The separation into tables is for two reasons, one, it makes things clearer, and two, if you don't need a whole table, you don't have to have it in your kernel, and you can save space.

(I don't see any reason why you couldn't implement iptables without the tables, by allowing any type of rule to be attached to one big chain at each hook. However this would make configuration more complicated, make your kernel bigger than it needs to be, and probably harm a load of other stuff I can't think of right now... but I digress)

Anyway rather than repeat the entire netfilter HOWTO documents here I'll just say what I did. Firstly the input chain

I should note at this point that instead of just dropping packets I set it to "reject" them. This means you send back an ICMP packet saying the connection has been refused. You can also send back a TCP RESET for refused TCP connections. I have still yet to decide whether this is a good thing or not. It makes things like port scans faster (and I do like to portscan myself from time to time just to check it's all still working) but it could potentially be used to flood hosts with ICMP port unreachables or TCP resets by faking your source address. I don't know.

Anyway the OUTPUT chain, in contrast, can probably be left empty with a default polict of acceptance, since it is likely that you don't want to block anything your server does. One thing I have seen in OUTPUT chains is the dropping of all traffic leaving on port 135; ISPs such as plusnet interpret this as possible virus traffic and shut you down until you reboot your modem, even if it was actually just something harmless, like nmap. NTL don't do that though so at the moment I don't care.

The FORWARD chain is slightly more complicated. In some sense it needs to be the INPUT chain and the OUTPUT chain both at once. You have to be more careful and look at which way packets are heading when they reach it. You probably want to allow hosts on your network to connect to hosts outside it, but not hosts outside to connect to hosts within; although, if you have to use NAT you get that anyway.

That bring me nicely to NAT. How's that for a segué! It stands for Network Address Translation and means rewriting either the source or the destination address of packets as they enter or leave your network. A common use of NAT, and the only thing I use it for currently, is called masquerading:

As you can see, connection tracking is inherently a part of NAT so if you use NAT at all you get the state matching stuff for the filter table for free!

Other uses of NAT include things like port forwarding: say you are trying to play an online game and running a server for your friends to connect to. More than likely this game is Windows-only so you have to run the server program on a Windows box. You don't want to connect a Windows box directly to the internet. So you open the game's port and use NAT to forward all traffic into that port to the windows box. I did this a few months ago so the girl and I could play Doom over the internet, because I don't have X or any Doom stuff installed on my router. (Don't try this though, prboom's network code is really meant for LANs and runs really slowly over the internet, we called it treacle mode, it was quite painful)

The final table is the mangle table, which on recent kernels at least puts chains on all possible hooks. It is meant for changing arbitrary variables in packets. It is usually not necessary and has quite specialised uses. I use it to mark packets to help the traffic shaping script.

Yeah speaking of which I'll save traffic shaping for another time as this update is long enough already. I nearly said "long and boring enough" but I'll get yelled at if I'm too negative about my things, so yeah