Lokale Firewall für meinen Webserver


Wenn man einen eigenen Webserver betreibt, hat man ganz schnell "Freunde" aus aller Welt. Mit ein paar Zeilen Code ist es dann auf einmal viel ruhiger im Log.

# example configuration file for ferm
#
# requires:
# - ferm: http://ferm.foo-projects.org/
# - ipset: http://ipset.netfilter.org/
# - fail2ban: https://github.com/fail2ban/fail2ban/releases
#
# firewall for a web server with geoblocking and blocking of
# some known malware sites (example!)
# for the ipsets to work, the blacklist.sh script is needed
# restart fail2ban after ferm restart / configuration change!
#
# check http://opendbl.net/ for additional lists.
#
# dj0Nz 2018

@def $HOME = ( 192.168.xxx.yyy );
@def $BROADCAST = ( 192.168.xxx.255 255.255.255.255 );

table filter {
    chain INPUT {
        policy DROP;

        # connection tracking
        mod state state INVALID DROP;
        mod state state (ESTABLISHED RELATED) ACCEPT;

	# include blacklist ipsets
	mod set set dshield src DROP;
	mod set set talos src DROP;
	mod set set tor src DROP;

        # geoblocking ... handle with care ;)
	mod set set geoblock src DROP;

	# respond to ping
        proto icmp icmp-type echo-request ACCEPT;

	# allow ssh connections from home network
        saddr $HOME proto tcp dport 22 {
		LOG log-prefix 'SSH Login: ';
			ACCEPT;
		}

	# allow http from home network
        saddr $HOME proto tcp dport ( 80 443 ) ACCEPT;

	# allow http
	# for the de-set ipset see blacklist.sh
        mod set set de-set src {
		proto tcp dport ( 80 443 ) {
			mod connlimit connlimit-above 50 REJECT;
			mod connlimit connlimit-above 250 connlimit-mask 0 REJECT;
			ACCEPT;
	        }
	}

	# allow local packets
        interface lo ACCEPT;
    }

    chain OUTPUT {
	    policy ACCEPT;
	    mod state state (ESTABLISHED RELATED) ACCEPT;
    }

    chain FORWARD {
        policy DROP;
        mod state state INVALID DROP;
        mod state state (ESTABLISHED RELATED) ACCEPT;
    }
}

Service Unit für ipset:

[Unit]
Description=ipset persistent rules
Before=ferm.service
ConditionFileNotEmpty=/etc/ipset.conf

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/sbin/ipset -exist -file /etc/ipset.conf restore
ExecStop=/sbin/ipset -file /etc/ipset.conf save

[Install]
WantedBy=multi-user.target

Blacklist download Skript:

#!/bin/bash

# create blacklist ipsets to use with
# local firewall input chain
#
# dj0Nz 05/2018

# recreate existing sets
ipset -q create dshield hash:net
ipset -q create talos hash:ip
ipset -q create geoblock hash:net
ipset -q create tor hash:ip
ipset -q create de-set hash:net
ipset flush dshield
ipset flush talos
ipset flush geoblock
ipset flush tor
ipset flush de-set

# country list for geoblocking
countries="cn ru kr pk tw sg hk"

# my external ip address
ext_ip=`dig @resolver1.opendns.com A myip.opendns.com +short -4`

# dshield first
input=/tmp/dshield.tmp
output=/tmp/dshield.list

if [ -f $input ]; then
   rm $input
fi
if [ -f $output ]; then
   rm $output
fi

wget -q https://isc.sans.edu/block.txt -O $input
grep '^[0-9]' $input | awk '{print $1"/"$3}' >> $output
while read -r line
do
   ipset add dshield $line
done < $output

# cisco talos
input=/tmp/talos.tmp
wget -q https://talosintelligence.com/documents/ip-blacklist -O $input
while read -r line
do
   ipset add talos $line
done < $input

# geoblocking
input=/tmp/countries.tmp

if [ -f $input ]; then
   rm $input
fi

for country in $countries
do
   if [ -f /tmp/$country.zone ]; then
      rm /tmp/$country.zone
   fi
   wget -q http://www.ipdeny.com/ipblocks/data/countries/$country.zone -O /tmp/$country.zone
   cat /tmp/$country.zone >> $input
done
while read -r line
do
   ipset add geoblock $line
done < $input

# german networks
if [ -f /tmp/de.zone ]; then
   rm /tmp/de.zone
fi
wget -q http://www.ipdeny.com/ipblocks/data/countries/de.zone -O /tmp/de.zone
while read -r line
do
   ipset add de-set $line
done < /tmp/de.zone

# get a list of Tor exit nodes that can access $ext_ip, skip the comments and read line by line
# copied from http://mikhailian.mova.org/node/194
wget -q https://check.torproject.org/cgi-bin/TorBulkExitList.py?ip=$ext_ip -O -|sed '/^#/d' |while read ip
do
  ipset -q -A tor $ip
done

# save for later use (system reboot etc)
ipset save -file /etc/ipset.conf