Manuelles Schließen eines Ports über die Befehlszeile

370173
Glorfindel

Ich möchte einen offenen Port schließen, der sich im Überwachungsmodus zwischen meiner Client- und Serveranwendung befindet.

Gibt es in Linux eine manuelle Befehlszeilenoption, um einen Port zu schließen?

HINWEIS: Ich habe erfahren, dass "nur die Anwendung, die den verbundenen Socket besitzt, diese schließen soll, was passieren wird, wenn die Anwendung beendet wird."

Ich verstehe nicht, warum dies nur durch die Anwendung möglich ist, die sie öffnet ... Aber ich bin immer noch gespannt, ob es einen anderen Weg gibt, dies zu tun.

95
Nein, geöffnete Ports * gehören * zu dem Prozess, der sie geöffnet hat, eine Kontrolle von außen ist nicht möglich. Das ist eine gute Sache, oder alle Anwendungen müssten davon ausgehen, dass ihre offenen Ports (und Dateien) fehlerhaft sind. Sie können jedoch den Verkehr zu einem Port durch Firewalling (iptables) blockieren. Dies schließt jedoch nicht und gibt den Port nicht für andere Zwecke frei. Jürgen Strobel vor 13 Jahren 5
Viele Antwortende haben den Punkt dieser Frage verfehlt. Es ist Unsinn zu erklären, dass nur die Anwendung, die den Port besitzt, die Verbindung trennen kann. Ich kann es trennen, indem ich zur Box gehe und das Ethernet-Kabel aus der Steckdose zieht oder die Anwendung am anderen Ende der Verbindung abschaltet! Die Anwendung muss dafür geschrieben werden. Wie testen Sie also, ob die Anwendung ordnungsgemäß geschrieben wurde, ohne dass ein Eingriff des Computers und / oder die Kontrolle über den anderen Computer erforderlich ist? Dale Wilson vor 10 Jahren 9
"... es ist keine Kontrolle von außen möglich." Das ist eine wichtige Bemerkung, die mich zur nächsten Frage führte. Wie kann ich von außen an dem Prozess teilnehmen? GDB. Dankó Dávid vor 6 Jahren 0

13 Antworten auf die Frage

114
Dankó Dávid

Ich hatte das gleiche Problem, der Prozess muss am Leben bleiben, aber der Socket muss geschlossen werden. Das Schließen eines Sockets während eines laufenden Prozesses ist nicht unmöglich, aber schwierig:

  1. Lokalisieren Sie den Prozess:

    netstat -np 

    Du bekommst eine source/destination ip:port portstate pid/processnameKarte

  2. Ermitteln Sie dabei den Dateideskriptor des Sockets

    lsof -np $pid 

    Sie erhalten eine Liste: Prozessname, PID, Benutzer, FileDescriptor, ... eine Verbindungszeichenfolge.

    Suchen Sie die übereinstimmende fileDescriptor-Nummer für die Verbindung.

    Verbinden Sie nun den Prozess:

    gdb -p $pid 
  3. Schließen Sie nun die Steckdose:

    call close($fileDescritor)  //does not need ; at end. 

    Dann trennen Sie:

    quit 

    Und die Steckdose ist geschlossen.

