[Linux] Port knocking mit knockd

Einleitung

Jeder der einen Linux-Server mit Passwort-Auth verwendet kennt es.
Man hat einen openSSH-Server laufen und zwischen durch beim durchsuchen
der eigenen Logs fällt einem auf, dass im auth.log mehrere fehlgeschlagene
versuchte Logins zu finden sind die von möglicherweise sogar gehackten
Servern getätigt wurden. Teilweise wird dort sogar mit irgendwelchen Scripten
oder Tools versucht anhand von Wörterbüchern die häufig verwendete Passwörter
beinhalten in den eigenen Server einzubrechen.
Nun die beste Lösung hier wäre natürlich die Verwendung von Keys zur Authentification.

Aber was soll man tun wenn man darauf aus welchen Gründen auch immer gerne verzichten
würde?

Port-Knocking (knockd)

Hier schafft der Begriff “Port Knocking” eine neue Sichtweise für die Lösung dieses
Problems. Port Knocking ist mittlerweile nichts mehr neues. Es hat sich nur noch nicht
so richtig etabliert.

Als erstes gilt es zu klären was man unter dem Begriff “Port Knocking” eigentlich verstehen
soll. Nun Port Knocking ist wie der Name es wohl bereits vermuten lässt das anklopfen an
einem bestimmten Port.

Nun fragt man sich natürlich was man genau darunter verstehen soll. Dies lässt sich ebenso
einfach erklären wie der Begriff ins deutsche übersetzt.

Unter der Verwendung von Port-Knocking stellt man zuerst sicher dass alle genannten Ports
auf die Port Knocking angewandt werden soll geschlossen sind.
Das mag nun etwas verwirrend klingen, denn schließlich müssten ja eig. Ports geöffnet sein
damit man mit diesen eine Verbindung zum jeweiligen Dienst aufbauen kann, wie z.B.
einem openSSH-Server. Dennoch schafft die Methode des Port Knockings, dass zu dem jeweiligen
Dienst eine Verbindung hergestellt werden kann. Dies geschieht da durch, dass man mit dem
Server vereinbart wie angeklopft werden soll an dem jeweiligen genannten Port. Erst wenn
das abgesprochene Schema mit dem jeweiligen Port exakt genauso abgearbeitet wurde öffnet
sich der jeweilige Port. Das Absprechen hierbei geschieht da durch, dass man dem Server
sagt auf welchen Ports angeklopft werden soll und mit welchem Protokoll (z.B. TCP und UDP).

Hierbei kommen wir schon zu dem netten Tool “knockd” was unter vielene Linux Distributionen
über den jeweiligen Paket-Manager heruntergeladen werden kann oder auch selbst kompiliert
werden kann.

Im Weiteren Verlauf gehe ich davon aus, dass ihr Knockd nicht selbst kompiliert, sondern
die entsprechenden Binaries aus dem jeweiligen Repository ladet.
Alle meine genannten Befehle beziehen sich auf ein Debian Squeeze System.

Zu aller erst beginnen wir mit der Installation des knockd Dienstes. Dies wie bereits oben
beschrieben erledigen wir über den Paket-Manager in dem Falle APT.

apt-get install -y knockd

Nach erfolgreicher Installation von knockd müssen wir uns nun um die Konfiguration von knockd
kümmern. Diese ist relativ einfach gestrickt und befindet sich im Verzeichnis /etc/.

Dazu öffnen wir erst einmal die Konfigurationsfile mit einem beliebigen Editor.
Ich verwende hierfür den Editor nano.

nano /etc/knockd.conf

Dessen Inhalt sieht standardgemäß so aus:

[openSSH]
sequence    = 7000,8000,9000
seq_timeout = 5
command     = /sbin/iptables -I INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags    = syn

[closeSSH]
sequence    = 9000,8000,7000
seq_timeout = 5
command     = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags    = syn

Das alles mag nun relativ verwirrend aussehen, aber im Prinzip ist es wirklich simpel.

Anhand des Parameters sequence wird bestimmt an welchen Ports der jeweilige knock-Client
anklopfen muss und in welcher Reihenfolge.

