Pruebe si un puerto en un sistema remoto es accesible (sin telnet)


353

En los viejos tiempos, solíamos telnetver si un puerto en un host remoto estaba abierto: telnet hostname portintentaría conectarse a cualquier puerto en cualquier host y le daría acceso a la transmisión TCP sin procesar.

En estos días, los sistemas en los que trabajo no tienen telnet instalado (por razones de seguridad), y todas las conexiones salientes a todos los hosts están bloqueadas de forma predeterminada. Con el tiempo, es fácil perder la noción de qué puertos están abiertos para qué hosts.

¿Hay otra forma de probar si un puerto en un sistema remoto está abierto, usando un sistema Linux con un número limitado de paquetes instalados y telnetno está disponible?



Estaba teniendo este mismo problema. La respuesta de @Subhranath Chunder a continuación ayudó. Sin embargo, luego descubrí que instalar Telnet era una pequeña cuestión de ejecución brew install telnet. Así que espero que los usuarios de Linux puedan hacer lo mismo con yumy apt-get.
Mig82

Respuestas:


277

Bash ha podido acceder a los puertos TCP y UDP por un tiempo. Desde la página del manual:

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

Entonces podrías usar algo como esto:

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

Taa Daa!


Esto también parece funcionar en MinGW . Por ejemplo, un servidor VNC remoto en 192.168.2.100 responde con "RFB 003.008" utilizando "cat </dev/tcp/192.168.2.100/5900".
Peter Mortensen

1
@lornix, ok, pero en este caso tengo que obtener el mismo resultado con el uso de nc sin la opción -z, pero todavía no funciona: # nc -v -w5 127.0.0.1 Conexión 18080 a 127.0.0.1 puerto 18080 [tcp / *] tuvo éxito! # cat </dev/tcp/127.0.0.1/18080 Simplemente se cuelga sin ningún resultado. Solo quiero entender cuándo puedo usar la opción "/ dev / tcp / host / port"
Alexandr

55
@Alexandr ... en realidad, "se cuelga sin ningún resultado" es un comportamiento bastante esperado. El gato está esperando la entrada. nc tiene inteligencia adicional para permitirle detectar que no hay datos pendientes y deja de intentarlo. El gato no es tan inteligente. Intenta cat < /dev/tcp/localhost/22, deberías obtener tu encabezado sshd. Evidentemente, su proceso en el puerto 18080 espera que entre algo antes de enviar algo. El puerto 22 ( ssh ) te saluda con su versión y demás. ¡Pruébalo!
lornix

1
@lornix, muchas gracias por la explicación! Ahora la restricción es clara. Creo que usar nc debería ser una forma preferida de verificar los puertos.
Alexandr

2
Esto fue increíblemente útil cuando se trabajaba con un contenedor acoplable que no tenía nada instalado. Pude verificar rápidamente que el contenedor tenía acceso a DB no en contenedores a través de DNS. Ejemplo: cat </ dev / tcp / hostname / 5432
Michael Hobbs el

404

Agradable y detallado! De las páginas del manual.
Puerto único:

nc -zv 127.0.0.1 80

Múltiples puertos:

nc -zv 127.0.0.1 22 80 8080

Rango de puertos:

nc -zv 127.0.0.1 20-30

66
Parece estar lejos la mejor respuesta, gracias. ;-)
lpapp

66
Esto se colgó cuando se intentó en Ubuntu 14.04 (Trusty Tahr) para un servidor remoto (misma LAN) para puertos cerrados (se agotó el tiempo de espera después de 127 segundos), por lo que no es muy adecuado en scripts. Sin embargo, funcionó para un servicio que tenía un puerto abierto. Usar la opción "-w2" podría ser la solución.
Peter Mortensen

66
Use la opción -u para los puertos UDP.
Efren

8
En la versión 6.4 de ncat -z no se reconoce. Pude prescindir de z
smishra

55
Puede verificar múltiples rangos con: nc -zv 127.0.0.1 22,80,8080,20-30,443-446(nc Versión: 1.107-4).
bobbel

102

Netcat es una herramienta útil:

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

Saldrá 0si el puerto 123 está abierto y 1si está cerrado.


Esta es una respuesta mucho más elegante y fácil de escribir que la mía. Es lamentable para mí que los administradores de sistemas conscientes de la seguridad que retenían telnettambién ocultaran nc(aunque, curiosamente, no curlo wget).
Steve HHH

Sí, eso es completamente arbitrario y tonto.
Thnee

3
¡Que FORcomiencen las declaraciones!
Chad Harrison

1
Esto se colgó cuando se probó en Ubuntu 14.04 (Trusty Tahr) para un servidor remoto (misma LAN) para puertos cerrados (se agotó el tiempo de espera después de aproximadamente 127 segundos), por lo que no es muy adecuado en scripts. Sin embargo, funcionó para un servicio que tenía un puerto abierto, devolviendo 0. Usar la opción "-w2" podría ser la solución.
Peter Mortensen

1
Creo que -G 2sería más apropiado para el tiempo de espera de TCP
AB

58

El método más simple, sin utilizar otra herramienta, como socat, es como se describe en la respuesta de @ lornix anterior. Esto es solo para agregar un ejemplo real de cómo se haría uso del dispositivo psuedo /dev/tcp/...dentro de Bash si quisiera, por ejemplo, probar si otro servidor tenía un puerto determinado accesible a través de la línea de comando.

Ejemplos

Digamos que tengo un host en mi red llamado 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 razón por la que desea envolver el echo > /dev/...paréntesis de esta manera (echo > /dev/...)es porque si no lo hace, con las pruebas de conexiones inactivas, aparecerá este tipo de mensajes.

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

Estos no pueden simplemente ser redirigidos /dev/nullya que provienen del intento de escribir datos en el dispositivo /dev/tcp. Entonces capturamos toda esa salida dentro de un subcomando, es decir, (...cmds...)y redirigimos la salida del subcomando.


Esto es excelente. Ojalá fuera votado hasta la cima. Solo leí esto abajo en la página porque accidentalmente me desplacé antes de cerrarlo.
Aún así

@ Okuma.Tony: sí, eso siempre es un problema con las Q que tienen muchas respuestas 8-). Sin embargo, gracias por los comentarios, es apreciado.
slm

46

Descubrí que curlpuede hacer el trabajo de una manera similar telnete curlincluso le dirá qué protocolo espera el oyente.

Construya un URI HTTP a partir del nombre de host y el puerto como primer argumento para curl. Si curlpuede conectarse, informará una falta de coincidencia de protocolo y saldrá (si el oyente no es un servicio web). Si curlno puede conectarse, se agotará el tiempo de espera.

Por ejemplo, el puerto 5672 en el host 10.0.0.99 está cerrado o bloqueado por un firewall:

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

Sin embargo, desde un sistema diferente, se puede acceder al puerto 5672 en el host 10.0.0.99, y parece estar ejecutando un escucha AMQP.

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

Es importante distinguir entre los diferentes mensajes: el primer error fue porque curlno se pudo conectar al puerto. La segunda falla es una prueba de éxito, aunque se curlesperaba un escucha HTTP en lugar de un escucha AMQP.


55
Si curl no está disponible, wget podría estarlo. wget -qS -O- http://ip.add.re.ss:portefectivamente debería hacer lo mismo.
un CVn

44
Esto incluso funciona con un nombre de host, ej. curl myhost:22.
에이 바

Esto puede ser incorrecto. Tengo un servicio Tomcat ejecutándose, pero obtengo un error 404. # curl -k 192.168.194.4:6443 <html><head> <title> Apache Tomcat / 7.0.34 - Informe de error </title> <style> <! - H1 --- HR {color: # 525D76;} -> </style> </head><body> <h1> HTTP Estado 404 - / </h1> <HR size = "1" noshade = "noshade"> <p> <b> tipo </b> Informe de estado </p> <p> <b> mensaje </b> <u>/</u></p><p> <b> descripción </b> <u> El recurso solicitado no está disponible. </u> </p> <HR size = "1" noshade = "noshade"> <h3> Apache Tomcat / 7.0.34 </h3> </body> </html>

Vea mi publicación con un enfoque similar.
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!

Espero que resuelva tu problema :)


1
Sí, esto es mejor: el tiempo de espera es casi inmediato para puertos cerrados.
Peter Mortensen

1
¿Esto siempre utiliza TCP o hay alguna forma de que compruebe UDP?
kmoe


6

Estuve luchando durante todo un día porque ninguna de estas respuestas parecía funcionar para mí. El problema es que la versión más reciente de ncya no tiene la -zbandera, mientras que el acceso directo a través de TCP (según @lornix y @slm) falla cuando no se puede acceder al host. Finalmente encontré esta página , donde finalmente encontré no uno sino dos ejemplos de trabajo:

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

    (la -wbandera se encarga del tiempo de espera y la </dev/nullreemplaza -z)

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

    (el timeoutcomando se encarga del tiempo de espera y el resto es de @slm)

Luego, simplemente use &&y / o ||(o incluso $?) para extraer el resultado. Con suerte, alguien encontrará útil esta información.


4

Combinando las respuestas de @kenorb y @Azukikuru, podría probar el puerto abierto / cerrado / cortafuegos.

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

Otro enfoque con rizo para llegar a cualquier puerto

curl telnet://127.0.0.1:22

3

Aquí hay una función que elegirá uno de los métodos dependiendo de lo que esté instalado en su sistema:

# 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

2

No debería estar disponible en su caja, pero intente con nmap.


44
nmapes una buena herramienta, pero no está disponible en estos sistemas. En lugar de descargarlo nmap, compilarlo, instalarlo en mi directorio de inicio y luego copiarlo en todos los demás sistemas, esperaba encontrar una manera utilizando las herramientas existentes disponibles en la mayoría de las instalaciones de Linux.
Steve HHH

1

como referencia, ampliando la respuesta de @peperunas:

La forma de usar nmap para probar es:

nmap -p 22 127.0.0.1

(el ejemplo anterior usa localhost para fines de demostración)


0

Si tiene que probar más que en el sistema, puede usar nuestra herramienta de prueba dda-serverpec ( https://github.com/DomainDrivenArchitecture/dda-serverspec-crate ) para tales tareas. Puedes definir tus expectativas

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

y pruebe estas expectativas ya sea contra localhost o contra hosts remotos (conectarse mediante ssh). Para las pruebas remotas, debe definir un objetivo:

{: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"}}

Puede ejecutar la prueba con java -jar dda-serverspec.jar --targets targets.edn serverspec.edn

Debajo del capó estamos usando netcat como se propuso arriba ...

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.