web-dev-qa-db-fra.com

Fermer manuellement un port depuis la ligne de commande

Je souhaite fermer un port ouvert en mode d'écoute entre mon application cliente et serveur.

Existe-t-il une option de ligne de commande manuelle sous Linux pour fermer un port?

NOTE: J'ai appris que "seule l'application à laquelle appartient la prise connectée doit la fermer, ce qui se produira à la fin de l'application."

Je ne comprends pas pourquoi ce n'est possible que par l'application qui l'ouvre ... Mais je suis toujours impatient de savoir s'il existe un autre moyen de le faire.

101
codingfreak

J'ai eu le même problème, le processus doit rester en vie mais le socket doit se fermer. Fermer un socket dans un processus en cours n'est pas impossible mais difficile:

  1. localiser le processus:

    netstat -np
    

    Vous obtenez une carte source/destination ip:port portstate pid/processname

  2. localisez le descripteur de fichier du socket dans le processus

    lsof -np $pid
    

    Vous obtenez une liste: nom du processus, pid, utilisateur, descripteur de fichier, ... une chaîne de connexion.

    Localisez le numéro de fichier descripteur correspondant pour la connexion.

    Maintenant connectez le processus:

    gdb -p $pid
    
  3. Fermez maintenant la prise:

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

    Puis détachez:

    quit
    

    Et la prise est fermée.

124
Dankó Dávid

Vous êtes en quelque sorte de poser la mauvaise question ici. Il n'est pas vraiment possible de simplement "fermer un port" de l'extérieur de l'application qui a ouvert le socket en l'écoutant. La seule façon de procéder consiste à supprimer complètement le processus propriétaire du port. Ensuite, dans environ une minute ou deux, le port redeviendra disponible. Voici ce qui se passe (si vous ne vous en souciez pas, passez à la fin où je vous montrerai comment arrêter le processus possédant un port particulier):

Les ports sont des ressources allouées par le système d'exploitation à différents processus. Ceci est similaire à demander au système d'exploitation un pointeur de fichier. Cependant, contrairement aux pointeurs de fichier, un seul processus à la fois peut posséder un port. Grâce à l'interface de socket BSD, les processus peuvent demander à écouter sur un port, ce que le système d'exploitation accorde ensuite. Le système d'exploitation s'assurera également qu'aucun autre processus n'obtient le même port. À tout moment, le processus peut libérer le port en fermant le socket. Le système d'exploitation récupérera alors le port. Alternativement, si le processus se termine sans libérer le port, le système d'exploitation le récupérera éventuellement (bien que cela ne se produise pas immédiatement: cela prendra quelques minutes).

Maintenant, ce que vous voulez faire (fermer simplement le port à partir de la ligne de commande) n'est pas possible pour deux raisons. Premièrement, si cela était possible, cela signifierait qu'un processus pourrait tout simplement dérober la ressource d'un autre processus (le port). Ce serait une mauvaise politique, sauf si elle est limitée aux processus privilégiés. La deuxième raison est que nous ne savons pas ce qui arriverait au processus qui appartenait au port si nous le laissions continuer à fonctionner. Le code du processus est écrit en supposant qu'il possède cette ressource. Si nous l'enlevions simplement, le système s'écraserait tout seul. Les systèmes d'exploitation ne vous le permettent pas, même si vous êtes un processus privilégié. Au lieu de cela, vous devez simplement les tuer.

Quoi qu'il en soit, voici comment supprimer un processus possédant un port particulier:

Sudo netstat -ap | grep :<port_number>

Cela affichera la ligne correspondant au port de traitement du processus, par exemple:

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

Dans ce cas, procHoldingPort est le nom du processus qui a ouvert le port, 4683 est son pid et 8000 (notez qu'il s'agit de TCP) est le numéro de port qu'il détient.

Ensuite, regardez dans la dernière colonne, vous verrez /. Ensuite, exécutez ceci:

kill  <pid>

Si cela ne fonctionne pas (vous pouvez vérifier en réexécutant la commande netstat). Faire ceci:

kill -9 <pid>

En général, il vaut mieux éviter d'envoyer SIGKILL si vous le pouvez. C'est pourquoi je vous dis d'essayer kill avant kill -9. Le fait d’utiliser kill envoie le SIGTERM, plus doux.

Comme je l'ai dit, la réouverture du port prendra encore quelques minutes si vous procédez ainsi. Je ne sais pas comment accélérer cela. Si quelqu'un d'autre le fait, j'aimerais l'entendre.

75
user32538

Le four peut également être utilisé

fuser -k -n *protocol portno*

Ici le protocole est tcp/udp et portno est le numéro que vous souhaitez fermer. Par exemple.

fuser -k -n tcp 37

Plus d'informations sur page de manuel de fuser

19
RedBaron

