A Howto on using iptables to configure your firewall
Firewalls are set-up primarily to filter and/or enhance packets which pass through the network. When a packet arrives at a firewall, it will either disregard or process the packet. The network device of a firewall only disregards packets which are invalid in some network-technical way. We won't get into the details of which packets are disregarded automatically, but consider these disregarded packets malformed in some way. The most important thing is: The rest is being processed!! Here's where firewalls really kick in. iptables is such a firewall, and a very powerfull one! It handles packets based on the type of packet activity, and enqueues the packet in one of its builtin 'tables'. There are three tables in total. The first is the mangle table which is responsible for the alteration of service bits in the TCP header. This is hardly used in basic setups (at home or in SOHO). The second table is the filter queue which is responsible for packet filtering. It has three built-in chains in which you can place your firewall policy rules. These are the:
- Forward chain: Filters packets destined for networks protected by the firewall.
- Input chain: Filters packets destined for the firewall.
- Output chain: Filters packets originating from the firewall.
The third table is the nat table which is where Network Address Translation (NAT) is performed. It has two built-in chains; these are:
- Pre-routing chain: NATs packets when the destination address of the packet needs to be changed.
- Post-routing chain: NATs packets when the source address of the packet needs to be changed.
With each rule you set, you will need to specify the table. There is one exception, which is the 'filter' table. This exception is made because most of iptables' rules are filter rules. Therefore the filter table is the 'default' table.
Packet Processing In iptables
Below is a very simplified view of the way packets are processed by the chains.
PACKET IN --->---PREROUTING---[ routing ]--->----FORWARD---->---POSTROUTING--->--- PACKET OUT - mangle | - mangle - mangle - nat (dst) | - filter - nat (src) | | | | INPUT OUTPUT - mangle - mangle - filter - nat (dst) | - filter | | `---->----[ application ]---->----'
The packet enters the firewall via the PREROUTING chain in the
mangle table, if any. It is
then inspected by the rules in the
nat table's PREROUTING chain to see whether the packet
requires destination modification (
DNAT). It is important to change the destination now,
because as soon as it leaves the PREROUTING chain of the
nat table, it is routed.
If the packet is destined for a 'protected' network (Read: another network, whether it is protected is up
to your firewall configuration), it is filtered by the rules in the FORWARD chain of the
table and, if necessary, the packet undergoes
SNAT in the POSTROUTING chain before arriving at
Network B. When the destination server decides to reply, the packet undergoes the same sequence of steps.
Both the FORWARD and POSTROUTING chains may be configured to implement quality of service (QoS) features in
mangle tables, but this is not usually done in SOHO environments.
If the packet is destined for the firewall itself, it passes through the mangle table of the INPUT chain,
if configured, before being filtered by the rules in the INPUT chain of the filter table. If it
successfully passes these tests then it is processed by the intended application on the firewall.
At some point, the firewall needs to reply. This reply is routed through and inspected by the rules in the OUTPUT
chain of the
mangle table, if any. Next, the rules in the OUTPUT chain of the
table determine whether
DNAT is required and the rules in the OUTPUT chain of the
filter table are then inspected to help restrict unauthorized packets. Finally, before the packet
is sent back to the Internet,
SNAT and QoS mangling is done by the POSTROUTING chain.
Now we know how packets traverse the different tables and chains in iptables, it's time to explain how to inspect the packets. There are numerous inspections you can perform on a single packet, practically limited only by the specifications of TCP/IP and your knowledge of TCP/IP. All TCP flags and parameters can be tested; the source IP address, destination IP address, port numbers, connection status, the protocol number, etc., etc.
About TCP Connections
One aspect commonly neglected amongst users is the fact that TCP is a triple-handshake protocol. This means, in a more real-life based example, if machine 'workstation' wants to create a TCP connection to machine 'server', 'workstation' first needs to say "Hi, how are you?", at which 'server' needs to reply "Hi, I'm fine, how are you?". 'workstation' then says "I'm fine too", and then, only then, chit-chat is over, and the real conversation can be started.
In fact, these machines set certain TCP flags. 'workstation' sends a TCP packet with the SYN flag set, at which 'server' replies with a TCP packet with the SYN and ACK flags set. When 'workstation' receives this packet, it sends a TCP packet 'ACK'.
iptables uses NEW, ESTABLISHED, RELATED and INVALID to represent the connection status.
When closing the connection, basically the same triple-handshake is performed, but with FIN and ACK flags.
Why this needs to be secured
Imagine a 'workstation' just sends thousands of packets to 'server' with the SYN flag set. No, forget that. Let's suppose you have no dial-up Internet connection anymore. Let's suppose 'workstation' sends millions if not billions of packets to 'server' with the SYN flag set. Futuristic, huh?
All these packets cause 'server' to reply with a TCP packet with the SYN and ACK flags set. 'server' will assume these connections to have a certain status, called SYN-RECEIVED, waiting for the TCP packet with the ACK flag set from 'workstation', after which the connection is ESTABLISHED. This connection status has a default timeout of 60 seconds, meaning it takes 60 seconds before 'server' considers the connection failed and removes it. How many packets can you send in 60 seconds, and how many connections with status SYN-RECEIVED can 'server' handle? If 'workstation' replies with the appropriate ACK, things could get worse. The default timeout for a connection with status ESTABLISHED is 5 days...
Another situation is a very poorly described feature of iptables. To allow firewall redundancy, iptables allows incoming connections with status NEW, but without the SYN flag set. Remember if you don't filter those packets, they are processed!
Packet Inspection Options
||Match protocol. Options are tcp, udp, icmp, or any other protocol in /etc/protocols
||iptables -A INPUT --protocol tcp
||Match source IP address. The IP address can be represented in several ways.
||iptables -A INPUT --source 10.10.10.3
||Match destination IP address. The IP address can be represented in several ways, see --source
||iptables -A INPUT --destination 192.168.1.0/24
||Match the source port, only available with --protocol tcp, or --protocol udp
||iptables -A INPUT --protocol tcp --source-port 25
||Match the destination port, only available with --protocol tcp, or --protocol udp
||iptables -A INPUT --protocol udp --destination-port 67
||Match the state of the connection. Available when module 'state' is loaded with '-m state'. Possible options include:
||iptables -A INPUT -m state --state NEW,ESTABLISHED
||Matches packets to the interface used for the incoming packet. Usefull in destination NAT and machines with multiple NICs.
||iptables -t nat -A PREROUTING --in-interface eth0 (destination NAT)
||Matches packets to the interface used for the outgoing packet. Usefull in source NAT and machines with multiple NICs.
||iptables -t nat -A POSTROUTING --in-interface eth1 (source NAT)
||Matches packets with '--tcp-flags SYN,RST,ACK SYN' (and is a shorthand). Since this checks TCP flags, use --protocol tcp as well.
The example matches connections with status NEW, but without the SYN flag set. Generally, these packets should be dropped.
|iptables -A INPUT --protocol tcp ! --syn -m state --state NEW
||Match the TCP flags in the packet. This option takes two parameters: A list of flags to inspect, and a list of flags that should
Now that you are familiar with the most common packet inspection options, it's time to address how to configure what to do with the packets that match the rules. iptables uses targets. You can (and should!) specify these targets using the 'jump' option: --jump (or shorthand; -j). The list of builtin targets include the list below. These are not all builtin targets, just the most commonly used ones.
- Accept the packet matching this rule
- Silently drop the packet matching this rule
- Reject the packet mathing this rule, (very) verbosively. This target takes an optional parameter '--reject-with'. The type given can be icmp-net-unreachable, icmp-host-unreachable, icmp-port-unreachable (default), icmp-proto-unreachable, icmp-net-prohibitedor icmp-host-prohibited, which return the appropriate ICMP error message (port-unreachable is the default). With ICMP type of connections, the option echo-reply is also allowed. Finally, the option tcp-reset can be used on rules in (or called from) the INPUT chain which only match the TCP protocol: this causes a TCP packet with the RST flag set to be sent back.
- Log packets matching this rule. This is usefull in combination with rules you specify to DROP or REJECT packets, for purposes of troubleshooting.
- Processing of packets matching this rule returns to the chain this chain was called from
- Apply source NAT to all packets matching this rule. This target is only valid in the POSTROUTING chain of the nat table, or the OUTPUT chain of the nat table
- Apply destination NAT to all packets matching this rule. This target is only valid in the PREROUTING chain of the nat table
- This target is only valid in the nat table, in the POSTROUTING chain. It should only be used with dynamically assigned IP (dialup) connections: if you have a static IP address, you should use the SNAT target. Masquerading is equivalent to specifying a mapping to the IP address of the interface the packet is going out, but also has the effect that connections are forgotten when the interface goes down. This is the correct behavior when the next dialup is unlikely to have the same interface address (and hence any established connections are lost anyway). This is also the reason why you should use SNAT when you have a static IP address.
iptables also allows you to create custom chains, which can then be specified as a target to jump to. For example, you could create a so-called whitelist for trusted IP address, and a blacklist for evil nodes on the Internet. To create the chains, you would give the following commands:
iptables -N whitelist iptables -N blacklist
To add a rule to these chains (or any other chain), use:
iptables -A whitelist -s 192.168.0.0/24 -j ACCEPT iptables -A blacklist -s 188.8.131.52/24 -j DROP iptables -A blacklist -s 184.108.40.206/24 -j DROP
Then, specify these chains as a target in your INPUT, FORWARD and/or OUTPUT chain:
iptables -A INPUT -j whitelist iptables -A INPUT -j blacklist iptables -A OUTPUT -j whitelist iptables -A OUTPUT -j blacklist iptables -A FORWARD -j whitelist iptables -A FORWARD -j blacklist
You have now successfully whitelisted a network 192.168.0.0/24, and blacklisted some Class C address ranges of microsoft.com.
Accepting or denying connections to your firewall
Let's suppose you have a mail server directly connected to the Internet (ergo, no modem or router), and you want the machine to be completely secure, at least as far as the firewall is concerned. A mail server where mail is delivered typically uses port 25 (SMTP), and mail servers used by users to read their mail typically use port 110 (POP) and 143 (IMAP). Assuming you have a remote console, the firewall does not necessarily need to allow connections to port 22 (SSH). We also assume no mail has to be send via this mail server. So, connections from anywhere to your mail server's port 25, 110 and 143 should be allowed by the firewall. Basically, a firewall initialization script would look similar to this:
#!/bin/bash # Load the connection tracker kernel module modprobe ip_conntrack # Set the default target to DROP of all chains involved here. iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP # Always accept things going over the loopback interface iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT # DROP new connections without the SYN flag set. iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP # Get our whitelist and blacklist into place iptables -A INPUT -j whitelist iptables -A INPUT -j blacklist iptables -A OUTPUT -j whitelist iptables -A OUTPUT -j blacklist # Allow new SMTP connections iptables -A INPUT -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT # Allow new POP and IMAP connections iptables -A INPUT -p tcp --dport 110 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 110 -m state --state ESTABLISHED -j ACCEPT iptables -A INPUT -p tcp --dport 143 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -p tcp --sport 143 -m state --state ESTABLISHED -j ACCEPT iptables -N whitelist # Suppose your Internet connection has IP address 220.127.116.11 iptables -A whitelist -s 18.104.22.168 -j ACCEPT # This statement is a little redundant, at the end of the chain, iptables returns # to the previous chain... iptables -A whitelist -j RETURN iptables -N blacklist # However very unlickely to ever be incoming traffic, drop traffic coming from # the usual private IP address ranges iptables -A blacklist -s 10.0.0.0/8 -j DROP iptables -A blacklist -s 172.16.0.0/12 -j DROP iptables -A blacklist -s 169.254.0.0/16 -j DROP iptables -A blacklist -s 192.168.0.0/16 -j DROP # And blacklist this known spammer too! iptables -A blacklist -s spammer.com -j DROP
Notice that in the first few lines of the above example, we load a kernel module called 'ip_conntrack'. This module enables iptables to 'track connections', meaning that it can examine the status of connections by caching the related information for these connections.
Also, notice we set the policy for the INPUT, FORWARD and OUTPUT chains.
Tables, Chains, Rules, Targets...
You may have thought you're having a hard time getting all this information on tables, chains, rules, targets... What you're read so far in this document is not even half of it. So, get settled in your chair, we're moving to routing, forwarding and network address translation!
A few scenarios, starting with a relatively simple topology, should clarify a lot on routing as well as NAT, without getting into the real details. These topologies may differ from your situation, so please adapt and verify the commands and parameters used to match your situation. I recommend you apply your policies with logging while setting the INPUT and OUTPUT chain's policies to ACCEPT. Analyze your log before reverting the policies back to DROP or REJECT, because you will eventually make a mistake. The only thing I can guarantee you, is that the complexer your network topology is, the sooner you'll make a mistake. Be sure you have access to the console of the firewall.
Simple Firewall / Router Combination
As an example, we place a box between two networks, functioning as a router and a firewall. We'll just add some basic firewall security, further hardening is recommended. To keep it digestable, additional security is a seperate topic.
NETWORK A --------------------[ router / firewall ]---------------------- NETWORK B 192.168.1.0/24 192.168.1.1 192.168.2.1 192.168.2.0/24
Packets from A to B will pass the router, in an appearently transparent LAN. Considering there is no link with the internet, and all clients are 'trusted' desktop PC's, we barely need the firewall functionality and in this topology the router configuration is very simple.
We use the following command to start routing:
# echo 1 > /proc/sys/net/ipv4/ip_forward
Then, one day, we decide to strengthen the security between the two networks. We know Network B has some servers that host some websites that clients in Network A must be able to visit. We decide to implement the following:
- All packets between Network A and Network B must be dropped by default.
- Network A is allowed to visit websites hosted on webservers in Network B.
We implement the following in iptables on the router:
# iptables --policy FORWARD DROP # iptables --append FORWARD --source 192.168.1.0/24 --destination 192.168.2.0/24 --match state --state NEW,ESTABLISHED --protocol tcp \ --destination-port 80 -j ACCEPT # iptables --append FORWARD --source 192.168.2.0/24 --destination 192.168.1.0/24 --match state --state ESTABLISHED --protocol tcp \ --source-port 80 -j ACCEPT
First, we set the default action for everything that is forwarded by the router, to DROP. This disables all traffic between the two networks that is not explicitly allowed.
Second, we ACCEPT traffic from Network A to Network B, if the destination port is port 80 (HTTP), and the protocol is tcp. We allow all NEW and ESTABLISHED connections.
Third, we ACCEPT the responses which of course start at Network B and travel to the client in Network A. This is an already established connection, and we know the source port (the socket which the server uses to respond to the client), is port 80 (HTTP).
Here's another example, to show you how clients in Network A can also use the mail-, web-, and POP/IMAP- servers in Network B.
# iptables --policy FORWARD DROP # iptables --append FORWARD --source 192.168.1.0/24 --destination 192.168.2.0/24 --match state --state NEW,ESTABLISHED --protocol tcp \ --match multiport --destination-ports 25,80,110,143 -j ACCEPT # iptables --append FORWARD --source 192.168.2.0/24 --destination 192.168.1.0/24 --match state --state ESTABLISHED \ --match multiport --source-ports 25,80,110,143 -j ACCEPT
You can of course extend these commands to match your requirements. Notice the above examples only limit the network traffic between the two networks, and not traffic to, or from, the firewall itself.
NAT (Network Address Translation)
In computer networking, the process of network address translation (NAT, also known as network masquerading or IP-masquerading) involves re-writing the source and/or destination addresses of IP packets as they pass through a router or firewall. Most systems using NAT do so in order to enable multiple hosts on a private network to access the Internet using a single public IP address. According to specifications, routers should not act in this way, but many network administrators find NAT a convenient technique and use it widely. Nonetheless, NAT can introduce complications in communication between hosts.
Different types of NAT
- Full cone NAT is NAT where all requests from the same internal IP address and port are mapped to the same external IP address and port. Furthermore, any external host can send a packet to the internal host, by sending a packet to the mapped external address. It is also known as "one-to-one NAT".
- A restricted cone NAT is one where all requests from the same internal IP address and port are mapped to the same external IP address and port. Unlike a full cone NAT, an external host (with IP address X) can send a packet to the internal host only if the internal host had previously sent a packet to IP address X.
- A port restricted cone NAT is like a restricted cone NAT, but the restriction includes port numbers. Specifically, an external host can send a packet, with source IP address X and source port P, to the internal host only if the internal host had previously sent a packet to IP address X and port P.
- A symmetric NAT is a NAT where all requests from the same internal IP address and port to a specific destination IP address and port are mapped to the same external source IP address and port. If the same internal host sends a packet with the same source address and port to a different destination, a different mapping is used. Furthermore, only the external host that receives a packet can send a UDP packet back to the internal host.
Example Scenario: SOHO
In a SOHO (Small Office, Home Office) environment, you would typically have a single public IP address. We'll first show you how to setup basic routing, before actually running a secure firewall.
eth1 eth0 SOHO Network --------------------[ router / firewall ]---------------------- Internet 192.168.1.0/24 192.168.1.1 public-ip-address 0.0.0.0/0
The above network topology requires the router to use one public IP address for packets from the SOHO
Network to the Internet. Also, the router should accept inbound packets that are related to connections
initiated from the SOHO Network (responses etc.). Notice that there is no modem and no provider supplied router between our router and the Internet.
For the very basic router setup using iptables, you would use:
# iptables --policy INPUT DROP # iptables --policy FORWARD DROP # iptables --policy OUTPUT DROP # iptables --append INPUT --in-interface eth1 --source 192.168.1.0/24 --match state --state NEW,ESTABLISHED --jump ACCEPT # iptables --append OUTPUT --out-interface eth1 --destination 192.168.1.0/24 --match state --state NEW,ESTABLISHED --jump ACCEPT # iptables --append FORWARD --in-interface eth1 --source 192.168.1.0/24 --destination 0.0.0.0/0 --match state --state NEW,ESTABLISHED --jump ACCEPT # iptables --append FORWARD --in-interface eth0 --destination 192.168.1.0/24 --match state --state ESTABLISHED --jump ACCEPT # iptables --table nat --append POSTROUTING --out-interface eth0 --jump MASQUERADE
The router now forwards packets between the two networks, masquerades the outgoing packets from the SOHO
Network (so responses at least come back to the router again), and enables management from the SOHO
Network as well. Notice that we allow NEW connections from the LAN to the Internet, but not the other way around. Also, because we use MASQUERADE, our router/firewall will only have to FORWARD traffic that comes back from the Internet as a reponse, because, as you may remember from the Packet Processing Overview earlier in this document, as a reply comes back from the Internet, our router will use the nat table to match the existing connection, apply PREROUTING destination NAT as the packet comes in, and hit the FORWARD chain with a new destination IP address.
A SOHO Network with a Seperate Router and Firewall
The previous scenario suggests there is one single network device, apart from switches, hubs and modems, between the SOHO Network and the Internet. In most topologies, this is not the case. Many SOHO Networks have a router from the Internet provider to connect to the Internet. If that is the case, the network topology changes:
eth1 eth0 SOHO Network --------------------[ ROUTER B ]----------------[ ROUTER A ]-------------- Internet 192.168.2.0/24 192.168.2.1 192.168.1.2 192.168.1.1 public-ip 0.0.0.0/0 Where: * ROUTER A is the router of the Internet provider. * ROUTER B is your router.
In this case, configure the following:
- Configure ROUTER A to have a static route to 192.168.2.0/24 via 192.168.1.2
- Configure ROUTER A to have 192.168.1.2 as a default (virtual) server, using NAT
- Configure ROUTER B to have a default route to 0.0.0.0/0 via 192.168.1.1
ROUTER A will now NAT all incoming packets to 192.168.1.2, and MASQUERADE all outgoing packets with the public IP. The incoming packets will end up with ROUTER B, which is also the firewall.
Suppose there is a webserver in the SOHO Network, which must be available to the public (the Internet) as well as the clients on the LAN. This means you need to forward all requests to ROUTER B, port 80 to the webserver (suppose this webserver is at 192.168.2.20):
# iptables -A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.2.20
The same goes for other services that are hosted on the LAN.
Further Reading and Resources
- www.linuxhomenetworking.com on Iptables
We test this stuff on our own machines, really we do. But you may run into problems, if you do, come to #fedora on irc.freenode.net