Secure your servers using iptables
iptables is a highly flexible firewall utility built for Linux operating systems. It allows you to define various rules for the incoming and outgoing connections. For example, you could instruct
iptables to only accept connections from specific ports such as 80, 443, and 22, and neglect any other ports.
You can also instruct
iptablesto allow/deny certain ip addresses as well.
The very first thing to do is to install
iptables, on Ubuntu you may run:
sudo apt-get install -y iptables iptables-persistent
iptabels rules will be saved in the RAM, which means they will be lost in the next restart, Fortunately, there is an easy way to persist the rules using the
iptables-persistent package (we’ll see that later in the post).
Understanding the basics
iptables uses the chains concept, the chain contains a set of rules. There are three chains defined by default:
- INPUT: Traffic inbound to the server.
- FORWARD: Traffic forwarded (routed) to other locations.
- OUTPUT: Traffic outbound from the server.
For example, if you want to allow port 80, then you must append a rule in the
INPUT chain instructing
iptables to allow port 80.
Let’s list the rules in all the chains:
sudo iptables -L -v
You should get the following output:
Chain INPUT (policy ACCEPT 9 packets, 636 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 5 packets, 568 bytes) pkts bytes target prot opt in out source destination
The output shows that we have no rules defined for any of the chains.
In addition to chains,
iptables uses two policies to allow/block traffic:
Let me explain policies in a simplified way.
What do you want
iptables to do if the connection doesn’t match any of the existing rules?
For example, if you’ve allowed connections from port 80, 443 and 22, then what would you do if somebody tries to access your server through port 8800?
The default policy is
ACCEPT, which means allowing all the connections that don’t match any of the existing rules. But that’s an insecure behaviour.
Changing the default policy to
DROP allows us to have more control over the connections, so we just accept the ones that we need through the rules.
It’s imperative to avoid what’s so-called self-blocking in
Self-blocking happens when we block the network traffic by adding some rules, but those rules will not be applied to the current established and related incoming/outgoing traffic.
For example, if you change the policy to
DROP without allowing the established connections, then you’ll be kicked out of the server.
Please be aware that if you persist the
iptables rules, then there is no way to connect to the server again.
It’s mandatory to follow the instructions/commands in this post in order.
SSH to your server and run the following commands:
sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT sudo iptables -A OUTPUT -m conntrack --ctstate ESTABLISHED -j ACCEPT
Now, you should be safe, this means that all the established connections remain intact.
Time to create some rules:
sudo iptables -A INPUT -i lo -j ACCEPT sudo iptables -A OUTPUT -o lo -j ACCEPT
This command tells
iptables to accept loopback connections so that the server can send/receive anything from
127.0.0.1/localhost; this is useful if you have some services that reside on the same server; for example, MySQL, Redis, etc.…
By default, MySQL uses
bind-addressflag to know from where it should listen for connections. Read more about
Let’s demystify the commands:
-A INPUT: appends a new rule to the
-i lo: the network interface,
lomeans the loopback network.
-j ACCEPT: accept the connection.
Allowing Specific Ports
Let’s continue defining more rules:
## Accept connections from port 22 (SSH) sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT ## Accept connections from port 80 (HTTP) sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT ## Accept connections from port 443 (HTTPS) sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
This time, we used the
—dport flag to specify a port number, you can also use the
-s flag for ip addresses:
## Block an IP address sudo iptables -A INPUT -s 188.8.131.52 -j DROP
We’ve defined a few rules, perfect, so now, we can safely instruct
iptables to change the default policy to
sudo iptables -A INPUT -j DROP
Persist the rules:
sudo service netfilter-persistent save sudo service netfilter-persistent restart
You can easily flush (remove) all the rules by running the following commands:
sudo iptables -F INPUT sudo iptables -F OUTPUT sudo iptables -F FORWARD
Where to go from here?
If you want to know more about
iptables consider reading the following article:
Iptables Essentials: Common Firewall Rules and Commands | DigitalOcean