Gelegentlich kommt man in die Verlegenheit dass man daran gebunden ist SSH auf dem Standardport 22 zu betreiben, was sich dann schon nach kurzer Zeit in andauernden Bruteforceattacken niederschlägt. Für diesen Fall ist neben
fail2ban oder
denyhosts der
knockd ein guter Weg den Server gegen unerwünschte Angriffe abzusichern. Doch der Anklopfserver kann noch mehr - er verhindert von vornherein dass Angreifern die Extistenz bestimmter Dienste überhaupt bekannt wird oder kann im Notfall den Webserver neu starten.
Der knockd beobachtet ob auf Bestimmten, vorher festgelegten Ports Pakete in der vorher festgelegten Reihenfolge eintreffen und führt, wenn dies der Fall sein sollte, einen beliebigen Befehl aus. Praktisch nutzt man diese Funktion nun also dazu, das vorher über iptables gesperrte SSH durch das einfügen einer passenden Regel in in die iptables freizuschalten.
Zunächst installiert man den daemon über die Paketverwaltung des Betriebssystems - in diesem Fall Debian (Abwandlungen bei anderen Distributionen sind möglich).
aptitude install knockd
Standardmäßig muss der Eintrag
START_KNOCKD in der
/etc/default/knockd auf
1 angepasst werden damit der Daemon überhaupt startet. Bei Bedarf kann hier auch das Interface angepasst werden, auf dem der Daemon lauscht. Anschließend wird das configfile
/etc/knockd.conf angepasst - für SSH könnte das z.B. so aussehen:
[options]
UseSyslog
[opencloseSSH]
sequence = 9000,8000,7000
seq_timeout = 15
tcpflags = syn
start_command = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
cmd_timeout = 10
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
Durch die Option
UseSyslog werden Wichtige Informationen ins Syslog geschrieben. Wenn nun innerhalb des
seq_timeout (in Sekunden) nacheinander Pakete mit dem in
tcpflags festgelegten Flag an die in
sequence festgelgten TCP-Ports gesandt werden wird das
start_command ausgeführt. Nach Ablaufen des
cmd_timeout wird das
stop_command ausgeführt. Hierbei sollte man
sequence unbedingt durch eigene Werte ersetzen und dabei auch mehr als nur 3 Ports verwenden (5-8 eignen sich gut).
Nun empfiehlt es sich den daemon nicht gleich zu starten sondern zunächst mit
knockd --debug --verbose
im Debugmode zu schauen ob denn auch alles so läuft wies soll. Ein Beispiel:
server:
$ knockd --debug --verbose
[...]
Local IP: 192.168.0.18
listening on eth0...
client:
$ knock 192.168.0.18 9000 8000 7000
server:
2009-09-21 18:53:32: tcp: 192.168.0.121:49087 -> 192.168.0.18:9000 74 bytes
192.168.0.121: opencloseSSH: Stage 1
2009-09-21 18:53:32: tcp: 192.168.0.121:58850 -> 192.168.0.18:8000 74 bytes
192.168.0.121: opencloseSSH: Stage 2
2009-09-21 18:53:32: tcp: 192.168.0.121:44580 -> 192.168.0.18:7000 74 bytes
192.168.0.121: opencloseSSH: Stage 3
192.168.0.121: opencloseSSH: OPEN SESAME <-- Der Server hat die sequenz erkannt.
opencloseSSH: running command: /sbin/iptables -I INPUT -s 192.168.0.121 -p tcp --dport 22 -j ACCEPT <-- öffnet den Port.
192.168.0.121: opencloseSSH: command timeout <-- 10 Sekunden Später ...
opencloseSSH: running command: /sbin/iptables -D INPUT -s 192.168.0.121 -p tcp --dport 22 -j ACCEPT <-- ... wird der Port wieder geschlossen
Wenn das alles so funktioniert und der Eintrag währen dieser 10 Sekunden auch mit
iptables -L
angezeigt wird. Kann der Daemon über das initscript /etc/init.d/knockd gestartet werden. Allerdings passiert zumindest auf einem Standardsystem hier noch nicht viel, da standardmäßig SSH natürlich nicht gesperrt ist. Dies könnte beispielsweise über
iptables -A INPUT -p tcp --dport 22 --syn -j REJECT
geändert werden. Wie man sieht werden nur syn-Pakete gedropt. Dadurch werden bestehende Verbindungen nicht beeinträchtigt. Sonst würde die frisch hergestellte Verbindung ja binnen 10 Sekunden wieder getrennt werden. Wenn alles funktioniert sollte der Eintrag über die
/etc/rc.local übernommen werden damit die Firewall auch bei jedem Neustart wieder angepasst wird.
Wenn das ganze über eine SSH-Verbindung eingerichtet wird sollte diese offen gehalten werden bis alle Tests abgeschlossen sind, wenn was schief geht kommt man sonst womöglich nie wieder an seinen Server

. Falls vorher schon eine iptables Konfiguration existiert müssen die Befehle natürlich daran angepasst werden.
Noch eine Beispielkonfiguration wie man openvpn starten und stoppen könnte:
[options]
UseSyslog
[startOpenVPN]
sequence = 7000,8000,9000
seq_timeout = 5
command = /etc/init.d/openvpn start
tcpflags = syn
[stopOpenVPN]
sequence = 9000,8000,7000
seq_timeout = 5
command = /etc/init.d/openvpn stop
tcpflags = syn
knock 192.168.0.18 7000 8000 9000 startet nun openvpn und knock 192.168.0.18 9000 8000 7000 stoppt es.
Kommentare