Getting Started
Working with iptables from the commandline requires root priviledges, so you will need to become root for most things we will be doing.
Note: We will be turning off iptables and resetting your firewall rules, so if you are reliant on your linux firewall as your primary line of defense you should be aware of this.
Unfortunately, different Linux distros use different comands for starting, stopping and saving firewall rules, so you may need to check your documentation to find out how to do this on your Linux distro. I'm using Red Hat (or Fedora) for the purposes of this tutorial and I'll try to indicate where there may be differences.
First up, we need to establish we have iptables installed. It should be installed on most, if not all modern linux distros. Simply typing iptables --help at the shell should establish iptables is installed on your system:
Code:
# iptables --help
iptables v1.2.9
Usage: iptables -[AD] chain rule-specification [options]
iptables -[RI] chain rulenum rule-specification [options]
iptables -D chain rulenum [options]
iptables -[LFZ] [chain] [options]
iptables -[NX] chain
iptables -E old-chain-name new-chain-name
iptables -P chain target [options]
iptables -h (print this help information)
<snip>
And to see if iptables is actually running, we can use the -L switch to inspect the currently loaded rules:
Code:
# iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all -- anywhere anywhere
ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
ACCEPT all -- barney anywhere MAC 00:50:8D:6D:EF:23
DROP all -- wilma anywhere
ACCEPT all -- bart anywhere MAC 00:50:8D:FD:D6:32
ACCEPT tcp -- anywhere anywhere tcp dpt:ftp
ACCEPT tcp -- ict anywhere state NEW tcp dpt:ssh
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
If iptables is running you should see some rules similar to those above. If iptables doesn't appear to be running, you can check to see if any iptables modules are loaded:
Code:
# lsmod |grep ip
ipt_mac 2113 2
ipt_state 2113 2
ip_conntrack 40949 1 ipt_state
iptable_filter 3777 1
ip_tables 16577 3 ipt_mac,ipt_state,iptable_filter
OK, assuming you have worked out how to get iptables started, if it's not already, let's begin with a very simple set of rules to set up an spi firewall that will allow all outgoing connections but block all unwanted incoming connections. At the command prompt we could type the following commands:
Code:
iptables -F
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -L -v
and the final command gives us the following output:
Code:
Chain INPUT (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo any anywhere anywhere
0 0 ACCEPT all -- any any anywhere anywhere state RELATED,ESTABLISHED
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
There - that was easy wasn't it! We now have a fully featured spi firewall running that will allow all outgoing connections but block all unauthorized incoming connections as well as any forwarded packets. So, lets look at each of the 7 commands in turn and understand exactly what we've just done:
1. (iptables -F) First of all we've used the -F switch to flush all existing rules so we start with a clean state from which to add new rules.
2. (iptables -P INPUT DROP) The -P switch sets the default policy on the specified chain. So here we've set the default policy on the INPUT table to DROP. This means that if an incoming packet does not match one of the following rules it will be dropped.
3. (iptables -P FORWARD DROP) Similarly, here we've set the default policy on the FORWARD chain to DROP as we're not using our computer as a router so there should not be any packets passing through our computer.
4. (iptables -P OUTPUT ACCEPT) and finally, we've set the default policy on the OUTPUT chain to ACCEPT as we want to allow all outgoing traffic (as we trust our users).
5. (iptables -A INPUT -i lo -j ACCEPT) Now it's time to start adding some rules. We use the -A switch to append (or add) a rule to a specific chain, the INPUT chain in this instance. Then we use the -i switch (for interface) to specify packets matching or destined for the lo (or localhost, 127.0.0.1) interface and finally -j (jump) to the target action for packets matching the rule - in this case ACCEPT. So this rule will allow all incoming packets destined for the localhost interface to be accepted. This is generally required as many software apps expect to be able to communicate with the localhost adaptor.
6. (iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT). This is the rule that does most of the work, and again we are adding (-A) it to the INPUT chain. Here we're using the -m switch to load a module (state). The state module is able to examine the state of a packet and determine if it is NEW, ESTABLISED or RELATED. NEW refers to incoming packets that are new incoming connections that weren't initiated by the host system. ESTABLISED and RELATED refers to incoming packets that are part of an already established connection or related to and already established connection.
7. (iptables -L -v) Finally, we can list (-L) the rules we've just added to check they've been loaded correctly.
Finally, the last thing we need to do is save our rules so that next time we reboot our computer our rules are automatically reloaded. Unfortunately, the command to do this is different on different distros. On RH/Fedora systems, do:
Code:
/sbin/service iptables save
I'm not sure on other distro's so perhaps users can confirm, but for debian-based systems, try:
Code:
/etc/init.d/iptables save_active
and for Suse, try editing /etc/sysconfig/SuSEfirewall2 and restarting the firewall by running:
Code:
/sbin/SuSEfirewall2 restart
Obviously typing all these commands at the shell can become tedious, so by far the easiest way to work with iptables is to create a simple script to do it all for you. The above (for RH/Fedora) may be entered into your favourite text editor, saved (as myfirewall for example) and made executable:
Code:
#!/bin/bash
# iptables configuration file
# Ned Slider, 2006
# Flush all current rules from iptables
iptables -F
# Set default policies for INPUT, FORWARD and OUTPUT chains
iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT
# Set access for localhost
iptables -A INPUT -i lo -j ACCEPT
# Accept packets belonging to established and related connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Save settings with /sbin/service iptables save
# List iptables chains with 'iptables -L -v'
/sbin/service iptables save
iptables -L -v
Note we can also comment our script to remind us what were doing. Now we can simply edit our script and run it from the shell with the following command:
If you can't work out how to save your firewall rules in your distro, you could simply run the above script each time at startup.
OK, that's it for this week. Probably the hardest part for most users will be establishing you have iptables installed and running, and working out how to save your new firewall configuration at the end, as these are not the same on all distros. Everything else when working with iptables is identical so should work without issue. Post if you have any problems, and when everyone has successfully got this far, we'll continue with the next installment and look at how to safely open up our firewall for some common incoming connections.
Ned