Question Fermer manuellement un port de la ligne de commande


Je veux fermer un port ouvert qui est en mode écoute entre mon application client et serveur.

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

REMARQUE:  Je suis venu à savoir que "seule l'application qui possède le socket connecté devrait le fermer, ce qui se produira lorsque l'application se termine."

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 y a une autre façon de le faire.


91
2018-04-06 03:39


origine


Non, ports ouverts appartenir au processus qui les a ouverts, il n'y a pas de contrôle possible de l'extérieur. Ce qui est une bonne chose, ou toutes les applications devraient anticiper le traitement de leurs ports ouverts (et de leurs fichiers). Cependant, vous pouvez bloquer le trafic vers un port en utilisant un pare-feu (iptables), mais cela ne se fermera pas et renoncera au port pour d'autres utilisations. - Jürgen Strobel
Beaucoup de répondants ont manqué le but de cette question. Il est absurde de déclarer que seule l'application propriétaire du port peut la déconnecter. Je peux le déconnecter en allant au box et en tirant le câble Ethernet de la prise, ou en supprimant l'application à l'autre bout de la connexion! L'application doit être écrite pour gérer cela. Alors, comment testez-vous pour vous assurer que l'application est correctement écrite sans intervention physique et / ou contrôle de l'autre ordinateur? - Dale Wilson
"... il n'y a pas de contrôle possible de l'extérieur." C'est une remarque importante qui m'a guidé vers la question suivante: comment puis-je faire partie du processus de l'extérieur? GDB. - Dankó Dávid


Réponses:


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 un source/destination ip:port portstate pid/processname carte

  2. localiser 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.

    Recherchez le numéro de descripteur de fichier correspondant à la connexion.

    Connectez maintenant le processus:

    gdb -p $pid
    
  3. Fermez maintenant le socket:

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

    Puis détachez:

    quit
    

    Et la prise est fermée.


108
2017-11-01 01:43



sudo lsof -np $pid me donne environ 200 lignes et je suis confus sur la façon de trouver la FD désirée. Dans mon cas, le processus est un onglet Chrome et j'essaye de fermer les weblets ouverts ... - SET
Une ligne ressemble généralement à: firefox 14812 szupervigyor 97u IPv4 32814564 0t0 TCP 192.168.2.4:40385->173.194.39.65:https (ESTABLISHED) en tant que: nom_processeur pid utilisateur fd [open_for] périphérique de protocole inode protocol_data_toString - Dankó Dávid
* Une ligne ressemble généralement à: firefox 14812 szupervigyor 97u IPv4 32814564 0t0 TCP 192.168.2.4:40385->173.194.39.65:https (ESTABLISHED) comme: nom_processeur utilisateur pd fd [open_for] périphérique de protocole inode protocol_data_toString Vous devez connaître l'adresse IP distante adresse et trouver sur le dernier col. Dans mon exemple, le 97 est le FileDescriptor. La recherche est difficile si vous avez ouvert plusieurs connexions à l'hôte cible. - Dankó Dávid
c'est une solution brillante - marcorossi
Si vous souhaitez simuler la fermeture du socket par le côté distant (par exemple, le pair sortant), il vaut mieux utiliser shutdown: call shutdown($fileDescriptor, 0). - ecatmur


Vous êtes en quelque sorte en train de poser la mauvaise question ici. Il n'est pas vraiment possible de simplement "fermer un port" en dehors de l'application qui a ouvert le socket en l'écoutant. Le seul moyen d'y parvenir est de supprimer complètement le processus propriétaire du port. Puis, dans environ une minute ou deux, le port sera à nouveau disponible pour utilisation. Voici ce qui se passe (si vous ne vous en souciez pas, passez à la fin où je vous montre comment tuer 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 le système d'exploitation pour un pointeur de fichier. Cependant, contrairement aux pointeurs de fichiers, seul un processus à la fois peut posséder un port. Grâce à l'interface de socket BSD, les processus peuvent faire une demande d'écoute sur un port, ce que le système d'exploitation va alors accorder. 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. Si le processus se termine sans libérer le port, le système d'exploitation récupèrera éventuellement le port (même si cela ne se produira pas immédiatement: cela prendra quelques minutes).

Maintenant, ce que vous voulez faire (fermez simplement le port depuis la ligne de commande) n’est pas possible pour deux raisons. Premièrement, si cela était possible, cela signifierait qu'un processus pourrait simplement voler la ressource d'un autre processus (le port). Ce serait une mauvaise politique, à moins de se limiter à des processus privilégiés. La deuxième raison est qu'il est difficile de savoir ce qui arriverait au processus qui possédait le port si nous le laissions continuer à fonctionner. Le code du processus est écrit en supposant qu'il possède cette ressource. Si nous le retirions simplement, cela finirait par tomber dessus, donc les systèmes d'exploitation ne vous permettent pas de le faire, 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 tuer un processus qui possède un port particulier:

sudo netstat -ap | grep :<port_number>

Cela affichera la ligne correspondant au port de maintien 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 que c'est TCP) est le numéro de port qu'il contient.

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). Faites 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. Juste en utilisant kill envoie le gentil SIGTERM.

Comme je l'ai dit, le port prendra encore quelques minutes si vous le faites. Je ne sais pas comment accélérer cela. Si quelqu'un d'autre le fait, j'adorerais l'entendre.


73
2018-04-06 04:05



