Firewalls: iptables

Iptables is an application that can be used to configure the Linux kernel firewall. The kernel firewall consists of different tables that can be manipulated with iptables by using default or custom tables and different rules for each table. The kernel firewall is implemented with different Netfilter modules including connection tracking (conntrack).

Iptables is by default installed with most Linux distributions and loaded automatically. You do not need to install it. All changes to iptables must be done with root privileges. In addition to the links on this pages you should consult manual pages of iptables command

man iptables

Tables

There are four default chains and also user added tables, (see: Traversing tables and chains, the default tables are:

  • mangle - for altering the packets with (not for filtering):
    • TOS (Type Of Service)
    • TTL (Time To Live)
    • MARK (set a special mark to packet as an integer)
    • SECMARK (set security context mark for a single packet)
    • CONNSECMARK (set security mark for whole connection)
  • nat - for changing source/destination fields of packets (Network Address Translation) with:
    • DNAT - For changing the destination address of the packet for rerouting.
    • SNAT - Change the private addresses in your LAN to the packets that are sent outside LAN - and vice versa.
    • MASQUERADE - Like SNAT, but works better with dynamic IPs provided by the ISP.
  • raw - Disable/enable connection tracking on packet basis. You will not need this.
  • filter - The packet filtering is done with this table based on state, host, port, protocol and marks, you can select a target for a packet:
    • ACCEPT - Accept a packet
    • LOG - Log the packet
    • DROP - Drop the packet altogether - leaves TCP connections hanging
    • REJECT - Reject the packet - with TCP this results in proper closing of the connection
    • REDIRECT - Redirect the packets from a port to another.

Chains

The default chains are:

  • INPUT - Incoming packets to local computer
  • OUTPUT - Outgoing packets from local computer
  • FORWARD - Forwarded packets
  • PREROUTING - When routing is enabled, the packets will be processed by these rules before routing
  • POSTROUTING - When routing is enabled, the packets will be prosessed by these rules before sending them to network

The chains belong to different tables.

More chains to certain table can be added with iptables by:

sudo iptables -t insert_table_name -N insert_chain_name_here

And to remove a chain

sudo iptables -t insert_table_name -X insert_chain_name_here

Rules

See: How a rule is built

The basic syntax (from command line) is:

sudo iptables -t table_name command -m match -j target

Where

  • -t table_name is not required - iptables uses the filter table by default.
  • command can be (see Commands and their abbreviations):
    • --append - add to end, e.g. Accept all to HTTPS port
      sudo iptables --append INPUT -p tcp --dport 443 -j ACCEPT
    • --delete - delete a rule, e.g. delete the previous (has to be exact match!)
      sudo iptables --delete INPUT -p tcp --dport 443 -j ACCEPT
    • --replace - replace a rule at certain line in the speficied table, e.g., replace first rule in the default table
      sudo iptables --replace INPUT 1 -p tcp --dport 443 -j DROP
    • --insert - insert a rule at place X in the chain, e.g. add rule as second in the default table:
      sudo iptables --insert INPUT 2 -p tcp --dport 22 -j ACCEPT
    • --list - list all rules in the selected table
    • --flush - flush the selected table
    • --zero - reset all counters at the selected table
    • --new-chain - add a new chain
    • --delete-chain - delete chain
    • --policy - Change policy on the selected chain either to DROP or ACCEPT, e.g. set OUTPUT chain to reject all outgoing traffic:
      sudo iptables --policy OUTPUT DROP
    • --rename-chain - Rename a chain
  • match can be either generic, implicit or explicit, here are some most used:
    • --protocol - protocol type (tcp/udp/icmp/sctp) or integer
    • --src - Source IP address/address range, e.g., accept all from a network
      sudo iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT
    • --src-range - Like previous but a range can be defined
      sudo iptables -A INPUT -p tcp -m iprange --src-range 192.168.0.1-192.168.0.100
    • --dst - Destination IP address/address range
    • --dst-range - Like previous but a range can be defined
      sudo iptables -A INPUT -p tcp -m iprange --dst-range 192.168.0.1-192.168.0.100
    • --in-interface and --out-interface - Specify a interface to be used with chain, e.g.,
      sudo iptables -A INPUT -i eth0 -j LOG
    • --source-port and --destination-port - for tcp/udp/sctp, specify the port that is used, e.g., allow all outgoing on eth2 to http destination port
      sudo iptables -A OUTPUT -p tcp -o eth2 --destination-port 80 -j ACCEPT
      • Or use multiple ports with
        sudo iptables -A OUTPUT -p tcp -o eth2 -m multiport --destination-port 80,8080,443 -j ACCEPT
    • --icmp-type - select ICMP type to match, e.g., allow ICMP requests from one address only
      sudo iptables -A INPUT -p icmp --icmp-type 8 -s 157.24.24.111 -j ACCEPT
      sudo iptables -A INPUT -p icmp --icmp-type 8 -j DROP
    • --state - match by state (INVALID, ESTABLISHED, NEW and RELATED, e.g., accept new and established:
      iptables -A INPUT -p tcp  -m state --state NEW,ESTABLISHED -j ACCEPT
  • The targets are defined with -j, see all targets. Note that target can also be a used defined chain.

Firewall startup, saving and restoring

Almost all actions described here need root privileges.

Startup

The separate commands can be put into a script file (rc.firewall), e.g.,

#!/bin/bash
iptables -A INPUT -i eth0 -m multiport --dst-port 80,443,8080 -j ACCEPT
iptables -t filter -P INPUT DROP

And to enable it to execute

chmod +x rc.firewall

And to enable the firewall to load at startup you can (select one)

  1. Edit rc.local and add following line
    sh /path/to/rc.firewall
  2. Add a iptables file to /etc/init.d/iptables with e.g., following content
    #! /bin/bash
    ### BEGIN INIT INFO
    # Provides:          iptables
    # Required-Start:    mountkernfs $local_fs
    # Required-Stop:     mountkernfs $local_fs
    # X-Start-Before:    networking
    # X-Stop-After:      networking
    # Default-Start:     2 3 4 5
    # Default-Stop:      0 1 6
    # Short-Description: Iptables
    # Description:       Debian init script for iptables from https://github.com/Sirtea/iptables-init-debian
    ### END INIT INFO
     
    case "$1" in
        start)
            sh /path/to/rc.firewall
        ;;
        stop)
            iptables -F
            iptables -X
        ;;
        restart)
            iptables -F
            iptabels -X
            sh /path/to/rc.firewall
        ;;
        *)
            echo "Usage: /etc/init.d/iptables {start|stop|restart}"
            exit 1
        ;;
    esac
     
    exit 0

    (execute the script) and run

    update-rc.d iptables defaults

    For further info see

    man update-rc.d
  3. Edit /etc/network/interfaces and append following to the networking interface you are using
    ifup sh /path/to/rc.firewall
    ifdown iptables -F
  4. Or if the distribution provides iptables-persistent package install it with
    sudo apt-get install iptables-persistent

    That is basically the same as 2nd option but all rules have to be set to /etc/iptables/rules - the script does not flush the tables nor it will remove user defined chains when stopping.

