Zabijanie połączenia TCP w systemie Linux

49

Mam pewne martwe połączenie w jednej aplikacji, która jest zawieszona, jeśli komputer kliencki jest martwy.

->192.168.1.214:49029 (ESTABLISHED)

Czy istnieje sposób na zakończenie tej opcji z wiersza poleceń systemu Linux bez ponownego uruchamiania serwera?

Po wyszukiwaniu znalazłem rozwiązanie o nazwie tcpkill. Ale to nie zadziała dla mnie. Ponieważ trwale blokuje ten ip.

Vivek Goel
źródło
Odpowiedź na użycie sspolecenia jest znacznie łatwiejsza i bardziej ogólna niż inne.
nealmcb

Odpowiedzi:

35

Pochodzi z: http://rtomaszewski.blogspot.sk/2012/11/how-to-forcibly-kill-established-tcp.html

Aby „zabić” gniazdo, musisz wysłać pakiet resetowania TCP. Aby go wysłać (i zostać zaakceptowanym przez drugą stronę), musisz znać rzeczywisty numer sekwencyjny TCP.

1) Wspomniana już tcpkillmetoda uczy się numeru SEQ poprzez pasywne wąchanie sieci i oczekiwanie na nadejście prawidłowych pakietów tego połączenia. Następnie wykorzystuje wyuczony numer SEQ do wysyłania pakietów RSET do obu stron. Jednak jeśli połączenie jest bezczynne / zawieszone i nie przepływa danych, nic nie zrobi i będzie czekać wiecznie.

2) Inna metoda wykorzystuje skrypt Perla o nazwie killcx( link do Sourceforge ). To aktywnie wysyła sfałszowane pakiety SYN i uczy się numeru SEQ z odpowiedzi. Następnie wysyła pakiety RSET w taki sam sposób jak tcpkill.

Alternatywnym podejściem (w oparciu o to, co chcesz osiągnąć) jest użycie gdbdebugera w celu przyłączenia się do procesu będącego właścicielem tego gniazda / połączenia i wydania close()w jego imieniu syscall - jak szczegółowo opisano w tej odpowiedzi .

Jeśli chcesz poradzić sobie tylko z zawieszonymi połączeniami (druga strona jest martwa), istnieją różne limity czasu (na przykład utrzymywanie protokołu TCP), które powinny automatycznie zamykać takie połączenia, jeśli są poprawnie skonfigurowane w systemie.

Marki555
źródło
Czy zadziałałoby, gdybyśmy po prostu zamknęli gniazdo TCP za pomocą deskryptora pliku (fd)? exec fd> & -
Alexander Gonchiy
@AlexanderGonchiy w przypadku połączeń na żywo uniemożliwiłoby procesowi reagowanie na pakiety, więc spowodowałoby przekroczenie limitu czasu połączenia. W przypadku bezczynnych połączeń nic by się nie wydarzyło. Nie jestem pewien, czy jądro wyśle ​​coś do sieci po zamknięciu fd.
Marki555
Wąchałem numer sekwencyjny. Więc co powinienem zrobić?
user3132194,
18

tcpkillmoże zrobić to dla ciebie. W Ubuntu jest w dsniffpakiecie.

Coś jak:

$ sudo tcpkill -i wlan0 host 192.168.1.214

(lub inne tcpdumppodobne wyrażenie określające, które połączenie należy zabić).

jcv
źródło
4
Działa to tylko wtedy, gdy połączenie transmituje cokolwiek. Nie będzie działać w przypadku zawieszonych / bezczynnych połączeń TCP (szczegóły w mojej odpowiedzi)
Marki555
17

W jądrze Linuksa> = 4.9 możesz użyć sspolecenia z iproute2 z klawiszem-K

ss -K dst 192.168.1.214 dport = 49029

jądro musi zostać skompilowane z CONFIG_INET_DIAG_DESTROYwłączoną opcją.

Pavel
źródło
1
W przypadku systemu Linux jest to naprawdę najlepszy sposób i właściwie jedyny sposób, jeśli masz bezczynne połączenia ( tcpkillnie może działać). Przyznaję jednak, że nie sprawdziłem, killcxale wydaje się, że wiele programów zabezpieczających uniemożliwiłoby to działanie, chyba że zmodyfikujesz iptables, aby przepuścić te sfałszowane pakiety.
Seth Robertson
Dzięki! Działa jak urok z sudo ss -K ....Ubuntu Bionic 18.04 LTS. Miałem tmuxproces, który utknął na małym ekranie z powodu zdalnego, ale martwego, ale nie przekroczonego limitu czasu połączenia. Wszystko naprawione!
nealmcb
6

Zrób - jako root netstat -tunp|grep 49029. Ostatnia kolumna danych wyjściowych powinna zawierać identyfikator PID i nazwę programu procesu odpowiedzialnego za to połączenie.

Jeśli masz szczęście, istnieje tylko jeden proces dla tego połączenia.

Jeśli masz pecha, staje się to bardziej skomplikowane (PID odpowiada za więcej niż tylko jedno połączenie). Co to za usługa?

Dlaczego chcesz zakończyć tę sesję?

Nils
źródło
8
Nie mogę zabić tego procesu. Jest to serwer gearman. Chcę po prostu zamknąć połączenie.
Vivek Goel,
0

tcpkillnie można zamknąć martwego (zawieszonego) połączenia. Jest oparty libpcap, buduje pakiet do wysłanego FINpakietu. Jeśli połączenie jest już martwe, nie może uzyskać poprawnego numeru sekwencyjnego.

Jedynym sposobem jest zamknięcie procesu, więc sprawia, że ​​wszędzie NIE jest SPOF.

alswl
źródło