Centos comes with a powerful firewall called iptables, that gives you very granular control over access to your server.

Iptables is basically a list of of rules that tells the system what connections to accept or reject, and can protect both incoming and outgoing connections on specific ports.

Set up an Escape Route

Before you do anything with iptables, make sure you give yourself an escape route. It’s super easy to make a mistake and lock yourself out of your own machine (in fact, I just did that to myself a few minutes ago and had to contact my hosting provider to ask them to turn off the iptables service so I could ssh back into my dedicated server).

Your escape route in this case is a cron job that turns off the iptables service every 10 minutes. That gives you plenty of time to set up and test your firewall rules, but resets them in 10 minutes so you can get back in if you messed anything up.

crontab -e

 

Running crontab -e opens the cron job editor in vim. Type a lowercase i to enter into edit mode, and the add this line:

0-59/10 * * * * /sbin/service iptables stop > /dev/null

Hit the esc key to get out of insert mode, and then type Shift+: to get a command prompt, and type wq to write and quit the cronjob editor. This saves your cron task and gives you 10 minutes to configure and test your firewall before it turns the firewall off.

Configure the Firewall

Now we’re ready to add the firewall settings by configuring iptables. The first thing we’ll do is clear all existing firewall rules, so we have a clean slate:

iptables -F

 

Then we’ll add rules to allow localhost connectivity, and web traffic on ports 80 and 443 (http and https), ftp on ports 21 and 20, mail (pop3 and imap), and ssh.

iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -p tcp --dport 21 -j ACCEPT
iptables -A OUTPUT -p tcp --sport 20 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 110 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 995 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 143 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT

We’ll also add a few rules to block some common types of server attacks, including blocking null packets (recon packets typically used to try and see how we configured the server and find out weaknesses), blocking syn-flood attacks (where attackers open a new connection, but don’t state what they want and instead just consume system resources) and lastly we will block XMAS packets which are also a type of recon packets.

iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP
iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP

We’ll add one more rule that will allow us to use outgoing connections (ie. ping from VPS or run software updates):

iptables -I INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

Lastly, we’ll allow all outgoing communications and block every other type of incoming connection:

iptables -P OUTPUT ACCEPT
iptables -P INPUT DROP

Save the Firewall Settings

Remember the clock is ticking on our escape route, which will reset our firewall every 10 minutes. Before you save your iptables permanently, make sure you run a quick test by refreshing your website and making sure it’s still serving web pages. You can also try to ssh into the server from a different terminal.

You can also list out all the settings you added, to make sure you didn’t miss any:

iptables -L -n

To save your firewall settings permanently, save them to /etc/sysconfig/iptables and restart the iptables service. Your saved rules will persist even after the server is rebooted.

iptables-save | sudo tee /etc/sysconfig/iptables
service iptables restart

Don’t forget to go back and remove the cronjob you added, by running crontab -e and removing the line you added.