But there is a better way, the iptables comes with commands for saving and restoring the firewall configuration. These tools also allow you to save the packet counters for each connection.

First see manual pages of both

man iptables-save
man iptables-restore

Both saving and restoring can be put using one of the aforementioned three examples (second one might be most usable).

Saving

To save current configuration to a file named iptables.firewall

iptables-save -c > /path/to/iptables.firewall

Restoring

To restore the firewall from iptables.firewall

iptables-restore -c < /path/to/iptables.firewall

Exercise task

Using the information on these pages create a basic firewall to Server Ubuntu virtual machine either manually or to a script file (no need to set it to startup at boot) that:

  • Allows access only to HTTPS and alternative HTTP port.
  • Redirects all traffic from alternative HTTP port to default HTTP port on the local computer.
  • Drops all TCP connection except which are already established.
  • Logs all attempts to the default SSH port. Set prefix to “SSH Login attempt ”.

Test the rules by using the Wireshark Ubuntu virtual machine - remember to set the both virtual machines to use NAT as network adapter type from vmplayer settings. Connect to the Server ubuntu with normal browser to HTTP, HTTPS and alternative HTTP ports, and for SSH rule testing use

ssh administrator@server.ubuntu.ip.address

Finally, try the saving and restoring functions on your firewall.

After you are finished remember to flush the firewall rules on all affected tables.

Example firewall commands

With following commands you should be able to establish a firewall that is specified above:

iptables -t nat -A PREROUTING -i eth1 -p tcp --dport 8080 -j REDIRECT --to-port 80
 
iptables -A INPUT -i eth1 -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -m multiport --dport 443,8080 -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -m tcp --dport 22 -j LOG --log-prefix "SSH"
iptables -A INPUT -i eth1 -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -j DROP
iptables -A INPUT -i eth1 -p tcp -j DROP

Reading material

Last modified: 2014/02/04 15:55