Trochę schowane porty
Dzisiaj na jednym forum zobaczyłem pytanie, czy można jakoś tak zrobić, by port wydawał się zamknięty dla kogoś, kto skanuje sieć, ale by “normalny” klient mógł się połączyć. Odpowiedź w zasadzie powinna brzmieć NIE (no, w każdym razie dla NORMALNEGO klienta), ale można próbować pewnej sztuczki...
Na początek mały przykład. To jest wynik tcpdump przy skanowaniu nmap portów od 1 do 10.
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes 22:28:46.964121 arp who-has 192.168.1.240 (ff:ff:ff:ff:ff:ff) tell 192.168.1.254 22:28:46.974117 IP 192.168.1.254.44523 > 192.168.1.240.5: tcp 0 22:28:46.975984 IP 192.168.1.254.44523 > 192.168.1.240.10: tcp 0 22:28:46.977954 IP 192.168.1.254.44523 > 192.168.1.240.8: tcp 0 22:28:46.979555 IP 192.168.1.254.44523 > 192.168.1.240.6: tcp 0 22:28:46.981465 IP 192.168.1.254.44523 > 192.168.1.240.4: tcp 0 22:28:46.983230 IP 192.168.1.254.44523 > 192.168.1.240.2: tcp 0 22:28:46.985160 IP 192.168.1.254.44523 > 192.168.1.240.3: tcp 0 22:28:46.986640 IP 192.168.1.254.44523 > 192.168.1.240.9: tcp 0 22:28:46.988536 IP 192.168.1.254.44523 > 192.168.1.240.1: tcp 0 22:28:46.990222 IP 192.168.1.254.44523 > 192.168.1.240.7: tcp 0 22:28:48.076636 IP 192.168.1.254.44524 > 192.168.1.240.7: tcp 0 22:28:48.076871 IP 192.168.1.254.44524 > 192.168.1.240.1: tcp 0 22:28:48.077077 IP 192.168.1.254.44524 > 192.168.1.240.9: tcp 0 22:28:48.077284 IP 192.168.1.254.44524 > 192.168.1.240.3: tcp 0 22:28:48.077522 IP 192.168.1.254.44524 > 192.168.1.240.2: tcp 0 22:28:48.077729 IP 192.168.1.254.44524 > 192.168.1.240.4: tcp 0 22:28:48.077939 IP 192.168.1.254.44524 > 192.168.1.240.6: tcp 0 22:28:48.078147 IP 192.168.1.254.44524 > 192.168.1.240.8: tcp 0 22:28:48.078383 IP 192.168.1.254.44524 > 192.168.1.240.10: tcp 0 22:28:48.078605 IP 192.168.1.254.44524 > 192.168.1.240.5: tcp 0
Jak widać każdy z portów sprawdzany jest DWA razy. I tutaj pojawia się miejsce dla małej sztuczki. TCP/IP projektowane było do pracy w warunkach, kiedy zagubienie pakietu w transmisji nie jest niczym szczególnym. Z tego też powodu w procesie nawiązywania połączenia wysłany pakiet SYN jest powtarzany kilkukrotnie. Ilość powtórzeń jest wartością parametryzowalną, ale zwykle wynosi od 2 do 4, co powoduje, że próba połączenia z poziomu NORMALNEGO klienta generuje od 3 do 5 pakietów SYN, a więc przynajmniej o jeden więcej niż nmap przy standardowym skanowaniu portów w trybie synscan. Oczywiście, między kolejnymi powtórzeniami pakietu SYN mija coraz więcej czasu. Wygląda to mniej więcej tak (mój Linuks ma ustawioną wartość powtórzeń na 3):
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes 22:35:40.338483 IP 192.168.1.254.1426 > 192.168.1.240.222: tcp 0 22:35:43.339291 IP 192.168.1.254.1426 > 192.168.1.240.222: tcp 0 22:35:49.338378 IP 192.168.1.254.1426 > 192.168.1.240.222: tcp 0 22:36:01.336559 IP 192.168.1.254.1426 > 192.168.1.240.222: tcp 0
Na czym więc powinna polegać ta sztuczka? Wystarczy, gdy port będzie odpowiadał dopiero na 3 próbę połączenia. Oczywiście, połączenie będzie strasznie wolno nawiązywane, ale czy ja mówiłem, że rozwiązanie będzie praktyczne? Jak można zrealizować coś takiego? Iptables i moduł recent. Konkretnego przykładu reguł w tej chwili nie podam, bo mi się nie chce ich testować. Czy można to wykorzystać praktycznie? Można, oczywiście jest to rozwiązanie sztukowane sznurkami i wcale doskonale nie działa, poza tym z uwagi na możliwości modułu recent wcale nie jest powiedziane, że ktoś skanując kilka razy serwer w końcu tego portu nie wykryje, ale tak jak już pisałem, to jest pewien eksperyment myślowy, ot taka sztuka dla sztuki. Ogólnie koncepcja nie jest nowa, istnieje takie pojęcie jak port-knocking. Chodzi o to, że pewne porty stają się dostępne dopiero po wysłaniu pewnej sekwencji pakietów. Powiedzmy, że serwer SSH staje się dostępny dopiero po tym, jak ktoś spróbuje połączyć się na porty 21, 29 i 333 w ciągu 3 sekund. Istnieje również stosowny demon. Sam stosuję podobne rozwiązanie do ukrycia serwera SSH na swoim serwerku. Denerwowały mnie wpisy w logach o próbach odgadnięcia hasła, a ponieważ bywam czasami w różnych miejscach, nie mogłem wpisać w regułach konkretnych adresów, z których będę się łączył. Nie chciałem jednak stosować skomplikowanej sekwencji “pukania”, w związku z czym poszedłem na łatwiznę. Stworzyłem regułkę właśnie z wykorzystaniem modułu recent, która otwiera port 22 na jedną próbę połączenia z danego adresu IP, pod warunkiem, że wcześniej z tego adresu mój serwer został cztery razy spingowany. Port jest otwierany na 30 sekund. Stosowne reguły wyglądają mniej więcej tak:
-N INKNOCKSSH -A INKNOCKSSH -m recent —remove —name INKNOCKSSH -j ACCEPT -A INPUT -i ppp0 -m recent —set —name INKNOCKSSH -m icmp -p icmp —icmp-type echo-request -j DROP -A INPUT -i ppp0 -m recent —rcheck —hitcount 4 —seconds 30 —name INKNOCKSSH -m state —state NEW -p tcp -m tcp —dport 22 -j INKNOCKSSH
Choć rozwiązanie jest prymitywne, to spełnia swoje zadanie. Normalnie port 22 nie jest otwarty. Wpisy o zgadywaniu hasła przestały drażnić moje oczy...
Oryginał tego wpisu dostępny jest pod adresem Trochę schowane porty
Autor: Paweł Goleń