May 4, 2017

Building Linux Firewalls With Good Old Iptables: Part 1


In this two-part series, Carla Schroder shows how to run iptables from the command line, so you can set policies on what to deny or allow.

Of course, we still need firewalls on our computers, even though that is not a subject we see much in these here modern times. There are Linux and BSD firewalls, prefab firewalls on commercial hardware from little to big that are most likely based on an open source firewall and a multitude of GUI helpers. In this two-part series, we will learn how to run iptables from the command line and then how to set up a firewall for an individual PC and a LAN firewall.

Pointy-Clicky Meh

I don't think those commercial products with their own special interfaces or those GUI helpers really help all that much because you still need knowledge beyond pointy-clicky. You need to know at least the basics of TCP/IP, and then iptables will make sense to you. I will show you how to configure your firewall by bypassing the fripperies and using plain old unadorned iptables. Iptables is part of netfilter, and I am still, after all these years, fuzzy on exactly what netfilter and iptables are. The site says " is home to the software of the packet filtering framework inside the Linux 2.4.x and later kernel series. Software commonly associated with is iptables." It's enough for me to know that iptables is native to the Linux kernel so you always have it. Also, it's strong and it's stable, so once you learn it your knowledge will always be valid.

Iptables supports both IPv4 and IPv6. It inspects all IP packet headers passing through your system, and routes them according to the rules you have defined. It may forward them to another computer, or drop them, or alter them and send them on their way. It does not inspect payload, but only headers. Packets must traverse tables and chains, and there are three built-in tables: filter, NAT, and mangle. Chains are lists of the rules you have defined. Rules that apply to any matching packets are called targets. These are easier to understand in action, which we shall get to presently.

Iptables tracks state, which makes it more efficient and more secure. You can think of it as remembering which packets are already permitted on an existing connection, so it uses ephemeral ports rather than requiring great gobs of permanent holes in your firewall to allow for all the different IP protocols. Of course, it doesn't really remember, but rather reads packet headers to determine which packets belong in a particular sequence.

A brief digression: the current Linux kernel is well into the 4.x series, and the netfilter documentation still references 2.x kernels. Note that ipchains and ipfwadm -- the ancestors of iptables -- are obsolete since years ago, so we only need to talk about iptables.

Distro Defaults Bye

Your first task is to find out if your Linux distribution starts a firewall by default, how to turn it on and off, and whether it uses iptables or something else. Most likely it's iptables. Conflicting rules are less fun than they sound, so copy and save any existing configurations you want to keep, disable it, and start over.

Command Line, Hear Us Roar

In part 1, we'll run some basic rules, and learn a bit about how iptables works. When you run these rules from the command line they are not persistent and do not survive reboots, so you can safely test all manner of mad combinations without hurting anything.

Check your iptables version:

$ iptables --version
iptables v1.6.0

Take a few minutes to read man iptables. It is a helpful document, and you will be happy you studied it. It provides an excellent overview of the structure of iptables and its features, including Mandatory Access Control (MAC) networking rules, which are used by SELinux, what the built-in tables do, how routing operates, and the commands for doing stuff and finding stuff.

Let's list all active rules. This example shows there are no active rules, and a blanket ACCEPT policy, so iptables, in effect, is turned off:

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

Chain FORWARD (policy ACCEPT)
target     prot opt source    destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source    destination    

The filter table is the default, and the most used. This example blocks all incoming (INPUT) packets that originate from a particular network. You could leave out -t filter, but it's a good practice to make everything explicit. These examples follow the syntax iptables [-t table] {-A|-C|-D} chain rule-specification:

# iptables -t filter -A INPUT -s -j DROP

This example drops all packets from an IPv6 network:

# ip6tables -t filter -A INPUT -s 2001:db8::/32 -j DROP

These example networks are officially set aside for examples in documentation; see RFC5737 and RFC3849.

Now you can see your new rules:

# iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all  --         anywhere
# ip6tables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
DROP       all      2001:db8::/32        anywhere

Remove these rules with the -D switch:

# iptables -t filter -D INPUT -s -j DROP
# ip6tables -t filter -D INPUT -s 2001:db8::/32 -j DROP

Define Policy

Trying to write individual rules for all contingencies is for people who have nothing else to do, so iptables supports policies for the built-in chains. These are the most commonly used policies:

# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT ACCEPT

Run iptables -L to compare. This applies the principal of "Deny all, allow only as needed". These policies are the defaults, and so they are applied in the absence of any matching rules. All incoming packets are dropped, and all outgoing packets are not blocked. But policy alone is not enough, and you still need a set of rules. You must always allow localhost:

# iptables -A INPUT -i lo -j ACCEPT

You probably want some two-way communication, so this allows return traffic from connections you initiated, such as visiting Web sites and checking email:

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

This demonstrates connection-tracking, the wonderful feature that allows you to write many fewer rules to cover a multitude of situtations. Run ip6tables to apply the same rules to your IPv6 sessions.

Kernel Modules

Iptables relies on a number of kernel modules, which are loaded automatically when you run these commands. You can see them with lsmod:

$ lsmod
Module                  Size  Used by
nf_conntrack_ipv6      20480  1
nf_defrag_ipv6         36864  1 nf_conntrack_ipv6
ip6table_filter        16384  1
ip6_tables             28672  1 ip6table_filter
nf_conntrack_ipv4      16384  1
nf_defrag_ipv4         16384  1 nf_conntrack_ipv4
xt_conntrack           16384  1
nf_conntrack          106496  2 xt_conntrack,nf_conntrack_ipv4
iptable_filter         16384  1
ip_tables              24576  1 iptable_filter
x_tables               36864  4 ip_tables,xt_tcpudp,xt_conntrack,iptable_filter

That's it for today. Remember to check out man iptables, and come back next week to see two example iptables scripts for lone PCs and for your LAN.

Read Part 2 of Building Linux Firewalls with Iptables


Learn more about Linux through the free "Introduction to Linux" course from The Linux Foundation and edX.

Click Here!