Blacklist met iptables

inleiding firewallInleiding

Mijn vriendin heeft een website: HappyMinds. Ik host die site voor haar – net als deze site – op een desktop pc waar ik CentOS 5 op heb staan. En zeg nou zelf… wat is er nu leuker als je net je eigen website hebt dan de bezoeker stats in de gaten houden? Dat doen we allemaal toch. Tussen het schrijven van haar blogs en de stats heeft ze heel veel plezier aan die site. Er was in het begin een issue met bezoekende russen, maar dat heeft zich allemaal opgelost.

Tot er op een dag een script kiddie voorbij komt die eens gaat kijken of hij in kan breken in die site. Zelf negeer ik dat soort dingen. Zorg dat de software up to date is, de wachtwoorden redelijk sterk zijn, enz. Maar je hebt wel gelijk enkele duizenden page views daar waar het er eerst tientallen waren. Dit heeft een vernietigend effect op de statistieken.

Zelf besteedde ik er nog niet eens zoveel aandacht aan. Maar het liet mijn vriendin niet los. Dus ik krijg een paar dagen terug een screenshot in de app met de mededeling dat het ip hupeldepup was en dat die een bekende hacker is, kijk maar op de screenshot. En verdomd, ze had een website gevonden (http://www.abuseipdb.com) met ip nummers van bekende abuser. Zoiets als een dnsbl voor spam, maar dan voor script kiddies.

Inspiratie PicassoHet idee

En dit gaf me inspiratie genoeg om eens wat te doen aan dat tuig. Ik bedacht dat ik bij een verbindingspoging het ip nummer kon checken bij abuseipdb en dan toevoegen aan een ipset blacklist dan wel whitelist. Een firewall met een ipset blacklist. Zeg maar een dynamisch filter voor een website, en misschien wel meer. Bezwaar van deze methode is de load voor de abuseipdb site. Ze beperken API gebruikers tot 2500 requests per maand. En daar heb ik wel begrip voor.

Iets anders nodig dus.

De mensen van http://openbl.org onderhouden een netwerk van honeypots. Het resultaat van deze honeypots publiceren ze in een aantal tekst bestanden die je kunt downloaden.  Gewoon simpelweg 1 ip nummer per regel. Ik moest dus iets maken wat periodiek dit bestand download en toevoegt aan een ipset.

verdedigingDe uitvoering

Dat is dit bash script geworden. Uitleg staat in het commentaar:
(Nee, ik ga hier geen cursus scripten geven :D)

#! /bin/bash

# make_blacklist
# load the blacklist for an iptables based firewall
# Written by Peter Kaagman <prjv.kaagman@gmail.com>;
# version 1.0.0 20150218

# Set the path so you which executable you run
# being paranoid?
PATH=/usr/bin:/usr/sbin:/sbin:/bin
# The url for the list at openbl
url=http://www.openbl.org/lists/base.txt

function load_blacklist {
 #
 # Load the blacklist in a copy list
 ipset destroy blacklist2 >& /dev/null # destroy is if needed
 ipset create blacklist2 hash:ip # (re)create it
 #
 # Download the new list
 # and itterate it
 for ip in `wget -q $url -O -|grep -v ^#`; do
   # add the ip to the newly created blacklist2
   ipset add blacklist2 $ip
 done
 #
 # Swap this list with the excisting one
 # The list blacklist should be created by you iptables script
 ipset swap blacklist blacklist2
 #
 # Remove blacklist2
 ipset destroy blacklist2
}

#echo Creating blacklist
load_blacklist

Het gebruik van ipset vereist dat je dit script uitvoerd als root. Je maakt namelijk met ipset een tabel aan in kernel space. Zo noemen ze dat geloof ik. Lees de manpage van ipset er maar op na.

Het script gaat er vanuit dat de ipset tabel al bestaat. Die moet aangemaakt zijn door je firewall script. Zonder (iptables) firewall heb je trouwens erg weinig aan de ipset lijst die het script maakt. Iptables is het eigenlijke filter, de ipset lijst de referentie bron.

De volgende stap is dan ook het maken van een firewall script, of inpassen in je bestaande script. Ik heb in het verleden wel firewalls “from scratch” gemaakt. Maar ik ben dit keer gaan googlen en heb iets gevonden wat me aanstaat op de site https://tty1.net. Dank je wel Thomas Pircher.

Ik zal niet Thomas zijn complete script hier plaatsen, maar beperk me tot de delen die ik aangepast heb. De plaats waar ik mijn code toevoeg is direct na het instellen van de default policies. Ik wil graag dat ip nummers die in de blacklist staan zo snel mogelijk gedropped worden. Ik heb de filter regels ook niet beperkt tot de poorten 80 en 443 (http en https). Het zijn abusers, ze hebben dus ook niets te zoeken op anderen diensten – zoals ssh – die actief zijn op mijn server.

# default policy
$iptables -P INPUT   DROP
$iptables -P FORWARD DROP
$iptables -P OUTPUT  DROP

# drop blacklist
# first create the ipset blacklist
# make_blacklist assumes it excists
$ipset create blacklist hash:ip >& /dev/null
# no network at the moment,
# so we load the list later on

# log on match
$iptables -A INPUT
          -m set --match-set blacklist src
          -p TCP 
          -j LOG --log-prefix 'BlackListed'
# and drop on match
$iptables -A INPUT
          -m set --match-set blacklist src
          -p TCP 
          -j DROP

# drop broadcast (do not log)
$iptables -A INPUT 
          -i $int_if
          -d 255.255.255.255
          -j DROP

Direct na het instellen van de default policies (drop) is er uiteraard nog geen netwerkverkeer mogelijk. Het laden van de lijst moet daarom als laatste gedaan worden.

## log all the rest before dropping
#$iptables -A INPUT   -j LOG --log-prefix 'IN '
$iptables -A INPUT   -j REJECT --reject-with icmp-port-unreachable
#$iptables -A OUTPUT  -j LOG --log-prefix 'OU '
$iptables -A OUTPUT  -j REJECT --reject-with icmp-port-unreachable
#$iptables -A FORWARD -j LOG --log-prefix 'FW '
$iptables -A FORWARD -j REJECT --reject-with icmp-port-unreachable

# firewall loaded, so let load the blacklist
$make_blacklist

Zoals je kunt zien laad ik de lijst vlak na het logging blok. Wat is uit gecomment trouwens. $make_blacklist en $iptables zijn variabelen met als waarde de plek van de executable/script. Dat is een techniek die je wel vaker ziet, het verhoogt de portabiliteit van het script omdat je dergelijke toewijzingen op een centrale plek maar één keer hoeft te doen:

iptables=/sbin/iptables
ipset=/sbin/ipset
make_blacklist=/home/pkn/make_blacklist.sh
int_if=eth0                     # internal (local) interface, e.g. eth0
int_ip=192.168.178.2            # internal (local) IP, e.g. 192.168.1.94

Zoals je ziet staat “make_blacklist” in mijn home directory. Zou ik die willen verplaatsen dan hoef ik daarna alleen maar die variabele toewijzing te veranderen.

centos rebootOverleef een reboot

Goed… ik heb nu dus een script om die blacklist te laden, en dat script wordt aangeroepen bij het laden van de firewall. Voor het mooie wil ik nu nog 2 dingen voor elkaar krijgen:

  • de firewall moet persistent zijn: ook actief zijn na een reboot
  • de blacklist moet periodiek ververst worden

Voor beide problemen zijn er standaard oplossingen.  Voor wat betreft de firewall heeft CentOS – wat ik op dit systeem gebruik –  een standaard oplossing. In kende deze oplossing vooraf niet, maar een 3 minuten google leverde een pagina van http://xmodula.com op. Daar staat een duidelijke uitleg over het hoe en wat, maar het komt op het volgende neer. Ik moet een script maken in /etc/sysconfig/network-scripts met de naam ifup-local. Dit script zal vervolgens aangeroepen worden door ipup-post wat in dezelfde directory staat. Ik heb het script de volgende inhoud gegeven:

#!/bin/sh
if [[ "$1" == "eth0" ]]
then
  echo "this part will be executed right after eth0 is up."
  echo "so you can put any startup command for eth0 here"
  /home/pkn/firewall.sh start
else
  #DO_NOTHING
fi

Vergeet niet het script executable te maken (sudo chmod +x /etc/sysconfig/network-scripts/ifup-local).

Als laatste het up to date houden van de blacklist. Bij het laden van de firewall wordt dit script al aangeroepen. Daar geen probleem dus. Maar het servertje blijft weken, zo niet maanden online. Of eigenlijk: de interface blijft online.  Maar er is niets op tegen om het script om de blacklist te maken periodiek aan te roepen. Cron is hiervoor uitermate geschikt. De moderne distro’s zijn voorbereid voor dergelijke jobs met directories /etc/cron.daily, /etc/crond.weekly enz. Ik heb ervoor gekozen de blacklist dagelijk te verversen. Nu kan je ervoor kiezen om het script te kopiëren naar /etc/cron.daily, maar dat is niet handig. Je loopt dan risico meerdere versies te krijgen bij aanpassingen. Handiger is het om een symbolic link te maken. Dit heb ik als volgt gedaan:

sudo ln -s /home/pkn/make_blacklist.sh /etc/cron.daily/make_blacklist

De naam van de symbolic link heb ik zonder de extensie .sh gemaakt. Dit omdat sommige setups van crond geen bestanden uitvoeren met extensies. Om problemen te voorkomen laat ik de extensie dus altijd weg.

virus protectie condoomHoe nu verder

Deze setup draait nu al een tijdje bij mij. Mijn BlackList deel houdt verkeer tegen, maar ik zie ook dat andere delen van Thomas zijn firewall hun werk doen. Veel ssh verbindingspogingen worden nu bij de voordeur tegengehouden. Is dit perfect dan? Nee natuurlijk niet! Ik zit al te denken aan wat aanvullingen:

  • analyse van  /var/log/secure en daaruit zelf abusers halen die er nog door komen
  • het toch betrekken van de abuseipdb api in de huidige opzet met een black en whitelist

En waarschijnlijk komt er na verloop van tijd nog wel iets anders bij me op. Wie weet… misschien vanuit de feedback op dit artikel.

reflectieReflectie

Ik had dit artikel een dag gepost en wat denk je? 51.000 Hits op de wp-login URL van een ip nummer wat in geen enkele blacklist te vinden is. Oftewel ik loop achter de feiten aan.

Ik had al eerder in dit artikel de anologie getrokken met e-mail. Deze manier van toegang filteren lijkt erg veel op het gebruik van één of meerdere dnsbl’s in je sendmail configuratie. Het heeft zonder meer waarde, maar je moet niet denken dat je dan klaar bent. Voor e-mail heb je bijvoorbeeld SpamAssasin. Nu iets dergelijks verzinnen voor algemeen netwerk verkeer, http, ssh, whatever.

Ik voel een volgend project opkomen 😀

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *

Blacklist met iptables

inleiding firewallInleiding

Mijn vriendin heeft een website: HappyMinds. Ik host die site voor haar – net als deze site – op een desktop pc waar ik CentOS 5 op heb staan. En zeg nou zelf… wat is er nu leuker als je net je eigen website hebt dan de bezoeker stats in de gaten houden? Dat doen we allemaal toch. Tussen het schrijven van haar blogs en de stats heeft ze heel veel plezier aan die site. Er was in het begin een issue met bezoekende russen, maar dat heeft zich allemaal opgelost.

Tot er op een dag een script kiddie voorbij komt die eens gaat kijken of hij in kan breken in die site. Zelf negeer ik dat soort dingen. Zorg dat de software up to date is, de wachtwoorden redelijk sterk zijn, enz. Maar je hebt wel gelijk enkele duizenden page views daar waar het er eerst tientallen waren. Dit heeft een vernietigend effect op de statistieken.
Lees verder Blacklist met iptables

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Verplichte velden zijn gemarkeerd met *