"sudo lsof -np $ pid" gibt mir etwa 200 Zeilen und ich bin verwirrt, wie ich die gewünschte FD finden kann. In meinem Fall ist ein Chrome-Tab und ich versuche, geöffnete Websockets zu schließen ... SET vor 10 Jahren 1
Eine Zeile sieht normalerweise wie folgt aus: firefox 14812 szupervigyor 97u IPv4 32814564 0t0 TCP 192.168.2.4:40385->173.194.39.65:https (ESTABLISHED) als: process_name pid Benutzer fd [geöffnetes_für] Protokollgerät inode protocol_data_toString Dankó Dávid vor 10 Jahren 2
* Eine Zeile sieht normalerweise wie folgt aus: firefox 14812 szupervigyor 97u IPv4 32814564 0t0 TCP 192.168.2.4:40385->173.194.39.65:https (ESTABLISHED) als: Prozessname pid-Benutzer fd [geöffnetes_für] Protokollgerät im Modus protocol_data_toString Adresse und finden Sie in der letzten Spalte. In meinem Beispiel ist 97 der FileDescriptor. Die Suche ist schwierig, wenn Sie mehrere Verbindungen zum Zielhost hergestellt haben. Dankó Dávid vor 10 Jahren 2
Dies ist eine brillante Lösung marcorossi vor 9 Jahren 7
- Das ist wirklich ein Lebensretter. mik vor 8 Jahren 0
Wenn Sie simulieren möchten, dass der Socket durch das entfernte Ende geschlossen wird (z. B. das Peer-Exit), verwenden Sie besser 'shutdown': `call shutdown ($ fileDescriptor, 0)`. ecatmur vor 8 Jahren 7
Erstaunlich, genau das, was ich brauchte. 0atman vor 8 Jahren 0
Ich habe nie daran gedacht. Mein Redis-Server akzeptierte keine Verbindungen. Aber ich muss es am Leben erhalten. Dies hat mir geholfen, das Problem zu lösen. * Lebensretter * Shiplu Mokaddim vor 8 Jahren 1
Ich frage mich, warum es in Linux so verdreht ist. In Windows kann ich einfach den Process Explorer (Download von der MS-Website) starten, eine Liste der Handles pro Prozess anzeigen und sie mit der Maus nacheinander schließen. Durch die Verwendung von gdb wird das Programm sogar angehalten, was aufgrund von Zeitüberschreitungen eine Pita darstellt. Mark Jeronimus vor 6 Jahren 0
Ich habe einen "Node" -Prozess, der mit einem sehr langen Timeout (~ 5 Stunden) ausgeführt wird, und hat einige offene Verbindungen, die letztendlich fehlschlagen werden. Deshalb habe ich versucht, auf jedem dieser Sockets sowohl "shutdown" als auch "close" aufzurufen, aber der Prozess war weiterhin der Fall verstopft. Ich kann von der Ausgabe von "lsof" bestätigen, dass diese Buchsen nicht mehr vorhanden sind. Gibt es noch etwas, das ich tun kann, anstatt auf 5 Stunden zu warten, bis das Timeout normal ist? haridsv vor 6 Jahren 0
Nun, ich möchte kein Troll sein, aber in Unixen ist / proc der native Process Explorer im System. Wir können jedoch einen wirklichen Dummy-Befehl zum Schließen einer fd eines Prozesses erstellen: `#! / Bin / bash echo -e" call close ($ 2) \ ndetach \ nquit \ n "| gdb -p $ 1> / dev / null 2> & 1` `close-proc-fd $ pid $ fd, das Sie in ein Backend der Anwendung integrieren können. Diese Lösung ist jedoch eine Overkill-Lösung. Dankó Dávid vor 6 Jahren 0
"Mit gdb pausiert das Programm sogar", tut es leider trotzdem (https://stackoverflow.com/questions/9746018/gdb-attach-to-a-process-outout-stop), aber Sie können die Ausführung fortsetzen gleich nach dem anhängen. Dankó Dávid vor 6 Jahren 0
74
Guy Avraham

You're kind of asking the wrong question here. It isn't really possible to simply "close a port" from outside the application that opened the socket listening on it. The only way to do this is to completely kill the process that owns the port. Then, in about a minute or two, the port will become available again for use. Here's what's going on (if you don't care, skip to the end where I show you how to kill the process owning a particular port):

Ports are resources allocated by the OS to different processes. This is similar to asking the OS for a file pointer. However, unlike file pointers, only ONE process at a time may own a port. Through the BSD socket interface, processes can make a request to listen on a port, which the OS will then grant. The OS will also make sure no other process gets the same port. At any point, the process can release the port by closing the socket. The OS will then reclaim the port. Alternatively, if the process ends without releasing the port, the OS will eventually reclaim the port (though it won't happen immediately: it'll take a few minutes).

Now, what you want to do (simply close the port from the command-line), isn't possible for two reasons. First, if it were possible, it would mean one process could simply steal away another process's resource (the port). This would be bad policy, unless restricted to privileged processes. The second reason is it is unclear what would happen to the process that owned the port if we let it continue running. The process's code is written assuming that it owns this resource. If we simply took it away, it would end up crashing on it's own, so OS's don't let you do this, even if you're a privileged process. Instead, you must simply kill them.

Anyway, here's how to kill a process that owns a particular port:

sudo netstat -ap | grep :<port_number> 

That will output the line corresponding to the process holding port, for example:

tcp 0 0 *:8000 *:* LISTEN 4683/procHoldingPort 

In this case, procHoldingPort is the name of the process that opened the port, 4683 is its pid, and 8000 (note that it is TCP) is the port number it holds.

Then, look in the last column, you'll see /. Then execute this:

kill <pid> 

If that doesn't work (you can check by re-running the netstat command). Do this:

kill -9 <pid> 

In general, it's better to avoid sending SIGKILL if you can. This is why I tell you to try kill before kill -9. Just using kill sends the gentler SIGTERM.

Like I said, it will still take a few minutes for the port to re-open if you do this. I don't know a way to speed this up. If someone else does, I'd love to hear it.

@ smehmood - Vielen Dank für die ausführliche Erklärung .. Ein kleiner Zweifel .. Wie kann der Kernel einen offenen Port durch einen abrupt abgebrochenen Prozess wiederherstellen? .. die von Ihnen bereitgestellte Lösung scheint den Prozess zu stoppen, der den Port hält ... vor 14 Jahren 0
@codingfreak Der Kernel weiß, dass der Prozess weg ist. Es weiß, dass es den Port zurückfordern kann. Es gibt tatsächlich Regeln für den Zeitpunkt des Schließens des Ports, um sicherzustellen, dass keine Streupakete im 'Netz schweben. Woher weiß es, dass es diese Ressourcen hat? das ist, was der Kernel macht, verfolgt die Dinge. Rich Homolka vor 10 Jahren 3
Bis jemand etwas vernünftiges wie "unix.tools.port.close" () `Ich würde 'init 6' verwenden. Snowcrash vor 7 Jahren 0
18
RedBaron

