iptables

The iptables command under Linux helps in defining rules for packet filtering for establishing and configuring firewalls under Linux. iptables, also, helps in configuring the Network Address Translation (NAT) for placing a local area network behind a single public IP address for accessing the Internet and for other uses.

The network communication takes place in the units of Internet Protocol (IP) packets. The host computer systems can be secured from unwanted or undesirable packets from and to the external world by having a set of rules for examining the packets and taking some action like discarding and accepting the packets. This is known as packet filtering and is a major function of firewalls in network security. iptables helps us in establishing and configuring firewalls.

Basic concepts

The rules for packet filtering are kept in a sequence in chains. The chains are stored in tables in the kernel.

Chains

Each table contains built-in and user-defined chains. A chain contains a list of rules which match IP packets based on the criteria specified in a rule. Once a packet matches a rule, the action specified in the rule is taken on the packet. The built-in chains are INPUT, FORWARD, OUTPUT, PREROUTING and POSTROUTING. The INPUT chain is for packets meant for the local processes running on the host. The FORWARD chain is for packets that come to this host but are destined for some other host and hence are to be forwarded. The OUTPUT chain is for packets generated by the local processes with some other host as the destination and are to be sent out. The PREROUTING chain is for packets coming on a network interface before any processing. The POSTROUTING chain is for processing the packets just before they go out.
Built-in chains for packet filtering
Fig. 1 Built-in chains for packet filtering

Tables

The kernel has five tables. These are the filter, nat, mangle, raw and security tables. The filter table has INPUT, FORWARD and OUTPUT built-in chains and is the default table for packet filtering. The nat table is for configuring the NAT. It has PREROUTING, OUTPUT and POSTROUTING built-in chains. The mangle table is for specialized alteration of certain fields like TOS and TTL in the packet header. It has all the five built-in chains. The raw table is for marking the packets so that they are not used in connection tracking. It has PREROUTING and OUTPUT built-in chains. The security table is for Mandatory Access Control (MAC) implemented by Linux Security Modules. It has INPUT, FORWARD and OUTPUT built-in chains. In this tutorial, we will focus on the filter table.

Rules

A rule specifies the criteria for matching a packet and a target. The target is the action to be taken on a packet if it matches the matching criteria.

Targets

As mentioned above, a target is the action to be taken when a packet matches a rule. Examples of a target are the keywords, ACCEPT, DROP, QUEUE and RETURN. The ACCEPT target is to allow the packet in, that is the packet gets past the concerned chain. The DROP target means that the packet is discarded. The QUEUE target implies that the packet is queued for local processes. The RETURN target means that the packet has completed its course in the concerned chain. If it is a user-defined chain, the control returns to the calling chain. If it is a built-in chain, the fate of the packet depends upon the chain policy as set by the iptables -P command (the default policy is ACCEPT). A target can also be a user-defined chain.

iptables syntax

The iptables command syntax is,

iptables [-t table] command [chain] [parameter [options]]...

iptables commands

The iptables commands are,

iptables commands
Command Description
-A, --append chain rule-spec Append rule at the end of the chain
-C, --check chain rule-spec Check for existence of rule in chain
-D, --delete chain {rule-spec I rulenum} Delete rules from chain
-I, --insert chain [rulenum] rule-spec Insert rule in chain
-R, --replace chain rulenum rule-spec Replace rule in chain
-L, --list [chain] List rules
-F, --flush [chain] Flush rules
-Z, --zero [chain [rulenum]] Zero the packet and byte counters
-N, --new-chain chain Create a new user defined chain
-X, --delete-chain [chain] Delete the user defined chain
-P, --policy chain target Set policy for the chain to the target
-E, --rename-chain old-chain new-chain Rename the user defined chain
-h, --help Print the command usage help

PARAMETERS

The parameters are,

iptables command parameters
Parameter Description
[!] -p, --protocol protocol The protocol for the rule
[!] -s, --source address [/mask] [,...] Source addresses for the rule
[!] -d, --destination address [/mask] [,...] Destination addresses for the rule
-j, --jump target The target for the rule
[!] -i, --in-interface name The network interface on which a packet was received.
[!] -o, --out-interface name The network interface on which a packet would be sent out.
[!] -f, --fragment Rule is for second and further fragments
-c, --set-counters packets bytes Initialize packet and byte counters of a rule
-m module [--module-arg value,...] Match packets using module with optional module specific arguments
-v, --verbose Verbose output.
-n, --numeric Print IP address and port numbers in numeric format.
-x, --exact Print the exact values of packet and byte counters (without rounding). Used with -L command.
--line-numbers Print line numbers while listing rules, giving the position of the rule in the chain.

