A properly configured firewall is one of the most important components in a server security. Iptables is a powerfull firewall tool installed on most Linux distributions and provides packet filtering and network address translation (NAT).
To see the current iptables rules issue the following command:
sudo iptables -nvL
In order to use iptables, you need to have root privileges to make changes. This means you need to log in as root or to use sudo.
If you have Ubuntu installed and you haven't made any changes to the default iptables rules, you should see something like the following:
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
Iptables includes 3 predefined chains in the filter table by default. These default chains are:
- INPUT - All packets destined for the host machine.
- OUTPUT - All packets originating from the host machine.
- FORWARD - All packets neither originating from nor destined for the host machine, but the packets that the host is routing.
Iptables rules are processed in order from top to bottom, once the rule matched criteria no further processing is done. If no matching rule is found, then the default policy of that chain is applied to that packet.
As shown in the output of the
sudo iptables -nvL command, on a Debian\Ubuntu machine the default chain policy for INPUT and FORWARD is set to ACCEPT, which we would set to DENY and add rules to accept traffic on loopback device and certain ports.
Before continuing with this guide, make sure the default chain policy is set to ACCEPT or you can easily lock yourself out of your machine. If the default policy is set DENY run the following command to set the policy to ACCEPT:
sudo iptables -P INPUT ACCEPT
First, we'll flush all existing rules so we can start with clean tables.
sudo iptables -F
Let's start adding some basic rules, we can use the
-A switch to append or
-I switch to prepend a rule to a specific chain.
The first and foremost we have to allow all loopback (lo0) traffic and drop all traffic to 127.0.0.0/8 that doesn't use the lo0 interface:
sudo iptables -A INPUT -i lo -j ACCEPT sudo iptables -A INPUT ! -i lo -d 127.0.0.0/8 -j REJECT
The following rule will accept all established connection
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
The next rule will allow icmp packets also known as ping packets.
sudo iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
By default SSH uses port 22, and we want to allow remote logins
sudo iptables -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
If you have changed the default SSH port, you need to allow traffic from that port. For example, if you have read Initial Ubuntu Server Setup and changed the SSH port to 9922 then issue the following command
sudo iptables -A INPUT -p tcp -m state --state NEW --dport 9922 -j ACCEPT
Now we need to open some specific ports, depending on what applications are running on our machine.
If we have a web server (apache or nginx) running on the default ports 80 and 443, we need to add a rule to the INPUT chain to allow HTTP packets to go through the firewall:
sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
Similar to the above, depending on what applications are running, we need to open some other ports as well. Below are the most common services/applications and their ports:
| Port | Service | |------|---------| | 21 | FTP | | 22 | SSH | | 23 | Telnet | | 25 | SMTP | | 43 | WHOIS | | 53 | DNS | | 80 | HTTP | | 110 | POP3 | | 123 | NTP | | 143 | IMAP | | 161 | SNMP | | 443 | HTTPS | | 465 | SMTPS | | 587 | MSA | | 993 | IMAPS | | 995 | POP3S |
Set the default chain policy for INPUT and FORWARD to DENY
sudo iptables -P INPUT DROP sudo iptables -P FORWARD DROP sudo iptables -P OUTPUT ACCEPT
To delete a rule, use the
-D switch, execute the same commands just replace the
-D. For example to remove the rule for port 443 run:
sudo iptables -D INPUT -p tcp --dport 443 -j ACCEPT
Also we can delete iptables rules by line number, first list the rules by chain number:
sudo iptables -nv -L --line-numbers
And then delete the line you want. For example to remove rule number 7 run:
sudo iptables -D INPUT 7
All rules created with the iptables command are stored in memory and they will be lost when the system reboots. Instead of adding the same rules each time the system reboots, we can save the rules in a file and use that file to load the rules at boot time.
If you are running CentOS, you can save the current rules with the following command:
sudo service iptables save
If you are running Ubuntu, first you need to install the package called
iptables-persistent and then save the rules.
sudo apt-get install iptables-persistent sudo service iptables-persistent save
I just wanted to give a good starting point for building your own firewall rules. There is much more you can do with iptables, but in this article I only covered the basics.