In the following article we will show you how you can secure and protect your Ubuntu or Debian based virtual server using a firewall application, called iptables.
What is iptables?
It is is a user space application program that allows a system administrator to configure the tables provided by the Linux kernel firewall (implemented as different Netfilter modules) and the chains and rules it stores.
In order to keep down the number of attempted break-ins and to filter the ports opened on your virtual server, it is necessary to properly configure your firewall.
To make the management of your server’s firewall rules easier, we will provide a simple shell script that will help with the management of the firewall rules. Basically, whenever you need to change your firewall rules, you would use this script to add/remove the desired rule(s).
SET-UP FIREWALL RULES
Before wrapping the rules in a script, let’s split it in sections so you can know the design of the firewall and what rules will be in place.
FLUSH OLD RULES
The firewall rules can be flushed using the following commands:
## iptables --flush ## iptables --delete-chain ## iptables --table nat --flush ## iptables --table nat --delete-chain
DETERMINE SERVICE PORTS
You have to know what services you have exposed to the public so you can set appropriate rules for them. One way to find what services are listening on what ports is to use the netstat
or ss
commands as in:
## netstat -tunlp or ## ss -tunlp
for example, we are using one of our Ubuntu 12.04 LTS virtual servers and the following is the output of the netstat
command:
## netstat -tunlp Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:3306 0.0.0.0:* LISTEN 296/mysqld tcp 0 0 0.0.0.0:587 0.0.0.0:* LISTEN 449/sendmail: MTA: tcp 0 0 0.0.0.0:110 0.0.0.0:* LISTEN 261/dovecot tcp 0 0 0.0.0.0:143 0.0.0.0:* LISTEN 261/dovecot tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 590/apache2 tcp 0 0 209.135.140.77:53 0.0.0.0:* LISTEN 353/named tcp 0 0 127.0.0.1:53 0.0.0.0:* LISTEN 353/named tcp 0 0 0.0.0.0:21 0.0.0.0:* LISTEN 173/vsftpd tcp 0 0 0.0.0.0:5622 0.0.0.0:* LISTEN 630/sshd tcp 0 0 0.0.0.0:25 0.0.0.0:* LISTEN 449/sendmail: MTA: tcp 0 0 127.0.0.1:953 0.0.0.0:* LISTEN 353/named tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 590/apache2 tcp 0 0 0.0.0.0:993 0.0.0.0:* LISTEN 261/dovecot tcp 0 0 0.0.0.0:995 0.0.0.0:* LISTEN 261/dovecot udp 0 0 209.135.140.77:53 0.0.0.0:* 353/named udp 0 0 127.0.0.1:53 0.0.0.0:* 353/named
so this means that we have the following ports opened to the public:
- 25 (smtp)
- 587 (smtp submission)
- 110 (pop3)
- 143 (imap)
- 993 (imap ssl)
- 995 (pop3 ssl)
- 80 (http)
- 443 (https)
- 53 (dns)
- 21 (ftp)
- 5622 (ssh)
SET-UP DEFAULT POLICIES
ok, so now we can set-up our firewall’s policies to DROP everything in the INPUT and FORWARD chains and allow traffic in the OUTPUT chain.
the default table filter
contains three built-in chain:
- Inbound traffic addressed to the machine itself hits the INPUT chain.
- Outbound, locally-generated traffic hits the OUTPUT chain.
- Routed traffic which should not be delivered locally hits the FORWARD chain.
check man 8 iptables
for more information on this
default policies can be applied using the following commands:
## iptables -P INPUT DROP # <- do not run this over ssh as it will lock you out ## iptables -P FORWARD DROP ## iptables -P OUTPUT ACCEPT
SET-UP FIREWALL RULES
Next thing to do is to actually set-up the firewall rules for our services. As the INPUT chain is DROPPED, we will need to white-list the services which are listening on public ports, so:
the first thing is to enable free use of the loopback interfaces
, to ensure all TCP sessions should begin with SYN and to allow established and related packets:
## iptables -A INPUT -i lo -j ACCEPT ## iptables -A OUTPUT -o lo -j ACCEPT ## iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP ## iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
next, let’s open our service ports by using firewall rules like:
### SSH ## iptables -A INPUT -p tcp --dport 5622 -m state --state NEW -j ACCEPT ### HTTP ## iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT ### SMTP ## iptables -A INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT
and so on. Once all the services are white-listed, it is a good idea to allow ICMP packets and to LOG and DROP everything else in the INPUT chain.
## iptables -A INPUT -p ICMP --icmp-type 8 -j ACCEPT ## iptables -A INPUT -j LOG ## iptables -A INPUT -j DROP
SAVE/RESTORE THE FIREWALL RULES
Firewall rules are not persistent by default, which means they will be lost if you reboot your virtual server for example. To save your current firewall in /etc/fwall.rules
you would use something like:
## iptables-save > /etc/fwall.rules
and to restore the saved rules, you would use something like:
## iptables-restore -c /etc/fwall.rules
to make the rules automatically restored on system start-up, you would either have to use a package named iptables-persistent
or you can simply create a script in /etc/network/if-pre-up.d
which will load the rules saved in /etc/fwall.rules
, for example:
## vim /etc/network/if-pre-up.d/iptables #!/bin/bash test -e /etc/fwall.rules && iptables-restore -c /etc/fwall.rules ## chmod +x /etc/network/if-pre-up.d/iptables
FIREWALL SCRIPT
save the script in /usr/local/bin/fwall-rules
and make it executable
#!/bin/bash IPTABLES=/sbin/iptables echo " * flushing old rules" ${IPTABLES} --flush ${IPTABLES} --delete-chain ${IPTABLES} --table nat --flush ${IPTABLES} --table nat --delete-chain echo " * setting default policies" ${IPTABLES} -P INPUT DROP ${IPTABLES} -P FORWARD DROP ${IPTABLES} -P OUTPUT ACCEPT echo " * allowing loopback devices" ${IPTABLES} -A INPUT -i lo -j ACCEPT ${IPTABLES} -A OUTPUT -o lo -j ACCEPT ${IPTABLES} -A INPUT -p tcp ! --syn -m state --state NEW -j DROP ${IPTABLES} -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT ## BLOCK ABUSING IPs HERE ## #echo " * BLACKLIST" #${IPTABLES} -A INPUT -s _ABUSIVE_IP_ -j DROP #${IPTABLES} -A INPUT -s _ABUSIVE_IP2_ -j DROP echo " * allowing ssh on port 5622" ${IPTABLES} -A INPUT -p tcp --dport 5622 -m state --state NEW -j ACCEPT echo " * allowing ftp on port 21" ${IPTABLES} -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT echo " * allowing dns on port 53 udp" ${IPTABLES} -A INPUT -p udp -m udp --dport 53 -j ACCEPT echo " * allowing dns on port 53 tcp" ${IPTABLES} -A INPUT -p tcp -m tcp --dport 53 -j ACCEPT echo " * allowing http on port 80" ${IPTABLES} -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT echo " * allowing https on port 443" ${IPTABLES} -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT echo " * allowing smtp on port 25" ${IPTABLES} -A INPUT -p tcp -m state --state NEW -m tcp --dport 25 -j ACCEPT echo " * allowing submission on port 587" ${IPTABLES} -A INPUT -p tcp -m state --state NEW -m tcp --dport 587 -j ACCEPT echo " * allowing imaps on port 993" ${IPTABLES} -A INPUT -p tcp -m state --state NEW -m tcp --dport 993 -j ACCEPT echo " * allowing pop3s on port 995" ${IPTABLES} -A INPUT -p tcp -m state --state NEW -m tcp --dport 995 -j ACCEPT echo " * allowing imap on port 143" ${IPTABLES} -A INPUT -p tcp -m state --state NEW -m tcp --dport 143 -j ACCEPT echo " * allowing pop3 on port 110" ${IPTABLES} -A INPUT -p tcp -m state --state NEW -m tcp --dport 110 -j ACCEPT echo " * allowing ping responses" ${IPTABLES} -A INPUT -p ICMP --icmp-type 8 -j ACCEPT # DROP everything else and Log it ${IPTABLES} -A INPUT -j LOG ${IPTABLES} -A INPUT -j DROP # # Save settings # echo " * SAVING RULES" if [[ -d /etc/network/if-pre-up.d ]]; then if [[ ! -f /etc/network/if-pre-up.d/iptables ]]; then echo -e "#!/bin/bash" > /etc/network/if-pre-up.d/iptables echo -e "test -e /etc/iptables.rules && iptables-restore -c /etc/iptables.rules" >> /etc/network/if-pre-up.d/iptables chmod +x /etc/network/if-pre-up.d/iptables fi fi iptables-save > /etc/fwall.rules iptables-restore -c /etc/fwall.rules
## chmod +x /usr/local/bin/fwall-rules
to activate the rules you’ve prepared in the script, just execute
## fwall-rules
from the command line. To add or remove a rule, you just need to to open the script, add or remove your desired rule, save and run it again, for example:
## fwall-rules * flushing old rules * setting default policies * allowing loopback devices * allowing ssh on port 5622 * allowing ftp on port 21 * allowing dns on port 53 udp * allowing dns on port 53 tcp * allowing http on port 80 * allowing https on port 443 * allowing smtp on port 25 * allowing submission on port 587 * allowing imaps on port 993 * allowing pop3s on port 995 * allowing imap on port 143 * allowing pop3 on port 110 * allowing ping responses * SAVING RULES
Of course you don’t have to do any of this if you use one of our Linux VPS hosting services, in which case you can simply ask our expert linux admins to do this for you. They are available 24×7 and will take care of your request immediately.
PS. If you liked this post please share it with your friends on the social networks using the buttons on the left or simply leave a reply below. Thanks.
Do you know any options to use now that “state” isn’t available any longer under ubuntu 14.04?
I cannot access or install conntrack there I ain’t got no kernel access and state isn’t available any longer for iptables.
So what do?
Fucking Linux. Now I remember why I moved to BSD…