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

353

Autrefois, nous telnetvoyions si un port sur un hôte distant était ouvert: telnet hostname portil tenterait de se connecter à n'importe quel port d'un hôte et vous donnerait accès au flux TCP brut.

De nos jours, telnet n'est pas installé sur les systèmes sur lesquels je travaille (pour des raisons de sécurité) et toutes les connexions sortantes vers tous les hôtes sont bloquées par défaut. Avec le temps, il est facile de ne plus savoir quels ports sont ouverts pour quels hôtes.

Existe-t-il un autre moyen de vérifier si un port d'un système distant est ouvert - en utilisant un système Linux sur lequel un nombre limité de packages est installé et qui telnetn'est pas disponible?

Steve HHH
la source
J'avais le même problème. La réponse de @Subhranath Chunder ci-dessous a aidé. Cependant, j’ai alors découvert que l’installation de Telnet n’était qu’une affaire d’exécution brew install telnet. Je pense donc que les utilisateurs de Linux peuvent faire la même chose avec yumet apt-get.
Mig82 le

Réponses:

277

Bash est capable d'accéder aux ports TCP et UDP depuis un moment. De la page de manuel:

/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!

Lornix
la source
Cela semble aussi fonctionner dans MinGW . Par exemple, un serveur VNC distant sur 192.168.2.100 répond par "RFB 003.008" en utilisant "cat </dev/tcp/192.168.2.100/5900".
Peter Mortensen
1
@lornix, d'accord, mais dans ce cas, je dois obtenir le même résultat avec use nc sans l'option -z, mais cela ne fonctionne toujours pas: # nc -v -w5 127.0.0.1 18080 Connexion à 127.0.0.1 18080 port [tcp / *] réussi! # cat </dev/tcp/127.0.0.1/18080 Bloque juste sans résultat. Je veux juste comprendre quand je peux utiliser l'option "/ dev / tcp / host / port"
Alexandr
5
@ Alexandr ... en fait, "se bloque sans résultat" est à peu près le comportement attendu. le chat est en attente d'entrée. nc a des compétences supplémentaires pour lui permettre de détecter les données en attente et arrête d'essayer. chat n'est pas tout à fait aussi intelligent. Essayez cat < /dev/tcp/localhost/22, vous devriez obtenir votre en-tête sshd. Il est évident que votre processus sur le port 18080 attend que quelque chose entre avant d'envoyer quoi que ce soit. Le port 22 ( SSH ) vous salue avec sa version et tout le reste. Essaye le!
Lornix
1
@lornix, merci beaucoup pour l'explication! Maintenant, la restriction est claire. Je pense que l’utilisation de nc devrait être un moyen privilégié de vérifier les ports.
Alexandr
2
Cela a été incroyablement utile lorsque vous travaillez avec un conteneur Docker sur lequel rien n’est installé. A pu vérifier rapidement que le conteneur avait accès à une base de données non conteneurisée via DNS. Exemple: cat </ dev / tcp / hostname / 5432
Michael Hobbs
404

Sympa et prolixe! À partir des pages de manuel.
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
Subhranath Chunder
la source
6
Semble être la meilleure réponse, merci. ;-)
lpapp
6
Ceci a été suspendu lors d’une tentative sous Ubuntu 14.04 (Trusty Tahr) pour un serveur distant (même réseau local) pour les ports fermés (le délai a expiré après 127 secondes) - n’est donc pas très approprié dans les scripts. Cela fonctionnait bien pour un service avec un port ouvert. L'utilisation de l'option "-w2" pourrait être la solution.
Peter Mortensen
6
Utilisez l'option -u pour les ports UDP.
Efren
8
Sur la version 6.4, ncat -z n'est pas reconnu. Je pouvais me passer de z
smishra
5
Vous pouvez vérifier plusieurs plages avec: nc -zv 127.0.0.1 22,80,8080,20-30,443-446(nc Version: 1.107-4).
Bob
102

Netcat est un outil utile:

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

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

