How to set up a firewall with IPTables on Ubuntu and CentOS

In this article, we are going to show you how to configure a firewall with Iptables on a Linux VPS running Ubuntu or CentOS as the operating system. Iptables is an administration tool for IPv4 packet filtering and NAT, and is used to create and manage IPv4 packet filtering rule tables in the Linux kernel.

Setting up and configuring your firewall correctly is one of the most important things you should do to secure your server.

In IPTables, several different packet mapping tables are defined, and each table can contain several built-in nets as well as some user-defined chains. Chains are actually lists of rules that match a set of packets, and each rule determines what to do with the matched packet.

The default table is the table filter and contains embedded circuits INPUT, FORWARD, and OUTPUT… The INPUT chain is used for packets destined for local sockets, the FORWARD chain is used for packets routed over the local socket, and the OUTPUT chain is used for locally generated packets.

Connect to the server via SSH and open the list of rules defined on a particular chain using the following syntax:

sudo iptables -L CHAIN

Replace Chain with one of the built-in chains to see the specific rules. If no nets are selected, all nets in the output will be listed.

sudo iptables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Firewall rules specify what to do with a specific packet if it meets certain criteria, and in case the packet does not match the criteria, the next firewall rule specified in the chain will be considered. This is very important to know when defining firewall rules because you can easily block yourself from your server if you define a rule that accepts packets from your local IP after the blocking rule.

Targets that can be used for firewall rules ACCEPT, DROP, QUEUE and RETURNACCEPT will allow the packet, DROP will drop the packet, QUEUE will forward the packet to user space, and RETURN will stop the batch move along the current chain and resume at the next rule in the previous chain. The default chain policy will determine what to do with a packet if it does not match a specific firewall rule. As you can see in the output of the first command, the default policy for all inline chains is set to ACCEPT. ACCEPT will allow the packet to pass through and has no security whatsoever.

Before adding any specific rules, add the following:

sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

This will prevent connections that have already been created and will not be dropped and the current SSH session will remain active.

Then add rules to allow traffic on the local interface:

sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A OUTPUT -o lo -j ACCEPT

Next, allow SSH access to the server for your local IP address, so only you can access the server:

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

Where your local IP address and 22 is the listening port of your SSH daemon. In case your local IP address changes dynamically, it is better to omit the part -s and use a different method to protect the SSH service from unwanted traffic.

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

Next, allow access to important services like HTTP / HTTPS server:

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

Now list the current rules and check if everything is in order. For detailed output, you can use the following command:

sudo iptables -nvL

If you have other services that you want to allow access, it is best to do so now. Once you’re done, you can set the default policy for the DROP input inline circuit.

sudo iptables -P INPUT DROP

This will result in any packet that does not meet the criteria of the firewall rules. The end result should be similar to the following:

Chain INPUT (policy DROP 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination
    0     0 ACCEPT     all  --  *      *              ctstate RELATED,ESTABLISHED
    0     0 ACCEPT     all  --  lo     *  
    0     0 ACCEPT     tcp  --  *      *              tcp dpt:22
    0     0 ACCEPT     tcp  --  *      *              tcp dpt:80
    0     0 ACCEPT     tcp  --  *      *              tcp dpt:443

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  

However, if you restart the server now, you will lose all the firewall rules that you defined, so it is very important that the rules remain constant.

In case you are using Ubuntu VPS you need to install an additional package for this purpose. Go ahead and install the required package with the following command:

sudo apt-get install iptables-persistent

On Ubutnu 14.04 you can save and reload firewall rules using below commands:

sudo /etc/init.d/iptables-persistent save
sudo /etc/init.d/iptables-persistent reload

On Ubuntu 16.04 use the following commands instead:

sudo netfilter-persistent save
sudo netfilter-persistent reload

If you are using CentOS VPS, you can save your firewall rules with below command:

service iptables save

PS … If you liked this post, you can share it with your friends on social networks using the buttons below or just leave a comment in the comments section.