Iptables firewall and SSH brute-force blocking with fail2ban on Ubuntu server

This is a quick howto to get an iptables firewall setup on Ubuntu server, with fail2ban enabled to block brute-force’d attempts at breaking in over SSH. I’m running this on Ubuntu 10.04 LTS, but it should work similarly on other versions.

Warning! If you get your iptables config wrong, you can end up blocking yourself out of your server, so be careful! Always best to have serial console access to the box just in case…

IPTables rules can be configured one-by-one; you can list the current iptables with:

sudo iptables -L

This should print something like:

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

Chain fail2ban-ssh (0 references)
target     prot opt source               destination

This basically means accept everything, from everyone. Incidentally, if you need to flush (get rid of) all your iptables rules:

iptables -F

Running an iptables command like this:

-A INPUT -i lo -j ACCEPT

will allow (-j ACCEPT) all incoming connections (-A INPUT) on the localhost interface (-i lo). On the other hand, this:

iptables -A INPUT -j DROP

will drop (i.e. reject) everything incoming. What we’d like to end up with is a firewal which allows everything on localhost, allows certain incoming ports on tcp and udp, a host which is always allowed no matter what, and block everything else (whilst also allowing existing connections) – for an iptables rule set which does that for these ports and this host:

Ports to allow
22 – SSH (tcp)
80 – HTTP (tcp)
443 – HTTPS (tcp)
110 – POP3 (tcp)
995 – POP3S (tcp)
1194 – OpenVPN (tcp and udp)

Host to allow:
123.123.123.123

The iptables commands to generate that list are:

sudo iptables -A INPUT -i lo -j ACCEPT
sudo iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 110 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 995 -j ACCEPT
sudo iptables -A INPUT -p tcp -m tcp --dport 1194 -j ACCEPT
sudo iptables -A INPUT -p udp -m udp --dport 1194 -j ACCEPT
sudo iptables -A INPUT -s 123.123.123.123 -j ACCEPT
sudo iptables -A INPUT -j DROP

If you run all of these, then run iptables -L again, you should get something like:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere            state RELATED,ESTABLISHED
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:ssh
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:https
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:www
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:pop3
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:pop3s
ACCEPT     tcp  --  anywhere             anywhere            tcp dpt:openvpn
ACCEPT     udp  --  anywhere             anywhere            udp dpt:openvpn
ACCEPT     all  --  123.123.123.123          anywhere
DROP       all  --  anywhere             anywhere

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

If you’re still connected, then everything’s working ok so far!

Next up, we’d like to get these rules automagically loaded on startup, so we’ll create a save-state for iptables:

sudo iptables-save > /etc/iptables.rules

Now flush your rules, (iptables -F) so we can then restore our rules with:

sudo iptables-restore < /etc/iptables.rules

Running iptables -L again after that should give you the same rules active you had before. HOORAY!

To get this to happen automatically on startup, create a file in /etc/network/if-pre-up.d – everything in this folder gets run automatically on startup just before the network interface is brought online.

#!/bin/sh
# this file is /etc/network/if-pre-up.d/iptables-restore
iptables-restore < /etc/iptables.rules
exit 0

then make sure it's executable! Otherwise, it won't do anything:

sudo chmod a+x /etc/network/if-pre-up.d/iptables-restore

If you reboot now, your box should come back eventually, you should still be able to login, and running iptables -L should give you your list of configured iptables rules.

fail2ban

Fail2ban will help block some ips if they appear to be hammering your server trying to login. It's quite easy to get going on ubuntu:

sudo apt-get install fail2ban

That's pretty much it... just make sure that the /etc/fail2ban/jail.conf file includes the [ssh] section, and that it's enabled. Then, restart the fail2ban daemon:

sudo /etc/init.d/fail2ban restart

then you should now have some extra iptables rules:

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
fail2ban-ssh  tcp  --  anywhere             anywhere            multiport dports ssh
...

And that's that. Your server is now just a little bit more secure 🙂 good luck!


Posted

in

,

by

Tags:

Comments

One response to “Iptables firewall and SSH brute-force blocking with fail2ban on Ubuntu server”

  1. Rana Avatar
    Rana

    Thanks Dude, It Works.. (y)

Leave a Reply to RanaCancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.