Introduction to iptables

Protect your server with this powerful firewall thanks to basic and easy to understand rules.

Introduction

iptables is a powerful tool that every system administrator should know and use. But as a web developer, it is sometimes difficult to take advantage of all the functionalities that this huge firewall offers.

The following is an example of a restrictive and useful iptables configuration, in which we will close all ports and open the necessary ones according to our personal needs.

The first thing to do is to specify what kind of rules we are going to add. This is done by marking the start and end:

*filter

# Here are our rules

COMMIT

Basic rules

We will use a restrictive policy where we will close all ports by default:

-P INPUT DROP
-P OUTPUT DROP
-P FORWARD DROP

If a connection already got permission to interact with our machine, we let it continue to have them:

-A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
-A OUTPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

We also allow loopback connections from our machine:

-A INPUT -i lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT

And finally we configure the logging system:

-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A OUTPUT -j LOG --log-prefix "[Output Log] "

Common rules

The rules are fairly simple: specify the protocol, the port and include INPUT if you want incoming connections and/or OUTPUT if you want outgoing connections.

For example, if our server runs an HTTP service (Apache, Nginx, etc), we generally want port 80 (HTTP) and 443 (HTTPS) to be accessible from the outside:

-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

And in turn, if we want to browse from our server to the outside (e.g. with lynx or another browser), we will need to create the same rule but this time changing INPUT to OUTPUT:

-A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT

Simple, isn't it? Here is a list of common rules that we might be interested in adding.

SSH

In order to be able to connect via SSH and in turn allow our server to connect via SSH to other servers, we will need to create the INPUT and OUTPUT rules for port 22:

-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 22 -j ACCEPT

DNS

If we want our server to be able to query domain names to other DNS servers, we will need to open port 53:

-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT

And if our server runs a DNS service (e.g. BIND), we will use INPUT:

-A INPUT -p udp -m udp --dport 53 -j ACCEPT

FTP

In the case of the FTP protocol, normally our server will run the FTP service on port 21. We will rarely need to connect from our server to the outside via FTP, so just INPUT:

-A INPUT -p tcp -m tcp --dport 21 -j ACCEPT

Rsync

It is very common to use rsync for backups. In addition, some Linux package managers also use rsync to download packages. For these cases we use the OUTPUT rule for port 873:

-A OUTPUT -p tcp -m tcp --dport 873 -j ACCEPT

Git

The default port for Git is 9418. Since we do not run a Git server on our machine and only need to download software via GitHub, we will use the following:

-A OUTPUT -p tcp -m tcp --dport 9418 -j ACCEPT

Ping

If we want our server to be able to send and receive pings, these are the rules:

-A INPUT -p icmp -j ACCEPT
-A OUTPUT -p icmp -j ACCEPT

Summary

If you want to copy and paste the entire rules file, remember that it is available at articles/introduction-to-iptables/rules.

In the blog repository on GitHub you will find all the content associated with this and other articles.

Customs control

To further limit the port opening and access from a specific IP (for example, to connect only from our desktop computer), just add the parameter -s 12.34.56.78 to the rule in question.

To load the rules in iptables just save these rules in a file and then run iptables-restore < file.

Once we have loaded the rules in iptables, if we want to replace the rules with new ones or if we want to delete the current ones, we must execute a series of commands:

iptables -F
iptables -X
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT

This will remove the existing rules and allow access to everything again.

Be careful!

If we just flush (iptables -F), we will remove the rules but we will be offline, so this is not a good idea.

You can support me so that I can dedicate even more time to writing articles and have resources to create new projects. Thank you!