Fixierer kann auch verwendet werden

fuser -k -n *protocol portno* 

Hier ist Protokoll TCP / UDP und PortNr ist die Nummer, die Sie schließen möchten. Z.B

fuser -k -n tcp 37 

Weitere Informationen finden Sie auf der Fixierer-Manpage

Nur den Besitzprozess zu töten funktionierte nicht für mich, aber die Fixiereinheit tat es. Vielen Dank! webwurst vor 11 Jahren 0
Ich erhielt gemischte Ergebnisse, selbst nachdem ich die Fixierstation verwendet hatte, bekam ich "Socket bereits verwendet", als ich versuchte, den Port von der getöteten App wiederzuverwenden, obwohl er dies als root tat. Auf der anderen Seite schien die Zeit, um die Steckdose zu befreien, kürzer als zuvor zu sein, also danke trotzdem. Jan Vlcinsky vor 10 Jahren 0
@ JanVlcinsky Möglicherweise gibt es einen "Guardian" -Prozess, der den Abbruchprozess kurz nach dem Ausführen von "Fixierer" erneut startet. RedBaron vor 10 Jahren 0
@RedBaron: Laut Kommentar http://superuser.com/a/415236/153413 liegt mein Problem in einer schlecht geschriebenen Anwendung, die den Socket bei Beendigung nicht aufräumt / schließt. `Fuser` findet also den Prozess über den Port und tötet ihn, löst jedoch nicht die Tatsache, dass der Socket nicht geschlossen ist. 60 Sekunden und der Kernel erledigt das für mich. Jan Vlcinsky vor 10 Jahren 0
5
supercheetah

You could alternatively use iptables:

iptables -I INPUT -p tcp --dport 80 -j DROP 

It basically accomplishes what you want. This will drop all TCP traffic to port 80.

Nein, dadurch bleibt die Socket geöffnet, bis alle Timeouts sie schließen. (Dadurch wird der gesamte Datenverkehr vor dem Eigentümerprozess ausgeblendet, der dann keine Möglichkeit hat, zu wissen, dass er geschlossen werden sollte.) Sie können '-j REJECT' verwenden, um das TCP-Reset-Flag zurückzugeben, das dann als Eigentümerprozess angesehen werden würde (aber nur.) wenn die andere Seite versucht, etwas zu senden). Marki555 vor 9 Jahren 4
3
Ben
netstat -anp | grep 80 

It should tell you, if you're running apache, "httpd" (this is just an example, use the port your application is using instead of 80)

pkill -9 httpd 

or

killall -9 httpd 
Versuchen Sie es mit einem normalen Kill, bevor Sie auf -9 zurückgreifen Thilo vor 14 Jahren 3
@omfgroflmao - Aber es wird den Prozess beenden, der den Port geöffnet hat? vor 14 Jahren 0
@codingfreak Der Prozess, der den Port hält, ja, er wird beendet. vor 14 Jahren 0
2
jackenheimer

