Automating your iptables

Ever wondered how to use iptables on debian, without using any GUI solution? Let me explain how I do it.

Usually I use two files /etc/iptables_secure.sh and /etc/iptables_open.sh. The secure script has firewall enabled, while the open script makes iptables accept all connections. Also, I use /etc/init.d/firewall to start and stop the firewall at boot.

First, start by creating the following three files.

/etc/iptables_secure.sh

#!/bin/sh

IPT="/sbin/iptables"

# Flush old rules, old custom tables
$IPT --flush
$IPT --delete-chain

# Set default policies for all three default chains
$IPT -P INPUT DROP
$IPT -P FORWARD DROP
$IPT -P OUTPUT ACCEPT

# Enable free use of loopback interfaces
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

# All TCP sessions should begin with SYN
# $IPT -A INPUT -p tcp ! --syn -m state --state NEW -s 0.0.0.0/0 -j DROP

# Accept established connections
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

echo "Opening CARP"
$IPT -A INPUT --protocol 112 -j ACCEPT

# Brute force
# Limit the number of ssh connections to 6 per minute
$IPT -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
$IPT -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 6 --rttl --name SSH -j DROP

# Limit the number of ftp connections to 10 per minute
# $IPT -A INPUT -i eth0 -p tcp --dport 21 -m state --state NEW -m recent --set --name FTP
# $IPT -A INPUT -i eth0 -p tcp --dport 21 -m state --state NEW -m recent --update --seconds 60 --hitcount 10 --rttl --name FTP -j DROP

echo "Opening FTP"
$IPT -A INPUT -p tcp --dport 20 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p tcp --dport 21 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p tcp --sport 1024: --dport 1024:  -m state --state ESTABLISHED -j ACCEPT
$IPT -A OUTPUT -p tcp --sport 1024: --dport 1024:  -m state --state ESTABLISHED,RELATED -j ACCEPT


echo "Opening HTTP(S)"
$IPT -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p tcp --dport 443 -m state --state NEW -j ACCEPT

echo "Opening SSH"
$IPT -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT

echo "Opening MySQL"
$IPT -A INPUT -p tcp --dport 3306 -m state --state NEW -j ACCEPT

echo "Opening port 7777 - ocfs2"
$IPT -A INPUT -p tcp --dport 7777 -m state --state NEW -j ACCEPT
$IPT -A INPUT -p udp --dport 7777 -j ACCEPT

echo "Opening NTP"
$IPT -A INPUT -p udp --dport 123 -j ACCEPT
$IPT -A INPUT -p tcp --dport 123 -m state --state NEW -j ACCEPT

# echo "Opening all from same subnet"
# $IPT -A INPUT -p tcp -s 192.168.1.0/24 -m state --state NEW -j ACCEPT

# Accept inbound ICMP messages
echo "Opening ping and traceroute"
$IPT -A INPUT -p ICMP --icmp-type 8 -s 0.0.0.0/0 -j ACCEPT
$IPT -A INPUT -p ICMP --icmp-type 11 -s 0.0.0.0/0 -j ACCEPT

/etc/iptables_open.sh

#!/bin/sh
echo "Opening firewall"
IPT="/sbin/iptables"

# Flush old rules, old custom tables
$IPT --flush
$IPT --delete-chain

# Set default policies for all three default chains
$IPT -P INPUT ACCEPT
$IPT -P FORWARD ACCEPT
$IPT -P OUTPUT ACCEPT

# Enable free use of loopback interfaces
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

/etc/init.d/firewall

#! /bin/sh
### BEGIN INIT INFO
# Provides:          firewall
# Required-Start:     $portmap
# Required-Stop:
# Should-Start:      udev-mtab
# Default-Start:     2
# Default-Stop:      0 6
# Short-Description:
# Description:
### END INIT INFO

. /lib/init/vars.sh
. /lib/lsb/init-functions

case "$1" in
    start)
        sh /etc/iptables_script.sh
        ;;
    restart|reload|force-reload)
        echo "Error: argument '$1' not supported" >&2
        exit 3
        ;;
    stop)
        sh /etc/iptables_open.sh
        ;;
    *)
        echo "Usage: $0 start|stop" >&2
        exit 3
        ;;
esac

Now use chmod to make /etc/init.d/firewall executable.

chmod +x /etc/init.d/firewall

You should now be able to issue /etc/init.d/firewall start and /etc/init.d/firewall stop in order to enable or disable the firewall. Also, in order to make the firewall start at boot time, issue the following command.

update-rc.d firewall defaults

Ask me if there is something you don’t understand!

Virtual hosting with Apache – the good way

There are so many amazingly bad guides to Apache and virtual hosting, so i decided to create a good one. This guide uses Apache2 running om Debian 6. I will not cover installation and stuff. Also, I cut right to the chase.

First, the NameVirtualHost property should just be declared once, and ports.conf is a good place to have it.

/etc/apache2/ports.conf

NameVirtualHost *:80
Listen 80

Second, do not place all virtual hosts in a single file, that’s not very dynamic. Look at this:

# ls /etc/apache2/sites-*
/etc/apache2/sites-available:
total 8
dr-xr-x--- 2 root           www-data     3896 Jun 26 15:33 .
dr-x------ 5 www-data        www-data     3896 Jun  8 13:15 ..
-rwxr-x--- 1 root           www-data     569  Apr 11 21:51 default
-rwxr-x--- 1 root           www-data     569  Apr 19 11:40 sub1.example.org
-rwxr-x--- 1 root           www-data     569  Apr 19 11:41 sub2.example.org
-rwxr-x--- 1 root           www-data     569  Jun 26 15:25 goodworkaround.com

/etc/apache2/sites-enabled:
total 0
dr-xr-x--- 2 www-data  www-data 3896 Jun 26 15:33 .
dr-x------ 5 www-data  www-data 3896 Jun  8 13:15 ..
lrwxrwxrwx 1 root   root  26 Apr 11 21:52 000-default -> ../sites-available/default
lrwxrwxrwx 1 root   root  41 Apr 19 11:49 sub1.example.org -> ../sites-available/sub1.example.org
lrwxrwxrwx 1 root   root  41 Apr 19 11:50 sub2.example.org -> ../sites-available/sub2.example.org
lrwxrwxrwx 1 root   root  37 Jun 26 15:29 goodworkaround.com -> ../sites-available/goodworkaround.com

So what am I doing that no one else is doing? I am symlinking, and I am splitting each domain or subdomain into separate files. Just use place all the domains in the sites-available folder, and symlink it from sites-enabled. This makes it easy to disable sites temporary, by just removing the symlink and reloading apache. Lets take a look one of those files.

/etc/apache2/sites-available/goodworkaround.com

<VirtualHost *:80>
        ServerAdmin webmaster@goodworkaround.com
        ServerName goodworkaround.com
        # ServerAlias www.goodworkaround.com

        DocumentRoot /home/mariussm/websites/goodworkaround.com

        <Directory />
                Options FollowSymLinks
                AllowOverride None
        </Directory>

        <Directory /home/mariussm/websites/goodworkaround.com>
                Options FollowSymLinks MultiViews
                AllowOverride All
                Order allow,deny
                allow from all
        </Directory>

        ErrorLog ${APACHE_LOG_DIR}/goodworkaround.com.error.log

        # Possible values include: debug, info, notice, warn, error, crit,
        # alert, emerg.
        LogLevel warn

        CustomLog ${APACHE_LOG_DIR}/goodworkaround.com.access.log combined

</VirtualHost>

As you can see, it listens on all interfaces (*:80) on port 80, cares only for the hostname goodworkaround.com and has a root folder. So hey, that’s the easy way.