Vous pouvez aussi utiliser iptables:

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

Fondamentalement, il accomplit ce que vous voulez. Cela abandonnera tout le trafic TCP vers le port 80.

5
supercheetah
netstat -anp | grep 80

Si vous utilisez Apache, il devrait vous indiquer "httpd" (ceci est un exemple, utilisez le port utilisé par votre application au lieu de 80)

pkill -9 httpd 

ou

killall -9 httpd
3
Ben

Vous pourriez probablement simplement savoir quel processus a ouvert le socket auquel le port est associé et tuer ce processus.

Mais vous devez réaliser que si ce processus n’a pas de gestionnaire qui désinitialise tout ce qu’il utilisait (fichiers ouverts, sockets, fourchettes, choses pouvant persister s’il n’est pas fermé correctement à la fin), faites glisser la performance du système. De plus, le socket restera ouvert jusqu'à ce que le noyau réalise que le processus a été tué. Cela prend généralement environ une minute.

Je suppose que la meilleure question serait: quel port (appartenant à quel processus) voulez-vous arrêter?

Si vous essayez de mettre fin à une porte dérobée ou à un virus que vous avez trouvé, vous devez au moins connaître les données échangées avant de les supprimer. (Wireshark est bon pour cela) (et le nom de l'exécutable du processus afin que vous puissiez le supprimer et l'empêcher de revenir au redémarrage) le processus lui-même.

Habituellement, il y aura un programme de contrôle (HTTPD stop | start ou quelque chose). Ou, si c'est une affaire de système, vous ne devriez probablement pas jouer avec. Quoi qu'il en soit, je pensais que puisque tout le monde vous donnait l'angle de la marche à suivre, je devrais vous donner les mises en garde.

2
jackenheimer

J'ai d'abord cherché les processus de mongo et de noeud, puis j'ai fait ce qui suit:

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

Une fois identifié, il suffit de tuer les processus avec la commande kill.

kill -9 10418
kill -9 10490

Enfin, tapez meteor et il devrait fonctionner à nouveau.

2
abautista

Si vous souhaitez que votre port soit libéré plus tôt, vous devez définir la valeur suivante:

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

pour le régler de 60 secondes (par défaut) à 1 seconde

1
Daniel

Je suis conscient que cette réponse ne répond pas à la question elle-même, à proprement parler, mais en y lisant cette information pourrait être pertinente:

Le comportement par défaut de la liaison d'un socket à un port (et à une adresse) est le suivant: lorsque le socket est fermé par un arrêt brutal du processus, le socket reste dans TIME_WAIT pendant un certain temps. Cela signifie que vous ne pouvez pas immédiatement renouer avec cette adresse/ce port. Si vous développez le système lui-même via l'interface de socket BSD standard, vous pouvez (au moins dans une certaine mesure) contrôler ce comportement avec l'option de socket SO_REUSEADDR. Cela vous permettra fondamentalement de vous connecter à la même adresse/au même port si le socket est à l'état TIME_WAIT. Encore une prise par port si!

Toutefois, ces informations ne doivent être utilisées que dans le cadre de l'aide au développement, car TIME_WAIT a une raison d'exister, ce qui a déjà été expliqué dans les autres réponses.

1
Tommi Tuura

Vous pouvez écrire un script qui modifie les iptables et les redémarre. Un script pour ajouter une règle supprimant tous les paquets sur le port, un autre script pour supprimer ladite règle.

Les autres réponses vous ont montré comment tuer le processus lié au port - ce n'est peut-être pas ce que vous voulez. Si vous souhaitez que le serveur continue à fonctionner, tout en empêchant les connexions des clients, vous souhaitez bloquer le port, pas arrêter le processus.

1
Michael Shimmins

Vous pouvez utiliser la commande nommée killcx pour fermer une connexion sans qu'aucun processus ne soit tué.

  • syntaxe:
killcx [dest_ip:dest_port] {interface}

  dest_ip              : remote IP
  dest_port            : remote port
  interface (optional) : network interface (eth0, lo etc).
  • exemple:
killcx 120.121.122.123:1234
killcx 120.121.122.123:1234 eth0
1
shuaiming

Un autre problème: le noyau possède parfois des ports eux-mêmes. Je sais que NAT le routage maintient certains ports ouverts pour NAT use. Vous ne pouvez pas tuer un processus pour cela, il s’agit d’un noyau et une reconfiguration et un redémarrage sont nécessaires.

1
Rich Homolka

Si vous ne voulez pas de trafic sur le socket mais que vous vouliez garder le processus actif: tcpkill .

tcpkill -i eth0 Host xxx.xxx.xxx.xxx and port yyyy

Lance un démon de détection qui intercepte et supprime tout le trafic sur ce port. Très pratique pour tester vos applications pour les scissions de réseau.

0
RickyA