Setting up IPTables

'''IMPORTANT:''' 192.0.2.0/24 is being used as the network in the examples below. Please update the ip addresses before using any of the examples!!

Going on the basis that the fastest way to learn something is to see an example, the following example will allow all SMTP, DNS, POP3, HTTP and HTTPS traffic while restricting SSH access to 192.0.2.0/24:

Of course the first thing to note there is that there's no corresponding outgoing rules. This is because iptables is "stateful". What this means is that once the initial connection has been created, iptables will keep track of it and allow all related packets in and out.

Also, the above rule set applies to all ips on the server, hence all the 0.0.0.0/0 in the destination column. If your server has two ips and you want to restrict mail and dns to one ip, while both ips have the HTTP ports open this will have to change. Presuming that the two ips are 192.0.2.2 and 192.0.2.3, and you only want SSH, Mail and DNS on 192.0.2.2, the ruleset would then become:

When an incoming connection comes into the server, iptables will go through the rules in order. So, for example, when 192.0.2.20 tries to connect to SSH for the first time on 192.0.2.2, iptables goes through all the rules until it gets to rule 8, and then it accepts the connection. When the next packet in the same session comes in, iptables see it as an already established connection and triggers on the first rule. This is why the "-m state --state ESTABLISHED,RELATED" rule needs to be kept near the start.

The default policy on the INPUT chain is DROP. What this means is that if a connection comes in that isn't allowed by any of the ACCEPT rules, it's dropped silently. The alternative to DROP is REJECT. This actually straight out tells the connecting ip that the port is closed. It's personal preference as to which you use.

So, what happens if one ip, say 192.0.2.50, is hammering POP3 with a brute attack? It's possible to insert rule in anywhere within the rule set. In this case, rule number 9 is the one allowing POP3 access. The rule denying access to the ip has to be *BEFORE* that. The easiest way to do this is to insert the rule at rule 9, pushing rule 9 down to 10. This can be done by running the following the command:

Of course if the ip in question is really causing a general issue, you can run:iptables -I INPUT 1 -s 192.0.2.50 -j DROP

This will drop ANY packet coming from 192.0.2.50 coming into the server before any other rules are even considered.

Automatically Starting Up IPTables

Centos/RHEL

When you're happy with your rule set run: service iptables save This will save the ruleset in /etc/sysconfig/iptables.

To make sure that they are applied on startup, run chkconfig iptables on

Debian/Ubuntu

Debian Lenny And Squeeze

Create a file called '''/etc/network/if-pre-up.d/iptables_v4'''. This file should have 755 permissions and have content like the following:

#!/bin/bashiptables -F INPUTiptables -F OUTPUT........ Rest of rules.

This will then be called before the network interfaces are bought up.

General Tips

Restrict Mail To "mail" User

A common method for sending spam is to upload a perl script to a compromised site, and then send out the mail directly on port 25. This can bypass the local mail server and make it very awkward to track down what was responsible for sending the spam further down the line.

Fortunately, this is very simple to stop with iptables. As before, the fastest way is probably to use an example:# Allow the mail user to make outbound connections on port 25iptables -A OUTPUT -m owner --uid-owner mail -p tcp --dport 25 -j ACCEPT# Allow connections to localhostiptables -A OUTPUT -p tcp -d 127.0.0.1 --dport 25 -j ACCEPT# Block all other connections on port 25.# Only needed if the default policy for OUTPUT is ACCEPTiptables -A OUTPUT -p tcp --dport 25 -j REJECT

This won't stop spam from going out, however it will mean that mail can only be sent out by the mail user which in general means that it will have to go through the local MTA which means it will be logged.

Also, please be aware that the local MTA doesn't always run as ''mail''. For example, if you're using Postfix, it will run as the ''postfix'' user. The only change required in this case is to change the user after ''--uid-owner'' to ''postfix''.

This requires the ipt_owner kernel module to be available.

Grouping IPs

It's often handy to be able to group ips together separately for different rules. For example, rather than having multiple rules for hosts allowed to access SSH, you can have one rule in the INPUT table which then references another set of rules.

Now when someone attempts to access port 22 on 192.0.2.2, iptables will look at the SSH_ACCESS chain, and see if the source ip is there. If it is, it will ACCEPT the connection. If it's not listed, the connection is rejected.

Commenting

In all examples so far, all that has been used are bash comments. It is possible to put comments in the rules themselves for self documentation purposes. For example:iptables -A INPUT -p tcp --dport 80 -j ACCEPT -m comment --comment "Allow inbound HTTP"

Quick And Nasty Outbound NAT For Virtualisation

This is a handy rule which works when using multiple virtual servers on a bridged network where you want the VPS hosts to be able to get outbound access through the host server. This presumes that:* The host server has external connectivity* The host server has an ip on the same range as the virtual servers which is on the same bridge* The virtual servers have the above ip as their default gateway.

This will NAT any traffic not destined for 192.0.2.0/24 and send it out over the host servers default gateway.

Removing State Tracking

By default, IPTables will keep track of state. What this means is that iptables will keep track of what ips are connecting to what port and the corresponding connections back out. The main advantage to this is that it makes it harder to spoof connections. However, there's a disadvantage in that there has to be a table kept in memory for keeping track of all the connections. The vast majority of the time, this isn't a problem, however it can cause issues with a service that does a high volume of connections, for example DNS. The conntrack command allows the viewing and manipulation of the states table.

It's possible to disable the connection tracking on IPTables. For example, the following will disable connection tracking on all DNS UDP packets: