---
title: Introduction to iptables
description: Protect your server with this powerful firewall thanks to basic and easy to understand rules.
url: https://www.felixsanz.dev/articles/introduction-to-iptables
language: en
published: 2016-07-02
updated: 2016-07-02
tags:
  - linux
  - security
alternate-es: https://www.felixsanz.dev/es/articulos/introduccion-a-iptables
---

# Introduction to iptables

## Introduction

[iptables](https://en.wikipedia.org/wiki/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.

We will write all these rules in a **file** that will be loaded at the end with `iptables-restore`, so don't type them directly into the terminal or you may lock yourself out of the machine.

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 keep that permission:

```
-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](https://github.com/felixsanz/felixsanz_dev/blob/main/articles/introduction-to-iptables/rules).

In the [blog repository](https://github.com/felixsanz/felixsanz_dev) on GitHub you will find all the content associated with this and other articles.

> [!NOTE]
> **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.

> [!WARNING]
> **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.
