pf GeoIP Blocking
Varför?
Ibland ser man konstiga anrop i sina serverloggar, oavsett om det är åtkomstloggar från Apache eller nginx eller meddelanden från t.ex. sshd. Kanske blir man också aktivt attackerad av någon och vill stänga ute den personen, men då kommer det alltid olika IP-adresser. Om man sedan slår upp dem upptäcker man att de alltid kommer från samma land eller till och med samma internetleverantör. Det kan man ta reda på med verktyg som till exempel whois på kommandoraden.
Men kanske vill man bara göra innehållet tillgängligt i vissa länder, vilket också går att åstadkomma med geoblockering.
Det finns olika skäl till varför man vill blockera vissa personer från sin server. Man bör dock alltid tänka på att man inte av misstag blockerar sig själv. Innan du reser till ett av de länder som du blockerar på din server bör du därför låsa upp dig själv (eller använda ett VPN).
Installation
För att överhuvudtaget kunna tilldela IP-adresser till ett land behöver vi en databas som kan tillhandahålla dessa nödvändiga data. I FreeBSD Ports finns paketet ipdbtools. Med detta paket får man några verktyg för att lagra en IP-databas lokalt och hålla den uppdaterad. Uppgifterna kommer från RIR och är alltså identiska med de resultat som till exempel ett whois-sökresultat skulle ge.
För att installera paketet, kör följande kommando:
sudo pkg install ipdbtools
Jag kommer inte att gå in närmare på användningen av de enskilda verktygen som ingår i detta paket, eftersom man-sidorna innehåller tillräckligt med information om detta. Om du vill veta mer kan du hitta informationen i din shell med:
apropos ipdb
Jag uppdaterar min lokala databas regelbundet med hjälp av ett cronjob. För detta har jag skrivit ett litet skript som utför de nödvändiga kommandona. Jag sparar alla data i katalogen /etc/pf-tables/ och skriptet heter geoipblocker.sh:
#!/bin/sh
#Update Database
echo "Last Update:" >/etc/pf-tables/geoipupdate.log
date >> /etc/pf-tables/geoipupdate.log
echo "\n">>/etc/pf-tables/geoipupdate.log
ipdb-update.sh >> /etc/pf-tables/geoipupdate.log 2>&1
# Write IP addresses to file, followed by -t and the respective countries.
# For new countries, simply add a line
ipup -t RU -p > /etc/pf-tables/geoipblocker.table
ipup -t CN -p >> /etc/pf-tables/geoipblocker.table
ipup -t MN -p >> /etc/pf-tables/geoipblocker.table
# Load the file into a pf table
pfctl -t geoipblocker -T replace -f /etc/pf-tables/geoipblocker.table >> /etc/pf-tables/geoipupdate.log 2>&1
Nu måste vi anpassa våra brandväggsregler. Alla har olika många saker redan angivna här. Om filen fortfarande är tom rekommenderar jag att du först gör en grundläggande konfiguration och sedan kompletterar den.
Följande måste sedan läggas till i /etc/pf.conf:
# Create a table
table <geoipblocker> persist file "/etc/pf-tables/geoipblocker.table"
# block all IPs from the table
block quick on $external_if from <geoipblocker> to any
Kom ihåg att ersätta $external_if med ditt passande gränssnitt eller den passande variabeln. ”Quick” i regeln säkerställer att paket som matchar denna regel inte utvärderas vidare. Om du redan har ställt in port vidarebefordran i din regeluppsättning bör du kontrollera att det inte redan finns ett ”pass” där. Eftersom NAT och omdirigeringar utförs före filtren skulle detta säkerställa att dina interna tjänster fortfarande kan nås från de filtrerade adresserna.
Till exempel skulle följande regel vara problematisk:
rdr pass on $external_if proto tcp to $server_ext_ip port {http,https} -> $internal_server_ip
Istället bör man ta bort passet och utföra godkännandet i en separat regel:
pass in on $external_if proto tcp from any to $server_ext_ip port {http,https}
pass in on $external_if proto tcp from any to $internal_server_ip port {http,https}
Efter att reglerna har lagts till i /ertc/pf.conf måste det tidigare skapade skriptet göras körbart och köras manuellt en gång. Därefter kan man ladda om brandväggen:
chmox +x /etc/pf-tables/geoipblocker.sh
/etc/pf-tables/geoipblocker.sh
pfctl -vf /etc/pf.conf
När skriptet körs uppdateras IP-databasen och adresserna som hör till de valda länderna skrivs till en fil. Skriptet laddar dessa adresser till tabellen geoipblocker. För att dessa adresser också ska laddas när brandväggen startas om definieras tabellen persistent med datafilen i regeluppsättningen.
För att kontrollera om tabellen har laddats korrekt kan du använda följande på kommandoraden:
pfctl -t geoipblocker -T show
Detta bör ge en lång lista med prefix. Om du vill filtrera bör du inte använda grep, eftersom det inte går att söka efter subnät med det. Istället använder du följande kommando för att testa om en adress finns med i tabellen:
pfctl -t geoipblocker -Tt 1.2.3.4
Nu återstår bara att uppdatera IP-uppgifterna regelbundet, vilket vi gör genom att skapa en crontab med crontab -e. Detta öppnar en editor där du kan skriva följande innehåll:
0 3 * * 1 /etc/pf-tables/geoipblocker.sh
Detta säkerställer att uppgifterna uppdateras varje måndag klockan 3 på morgonen.
Slutsats
Med ipdbtools kan man i kombination med pf blockera sitt nätverk för vissa länder. Man bör naturligtvis vara försiktig så att man inte låser ut sig själv, till exempel när man är på semester. De regler som läggs till här fungerar självklart även för IPv6! Eftersom produkter som till exempel pfSense använder pf Firewall fungerar denna inställning även där.