How to Setup a Firewall to Secure Your Linux Server
Setting up a firewall is the second thing you should do immediately following the setup of your linux server (the first should be to Secure SSH Login).
I’ve had great success using RackSpace Cloud Servers, they are easy to setup and use (like this one, most of my linux based guides will use a Rackspace Cloud Server as a starting point). I will assume you have your server started and you are ready to begin at the command prompt. This guide uses an Ubuntu 10.04 LucidLynx LTS install, but these steps will work on most other Linux distributions.
Setting Up The Firewall Using Iptables
Here is how to setup a quick firewall using iptables. First lets check if there are any rules currently active:
sudo iptables -L
If there are none, you should see something like the following output:
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
We will be creating two files:
iptables.up.rules. The “test” file will be used when we add new rules and want to test them out first, and the “up” file will be used by iptables to apply rules on server startup.
Creating TEST Rules
The following are a basic set of rules to get you started with your linux server. As you can see I am making a few assumptions, with a few open ports, SSH, Web, FTP, PASV FTP, PING … however, from this rule set you should be able to create your own rules (e.g. like allowing external MySQL, port 3306):
Create/open the file:
sudo vi /etc/iptables.test.rules
Add the following to the file:
*filter :INPUT ACCEPT [0:0] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT -A OUTPUT -m state --state RELATED,ESTABLISHED,NEW -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 21 -m state --state ESTABLISHED,NEW -j ACCEPT -A INPUT -p tcp --dport 20 -m state --state ESTABLISHED -j ACCEPT -A INPUT -p tcp --dport 50000:60000 -m state --state RELATED,ESTABLISHED -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -j DROP COMMIT
Important: Before appying your rules, you should have some way to reboot your server should you lock yourself out with any rules you may have added.
Use the following command to apply your rules:
sudo iptables-restore < /etc/iptables.test.rules
Confirm your rules have been applied, with the following:
sudo iptables -L
If you need to flush/remove your rules, you can run the following command:
sudo iptables -F
Creating UP Rules
iptables.up.rules file will be used to apply rules on server startup. So when you reboot your server, the rules will automatically get applied.
Note: This file should always have known “working” rules.
If the rules in the
iptables.test.rules file are working as you expected, we begin by saving them to the “up” rules file, like so:
sudo iptables-save > /etc/iptables.up.rules
When ever you make changes to default system files, I recommend that you create a backup. The following command will simply create a backup copy of this system file.
sudo cp /etc/network/interfaces /etc/network/interfaces.bak
Open the file:
sudo vi /etc/network/interfaces
Find the following line:
iface lo inet loopback
Below the line add the following command, it should look like so:
iface lo inet loopback pre-up iptables-restore < /etc/iptables.up.rules
The “pre-up” command should basically be placed after the “lo” interface and before the “eth0″ interface.
To test your “up” file, you should try to reboot your server. Upon start up iptables should apply the files in the “up” file. You can confirm that the rules were applied with the following:
sudo iptables -L
Additional Useful Rules
I like to have external access to the MySQL server, so I can use desktop tools to manage the databases/tables, I will typically give myself access via a firewall rule (e.g. xxx.xxx.xxx.xxx being the IP I am allowing access from):
-A INPUT -p tcp -m tcp --dport 3306 -s xxx.xxx.xxx.xxx -j ACCEPT
Above, I use the port range of 50000:60000 for PASV FTP. Typically the PASV connections are only “RELATED,ESTABLISHED”, however you may run into issues when trying to setup secure FTP access via SSL/TLS, in these cases you may need to adjust to “RELATED,ESTABLISHED,NEW”. For more reading on why this is, see my post at server fault.
-A INPUT -p tcp --dport 50000:60000 -m state --state RELATED,ESTABLISHED,NEW -j ACCEPT
Adding HTTPS/SSL web access:
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
Adding SVN access:
-A INPUT -p tcp -m tcp --dport 3690 -j ACCEPT