Building a Professional Firewall with Linux and Iptables

screen-shot-2014-07-07-at-7.25.49-pm

My first position out of university was working as a firewall engineer for a large credit card processing company. It’s where I learned the way of the packet and how to build a proper firewall ruleset.

This article will show you how to build a firewall using Linux and Iptables that has the elegance and effectiveness of a top-end security organization.

Good firewall policy has three primary sections:

  • Management Rules: allow you to administer the system

  • Access Rules: control access to and from resources

  • A Default Deny Rule: drops all traffic that reaches it

The concept is simple:

You also do this visibly, meaning that most every rule you write will log when traffic hits it. Put another way:

  1. Have an organized ruleset (management/access/deny)

  2. Make your rules as granular as possible (least privilege)

  3. Properly document each rule

  4. Log the traffic that matches each rule

  5. Drop (and log) by default at the end of the policy

Let’s see how to do this with Linux and Iptables.

We’ll start by doing some setup items. First we’ll define your system’s IP address as a hostname.

#!/usr/bin/env bash
YOUR_HOSTNAME=123.456.789.012

Then we’ll start by flushing any existing rules.

/sbin/iptables -F

-F stands for flush.

And we’ll allow traffic for the local interface.

/sbin/iptables -A INPUT -i lo -j ACCEPT

-A stands for “append”. -i indicates the interface. -j means jump to a given chain.

And then we’ll allow traffic that’s part of an established connection. netfilter is a stateful engine, afterall.

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

Keep these all on one line in your real config. This broken for display purposes only. -m stands for “match”. -state matches the following states.

Management rules

In a large corporate environment it’s extremely critical that you set up your management rules so that 1) you can actually get to your firewalls to administer them, and 2) that you limit access to only the people who need it.

In our scenario, we’re going to have just one rule of this type: in this case a rule for SSH.

/sbin/iptables -A INPUT -d $YOUR_HOSTNAME -p tcp --dport 2222 
-j ACCEPT

-d stands for destination. -p stands for protocol. –dport stands for destination port.

Ok, now we’ll be able to SSH into the box on port 2222 (yes, it’s better to use an alternate port for remote access).

Access rules

Now let’s do a regular rule. In a larger environment it’d be much different than a management rule because the destination wouldn’t be the firewall itself, but in this case we’re actually making a firewall to protect a server or workstation, so the rules look the same.

Let’s open a port for an HTTP server.

/sbin/iptables -A INPUT -d $YOUR_HOSTNAME -p tcp --dport 80 
-j ACCEPT

Perfect.

The “default deny” rule

So we’ve got two ports allowed in here: web and ssh. Now we want to make it so that any other packets that hit this box get dropped on the floor.

/sbin/iptables -A INPUT -j DROP

Simple enough: we’re just saying drop everything, and the order is important. netfilter/iptables is a first-match engine, meaning that if you have this rule above something you care about you’ll never make it to that rule (and you’re likely to practice some foul language).

Ok, so now we’ve got a basic firewall. We can manage it (via SSH), we have an allow rule that allows the box to serve HTTP, and we have a deny all rule at the bottom.

But no security system is complete without monitoring, so let’s enable some logging.

You need two pieces for logging with iptables:

  1. You need to send logs using your ruleset

  2. You need to capture them correctly using your logging solution

Logging rules

Logging is pretty straightforward with iptables: you simply add a rule that matches the same exact situation right above the rule you want to log.

So when we had this rule for enabling an HTTP server above…

Unsupervised Learning — Security, Tech, and AI in 10 minutes…

Get a weekly breakdown of what's happening in security and tech—and why it matters.

/sbin/iptables -A INPUT -d $YOUR_HOSTNAME -p tcp --dport 80 
-j ACCEPT

…we can add a rule before it like so:

/sbin/iptables -A INPUT -p tcp --dport 80 -j 
LOG --log-level 7 --log-prefix "Accept HTTP"
/sbin/iptables -A INPUT -d $YOUR_HOSTNAME -p tcp --dport 80 
-j ACCEPT

This logs at level 7 with a message in the log saying it’s an HTTP request that was permitted through the firewall. Remember that this has to be above the actual rule, not below it, because once a packet hits a match it stops and goes on to the next packet.

You’ll want to add a similar logging rule above all your rules, including (and perhaps most importantly) on your default deny rule.

Capturing the logs we’ve sent

Ok, so now we’re sending logs, so how do we receive them?

netfilter is kernel functionality, so we’re going to capture it there inside of your preferred logging system. I’ll assume you’re using rsyslog, since that’s the top choice for modern distros right now.

To capture these logs, simply add the following to your /etc/rsyslog.conf file.

kern.debug /var/log/firewall.log 

Then restart rsyslog and tail your file:

tail -f /var/log/firewall.log

Voila!

Brilliant. So we now have a running firewall that’s logging properly. Let’s just do a couple of touch-ups.

Allowing ICMP

/sbin/iptables -A INPUT -p icmp -d $YOUR_HOSTNAME
--icmp-type 8/0 -j ACCEPT
/sbin/iptables -A INPUT -p icmp -d $YOUR_HOSTNAME 
--icmp-type 11/0 -j ACCEPT>

This allows two specific types of ICMP against your system—ping and time exceeded. Again, if you’re not into that you can omit these.

So I’ve included the various pieces above, and now here’s a full configuration that you can use as a template.

Download the script from there, execute it so it loads into your firewall, and then save it so it’ll survive reboots:

service iptables save

Happy packet dropping!

Notes

  1. For more information on how netfilter and iptables works, check out my (quite in need of an update) primer on it.

Related posts: