Firewall (iptables) instellen
Let op: als je de server op afstand beheert en je maakt een fout bij het instellen van je firewall loop je het risico dat je niet meer in kunt loggen. Voorzichtig dus.
Het eerste dat je op je nieuwe server moet doen is de firewall instellen. Uitgangspunt is dat je alle verkeer weigert tenzij je zeker weet dat je het nodig hebt. Wil je bijvoorbeeld een webserver draaien dan moet poort 80 open staan. Draai je geen webserver, laat poort 80 dan dicht. Hoe minder poorten er open staan, hoe veiliger je systeem is.
Tables en policies
iptables verdeelt zijn regels in drie tabellen. INPUT voor inkomend verkeer, FORWARD voor verkeer dat doorgestuurd moet naar een ander ip-adres en OUTPUT voor uitgaand verkeer. Per tabel kun je ook een 'policy' instellen. De policy geldt voor verkeer waar geen andere regels ingesteld worden. Om te beginnen gaan we instellen dat FORWARD altijd geweigerd wordt en OUTPUT altijd doorgelaten:
iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT
Inkomend verkeer
Met INPUT moet je even wat voorzichter omgaan, vooral als je de server op afstand beheert. Helemaal aan het eind gaan we bij INPUT ook de 'policy' DROP instellen maar pas nadat we alles open gezet hebben wat open moet staan. Om te voorkomen dat je per ongeluk jezelf buitensluit stel je eerst de regel in waardoor bestaande verbindingen open blijven:
iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
"-A INPUT" betekent toevoegen aan de tabel INPUT. "-m state" betekent dat we gaan vergelijken (matchen) op de status van de verbinding. "--state RELATED,ESTABLISHED" betekent dat we zoeken naar bestaande verbindingen. Tenslotte, "-j ACCEPT" betekent dat deze verbindingen geaccepteerd worden. Deze regel is nodig om er voor te zorgen dat uitgaande verbindingen vanaf je server (bijvoorbeeld een DNS lookup) beantwoordt kunnen worden.
Nu gaan we instellen dat ook alle verbindingen vanaf de computer zelf (localhost) geaccepteerd worden:
iptables -A INPUT -i lo -j ACCEPT
Hier zie je eerst het bekende "-A INPUT" en dan "-i lo". Dat verwijst naar de netwerkinterface localhost. Dan volgt weer "-j ACCEPT".
Vervolgens zetten we poort 22, dat is de poort die nodig is voor ssh toegang. Ik heb zelf de gewoonte om die alleen voor mijn eigen ip-adressen open te zetten. Stel dat mijn ip-adres 10.11.12.13 is, dan is de vereiste opdracht aan iptables:
iptables -A INPUT -p tcp --dport 22 -s 10.11.12.13 -j ACCEPT
Nieuw hier is "-p tcp --dport 22" wat betekent dat iptables deze regel toepast op tcp poort 22. En verder zie je "-s 10.11.12.13" wat aan iptables vertelt dat deze regel alleen geldt voor verkeer van ip-adres 10.11.12.13.
Er zit een evident nadeel aan het op deze manier beveiligen van toegang tot poort 22. Als je ergens op vakantie bent kun je niet zomaar verbinding met je server maken. Ik heb dat opgelost door de ip-adressen van mijn huis en kantoor in iptables te zetten. Als ik vanaf een andere locatie verbinding met de server wil maken, maak ik eerst een VPN verbinding naar huis of kantoor en open dan een terminalsessie naar de server. Het is ook aan te raden toegang van meer dan één ip-adres toe te laten. Je weet nooit of je ip-adres een keer wijzigt.
Nu gaan we voor een aantal poorten verkeer van iedereen accepteren. Bijvoorbeeld, als je een webserver draait wil je poort 80 open hebben voor iedereen:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
Na de voorgaande voorbeelden kun je deze regel lezen. We voegen aan de tabel INPUT toe dat verkeer op poort 80 altijd toegelaten wordt. Welke poorten je open wilt zetten hangt af van wat je doet met je server. Voor inkomende mail heb je poort 25 nodig. Als je mail op wilt halen wil je poorten 443, 465, 587 en 993 open hebben. Op het internet vind je allerlei overzichten van TCP poortnummers. Herhaal de bovenstaande opdracht met alle poorten die jij open moet hebben.
Ik heb er voor gekozen om op mijn server ping alleen toe te staan vanaf bepaalde door mij ingestelde ip-adressen. Dat doe je met de volgende opdracht:
iptables -A INPUT -p icmp -s 10.11.12.13 -j ACCEPT
In ieder geval bechermt je dat tegen 'ping floods'. Als allerlaatste stap stellen we in dat alle overige inkomend verkeer geweigerd wordt:
iptables -P INPUT DROP
Regels opslaan en inladen
Je kunt de ingestelde regels opslaan met twee opdrachten:
mkdir /etc/iptables/ iptables-save > /etc/iptables/myrules
Tenslotte moet je nog instellen dat iptables na een herstart van je systeem de regels ook weer inlaadt. Daarvoor moeten we een klein shell script maken. Start nano met de opdracht:
nano /etc/network/if-up.d/iptables
Voer vervolgens deze regels in:
#!/bin/sh iptables-restore < /etc/iptables/myrules
Sla op met control+o en sluit nano af met control+x. Maak het script nu uitvoerbaar met:
chmod +x /etc/network/if-up.d/iptables
Uiteraard mogen je regels een andere naam hebben dan myrules en mag je ze op een andere plek opslaan dan /etc/iptables.
En dan testen...
Het is belangrijk nu te testen of de regels goed ingesteld zijn en op ze bij herstart van het systeem goed laden. Herstart je server met:
shutdown -r now
Als je de server op afstand beheert zal je ssh verbinding nu afgesloten worden. Tel tot tien en maak een nieuwe ssh verbinding. Vervolgens kijk je wat er nu ingesteld is in de firewall:
iptables -L
Als het goed is zie nu de door jou ingestelde regels. Dat zou er ongeveer zo uit kunnen zien:
Chain INPUT (policy DROP) target prot opt source destination ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED ACCEPT all -- anywhere anywhere ACCEPT tcp -- 10.11.12.13 anywhere tcp dpt:ssh ACCEPT tcp -- 10.11.12.14 anywhere tcp dpt:ssh ACCEPT tcp -- anywhere anywhere tcp dpt:smtp ACCEPT tcp -- anywhere anywhere tcp dpt:www ACCEPT tcp -- anywhere anywhere tcp dpt:https ACCEPT tcp -- anywhere anywhere tcp dpt:ssmtp ACCEPT tcp -- anywhere anywhere tcp dpt:submission ACCEPT tcp -- anywhere anywhere tcp dpt:imaps ACCEPT icmp -- 10.11.12.13 anywhere ACCEPT icmp -- 10.11.12.14 anywhere Chain FORWARD (policy DROP) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
De firewal werkt en na een herstart worden de regels goed ingeladen. Als je de regels wilt zien met nummers van de poorten in plaats van namen zoals smtp doe je:
iptables -L -n
Regel op bepaalde plek invoeren
Met bovenstaande commandos voer je een nieuwe regel steeds aan het eind van het bestand in. Je kunt regels ook op een bepaalde plek invoeren met de -I modifier:
iptables -I INPUT 9 -p tcp --dport 8080 -j ACCEPT
Dit betekent dat de regel over poort 8080 op de negende regel ingevoegd wordt.
Regels (tijdelijk) wissen
Om tijdelijk regels te wissen kun je huidige regels met regelnummers tonen:
iptables -L INPUT -n --line-numbers
11 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:25 12 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80 13 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:443 14 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:465
Je kunt nu de regel met een bepaald nummer, 12 in dit voorbeeld, wissen door:
iptables -D INPUT 12
Dit kan handig zijn, bijvoorbeeld om toegang tot bepaalde poorten te testen. Je kunt atijd weer terug naar je originele set regels met:
iptables-restore < /etc/iptables/myrules
Eén IP-adres blokkeren
Als je in je logfiles merkt dat je vanaf een bepaald ip-adres lastig gevallen wordt kun je via iptables één ip-adres blokkeren. Bijvoorbeeld, om ip-adres 6.7.8.9 te blokkeren:
iptables -I INPUT -s 6.7.8.9 -j DROP
We gebruiken hier de -I
optie om de regel aan het begin van de chain input toe te voegen. Als je er I INPUT 6
van zou maken wordt deze regel als 6e in de tabel INPUT toegevoegd. Zonder getal wordt de nieuwe regel bovenaan ingevoegd. Iptables loopt de regels namelijk op volgorde af en stopt bij de eerste regel die van toepassing is. Je moet het ip-adres dus blokkeren vóór je met andere regels toegang geeft tot, bijvoorbeeld, poort 25.
Let op dat je de regels nu opnieuw op moet slaan, anders is de blokkade verdwenen na een herstart. Overigens kies ik er juist voor om dit soort blokkades niet op te slaan. In de meeste gevallen worden ip-adressen tijdelijk misbruikt en is het dus prima dat ze bij een volgende herstart vrijgegeven worden.
Een reeks ip-adressen blokkeren
Soms wil je een hele reeks ip-adressen blokkeren. Ik blokkeer bijvoorbeeld al het verkeer een zekere Taiwanese provider, waar driekwart van de pogingen om mijn server te hacken vandaan komt. Of beter gezegd kwam:
iptables -I INPUT -s 114.37.0.69/16 -j DROP
Dit blokkeert de ip-addressen 114.37.0.0 tot en met 114.37.255.255. De /16 betekent dat alleen de eerste twee delen van het ip-adres gematcht worden. Die reeksen werken alsvolgt
114.37.0.69/32 | == | 114.37.0.69 |
114.37.0.69/24 | == | 114.37.0.* |
114.37.0.69/16 | == | 114.37.* |
114.37.0.69/8 | == | 114.* |
De /32 optie heeft niet zoveel zin maar werkt wel.
Er is nog een manier om (grotere) reeksen ip-adressen te blokkeren:
iptables -I INPUT -m iprange --src-range 1.160.0.0-1.175.255.255 -j DROP
Hiermee blokkeer je alle ip-adressen die beginnen met 1.160 tot en met 1.175.