Iptables

From LQWiki
Jump to navigation Jump to search

Iptables is an administration tool for IPv4 packet filtering and NAT. Iptables allows one to build or setup a firewall using netfilter. Iptables is the successor of ipchains which was included in kernels up to 2.2.x

Most Linux-based firewalls are just iptables scripts. GUI front-ends exist (e.g. Firestarter and Guarddog) for those users who prefer not having to learn the command line syntax.

Default policies

Iptables has three default "chains" of rules to help determine what happens with packets of information being sent to or from your computer: INPUT, FORWARD, and OUTPUT. The INPUT chain evaluates packets that are arriving at your computer from an outside source. The FORWARD chain evaluates packets that are being sent through your computer as a router. The OUTPUT chain evaluates packets that are originating from your computer and are being sent out. Each of these three chains has a default policy which will apply to packets that do not meet any of the specific rules created in the tables.

The three default policies are ACCEPT, REJECT, and DROP. The ACCEPT policy accepts packets that have not matched any rules in the chain. The REJECT policy discards the same packets and sends an icmp packet (or tcp reset packet) back to the originator to let them know what happened. The DROP policy simply discards packets without letting anyone know about it.

Firewalling

A firewall typically sets the policies for incoming packages to DROP and defines rules for exceptions. This means, everything is forbidden that is not explicitly allowed.

SUSE example

Confirm that the firewall is stopped

rcSuSEfirewall2 status
Checking the status of SuSEfirewall2                                  unused

Show the default policy for incoming packages

iptables -L INPUT
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Start the firewall

rcSuSEfirewall2 start
Starting Firewall Initialization (phase 2 of 2)                       done

Confirm that the default policy has changed

