Linux IPtables

In this blog post I will describe how to set up a basic firewall on Linux using IPtables. Setting up a firewall is only half the work though; a smart information security professional will also test their firewall configuration thoroughly. I set up a virtual lab environment on my home laptop for testing purposes. To simulate a network with security zones (internal / external) I used a Vyatta router to divide the network into subnets. I set all of this up using VMware Workstation which is a commercial software, but you can simulate this just as well using Oracle’s free VirtualBox.

virtual lab topology


I created two virtual machines that were both running Xubuntu 13.10. One was simulating to be an internal web server and the other a developer machine. The internal web server was given the hostname “Xubuntu-web” and the IP address on a host-only virtual network. The developer machine was given the hostname “Xubuntu-dev” and the IP address on the same host-only network.

On Xubuntu-web the packages “openssh-server” and “apache2” were installed by using the command:

sudo apt-get install openssh-server apache2

 On Xubuntu-dev the packages “openssh-server” and “vsftpd” were installed by using the command:

sudo apt-get install openssh-server vsftpd

Before making any configuration changes, let’s make sure that everything is set up and working as it is supposed to. The image below shows that the two virtual machines were able to communicate on the network.

ping results

Xubuntu-web had an SSH server and a web server running (port 22 and port 80), and Xubuntu-dev had an FTP server and an SSH server running (port 21 and port 22), as shown in the image below.

running services

Finally, the three images below show that Xubuntu-web can access Xubuntu-dev’s FTP and SSH services, and Xubuntu-dev can access Xubuntu-web’s SSH and HTTP services.

web can ftp and ssh to dev

dev can ssh to web

dev can http to web


Now that the two Xubuntu boxes have some services running and can communicate with each other, it’s time to start restricting access using IPtables. Let’s say that we want to implement the following security restrictions:

  • The intranet website should only be accessible from the internal network
  • The intranet server’s SSH service should only be accessible from the developer machine
  • The intranet server should not be able to use FTP or SSH services
  • The developer machine’s SSH service should be accessible from anywhere
  • The developer machine’s FTP service should only be accessible from the internal network

The syntax for implementing the first rule is this:

Sudo iptables –A INPUT –source –p tcp –dport 80 –j ACCEPT

The breakdown of this command is as follows:

iptables                The command to configure the iptables firewall

-A                          Indicates that we will append a rule to the end of rule list

INPUT                  Indicates that this rule will be for incoming traffic

–source <ip>      The rule will apply to traffic originating from the designated address or range

-p <protocol>      The rule will apply to traffic matching the protocol

–dport  <port>   The rule will apply to traffic destined for the designated port

-j ACCEPT             Any traffic matching the rule will be accepted

Of course all the elements in this command can be changed based on what the rule is supposed to do or where it is supposed to fit in the rule list. For instance, instead of ‘-A’ to append a rule at the end of the list you can use ‘-I’ to insert a rule at a specific location, or ‘-D’ to delete a rule from the list. Instead of ‘-j ACCEPT’ you can use ‘-j REJECT’ to reject any traffic that matches the rule. To learn more about the syntax for IPtable rules and the different flags, I recommend the IPtable man pages, or otherwise this website.

While you are configuring your firewall or when you are done you can look at your rule list with this command:

Sudo iptables –L –n

The ‘-L’ flag displays the rule list, and the ‘-n’ flag enables numeric output. By default, IPtables will try to display output as hostnames, network names, or services. Using the ‘-n’ flag will speed up the output.

The rest of the firewall rules were implemented as shown in the images below.

firewall rules

From those images you might notice that I also added some rules that weren’t in the restriction requirements. For instance, the first rule in both lists allows incoming ICMP traffic from anywhere. This was purely done for testing purposes – so that I could make sure that a service is unavailable because the firewall is blocking it, not because the host cannot be contacted. In a production environment, this rule would likely not be implemented for security reasons. The second rule in both lists allows network traffic belonging to an established or related session. This means that any traffic coming back to a host that is part of, or related to, a session that the host originally established is allowed. Finally, the last rule in both incoming lists rejects all traffic other than what was explicitly allowed.


So now that the firewalls are up, let’s test them. Two additional virtual machines were used for the testing: A Windows XP box on the internal network, and a Kali Linux box on the external network (see the topology near the top of this blog post). The tests should show the following:

  • The intranet site should be accessible by all except Kali
  • The intranet server’s SSH service should only be accessible by the developer machine
  • The developer machines’ FTP service should be accessible only by Windows XP (because the intranet server is not allowing outgoing FTP or SSH requests)
  • The developer machine’s SSH service should be accessible by all except the intranet server (for the same reason)

First let’s check for the restrictions on access to the Intranet site. Using each virtual machine to open up a web browser and navigate to the Intranet site shows that both the developer machine and Windows XP have no problem reaching the site, but Kali Linux is blocked. This verifies that the site is only reachable from the internal network.

http test

Next we’ll test to make sure that only the developer machine can SSH into the Intranet web server. The developer machine was successfully able to establish an SSH connection with the server, but both Windows XP and Kali Linux are rejected. This verifies that our second restriction objective is met.

ssh to web test

Next we want to test that the developer’s FTP server is only accessible from the intranet. Connecting through Windows XP works just fine, but a connection from Kali Linux is rejected. The Intranet web server would be allowed to connect, but since that host has outbound SSH and FTP connections blocked through its own firewall the connection is rejected.

ftp to dev test

Finally, we want to test that the developer’s SSH service is accessible both from the internal and external network. Indeed, connecting from Windows XP and Kali Linux both leads to a successful SSH session. Again, the Intranet web server would also be allowed had the connection not been blocked by that host’s own firewall.

ssh to dev test

It seems that all desired network restrictions are enforced by the Linux IPtables firewalls. Although the title of this blog post was “Linux IPtables” a large part of the post was dedicated to testing the IPtable rules rather than setting them up. The thing is, setting up rules is easy once you get a hang of the syntax. However, setting them up correctly and verifying that they have been set up correctly is more complicated. The more rules you implement, the more difficult it gets because they tend to interfere with each other. You can’t test a rule from one host and assumes it works correctly. What I really wanted to show in this post was how to logically think through your firewall rules and how to test them from multiple hosts and subnets.

Leave me a comment for feedback!

Leave a Reply

Your email address will not be published.

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

3 × 3 =