The -m parameter loads the specified extended packet matching module and provides additional sub-commands which can be passed as arguments to the module. Some of above parameters provide the option of putting a ! in front and inverting the test.

EXAMPLES

Running iptables commands needs superuser privileges. So, on the command line, all iptables commands need to be prefixed with sudo. Or, the commands can be put in a shell script which can be sun with superuser privileges.

1. List all rules

The command,

sudo iptables -L INPUT

lists all rules of the INPUT chain for the default filter table. If the chain is not mentioned, the rules for all the chains are printed. To get the rules for other tables, the table name is to be passed as a parameter.

sudo iptables -L # lists rules for all chains in the filter table sudo iptables -t nat -L # lists rules for all chains in the nat table

The -n option prints numeric source and destination IP addresses, which is compact and the -v option gives packet and byte counts and the network interfaces, which is helpful. So, we can print the rules as follows,

sudo iptables -L -nv # lists rules for all chains in the filter table sudo iptables -t nat -L -nv # lists rules for all chains in the nat table

2. Flush all rules

sudo iptables -F # flush rules for all chains in the filter table sudo iptables -t nat -F POSTROUTING # flush rules for the POSTROUTING chain in the nat table

3. Append rules

The most commonly used iptables command is to add (append) rules to the chains. For example, to allow packets with the NEW, ESTABLISHED and RELATED states on the loopback and eth0 interfaces, we can append the rules,

sudo iptables -A INPUT -m state --state NEW,ESTABLISHED,RELATED -i lo -j ACCEPT sudo iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -o lo -j ACCEPT sudo iptables -A INPUT -m state --state NEW,ESTABLISHED,RELATED -i eth0 -j ACCEPT sudo iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -o eth0 -j ACCEPT

Here, we are using the state module to allow packets with only the NEW, ESTABLISHED and RELATED states for the INPUT and OUTPUT chains of the default filter table.

4. Chain policies

The default policy is ACCEPT. We can set the default policy as DROP so that the packets matching the firewall rules pass and the rest are dropped.

sudo iptables -P INPUT DROP sudo iptables -P OUTPUT DROP sudo iptables -P FORWARD DROP

The sequence of above mentioned iptables commands is important. It is necessary to have rules that allow packets to get matched on the INPUT and OUTPUT chains before setting the policy as DROP. For, if the rules to allow packets were not in place and the INPUT and OUTPUT chain policy was DROP, all packets would get dropped and no communication would be possible. For a remote server, it would effectively lock out access to the server. Also, the iptables -F command flushes all the rules, and if the policy for the chains is DROP and the iptables -F command is given, all communication with the server would be cut off. All this assumes that the commands were being given from the command line. However, in a script, the iptables -P policy setting commands can be put ahead of other commands. If the script runs successfully, the firewall is established. However, if there is an error in some command and the script aborts, there is a risk of communication cut off.

5. Open ports

Some of commonly used ports are 80, 443, 25, 465 and 993 for HTTP, HTTPS, SMTP, SMPTS and IMAP respectively. We can keep these ports open by the command,

# open ports - server iptables -A INPUT -p tcp -m multiport --dports 80,443,25,465,993 -j ACCEPT iptables -A OUTPUT -p tcp -m multiport --sports 80,443,25,465,993 -j ACCEPT # open ports - client iptables -A OUTPUT -p tcp -m multiport --dports 80,443,25,465,993 -j ACCEPT iptables -A INPUT -p tcp -m multiport --sports 80,443,25,465,993 -j ACCEPT

The use of multiport module allows one to specify more than one port in a single rule. The first two statements are for a server and the last two are for a client. For example, input to a web server has the destination port as 80 while, from the client point of view, the same message is an output message with the destination port 80. Similarly, an output from a web server is an input for a web browser client with the source port 80.

6. SSH Access

We can put the rules for secure shell (SSH) access. We can configure SSH access from a particular host (192.168.1.101, here) or a network (e.g., 192.168.1.000/24). The first two commands are from a server point of view and the last two are from a client point of view.

# allow ssh access - server (allow access from 192.168.1.101 only) iptables -A INPUT -p tcp -s 192.168.1.101 --dport 22 -j ACCEPT iptables -A OUTPUT -p tcp -d 192.168.1.101 --sport 22 -j ACCEPT # allow ssh access - client iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp --sport 22 -j ACCEPT

7. DNS queries and responses

Clients talk to DNS servers on port 53 and the local port number can be anything between 1024 and 65535. We can keep these ports open for DNS queries and responses.

iptables -A OUTPUT -p udp -o eth0 --dport 53 --sport 1024:65535 -j ACCEPT iptables -A INPUT -p udp -i eth0 --sport 53 --dport 1024:65535 -j ACCEPT

