|This article goes into the basics of IPTables. IPTables is a firewall for Linux based operating systems that is very powerful and can do very inticate things. In this article, I will touch the basics by setting up a standard firewall configuration for a single host.
The configuration will only check incoming packets and will do nothing with outgoing ones, neither will it handle NAT or packet inspection.
It is meant to get the novice user going with IPTables configurations and give some insight on how IPTables works. With a little bit of common sense, most users will be able to figure out how to implement rules that suit their needs.
A word of warning: Do not start playing around with IPTables on a remote machine. There is a genuine risk of locking yourself completely out of the machine, when you apply rules in the wrong order or when you simply forget to apply rules for your management protocols (such as SSH). When you have doubts, always test your rules on a machine that you have console access to, such as your local host or a virtual machine.
IPTables works by using 'chains' of rules that an inspected package must pass before being allowed in. The basic chains are INPUT, OUTPUT and FORWARD.
- INPUT: all packets coming IN to all interfaces
- OUTPUT: all packets goint OUT on all interfaces
- FORWARD: To forward packets from one interface or host to an other
You can create custom chains to make management of rulesets easier and make processing faster. To use these rules, you will need to 'jump' into these chains. If you are a scripter or programmer, think about these chains as an old-fashioned GOSUB: You pass something (in this case a packet of a certain type) to it and it sees if it can find match within the function. If there is no match, it will return to where the GOSUB was called.
Since we are locking a host down to the outside world, we will only deal with incoming packets, using the INPUT chain. We will also set up an ALLOWED chain for better manageavility. For now, we will allow all packets going out, as these need to be initiated by a process on the local host. This is also how most home-grade router/firewalls work.
Remember that if you need to set up a gateway device and therefore use the FORWARD chain, you will need to set up INPUT rules on the incoming interface and a matching OUTPUT rule on the interface that leads into your network. This rule can be an 'allow everything' type of rule, or you can specify specific rules to grant access to specific services.
With this knowledge in mind, there are 2 general ways of settings things up:
- Allowing everything but filtering out things you don't want. This leaves you open for many attacks and is therefore a bad approach.
- Blocking everything and explicitly allowing things you want to pass. This is what we will do.
Some things to consider:
- IPTables uses Top-to-bottom processing. If a match to a rule cannot be made, it will move on to the next rule.
- Therefore, the ORDER OF THE RULES IS IMPORTANT!
- Processing stops when an ACCEPT or DROP rule is met (there are exceptions, but none that are important to this article).
- Unless a packet matches a specific rule, it will continue processing untill in reaches the end of the ruleset.
- If a package reaches the end of the ruleset and there is no explicit DROP rule in place, it will pass by default!
Ultimately, the goal is to explicitly ACCEPT or DROP a packet. These rules are addressable as chains, even though they do not show up when looking at the ruleset with 'iptables -L -v'
iptables -L -v - (L)ist the chains (v)erbosely
iptables -D INPUT 3 - (D)elete the 3rd rule on the INPUT chain
iptables -I INPUT 3 - (I)nsert above rule 3 in the INPUT chain. If the rulenumber is not set, it will default to inserting above rule 1.
iptables -A INPUT - (A)ppend to the bottom of the INPUT chain. Don't use this on a rule that is closed with a DROP statement, otherwise the packet will be dropped before is reaches the rule that matches it.
How are the rules build up (e.g.):
iptables -A ALLOWED -i eth0 -p tcp -m tcp --dport 25 -j ACCEPT
iptables - invokes the iptables program
-A ALLOWED - (A)ppends this rule to the ALLOWED chain
-i eth0 - (i)nterface to apply the rule to
-p tcp - (p)rotocol to match
-m tcp --dport 25 -(m)atch tcp but only for d(estination)port 25 (SMTP)
-j ACCEPT - (j)ump to the ACCEPT chain (accept the package)
# Create the ALLOWED context, to specifically allow traffic to certain ports
iptables -N ALLOWED
# Allow all RELATED,ESTABLISHED connections
iptables -A INPUT -i eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
# Allow all communications from LOCALHOST
iptables -A INPUT -i lo -j ACCEPT
# Drop some weird and malformed packets
iptables -A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
iptables -A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,SYN FIN,SYN -j DROP
iptables -A INPUT -i eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN,RST -j DROP
iptables -A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,RST FIN,RST -j DROP
iptables -A INPUT -i eth0 -p tcp -m tcp --tcp-flags FIN,ACK FIN -j DROP
iptables -A INPUT -i eth0 -p tcp -m tcp --tcp-flags ACK,URG URG -j DROP
# If a packlet has not been dropped yet, see if we explicitly allow it
# by sending it through the ALLOWED chain.
# If no rules match, it will return here...
iptables -A INPUT -j ALLOWED
# So the packet returned from the ALLOWED chain, meaning that nothing matched.
# This means that it was not an established connection, a packet from localhost,
# a malformed packet, or a packet that was destined for a known (and allowed) port,
# as defined in the ALLOWED chain. What do we do?
# We DROP it.
iptables -A INPUT -j DROP
# Just for good measure, let's set the default policy for this chain to DROP
iptables -P INPUT DROP
# Define what we will allow to pass inspection in the ALLOWED chain
iptables -A ALLOWED -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
iptables -A ALLOWED -i eth0 -p tcp -m tcp --dport 25 -j ACCEPT
iptables -A ALLOWED -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A ALLOWED -i eth0 -p tcp -m tcp --dport 21 -j ACCEPT
iptables -A ALLOWED -i eth0 -p tcp -m tcp --dport 110 -j ACCEPT
# Since this chain is open-ended, the process will return to where this chain was called.
Some other notes to keep in mind:
- Editing the iptables file directly is bad practice. Use the iptables command with some switches to add/remove/edit rules.
- use iptables-save to save the configs
- save this to a file to re-use later (iptables-save > your-file-name)
- restore the file by using iptables-restore (iptables-save < your-file-name)