@smehmood - Merci pour l'explication détaillée .. Un petit doute .. Comment le noyau récupère-t-il un port ouvert par un processus tué brutalement? .. la solution que vous fournissez semble tuer le processus qui retient le port ...
@codingfreak Le noyau sait que le processus est parti. Il sait qu'il peut récupérer le port. Il y a en fait des règles sur le moment de la fermeture du port, pour s'assurer qu'il n'y a pas de paquets parasites flottant sur le réseau. Comment sait-il qu'il a ces ressources? c'est ce que fait le noyau, garde la trace des choses. - Rich Homolka
Jusqu'à ce que quelqu'un affiche quelque chose de sensible comme unix.tools.port.close(<my port number>) j'utiliserais init 6. - Snowcrash


Le four peut aussi ê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'infos sur page de manuel de fusion


18
2018-02-13 08:44



Juste tuer un processus propriétaire ne fonctionnait pas pour moi, mais fuser a fait. THX! - webwurst
J'ai obtenu des résultats mitigés, même après avoir utilisé fuser, j'ai eu "socket déjà utilisé" en essayant de réutiliser le port de l'application tuée même en tant que root. D'un autre côté, le temps nécessaire pour libérer le socket semblait être plus court qu'avant, alors merci. - Jan Vlcinsky
@JanVlcinsky Peut-être existe-t-il un processus "gardien" qui redémarre les processus tués quelques instants après fuser est couru? - RedBaron
@ RedBaron: selon le commentaire superuser.com/a/415236/153413 mon problème provient d'une application mal écrite, qui ne nettoie / ferme pas le socket en cours de résiliation. Alors fuser trouve le processus en utilisant le port et le tue, mais ne résout pas le fait que le socket n'est pas fermé. 60 secondes et le noyau le fait pour moi. - Jan Vlcinsky


Vous pouvez aussi utiliser iptables:

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

Il accomplit essentiellement ce que vous voulez. Cela laissera tout le trafic TCP au port 80.


4
2018-04-06 09:38



Non, cela gardera le socket ouvert jusqu'à ce que tous les délais soient fermés. (Cela cachera tout le trafic du processus propriétaire qui n’a alors aucun moyen de savoir si le processus doit le fermer.) -j REJECT pour renvoyer le drapeau de réinitialisation TCP, qui apparaîtrait alors au processus propriétaire (mais uniquement lorsque l'autre partie essaie d'envoyer quelque chose). - Marki555


netstat -anp | grep 80

Il devrait vous dire, si vous utilisez apache, "httpd" (ceci est juste un exemple, utilisez le port que votre application utilise au lieu de 80)

pkill -9 httpd 

ou

killall -9 httpd

3
2018-04-06 03:45



essayer une mise à mort normale avant de recourir à -9 - Thilo
@omfgroflmao - Mais ça va tuer le processus qui a ouvert le port ??
@codingfreak Le processus qui contient le port, oui il va le tuer.


Vous pourriez probablement juste savoir quel processus a ouvert le socket que le port est associé à, et tuer ce processus.

Mais vous devez vous rendre compte que si ce processus a un gestionnaire qui désinitialise tout ce qu’il utilisait (open des fichiers, des sockets, des fourchettes, des trucs qui peuvent s’attarder à moins qu’ils ne soient fermés correctement lors de la résiliation) vous auriez alors créé cette traînée sur les performances du système. De plus, la prise restera ouvrir jusqu'à ce que le noyau réalise que le processus a été tué. Que généralement juste prend 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 virus que vous avez trouvé, alors vous devriez au moins apprendre quelles données vont et viennent avant de le terminer. (wireshark est bon pour cela) (Et le nom du fichier exécutable pour que vous puissiez le supprimer et l'empêcher de revenir au redémarrage) ou, si c'est quelque chose que vous avez installé (comme HTTPD ou FTPD), vous devriez déjà avoir accès à le processus lui-même.

Habituellement, il aura un programme de contrôle (HTTPD stop | start ou autre). Ou, si c'est une chose 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 du "comment faire", je devrais vous donner les réserves.


2
2018-04-22 05:02



Très bon commentaire. J'ai un programme, qui sous terminaison ne ferme pas le socket ce qui entraîne un comportement décrit - le socket est inutilisable pendant environ 60 secondes. Lorsque j'arrête et que je commence ce processus, il se plaint pendant environ une minute, que l'adresse et le port sont déjà utilisés. La meilleure solution est de corriger correctement le processus de comportement pour le fermer correctement, mais cela n’est pas une option. Existe-t-il un moyen de demander au noyau de vérifier plus rapidement que le socket bloqué en moins de 60 secondes? - Jan Vlcinsky


J'ai d'abord cherché les processus mongo et node, 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 ça devrait fonctionner à nouveau.


2
2018-05-27 03:46





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 cette règle.

Les autres réponses vous ont montré comment tuer le processus lié au port - cela peut ne pas être ce que vous voulez. Si vous souhaitez que le serveur continue à fonctionner, mais pour empêcher les connexions des clients, vous devez bloquer le port et ne pas arrêter le processus.


1
2018-04-06 04:10



@Michael Shimmins ... hmm semble intrigant car nous pouvons bloquer le port côté serveur pour que le client n'envoie aucun message.
Eh bien, le client peut envoyer des messages tout ce qu’ils veulent. Nous venons de fermer la porte pour qu’ils ne puissent pas entrer.


Un autre problème: le noyau possède parfois des ports. Je sais que le routage NAT conserve certains ports ouverts pour une utilisation NAT. Vous ne pouvez pas tuer un processus pour cela, c'est un noyau, et une reconfiguration et un redémarrage sont nécessaires.


1
2017-11-01 02:08





Si vous souhaitez que votre port soit publié 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
2018-04-23 06:06