thnee
la source
C'est une réponse beaucoup plus élégante et scriptable que la mienne. Il est regrettable pour moi que les administrateurs système soucieux de la sécurité qui ont refusé de le telnetretenir se ncsoient également abstenus (quoique - étrangement - pas curlou wget).
Steve HHH
Oui, c'est complètement arbitraire et idiot.
Thnee
3
Que les FORdéclarations commencent!
Chad Harrison
1
Ceci a été corrigé lors de l’essai sur Ubuntu 14.04 (Trusty Tahr) pour un serveur distant (même réseau local) pour les ports fermés (il a expiré après environ 127 secondes) - n’est donc pas très approprié dans les scripts. Cela fonctionnait cependant pour un service ayant un port ouvert, renvoyant 0. Utiliser l'option "-w2" pourrait être la solution.
Peter Mortensen
1
Je pense que -G 2serait plus approprié pour le délai d'attente TCP
AB
58

La méthode la plus simple, sans faire appel à un autre outil, tel que socat, est décrite dans la réponse de @ lornix ci-dessus. Ceci est juste pour ajouter un exemple concret de la façon dont on utiliserait le périphérique psuedo /dev/tcp/...dans Bash si, par exemple, vous vouliez tester si un autre serveur avait 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 placer les echo > /dev/...parenthèses de cette manière (echo > /dev/...)est que si vous ne le faites pas, vous obtenez alors ce type de message avec les tests des connexions en panne.

$ (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/nullcar ils viennent de la tentative d'écrire des données sur le périphérique /dev/tcp. Nous capturons donc toute cette sortie dans une sous-commande, c'est-à-dire (...cmds...)et redirigeons la sortie de la sous-commande.

slm
la source
C'est excellent. Je souhaite qu'il soit voté jusqu'au sommet. Je n’ai lu que très loin dans la page parce que j’ai accidentellement fait défiler la page avant de la fermer.
Still.Tony
@ Okuma.Tony - Oui, c'est toujours un problème avec les questions à réponses multiples 8-). Merci pour les commentaires cependant, c'est apprécié.
slm
46

J'ai constaté que curlle travail peut être effectué de la même manière telnetet que curlje vous dirai même quel protocole attend l'auditeur.

Construisez un URI HTTP à partir du nom d'hôte et du port en tant que premier argument curl. S'il curlpeut se connecter, il signalera une incompatibilité de protocole et se fermera (si l'auditeur n'est pas un service Web). Si curlne peut pas se connecter, il expirera.

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

Toutefois, à partir d'un autre système, le port 5672 de l'hôte 10.0.0.99 est accessible et semble exécuter un écouteur AMQP.

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

Il est important de faire la distinction entre les différents messages: le premier échec était dû au fait que la curlconnexion au port était impossible. Le deuxième échec est un test de réussite, bien que curlprévu un écouteur HTTP au lieu d'un écouteur AMQP.

Steve HHH
la source
5
Si curl n'est pas disponible, wget pourrait l'être. wget -qS -O- http://ip.add.re.ss:portdevrait effectivement faire la même chose.
un CVn
4
Cela fonctionne même avec un nom d'hôte, ex. curl myhost:22.
에이 바
Cela peut être incorrect. J'ai un service Tomcat en cours d'exécution, mais je reçois une erreur 404. # curl -k 192.168.194.4:6443 <html> <head> <title> Apache Tomcat / 7.0.34 - Rapport d'erreur </ title> <style> <! - H1 --- HR {color: # 525D76;} -> </ style> </ head> <body> <h1> Statut HTTP 404 - / </ h1> <HR size = "1" noshade = "noshade"> <p> <b> type </ b> Rapport de statut </ p> <p> <b> message </ b> <u> / </ u> </ p> <p> <p> <b> description </ b> <u> La ressource demandée n'est pas disponible. </ u> </ p> <HR size = "1" noshade = "noshade"> <h3> Apache Tomcat / 7.0.34 </ h3> </ body> </ html>
Voir mon post avec une approche similaire.
Kenorb
12
[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ésoudra votre problème :)

Mohammad Shahid Siddiqui
la source
1
Oui, c'est mieux - le délai d'attente presque immédiatement pour les ports fermés.
Peter Mortensen
1
Est-ce que cela utilise toujours TCP ou y a-t-il un moyen de le faire pour vérifier UDP?
kmoe
6

Je me suis battu toute la journée parce qu'aucune de ces réponses ne semblait fonctionner pour moi. Le problème est que la version la plus récente de ncn'a plus le -zdrapeau, alors que l'accès direct via TCP (selon @lornix et @slm) échoue lorsque l'hôte n'est pas accessible. J'ai finalement trouvé cette page , où j'ai finalement trouvé non pas un mais deux exemples de travail:

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

    (le -wdrapeau prend en charge le délai d'attente, et le </dev/nullremplace le -zdrapeau)

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

    (la timeoutcommande 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.

Azukikuru
la source
4

En combinant les réponses de @kenorb et de @ Azukikuru, vous pouvez tester le port ouvert / fermé / avec un pare-feu.

timeout 1 bash -c '</dev/tcp/127.0.0.1/22 && echo Port is open || echo Port is closed' || echo Connection timeout

Une autre approche avec curl pour atteindre n'importe quel port

curl telnet://127.0.0.1:22
Miguel Ferreira
la source
3

Voici une fonction qui choisira l’une des méthodes en fonction de ce qui est installé sur votre système:

# Check_port <address> <port> 
check_port() {
if [ "$(which nc)" != "" ]; then 
    tool=nc
elif [ "$(which curl)" != "" ]; then
     tool=curl
elif [ "$(which telnet)" != "" ]; then
     tool=telnet
elif [ -e /dev/tcp ]; then
      if [ "$(which gtimeout)" != "" ]; then  
       tool=gtimeout
      elif [ "$(which timeout)" != "" ]; then  
       tool=timeout
      else
       tool=devtcp
      fi
fi
echo "Using $tool to test access to $1:$2"
case $tool in
nc) nc -v -G 5 -z -w2 $1 $2 ;;
curl) curl --connect-timeout 10 http://$1:$2 ;;
telnet) telnet $1 $2 ;;
gtimeout)  gtimeout 1 bash -c "</dev/tcp/${1}/${2} && echo Port is open || echo Port is closed" || echo Connection timeout ;;
timeout)  timeout 1 bash -c "</dev/tcp/${1}/${2} && echo Port is open || echo Port is closed" || echo Connection timeout ;;
devtcp)  </dev/tcp/${1}/${2} && echo Port is open || echo Port is closed ;;
*) echo "no tools available to test $1 port $2";;
esac

}
export check_port
Robert Boyd
la source
2

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

peperunas
la source
4
nmapest un bon outil, mais non disponible sur ces systèmes. Plutôt que de le télécharger nmap, de le compiler, de l'installer dans mon répertoire personnel, puis de le copier sur tous les autres systèmes, j'espérais trouver un moyen d'utiliser les outils existants disponibles dans la plupart des installations Linux.
Steve HHH
1

pour référence, développant la réponse de @peperunas:

la façon d'utiliser nmap pour tester, est:

nmap -p 22 127.0.0.1

(exemple ci-dessus utilise localhost à des fins de démonstration)

utilisateur138278
la source
0

Si vous devez tester plus que sur le système, vous pouvez utiliser notre outil de test, dda-serverspec ( https://github.com/DomainDrivenArchitecture/dda-serverspec-crate ) pour ces tâches. Vous pouvez définir vos attentes

{:netcat [{:host "mywebserver.com" :port "443"}
          {:host "telnet mywebserver.com" :port "80"}
          {:host "telnet mywebserver.com" :port "8443"}]}

et testez ces attentes soit avec localhost, soit avec des hôtes distants (connectez-vous via ssh). Pour les tests à distance, vous devez définir une cible:

{:existing [{:node-name "test-vm1"
             :node-ip "35.157.19.218"}
            {:node-name "test-vm2"
             :node-ip "18.194.113.138"}]
 :provisioning-user {:login "ubuntu"}}

Vous pouvez exécuter le test avec java -jar dda-serverspec.jar --targets targets.edn serverspec.edn

Sous le capot, nous utilisons netcat tel que proposé ci-dessus ...

jerger
la source