A simple firewall script

The above commands can be put in a script, as given below.

#!/bin/bash # # script for firewall using iptables # iptables -F iptables -X iptables -N val_input iptables -N val_output # allow packets with NEW, ESTABLISHED and RELATED states iptables -A val_input -m state --state NEW,ESTABLISHED,RELATED -i lo -j RETURN iptables -A val_output -m state --state NEW,ESTABLISHED,RELATED -o lo -j RETURN iptables -A val_input -m state --state NEW,ESTABLISHED,RELATED -i eth0 -j RETURN iptables -A val_output -m state --state NEW,ESTABLISHED,RELATED -o eth0 -j RETURN iptables -A val_input -j DROP iptables -A val_output -j DROP iptables -A INPUT -p tcp -j val_input iptables -A OUTPUT -p tcp -j val_output # open ports - server iptables -A INPUT -p tcp -m multiport --dports 80,443,25,465,993 -j ACCEPT iptables -A OUTPUT -p tcp -m multiport --sports 80,443,25,465,993 -j ACCEPT # open ports - client iptables -A OUTPUT -p tcp -m multiport --dports 80,443,25,465,993 -j ACCEPT iptables -A INPUT -p tcp -m multiport --sports 80,443,25,465,993 -j ACCEPT # allow ssh access - server iptables -A INPUT -p tcp --dport 22 -j ACCEPT iptables -A OUTPUT -p tcp --sport 22 -j ACCEPT # allow ssh access - client iptables -A OUTPUT -p tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp --sport 22 -j ACCEPT # allow DNS queries and replies - client iptables -A OUTPUT -p udp -o eth0 --dport 53 --sport 1024:65535 -j ACCEPT iptables -A INPUT -p udp -i eth0 --sport 53 --dport 1024:65535 -j ACCEPT # set policies for chains iptables -P INPUT DROP iptables -P OUTPUT DROP iptables -P FORWARD DROP

In the above script, there are two user-defined chains, val_input and val_output for validation of TCP packets on the INPUT and OUTPUT chains respectively. There are rules to check whether the state of the packet is NEW, ESTABLISHED or RELATED for the three network interfaces. If a packet's state is not one of these three values, it is dropped. Otherwise, it passes the validation and is checked with more rules. We open the ports for HTTP, HTTPS, SMTP, SMPTS, IMAP and SSH and also allow the DNS queries. Finally, the default policy for the three built-in chains, INPUT, OUTPUT and FORWARD is set to DROP, so that any packets not matching any of the above rules are dropped.

The nat table

The nat table is used for configuring the Network Address Translation (NAT) rules for packets. This helps in using the host as a router, where a private LAN is put behind a single IP address for Internet access. We can use the MASQUERADE target, where the source IP address of packets is changed to the IP address of the outgoing network interface. The MASQUERADE target is only valid for the POSTROUTING chain of the nat table. The MASQUERADE is used when the IP address of the outgoing network interface has been assigned dynamically using the DHCP. For example, the command,

sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE

translates the source IP address of the packets to that of network interface wlan0.

If the outgoing network interface's address is a static IP address, it is better to use the SNAT target, where the IP address is specified as a part of the command. For example, if the IP address of the outgoing network interface is 198.51.100.12, we can write,

sudo iptables -t nat -A POSTROUTING -j SNAT --to-source 198.51.100.12

With this, we can write a small script to configure the firewall for a Linux system, which can be used as a router and provides the source network address translation, SNAT.

#!/bin/bash # # script for source Network Address Translation using iptables # iptables -F iptables -t nat -F iptables -X iptables -N val_input iptables -N val_output # allow packets with NEW, ESTABLISHED and RELATED states iptables -A val_input -m state --state NEW,ESTABLISHED,RELATED -i lo -j RETURN iptables -A val_output -m state --state NEW,ESTABLISHED,RELATED -o lo -j RETURN iptables -A val_input -m state --state NEW,ESTABLISHED,RELATED -i eth0 -j RETURN iptables -A val_output -m state --state NEW,ESTABLISHED,RELATED -o eth0 -j RETURN iptables -A val_input -m state --state NEW,ESTABLISHED,RELATED -i wlan0 -j RETURN iptables -A val_output -m state --state NEW,ESTABLISHED,RELATED -o wlan0 -j RETURN iptables -A val_input -j DROP iptables -A val_output -j DROP iptables -A INPUT -p tcp -j val_input iptables -A OUTPUT -p tcp -j val_output iptables -t nat -A POSTROUTING -j SNAT --to-source 198.51.100.12

Software: