Testez si un port sur un système distant est accessible (sans telnet)

Dans le passé, nous telnet pour voir si un port d'un hôte distant était ouvert: le telnet hostname port tenterait de se connecter à n'importe quel port sur n'importe quel hôte et de vous donner accès au flux TCP brut.

Ces jours-ci, les systèmes sur lesquels je travaille n'ont pas telnet installé (pour des raisons de sécurité) et toutes les connexions sortantes à tous les hôtes sont bloquées par défaut. Avec le temps, il est facile de perdre la trace des ports ouverts aux hôtes.

Existe-t-il une autre façon de tester si un port sur un système distant est ouvert – en utilisant un système Linux avec un nombre limité de paquets installés, et telnet n'est pas disponible?

Bash a pu accéder aux ports TCP et UDP pendant un certain temps. De la page man:

 /dev/tcp/host/port If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open a TCP connection to the corresponding socket. /dev/udp/host/port If host is a valid hostname or Internet address, and port is an integer port number or service name, bash attempts to open a UDP connection to the corresponding socket. 

Donc, vous pouvez utiliser quelque chose comme ceci:

 xenon-lornix:~> cat < /dev/tcp/127.0.0.1/22 SSH-2.0-OpenSSH_6.2p2 Debian-6 ^C pressed here 

Taa Daa!

Agréable et verbose! Des pages man.
Port unique:

 nc -zv 127.0.0.1 80 

Plusieurs ports:

 nc -zv 127.0.0.1 22 80 8080 

Gamme de ports:

 nc -zv 127.0.0.1 20-30 

Netcat est un outil utile:

nc 127.0.0.1 123 &> /dev/null; echo $?

Sortira 0 si le port 123 est ouvert et 1 s'il est fermé.

La méthode la plus simple, sans utiliser un autre outil, comme socat , est telle que décrite dans la réponse de @ lornix ci-dessus. Ceci est juste pour ajouter un exemple réel de la façon dont on utiliserait le psuedo-device /dev/tcp/... dans Bash si vous vouliez, par exemple, tester si un autre serveur possédait un port donné accessible via la ligne de commande.

Exemples

Dites que j'ai un hôte sur mon réseau nommé skinner .

 $ (echo > /dev/tcp/skinner/22) >/dev/null 2>&1 \ && echo "It's up" || echo "It's down" It's up $ (echo > /dev/tcp/skinner/222) >/dev/null 2>&1 && \ echo "It's up" || echo "It's down" It's down 

La raison pour laquelle vous souhaitez envelopper echo > /dev/... entre parenthèses comme ceci, (echo > /dev/...) est parce que si vous ne le faites pas, puis, avec des tests de connexions en panne, vous allez Afficher ces types de messages.

 $ (echo > /dev/tcp/skinner/223) && echo hi bash: connect: Connection refused bash: /dev/tcp/skinner/223: Connection refused 

Ceux-ci ne peuvent pas simplement être redirigés vers /dev/null puisqu'ils proviennent de la tentative d'écriture de données sur le périphérique /dev/tcp . Nous capturons donc toutes ces sorties dans une sous-commande, c'est-à-dire (...cmds...) et redirigeons la sortie de la sous-commande.

J'ai trouvé que curl peut faire fonctionner de manière similaire à telnet , et curl vous dira même quel protocole l'auditeur attend.

Construire un URI HTTP à partir du nom d'hôte et du port comme premier argument à curl . Si curl peut se connecter, il signalera un incompatibilité de protocole et quitter (si l'auditeur n'est pas un service Web). Si curl ne peut pas se connecter, il sera expiré.

Par exemple, le port 5672 sur l'hôte 10.0.0.99 est fermé ou bloqué par un pare-feu:

 $ curl http://10.0.0.99:5672 curl: (7) couldn't connect to host 

Cependant, à partir d'un système différent, le port 5672 sur l'hôte 10.0.0.99 peut être atteint et semble exécuter un auditeur AMQP.

 $ curl http://10.0.0.99:5672 curl: (56) Failure when receiving data from the peer AMQP 

Il est important de distinguer les différents messages: la première erreur était que curl ne pouvait pas se connecter au port. La deuxième défaillance est un test de succès, même si curl attend un auditeur HTTP au lieu d'un auditeur AMQP.

 [admin@automation-server 1.2.2]# nc -v -z -w2 192.168.193.173 6443 nc: connect to 192.168.193.173 port 6443 (tcp) failed: Connection refused [admin@automation-server 1.2.2]# nc -v -z -w2 192.168.194.4 6443 Connection to 192.168.194.4 6443 port [tcp/sun-sr-https] succeeded! 

J'espère que cela résoud votre problème 🙂

Voici un one-liner:

 </dev/tcp/localhost/11211 && echo Port is open || echo Port is closed 

En utilisant la syntaxe Bash expliquée dans la réponse @lornix .

Il ne devrait pas être disponible sur votre boîte, mais essayez avec nmap .

Je luttais pour une journée entière parce qu'aucune de ces réponses ne semblait fonctionner pour moi. Le problème est que la version la plus récente de nc n'a plus le drapeau -z , alors que l'accès direct via TCP (comme selon @lornix et @slm) échoue lorsque l'hôte n'est pas accessible. J'ai finalement trouvé cette page , où je n'ai finalement trouvé qu'un, mais deux exemples pratiques:

  1. nc -w1 127.0.0.1 22 </dev/null

    (Le drapeau -w s'occupe du délai d'attente et </dev/null remplace l'indicateur -z )

  2. timeout 1 bash -c '(echo > /dev/tcp/127.0.0.1/22) >/dev/null 2>&1'

    (La commande timeout prend en charge le délai d'attente, et le reste provient de @slm)

Ensuite, utilisez simplement && et / ou || (Ou même $? ) Pour extraire le résultat. Espérons que quelqu'un trouvera cette information utile.