In der Regel openSSH z.B. wird verlangt das an dem Port 7000 als erstes angeklopft werden muss
dann an Port 8000 und zuletzt an Port 9000 innerhalb von 5 Sekunden, sonst führt dies zum Timeout.
Die Zeit des Timeouts ist definiert in der Regel seq_timout.
Wird in der entsprechenden Reihenfolge in der angegeben Zeit angeklopft wird ein Kommando ausgeführt
der zu den Iptables in den Chain INPUT eine neue Regel einfügt der den Port nur für den angeklopften
User öffnet. Für alle anderen die evtl. einen Port-Scan ausführen ist der Port 22 also der vom openSSH-
Server geschlossen.

Um den Port 22 wieder zu schließen springt die Regel closeSSH ein.
Innerhalb dieser ist die Sequenz Port 9000 als erstes anklopfen, dann 8000 und zuletzt 7000 definiert.
Wenn diese Ports innerhalb von 5 Sekunden angeklopft werden schließt sich der SSH Port wieder,
denn dann wird die beim Anklopfen erstelle Regel wieder aus dem INPUT Chain gelöscht und
der Port ist somit wieder geschlossen.

Als nächstes müssen wir den Dienst natürlich auch starten:

/etc/init.d/knockd start

Nun denkt man sich doch, dass in der Regel die Iptables Chains sowieso alle auf Accept stehen,
und somit alle Ports auf dennen ein Dienst lauscht geöffnet sind.
Dazu müssen wir nun natürlich auch noch eine neue Iptables Regel erstellen in der wir sagen,
dass der Port 22 immer geschlossen ist.

Dazu legen wir nun eine neue Regel an für den INPUT chain in Iptables:

iptables -A INPUT -s 127.0.0.1 -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -s 0.0.0.0/0 -p tcp --dport 22 -j DROP

Damit sagen wir das für alle eingehenden Verbindungen außer localhost der Port 22 geschlossen bleiben soll,
bzw. das alle Pakete die dort ankommen gedroped werden.

Hiermit steht schon mal unser Port-Knocking für die erste Zeit.

Allerdings wäre es für die Verwendung des dienstes knockd natürlich ratsam die angegebene Sequenzen zu ändern,
jeh nachdem wie man das gerne haben möchte und möglichst weit von der Standard-Konfiguration entfernt.

Als weiteren Punkt haben wir nun ja noch das Problem, dass man ggf. vergessen könnte den Port mittels
des erneuten Anklopfens zu schließen. Daher können wir unsere Konfiguration noch einmal anpassen,
damit sich der Port autom. wieder schließt.
Dazu ändern wir unsere Konfiguration auf wie folgt:

[opencloseSSH]
sequence    = 7000,8000,9000
seq_timeout   = 5
tcpflags      = syn,ack
start_command = /usr/sbin/iptables -I INPUT -s %IP% -p tcp --syn --dport 22 -j ACCEPT
cmd_timeout   = 1800
stop_command  = /usr/sbin/iptables -D INPUT -s %IP% -p tcp --syn --dport 22 -j ACCEPT

Die Änderung die wir hier vorgenommen haben sagt folgendes aus:
Zum öffnen des Ports muss auf den Ports 7000, 8000 und 9000 angeklopft werden.
Anschließend öffnet sich der Port für 30 Minuten (1800 Sekunden) nach Ablauf der Zeit
wird der Port autom. wieder geschlossen.

Als letztes stellt sich uns nun die Frage: Wie setzen wir das Port Knocking nun nach erfolgreicher
Konfiguration um?

Dazu wie oben leicht angedeuten gibt es Knock-Clients wie z.B.
den Client “knock”.

Die Syntax für diesen lautet wie folgt:

knock [options] <host> <port[:proto]> [port[:proto]]

Ein einfaches Beispiel zum zeigen wie das Anklopfen nun wirklich in die Tat umgesetzt werden könnte
ist:

knock myserver.example.com 123:tcp 456:udp 789:tcp

Hier sagen wir: Wir möchten auf dem Server myserver.example.com auf den Ports 123 via TCP, 456 via UDP
und 789 via TCP anklopfen.

Ein weiteres Beispiel wäre:

knock -u myserver.example.com 8284 4721 18592 42912

Hier sagen wir wir möchten wieder am Server myserver.example.com anklopfen auf den Ports 8284,4721, 18592
und 42912 mit dem Protokoll UDP.
Lassen wir den Parameter “u” weg, dann klopfen wir auf den 4 Ports via TCP an.

Nachdem erfolgreich auf den Ports angeklopft wurde kann eine SSH-Session mit jedem beliebigen SSH-Client
für den Zeitraum von 30 Minuten aufgebaut werden.

Leave a Reply