If you’re on Linux, you have plenty of options to protect your device. It comes with iptables, a command-line firewall utility that offer flexibility and excellent protection.
However, as it is a command-line utility, it requires a slight learning curve.
So, if you’re a system administrator or a Linux learner, you’re in the right place as we go through the common iptables commands with examples.
What is iptables?
iptables is a software-based Linux built-in firewall. It allows Linux users to create or define policies that directly and indirectly impact internet traffic.
This means you can use iptables to create rules blocking or allowing traffic via the port, source IP address, network interfaces, and more.
Once you define the rules, all traffic needs to go through it. So, for example, for every new connection, iptables will check for any pre-defined rules that match the connection. If it does, it’ll apply the rule to the connection. However, if there aren’t any associated applicable rules, it’ll implement the default rule.
To use iptables, you need to use the following command.
$ iptables -L -n -v
Here, the parameters are as below:
- -L is for listing all rules.
- -n makes the numeric output offer faster performance.
- -v for showing output in detailed format.
Once you run the iptables command without any parameter, it’ll return the following output:
iptables v1.8.7 (nf_tables): no command specified
Try `iptables -h' or 'iptables --help' for more information.
You need to install it if it runs into an error, such as the command “iptables” not found.
To install iptables in your Linux distribution, run the following command.
$ sudo apt-get install iptables
It’ll return the following as it is already pre-installed on my Linux distribution.
#output
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
iptables is already the newest version (1.8.7-1ubuntu5).
iptables set to manually installed.
0 upgraded, 0 newly installed, 0 to remove, and 35 not upgraded.
What is Firewall?
Firewalls are the most basic form of protecting systems, networks, and personal computers. It can be hardware- or software-based, relying on rules to function properly.
Most firewalls are highly customizable, allowing you to create or edit rules. For example, as packets from the internet use ports to get into a system, port-based scanning can help you filter them out. Apart from that, you can also allow or block services by source IP address or network interface.
If you’re using Linux, you get access to built-in iptables. However, you can also use a standalone Linux firewall to aid you in the process of protecting your system.
Why Do You Need iptables to Configure the Firewall?
But why should you use iptables at all? After all, there are good alternative command-line firewall utilities such as ufw and firewalld. Also, you can use standalone Linux firewalls that are simple to use and offer more features.
So, what makes iptables so appealing when configuring a firewall? The reasons to use it include:
- It offers excellent flexibility out of the box. You can set rules at the packet level.
- It is relatively easy to use once you know how it works.
- Block unwanted traffic in a straightforward manner.
- Redirect packets to an alternative IP address.
- Protect your systems against Denial of Service (DoS) attacks.
And much more!
Understanding iptables Architecture And Its Relation to Netfilter
To properly understand iptables, we need to learn about their architecture. First, it’ll give us a clear understanding of different iptables components. Then, once we know about each of them, we can use them to write firewall rules.
And, when we talk about iptables, Netfilter also comes into the picture. You can think of “Netfilter” as a big brother to iptables. It builds on top of iptables and offers a better feature set to manage your firewall. However, it does use iptables as one of the means to achieve excellent firewall capabilities.
Iptables is a command-line interface to Netfilter kernel-level hooks. These hooks can interact with the Linux network stack, which affects packets at the deepest level.
So, what does the iptables architecture look like:
Tables
iptables architecture starts with tables. These tables take care of rules organization. And each table is classified based on the decision type they’re making. In more simple terms, a table simplifies the overall package processing by attaching a specific way to process packages.
The different tables offered by iptables include:
- Filter table: Specifies decision type for packet filtering. In simple terms, it determines if a package should reach its destination or not.
- NAT table: Specifies decision type for address translation. Here, the routing of the packets is determined based on the NAT networks. For example, if a package cannot access NAT, it’ll skip and try to search for a non-NAT network.
- Mangle table: Manages the package’s special processing needs. For example, you can configure it to change the packet’s header information, such as TTL values.
- Raw table: The raw table lets you work diligently with the stateful aspect of the iptables firewall. Using the table, you can route packets based on their “state” before the Linux kernel starts tracking its state. It is primarily used to mark the packets, whether the connection tracking system handles them or not. If a packet is not tracked, it is set to NOTRACK target.
Chains
And, then, we have “chains” within “tables.”
These chains handle deep packet inspection at different stages of their journey. For example, you can inspect them when it reaches a port or a network interface. This way, a decision can be made before the package is released to a system’s process.
Just like tables, you also get different chains. These include:
- PREROUTING chain: Here, rules handle just-arrived packets at the network interface.
- INPUT chain: The rules mentioned in the INPUT chain handle incoming connection behavior. Once done, they’re given to the local process.
- OUTPUT chain: The OUTPUT chain deals with packets that processes produce.
- FORWARD chain: The FORWARD chain manages packets not meant for local systems. It is a carrier for other destined systems, such as a router.
- POSTROUTING chain: Lastly, we have the POSTROUTING chain, which deals with the packets about to leave through the network interface.
Not all chains are available in each table. For example, the FORWARD chain is only available in the mangle, filter, and security table. Similarly, the POSTROUTING chain is available on mangle and nat (SNAT). Only the OUTPUT chain is available in all the tables.
Target
Now, we have a “target.” Once a package arrives, it moves through chains to see which rule description fits best. If it fits the description of a rule, it performs the associated action based on it and then moves it to the target — sealing the packet’s fate.
In many cases, a packet will not fit any description or ruleset. And that’s where the default policy, a target, comes in.
The targets can be ACCEPT, DROP, and REJECT. These are terminating targets that decide the packet’s fate.
- ACCEPT: Accepts the packets.
- DROP: Drops the packet, making it unable for the sender to learn if the system is present or not.
- REJECT: Rejects the packet.
There’re also non-terminating targets which are mainly used to store information about the packet.
Most Common iptables Commands with Examples
Before you jump and start executing the iptables command, make sure:
- You have administrative access to run the commands. If the command fails due to administrative privileges, re-run the command with the
sudo
command in front of it. - The article is not a tutorial on how to configure iptables on Ubuntu.
- We’ll use the iptables command that works with IPv4. If you intend to work with IPv6, you’ll need to use ip6tables instead.
Checking the iptables Status
To check the current iptables status, you need to run the following command.
$ iptables -L -n -v
#output
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
The above output contains a lot of information. However, it also hints at an inactive firewall. That’s because, currently, all chains are set to ACCEPT and have no rules.
You’ll need to start adding rules to activate the firewall.
Adding Rules to the Chain
When you add a rule, it is always appended to the chain. Therefore, you must use the -A (Append) option. The syntax for it is as below:
$ sudo iptables - A
However, when you run it, it’ll return the following:
iptables v1.8.7 (nf_tables): option "-A" requires an argument
Try `iptables -h' or 'iptables --help' for more information.
The arguments that you can use to add rules are:
- – i: It stands for the interface. Here, you can mention the interface you’re adding rules for. It can be ppp0, eth0, and so on.
- – p: It stands for protocol. Here, you mention the rule to use a network protocol to filter packers. For example, you can say ICMP, TCP, UDP, etc. If you want the rule to work across all protocols, mention “all” as the argument value.
- – s: Next comes the source argument, which mentions the source of the traffic (as the IP address or hostname)
- – dport: The dport stands for the destination port, where you mention the port number to which the packet is destined.
- – j: Lastly, we have a TARGET argument where you can mention the TARGET name, ACCEPT, DROP, or RETURN
It is also essential to write the command in the following order:
$ sudo iptables -A <chain-name> -i <interface-name> - p <protocool-name> - s <source> --dport <port no.> -j <target>
Saving Changes to iptables
Once you add a rule, you can save it with iptables -save command.
$ sudo iptables -save
The output is as follows:
nitt@logan99:~$ sudo iptables-save
# Generated by iptables-save v1.8.7 on Sun May 14 13:37:34 2023
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 392 -j REJECT --reject-with icmp-port-unreachable
-A OUTPUT -o lo -j ACCEPT
COMMIT
# Completed on Sun May 14 13:37:34 2023
Persisting Rules Manually
By default, iptables doesn’t save the rules. So, if you restart your computer, it’ll remove all the rules. You’ll need to use the following commands to ensure you don’t have to reconfigure iptables.
For IPv4 rules, write the command:
$ sudo iptables-save > /etc/iptables/rules.v4
And for IPv6 rules, write the command:
$ sudo iptables-save > /etc/iptables/rules.v6
Persisting Rules Automatically
To make rules persist even after a restart, and that too automatically, you’ll need to install the iptables-presistent package.
To do so, run the following command.
$ sudo apt-get install iptables-persistent
It’ll open up the following window. Press enter on <Yes>.
As we’re working with the IPv4 table, it’ll only show IPv4 rules. If you’re working on IPv6, it’ll show the relevant window.
Note: The package only loads your saved iptables rules. So, whenever you change the iptables, you’ll need to save it with the iptables -save command.
Reloading Rules After the Restart
Once the rules are saved, you must restore them with the following command.
$ sudo iptables-restore < /etc/iptables/rules.v4
And
$ sudo iptables-restore < /etc/iptables/rules.v6
Enabling Traffic on Localhost / Enabling Loopback
To enable traffic on Localhost, use the following command:
$ sudo iptables -A INPUT -i lo -j ACCEPT
Here, the lo stands for the loopback interface for all localhost communications.
Similarly, we can allow packets to leave through the loopback interface.
$ sudo iptables -A OUTPUT -o lo -j ACCEPT
To check how it changed the rules, run iptables -L -n -V
#output
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
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
Enabling Traffic on Particular Ports
You can enable traffic to ACCEPT or REJECT on particular ports.
For example, SSL, HTTP, and SSH ports are important for the normal functioning of your apps. You can add rules to the ACCEPT packet through the port numbers to ensure they work as intended.
For SSL, run the following command.
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
For HTTPS, run the following command.
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
For allowing all HTTPS traffic at the eth0 interface.
$ iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
$ iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
For SSH, run the following command.
$ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
And to accept ALL incoming SSH traffic on the eth0 interface, run the following:
$ iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
$ iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
Another example would be to enable port traffic on a specific port for your custom app. Let’s say port 233.
To open up connections on that port, run.
$ sudo iptables -A INPUT -p tcp --dport 233 -j ACCEPT
Similarly, you can also disable connections on a particular port by using the REJECT target option.
Let’s block all connections at port 392.
$ sudo iptables -A INPUT -p tcp --dport 392 -j REJECT
To check, run the iptables -L -n -v command.
#output
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:233
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
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
0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
Delete Existing Rules
To delete existing rules, you’ll need to run the following command.
$ iptables -F
or
$ iptables --flush
Note: If you haven’t saved your rules, then they’re lost forever and cannot be restored using iptables -restore
Delete Rules with Line Numbers
To delete a specific rule, you’ll need to get the list of rules with numbers.
$ sudo iptables -L --line-numbers
#output
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
2 ACCEPT tcp -- anywhere anywhere tcp dpt:http
3 ACCEPT tcp -- anywhere anywhere tcp dpt:https
4 ACCEPT tcp -- anywhere anywhere tcp dpt:233
5 REJECT tcp -- anywhere anywhere tcp dpt:392 reject-with icmp-port-unreachable
Run the following command if you wish to remove rule number 4 for the INPUT chain.
$ sudo iptables -D INPUT 4
And, if you again run the iptables -n -v -L command.
#output
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
Display Only INPUT or OUTPUT Chain Rules
To display only INPUT chain rules, run the following command.
$ sudo iptables -L INPUT -n -v --line-numbers
#ouput
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
2 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
3 0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
4 0 0 REJECT tcp -- * * 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
Similarly, if you want to see only OUTPUT chain rules, run:
$ sudo iptables -L OUTPUT -n -v --line-numbers
#output
Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
num pkts bytes target prot opt in out source destination
1 0 0 ACCEPT all -- * lo 0.0.0.0/0 0.0.0.0/0
Start/Stop/Restart the Firewall
If you’re on RHEL/ Fedora Linux or CentOS, you can start/stop or restart the firewall by running the commands.
$ service iptables stop
$ service iptables start
$ service iptables restart
You can also use the systemctl command.
However, it’ll not work on Ubuntu.
Insert Rules at a Specific Place
If you want to insert rules at a specific position, you must use the following commands.
First, check the rules.
$ sudo iptables -L INPUT -n --line-numbers
#output
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
3 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
4 REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
Run the following command if you want to insert rules between 2 and 3.
$ sudo iptables -I INPUT 3 -s 252.32.1.2 -j DROP
Now, check the updated rules.
#output
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
3 DROP all -- 252.32.1.2 0.0.0.0/0
4 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443
5 REJECT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:392 reject-with icmp-port-unreachable
Block Incoming Traffic but Allow Outgoing Traffic
You’ll need to enter the following command to block all incoming traffic.
$ iptables -P INPUT DROP
$ iptables -P FORWARD DROP
$ iptables -P OUTPUT ACCEPT
$ iptables -A INPUT -m state --state NEW,ESTABLISHED -j ACCEPT
$ iptables -L -v -n
This way, you can ping or download packages but block any unknown incoming traffic.
Block a Particular IP address
To block a specific IP address, run the following command.
$ iptables -A INPUT -s 14.23.59.9 -J DROP
You can also define a variable to store the blocked IP address and then run the command.
BLOCK_THE_IP = “a.b.c.d”
And, then run:
$ iptables -A INPUT -s “BLOCK_THE_IP” -j DROP
Note: Change “a.b.c.d” to your preferred IP address.
Allowing System Pinging From Outside
You can get outside users to ping your server to make your network discoverable.
$ sudo iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
$ sudo iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
Allowing Internal Network to Talk to External Network
Run the following command to allow the internal network (let’s say eth0) to the external network (let’s say eth1).
$ sudo iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
Allow Outbound DNS
To allow DNS connections to your server, run the following command.
$ iptables -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT
$ iptables -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
Allow Rsycn From a Specific Network
If you use the Rsync command and want to enable it over a specific network, run the following command.
iptables -A INPUT -i eth0 -p tcp -s 192.168.101.0/24 --dport 873 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 873 -m state --state ESTABLISHED -j ACCEPT
Block Port
Run the following command to block a specific port and any incoming requests.
iptables -A INPUT -p tcp --dport 80 -j DROP
iptables -A INPUT -i eth1 -p tcp --dport 80 -j DROP
Block Outgoing Traffic to a Particular IP Address
You can block traffic to any IP address by running the following command.
$ host -t a geekflare.com
#output
geekflare.com has an address of 172.66.40.93
To block outgoing traffic to that particular IP address, run the following command.
iptables -A OUTPUT -d 72.66.40.93 -j DROP
Similarly, you can also block social media platforms such as Instagram, Twitter, and Facebook.
Find the social media IP address by running the following command:
$ host -t a social-media-web-adrress.com
For example, for Instagram, it would be:
$ host -t a www.instagram.com
Now, you’ll need to find CIDR for the IP address of that particular social media platform.
$ whois 185.89.219.11 | grep CIDR
Note: You may need to install the whois package by running sudo apt-get install whois
Now, enter the CIDR value in the following way:
$ iptables - A OUTPUT -p tcp -d CIDR-value -j DROP
Note: Make sure to change the CIDR value accordingly.
Allow or Block ICMP Ping Request
To allow or block ICMP ping requests, run the following commands.
$ iptables -A INPUT -p icmp --icmp-type echo-request -j DROP
$ iptables -A INPUT -i eth1 -p icmp --icmp-type echo-request -j DROP
Open a Particular Range of Ports
To open a range of ports, run the following command.
$ iptables -A INPUT -m state --state NEW -m tcp -p tcp --dport 8933: 8500 -j ACCEPT
List NAT Rules
To list NAT rules, run the following command:
$ sudo iptables -t nat -L -n -v
Or
$ sudo iptables -t nat -v -L -n --line-number
Reset Package Counters
To check the current iptables counter:
$ sudo iptables -L -n -v
To reset or clear the counters, run the following:
$ sudo iptables -Z
$ sudo iptables -L -n -v
For only resetting the INPUT chain counter, run:
$ iptables -Z INPUT
To reset a particular rule counter, run the following:
$ iptables -z INPUT RULE-NUMBER
Make sure to change RULE-NUMBER to that particular rule.
Final Words
iptables is a powerful firewall command-line utility. You can configure almost everything related to network resources, packets, interfaces, and particular scenarios.
Also, iptables offers plenty of options. Check out its main page using the man command to get the complete picture.
$ man iptables
$ man ip6tables
Next, check out a network firewall and how it helps stop attacks.