TCP-Verbindung unter Linux beenden

49

Ich habe in einer Anwendung eine unterbrochene Verbindung, die sich im Status "Hanged" befindet, wenn der Client-Computer nicht mehr funktioniert.

->192.168.1.214:49029 (ESTABLISHED)

Gibt es eine Möglichkeit, diese Option über die Linux-Befehlszeile zu beenden, ohne den Server neu zu starten?

Nach der Suche fand ich eine Lösung namens tcpkill. Aber es wird bei mir nicht funktionieren. Da es dauerhaft diese IP blockiert.

Vivek Goel
quelle
Die Antwort auf die Verwendung des ssBefehls ist viel einfacher und allgemeiner als die anderen.
Nealmcb

Antworten:

35

Ursprünglich von: http://rtomaszewski.blogspot.sk/2012/11/how-to-forcibly-kill-established-tcp.html

Um einen Socket zu "beenden", müssen Sie ein TCP-Reset-Paket senden. Um es zu senden (und von der anderen Seite akzeptiert zu werden), müssen Sie die tatsächliche TCP-Sequenznummer kennen.

1) Die bereits erwähnte tcpkillMethode lernt die SEQ-Nummer, indem sie passiv das Netzwerk abfragt und auf das Eintreffen gültiger Pakete dieser Verbindung wartet. Anschließend wird die gelernte SEQ-Nummer verwendet, um RSET-Pakete an beide Seiten zu senden. Wenn die Verbindung jedoch inaktiv ist / hängt und keine Daten fließen, wird sie nichts tun und für immer warten.

2) Eine andere Methode verwendet das Perl-Skript killcx( Link zu Sourceforge ). Dies sendet aktiv gefälschte SYN-Pakete und lernt die SEQ-Nummer aus der Antwort. Es sendet dann RSET-Pakete auf die gleiche Weise wie tcpkill.

Alternativ können Sie (basierend auf dem, was Sie erreichen möchten) den gdbDebugger verwenden, um eine Verbindung zu einem Prozess herzustellen, der über diesen Socket / diese Verbindung verfügt, und close()in seinem Namen den Befehl syscall ausgeben - wie in dieser Antwort beschrieben .

Wenn Sie sich nur mit gehängten Verbindungen befassen möchten (die andere Seite ist tot), gibt es verschiedene Zeitüberschreitungen (z. B. TCP-Keepalive), die solche Verbindungen automatisch schließen sollten, wenn sie auf dem System ordnungsgemäß konfiguriert sind.

Marki555
quelle
Würde es funktionieren, wenn wir einfach den TCP-Socket durch seinen Dateideskriptor (fd) schließen würden? exec fd> & -
Alexander Gonchiy
@AlexanderGonchiy für Live-Verbindungen würde verhindern, dass der Prozess auf Pakete reagiert, sodass die Verbindung eine Zeitüberschreitung aufweist. Bei Leerlaufverbindungen würde nichts passieren. Ich bin nicht sicher, ob der Kernel beim Schließen des fd etwas an das Netzwerk senden würde.
Marki555
Ich habe die Sequenznummer gerochen. Was sollte ich dann tun?
user3132194
18

tcpkillkönnte es für dich tun. In Ubuntu ist es im dsniffPaket.

So etwas wie:

$ sudo tcpkill -i wlan0 host 192.168.1.214

(oder ein tcpdumpähnlicher Ausdruck für die zu tötende Verbindung).

jcv
quelle
4
Dies funktioniert nur, wenn die Verbindung etwas überträgt. Es funktioniert nicht für gehängte / inaktive TCP-Verbindungen (siehe meine Antwort für Details)
Marki555
17

Auf einem Linux-Kernel> = 4.9 können Sie den ssBefehl von iproute2 mit key verwenden-K

ss -K dst 192.168.1.214 dport = 49029

Der Kernel muss mit CONFIG_INET_DIAG_DESTROYaktivierter Option kompiliert werden .

Pavel
quelle
1
Für Linux ist dies wirklich der beste Weg und so ziemlich der einzige Weg, wenn Sie inaktive Verbindungen haben ( tcpkillnicht funktionieren könnten). Ich gebe jedoch zu, dass ich nicht überprüft habe, killcxaber es scheint, als würde eine Menge Sicherheitssoftware verhindern, dass dies funktioniert, es sei denn, Sie ändern Ihre iptables, um diese gefälschten Pakete durchzulassen.
Seth Robertson
Vielen Dank! Arbeitete wie ein Zauber mit sudo ss -K ....Ubuntu Bionic 18.04 LTS. Ich hatte einen tmuxProzess, der wegen einer entfernten, aber toten, aber nicht zeitgesteuerten Verbindung auf einem kleinen Bildschirm hängen blieb. Alles repariert!
Nealmcb
6

Do - als root netstat -tunp|grep 49029. Die letzte Spalte der Ausgabe sollte die PID und den Programmnamen des Prozesses anzeigen, der für diese Verbindung verantwortlich ist.

Wenn Sie Glück haben, gibt es nur einen einzigen Prozess für diese Verbindung.

Wenn Sie Pech haben, wird es komplizierter (die PID ist für mehr als nur diese eine Verbindung verantwortlich). Was für ein Service ist das?

Warum möchten Sie diese Sitzung beenden?

Nils
quelle
8
Ich kann diesen Prozess nicht töten. Es ist Gearman Server. Ich möchte nur die Verbindung schließen.
Vivek Goel
0

tcpkillkann eine tote (gehängte) Verbindung nicht schließen. Es basiert darauf libpcap, dass es ein Paket zu einem gesendeten FINPaket zusammensetzt. Wenn die Verbindung bereits unterbrochen ist, kann sie nicht die richtige Sequenznummer erhalten.

Der einzige Weg ist, den Prozess zu schließen, also macht überall NICHT SPOF.

alswl
quelle