Maab S.
6min Read

The Beginners Guide to iptables

Guide to iptables blog cover

Iptables is a firewall utility in Linux that lets you define granular IP packet filter rules for your server. Using these rules, you can effectively control access to your server. It’s a utility that every Linux administrator should master.

In the following article, we’ll share everything you need to get started with iptables. Let’s begin!

What is iptables and how does it work

Iptables is a command-line interface that lets administrators configure Netfilter, the networking module of the Linux kernel. The packet filtering mechanism of iptables is governed by three entities: tables, chains, and targets.

A table is a collection of chains. Each chain contains a set of packet matching rules that allow you to control how traffic flows in and out of your system. The default table is known as filter. It has three predefined chains:

  • INPUT: For incoming packets.
  • FORWARD: For packets that will be relayed through the server to another destination.
  • OUTPUT: For outgoing packets.

In addition to specifying the matching criterion, a rule also defines a target. A target tells iptables what to do in case a rule is matched. The target value can be:

  • ACCEPT: Let the packet through.
  • DROP: Don’t let the packet through.
  • QUEUE: Used to forward packets to an external program in the user space.
  • RETURN: Stop the processing of the current chain, and send the packet back to the previous chain.
  • A user-defined chain: Let the packet be processed by another chain.

For every incoming and outgoing packet, the iptables engine checks all the predefined and user-defined chains, one by one. When it gets a match, it retrieves the target of the matched rule, and executes it. If a match isn’t found, the default policy of the chain is executed.


Installing iptables on Linux

If you don’t have iptables pre-installed on your system, follow the steps below to install it:

For CentOS:

sudo apt-get update 
sudo apt-get install iptables

For Ubuntu and Debian:

sudo apt-get update 
sudo apt-get install iptables

You can check the status of the currently active iptables configuration using the following command:

sudo iptables -L -v

The -L option lists down all the rules, and -v stands for verbose, which displays detailed information. If you haven’t configured any rules yet, expect an output like this:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in out   source destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in out   source destination

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target     prot opt in out   source destination

As you can see, all the default chains are set to ACCEPT, and don’t contain any rules. This allows all traffic to flow freely in and out of your system. In the following sections, let’s learn to add rules to these chains.


Understanding iptables syntax

When you add a rule to iptables, it gets appended to a chain. Keep the following command-line options in mind while adding rules:

  • -A -> append one or more rules to a chain.
  • -D -> Delete one or more rules from a chain.
  • -F -> Flush a chain, i.e. remove all its rules.
  • -N -> Create a new chain.
  • -i -> Indicates the network interface for which you want to define the rule. E.g. eth0, eth1, lo, docker0 etc.
  • -s -> The source of the packet. You can either specify a hostname or an IP address.
  • -p -> The network protocol of the packet. E.g. tcp, icmp, udp, sctp etc. You can also specify all here, which filters packets of all protocols.
  • --dport -> The destination port. E.g. 8080, 22, 443 etc.
  • -j -> The target value, e.g. ACCEPT, DROP, QUEUE, RETURN, or the name of a user-defined chain.

Putting it all together, you can use the following syntax to append a rule to an existing chain:

sudo iptables -A <chain_name> -i <interface> -p <protocol> -s <source> --dport <port>  -j <target value>

Open traffic on localhost

The first thing you should do is open all traffic on your localhost. This will allow all applications running on your machine to talk to each other and the localhost.

sudo iptables -A INPUT -i lo -j ACCEPT

The above command accepts all traffic destined to the localhost.


Block IPs using iptables

A common use-case of iptables is to block traffic from malicious IPs. The following command will drop all packets coming from 39.25.165.52.

iptables -A INPUT -s 39.25.165.52 -j DROP

You can also block a range of IPs, e.g. the following command will block all traffic from IPs falling within the range 30.25.165.0 – 30.25.165.255.

iptables -A INPUT -s 30.25.165.0/24 -j REJECT

To block outgoing traffic to a specific IP, use the following command:

iptables -A OUTPUT -d 39.25.165.52 -j DROP

The -d flag specifies the destination to block.


Enabling/disabling traffic on an interface

To enable traffic on an interface:

sudo iptables -A INPUT -i <interface> -j ACCEPT

To disable:

sudo iptables -A INPUT -i <interface> -j DROP

Enabling traffic for HTTP, HTTPS, and SSH

To allow remote connections, you should add a rule that allows traffic on the default SSH port, i.e. 22.

sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

If you expect to receive HTTP or HTTPS traffic, use the following commands to open the 80 and 443 ports.

sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT

Opening multiple ports

You can also specify multiple ports in the same rule. For example:

sudo iptables -A INPUT -p tcp  --match multiport --dports 112,143,883,995 -j ACCEPT

Dropping all other traffic by default

It’s considered a best practice to add explicit rules that only allow authorized traffic to pass through the required ports, and drop all other traffic by default. This ensures that only legitimate traffic is allowed into your system.

Once you have defined all the explicit –dport rules, use this command to drop everything else:

sudo iptables -A INPUT -j DROP

Deleting rules

Use the following command to clear your iptables, removing all rules.

sudo iptables -F

To delete a specific rule from a chain, you need to enter the name of the chain, and the rule number. You can get the rule number using this command:

sudo iptables -L OUTPUT –line-numbers

where OUTPUT is the name of the chain. Expect an output like the following:

Chain INPUT (policy ACCEPT)
num  target     prot opt source            destination

1    ACCEPT     all – 192.168.1.3          anywhere
2    ACCEPT     tcp – anywhere             anywhere tcp dpt:https
3    ACCEPT     tcp – anywhere             anywhere tcp dpt:ssh
4    ACCEPT     tcp – anywhere             anywhere tcp dpt:5421
5    ACCEPT     udp – anywhere             anywhere udp dpt:23

If we want to delete rule # 5 from the input chain, we can use this command:

sudo iptables -D INPUT 5

Alternatively, if you want to flush a chain (remove all its rules), you can use:

iptables –flush CUSTOMCHAIN

Replacing rules

If you make a mistake while defining a rule, you can replace it using the -R option. The following command replaces rule # 3 of the INPUT chain.

iptables -R INPUT 3 -s 49.35.155.20 -j ACCEPT

Persisting iptables across restarts

Any changes you make to iptables only get saved in memory. They aren’t written to disk by default. This means that you will have to redefine them on every restart. Fortunately, you can use the following built-in utility to persist your iptables configurations across restarts.

sudo /sbin/iptables-save

Make sure to run the above command each time you change something in your iptables.


The Author

Maab S.

Maab is an experienced software engineer who specializes in explaining technical topics to a wider audience.

More posts from Maab