Lokale Firewall für meinen Webserver


Wenn man einen eigenen Webserver betreibt, hat man ganz schnell "Freunde" aus aller Welt. Dagegen hilft leider manchmal nur blocken...

# 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