Mamy mocno zabezpieczony serwer gdzieś w Internecie. Aby nim zarządzać, chcemy mieć doń dostęp przez SSH. Ale nie chcemy, by dostęp ów miały osoby niepowołane, a zwłaszcza wszelakie sieciowe skanery portów. Rozwiązanie z pozoru łatwe. Do iptables dodajemy regułkę:
-A INPUT -p tcp --dport 22 -s [nasz_ip] -m state --state NEW -j ACCEPT
Schody zaczynają się, gdy zachodzi potrzeba od czasu do czasu dostać się na serwer np. z domu lub z laptopa w delegacji. Nasze IP bowiem bez wątpienia będzie zmienne. Zatem należałoby zastosować taką metodę, która na pewien czas otworzy nam dostęp. I tu z pomocą przychodzi knockd. Jest to sprytny demon, który nasłuchuje na wybranym interfejsie i po napotkaniu sekwencji połączeń tcp lub udp na określone porty (czyli "zapukań") wykonuje jakąś komendę. Czyli np. dodaje lub usuwa jakąś regułkę iptables.
Konfiguracja serwera
W pierwszej kolejności warto określić inny niż standardowy port dla SSH. Niechaj 22 zostanie dla znanych adresów IP na stałe otwartych w firewallu. dla dynamicznych będzie to 666. Jest to trywialne: edytujemy plik /etc/ssh/sshd_config i dodajemy doń linijkę:
Port 666
oczywiście pozostawiając istniejącą linijkę z portem 22 :-)
Kolejny krok to instalacja serwera knockd, co jest równie trywialne w Ubuntu:
Pukamy do serwera
~# apt-get install knockdW innych systemach może nie być tego pakietu, wtedy trzeba się posiłkować pakietem ze strony projektu lub kompilacją ze źródeł. Teraz edytujemy plik konfiguracyjny /etc/knockd.conf. Przyjmijmy, że chcemy sekwencją zapukań na porty 1666, 8081, 6667 otworzyć dostęp do portu 666, a sekwencją odwrotną go zamknąć.
[options]Po czym edytujemy /etc/default/knockd, w którym dajemy START_KNOCKD=1 i już możemy startować usługę.
UseSyslog
[openSSH]
sequence = 1666,8081,6667
seq_timeout = 5
command = /sbin/iptables -I INPUT 6 -s %IP% -p tcp --dport 666 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 6667,8081,1666
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 666 -j ACCEPT
tcpflags = syn
~# service knockd start
Pukamy do serwera
Pora przesiąść się do domowego Linuksa i zapukać w nasz tajemy sposób :-)
~$ knock example.com 1666 8081 6667I już możemy cieszyć się z dostępu do SSH na porcie 666. Gdy pracę skończymy, warto port zamknąć, pukając odwrotnie
~$ knock example.com 6667 8081 1666Proste jak puknięcie w stół :-)
Dla innych systemów operacyjnych (w tym Windowsa, MacOSa czy iPhona) klient pukający do pobrania ze strony http://www.zeroflux.org/projects/knock.
Oczywiście możemy wykorzystać mechanizm puknięć także w dowolnym programie bez instalacji dodatkowych pakietów. Wystarczy tylko otworzyć nieblokujące sockety na poszczególne porty z sekwencji. Przykładowy program w Pythonie, który to robi mógłby wyglądać tak:
import os, socket, fcntl
addr = 'example.com'
seq = [1666,8081,6667]
for port in seq:
print('Knocking %s' % port)
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
flags = fcntl.fcntl(s, fcntl.F_GETFL, 0)
fcntl.fcntl(s, fcntl.F_SETFL, flags | os.O_NONBLOCK)
try:
s.connect((addr,port))
except:
pass
s.close()
Bardziej zaawansowane konfiguracje knockd
Powyższy przykład był zupełnie podstawową konfiguracją serwera knockd i w praktyce raczej tak nie skonfigurujemy dostępu do serwera. Poważnym brakiem jest choćby konieczność samodzielnego zapukania aby zamknąć wcześniej otwarty dostęp.
Można użyć np. takiej konfiguracji:
[opencloseSSH]
sequence = 1590:tcp,7201:tcp,9999:udp
seq_timeout = 15
tcpflags = syn
start_command = /sbin/iptables -I INPUT 6 -s %IP% -p tcp --syn --dport 666 -j ACCEPT
cmd_timeout = 10
stop_command = /sbin/iptables -D INPUT -s %IP% -p tcp --syn --dport 666 -j ACCEPT
Po pierwsze - sekwencja zapukań pozwala ściśle definiować protokół (tcp lub udp), po drugie - możliwe jest określenie dwóch komend, jakie mają być wykonane. Komendę startową i komendę kończącą, która zostanie wykonana po np. 10 sekundach. Czyli po zapukaniu mamy 10 sekund na połączenie się SSH z serwerem, po czym knockd automatycznie zamknie możliwość nawiązywania nowych połączeń i przed kolejną próbą trzeba będzie ponownie zapukać.
Ciekawym (acz możliwe że trudnym do wykorzystania w praktyce) jest też mechanizm sekwencji jednorazowych.
Szczegółowy opis wszystkich opcji i parametrów na stronie projektu: http://www.zeroflux.org/projects/knock