The Beginners Guide to iptables
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.