Sie könnten wahrscheinlich nur herausfinden, welcher Prozess den Socket öffnet, mit dem der Port verbunden ist, und den Prozess beenden.

Allerdings müssten Sie feststellen, dass der Prozess nur dann erstellt wurde, wenn dieser Prozess über einen Handler verfügt, der alle verwendeten Elemente (offene Dateien, Sockets, Gabeln und solche, die noch warten können, wenn sie nicht ordnungsgemäß geschlossen wird) de-initialisiert Systemleistung ziehen. Außerdem bleibt der Socket offen, bis der Kernel erkennt, dass der Prozess beendet wurde. Das dauert normalerweise nur eine Minute.

Ich denke, die bessere Frage wäre: Welchen Port (zu welchem ​​Prozess) möchten Sie stoppen?

Wenn Sie versuchen, einer gefundenen Hintertür oder einem Virus ein Ende zu setzen, sollten Sie zumindest herausfinden, welche Daten vor und nach ablaufen. (Wireshark ist dafür gut geeignet) (Und der Name der ausführbaren Datei des Prozesses, damit Sie sie löschen und verhindern können, dass sie beim Neustart wieder hergestellt wird). Wenn Sie etwas installiert haben (wie HTTPD oder FTPD oder etwas anderes), sollten Sie bereits Zugriff darauf haben der Prozess selbst.

Normalerweise hat es ein Steuerungsprogramm (HTTPD-Start oder ähnliches). Wenn es sich um eine Systemsache handelt, sollten Sie sich wahrscheinlich nicht damit beschäftigen. Wie auch immer, ich dachte, da alle anderen Ihnen den "How-To" -Winkel geben, sollte ich Ihnen die Vorbehalte geben.

Sehr guter Kommentar. Ich habe ein Programm, das bei Beendigung den Sockel nicht schließt, was zu dem beschriebenen Verhalten führt - der Sockel ist etwa 60 Sekunden lang unbrauchbar. Wenn ich den Prozess stoppe und starte, beschwert er sich ungefähr eine Minute lang, dass die Adresse und der Port bereits verwendet werden. Die beste Lösung ist, den fehlerhaften Verhaltensprozess zu korrigieren, um ihn ordnungsgemäß zu schließen. Manchmal ist dies jedoch keine Option. Gibt es eine Möglichkeit, den Kernel früher als in 60 Sekunden nach dem blockierten Socket zu fragen? Jan Vlcinsky vor 10 Jahren 0
2
Alejandro BR

Ich habe zuerst nach dem Mongo und den Knotenprozessen gesucht und dann folgendes gemacht:

ps -A | grep node  10418 pts/23 00:00:05 node  10551 pts/23 00:00:00 node  ps -A | grep mongo  10490 pts/23 00:00:00 mongod 

Sobald Sie sie identifiziert haben, beenden Sie einfach die Prozesse mit dem Befehl "kill".

kill -9 10418 kill -9 10490 

Zuletzt tippen meteorund es sollte wieder funktionieren.

1
Michael Shimmins

You could write a script which modified the iptables and restarts them. One script for adding a rule dropping all packets on the port, another script for removing said rule.

The other answers have shown you how to kill the process bound to the port - this may not be what you want. If you want the server to keep running, but to prevent connections from clients then you want to block the port, not stop the process.

@Michael Shimmins ... hmm klingt interessant, da wir den Port auf der Serverseite blockieren können, sodass der Client keine Nachrichten sendet. vor 14 Jahren 0
Nun, der Kunde kann Nachrichten so senden, wie er möchte, wir haben die Tür gerade geschlossen, damit sie nicht hineinkommen können. vor 14 Jahren 0
1
Rich Homolka

Noch ein Problem: Manchmal besitzt der Kernel selbst Ports. Ich weiß, dass das NAT-Routing einige Ports für die NAT-Verwendung offen hält. Sie können einen Prozess dafür nicht beenden, dies ist ein Kernel und eine Neukonfiguration und ein Neustart sind erforderlich.

1
Daniel

Wenn Sie möchten, dass Ihr Port früher freigegeben wird, müssen Sie den folgenden Wert festlegen:

echo 1 > /proc/sys/net/ipv4/tcp_fin_timeout 

um es von 60 Sekunden (Standard) auf 1 Sekunde einzustellen