iptables -L INPUT
Chain INPUT (policy DROP)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere            state ESTABLISHED
ACCEPT     icmp --  anywhere             anywhere            state RELATED
input_ext  all  --  anywhere             anywhere
input_ext  all  --  anywhere             anywhere
input_ext  all  --  anywhere             anywhere
input_ext  all  --  anywhere             anywhere
input_ext  all  --  anywhere             anywhere
input_ext  all  --  anywhere             anywhere
input_ext  all  --  anywhere             anywhere
LOG        all  --  anywhere             anywhere            limit: avg 3/min burst 5 LOG level warning tcp-options ip-options prefix `SFW2-IN-ILL-TARGET '
DROP       all  --  anywhere             anywhere

Using stateful inspection

One of the most effective features of which you can take advantage with iptables is the stateful packet filtering technology. Iptables inspects the individual packets of information that are being sent to and from your computer and determines what broader connection each packet belongs to. For example, if you are remotely logging on to another machine via SSH, the computer you are currently using and the computer to which you are trying to connect will exchange many packets of information over port 22 (the port dedicated to SSH communications). Iptables sees all of these packets as belonging to a single connection and allows you to construct firewall rules that vary depending on the state of a given connection.

Specifically, connections can be categorized as "new", "established", or "related". A "new" connection involves packets that are being sent in an attempt to establish a connection. The first packet of information you send in your attempt to logon to the remote computer is received by that computer in the state "new", because its purpose is to establish a new connection. The subsequent packets that are sent for the purpose of sustaining that SSH connection are classified as an "established" connection. Packets can also be "related" to a connection that already exists.

If you are using a laptop or a desktop computer at home, you may want to prevent any attempt from the outside world to establish a connection with your computer (assuming that if you want a connection with another computer, you will establish it yourself). This goal can be accomplished with the following command.

iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

You can allow all outgoing connections originating from your computer with the following command.

iptables -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

Setting the default policy of the INPUT, FORWARD, and OUTPUT chains to REJECT or DROP and adding the above two lines will create a fairly useful introductory firewall for laptop computers and desktops used at home.

Allowing specific services

If the default policy of INPUT is set to REJECT or DROP and you are hosting services to which you would like other computers to have access, you will have to specifically allow such access in your firewall. For example, if you want all computers to be able to remotely logon to your computer via SSH, you can use the following command.

iptables -A INPUT -p tcp --dport 22 -j ACCEPT

You could replace the "22" in the above command with "ssh"

iptables -A INPUT -p tcp --dport ssh -j ACCEPT

and have the same effect. If you have used the stateful packet filtering feature of allowing all NEW, ESTABLISHED, and RELATED connection within the OUTPUT chain, then you will not have to worry about adding explicit OUTPUT statements to match the above INPUT statements regarding the SSH service. If you need to specifically allow SSH output, you can do so with the following command.

iptables -A OUTPUT -p tcp --sport ssh -j ACCEPT

Logging with Iptables

Logging is accomplished with rules using the LOG and ULOG targets. These targets are considered non-terminating, which means the next rule in the list is read after the LOG rule has completed.
Each packet that matches a LOG or ULOG rule is sent to the netfilter logging system, so logging in the filter table will produce a message for every packet in the whole communication stream, whereas logging in the nat table will only produce a message for the first packet of a stream.

LOG Target

This target logs into the kernel log system and can be redirected by syslogd or syslog-ng. dmesg can also be used to read the messages currently in the buffer.

-j LOG rules can be appended with switches to add a prefix, add a log-level and to log extra data from the packets. Each LOG rule can contain options like any other type of rule to fine tune what gets logged.

Just remember to place a LOG rule before a rule which directly acts on a packet. After a packet is acted on by a rule, it usually leaves the chain hence won't get logged.

iptables -t nat -I PREROUTING -i eth0 -j LOG --log-prefix "incoming " --log-level 6

This rule logs every new connection coming into eth0. New in the nat table means streams that have not been seen before. Notice the space after the prefix. This is to separate the prefix from the next field in the message. Make sure a prefix is added to every LOG rule rather than just some, otherwise log messages will have a different number of fields and log-watching software will produce errors.

iptables -I FORWARD -i eth0 -j LOG --log-prefix "incoming " --log-level 6

This rule will produce messages identical to the nat rule, but for every packet in the stream. Nothing exists to distinguish between which table or rule a message is from, so the prefix rule needs to say something intelligent, rather than just 1 2 3 etc.

ULOG Target

This target directs messages to a [Netlink] socket rather than the kernel buffer. A daemon which listens to these sockets is required in order to collect messages and pass them into a file or database. ulogd is the netfilter daemon for this. Rules must specify which of the 32 netlink groups is being monitored by ulogd. Several instances of ulogd can run at the same time, each requiring a different netlink group and destination for messages, which are specified in separate config files.

-j ULOG rules are appended with switches to specify the netlink group, message prefix and buffer threshold.

iptables -t nat -I PREROUTING -i eth0 -j ULOG --ulog-prefix incoming --ulog-nlgroup 2 --ulog-qthreshold 20

This rule will produce messages on netlink socket 2, and hold writing until 20 messages are stored. The prefix will be written in the same place in the message as the LOG rule, but is automatically separated from the next field so doesn't require manual spacing.

Log Rotation

The standard logrotate daemons handle copying, compressing and removing files to avoid the disk or partition becoming full and the system grinding to a halt.

For logfiles with constant data being written to them, it is recommended to use the copytruncate option with logrotate.d to minimise the interference to write cycles, and to use the delaycompress option to enable reading the rotated file with standard tools.

Be aware that some software rotates files itself, rather than using logrotate, so don't use both methods in the same directory.

dmesg

This command is used to read the kernel message buffer, enable access changing the console reporting level and clearing the buffer.

If the buffer is full of netfilter/iptables LOG messages, you will need to change from using LOG rules to using ULOG rules.

This impacts on several well used programs so some instructions can be found on the dmesg wiki page.

Banning individual IP addresses

Another way of preventing unwanted connections is to specifically REJECT or DROP packets from sources with whom you would prefer to have no business. You can reject packets from a specific source IP address with the following command.

iptables -A INPUT -p tcp -s xxx.xxx.xxx.xxx -j REJECT --reject-with tcp-reset

This technique will not be necessary if the default policy of INPUT is REJECT or DROP, because only packets that you specifically allow will be accepted. If the default policy of INPUT is ACCEPT, you will likely want to block traffic from specific IP addresses (or IP address ranges).

Example script

Here is an example script that will allow others access to your web service (port 80), which you would need if you are hosting a website on your computer that you would like others to see.

#!/bin/bash
# Firewall script that allows access to my web server

# Location of the iptables command
IPTABLES=/sbin/iptables

# Flush existing firewall rules
$IPTABLES --flush

# Delete any extraneous chains which may exist from a previous script
$IPTABLES --delete-chain

# Change the default policy of all three chains to DROP
$IPTABLES -P INPUT DROP
$IPTABLES -P FORWARD DROP
$IPTABLES -P OUTPUT DROP

# Use stateful inspection feature to only allow incoming connections
# related to connections I have already established myself
$IPTABLES -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPTABLES -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# Allow the world access to port 80 on my machine, the port through
# which others can access my web server
$IPTABLES -A INPUT -p tcp --dport 80 -j ACCEPT

# Included to allow the script to exit gracefully
exit 0

If you name this script my_firewall, then you can execute the script with the following command.

sh my_firewall

You could even add this line to any of the scripts that are executed when your computer boots to have your firewall running the entire time your computer is up and running. This is done by performing a:

iptables-save

You could also add this line to a crontab file to cause it to execute at fixed increments to make sure your firewall is never deactivated for given length of time.

The command prompt type the following

crontab -e

From their you can edit the crontab file, at the end of your crontab file add the entry, below is an example of a crontab entry that will run a copy of your firewall script every hour

0 * * * * sh /root/my_firewall

Save the crontab file and you should notice that every hour your iptables configuration will be reset to any state you specified in the my_firewall file.

Iptables firewalls

See also