Pregunta Pruebe si se puede alcanzar un puerto en un sistema remoto (sin telnet)


En los viejos tiempos, utilizamos telnet para ver si un puerto en un host remoto estaba abierto: telnet hostname port Intentarí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 por defecto. Con el tiempo, es fácil perder la pista de qué puertos están abiertos para qué hosts.

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


251


origen


Relacionado: verificar el estado de un puerto en el host remoto en SO - kenorb


Respuestas:


Bash ha podido acceder TCP y UDP puertos por un tiempo. Desde la página 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.

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!


214



Esto también parece funcionar en MinGW. Por ejemplo, un control remoto VNC el servidor en 192.168.2.100 responde con "RFB 003.008" usando "cat </dev/tcp/192.168.2.100/5900". - Peter Mortensen
Sin embargo, en los puertos que no estaban abiertos, se agotó el tiempo de espera después de 22 segundos (probado Ubuntu 14.04 (Trusty Tahr) para un servidor remoto). Curiosamente, el tiempo de espera es mucho más corto que el de nc (ver la respuesta de thnee) - Peter Mortensen
@lornix, vale, 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 18080 Conexión a 127.0.0.1 puerto de 18080 [tcp / *] tenido éxito! # cat </dev/tcp/127.0.0.1/18080 Simplemente cuelga sin ningún resultado. Solo quiero entender cuándo puedo usar la opción "/ dev / tcp / host / port" - Alexandr
@Alexandr ... en realidad, "se bloquea sin ningún resultado" es un comportamiento bastante esperado. gato está esperando la entrada. Carolina del Norte tiene inteligencia adicional para permitirle detectar que no hay datos pendientes y deja de intentarlo. gato no es bastante tan inteligente. Tratar cat < /dev/tcp/localhost/22, deberías obtener tu encabezado sshd. Evidentemente, su proceso en el puerto 18080 espera que ocurra algo, antes de enviar cualquier cosa. Puerto 22 (ssh) te saluda con su versión y otras cosas. ¡Pruébalo! - lornix
@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 puertos. - Alexandr


Agradable y detallado! De las páginas man.
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

294



Parece ser la mejor respuesta, gracias. ;-) - lpapp
Esto se ahorcó cuando se probó 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 los 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
Use la opción -u para puertos UDP. - Efren
En la versión 6.4 de ncat -z no se reconoce. Pude prescindir de z - smishra
Puede verificar múltiples rangos con: nc -zv 127.0.0.1 22,80,8080,20-30,443-446 (Versión nc: 1.107-4). - bobbel


Netcat es una herramienta útil:

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

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


96



Esta es una respuesta mucho más elegante y scriptable que la mía. Es desafortunado para mí que los administradores de sistemas conscientes de la seguridad que ocultaron telnet también retenido nc (aunque, curiosamente, no curl o wget) - Steve HHH
Sí, eso es completamente arbitrario y tonto. - thnee
Deja el FOR declaraciones comienzan! - Chad Harrison
Esto se ahorcó cuando se probó Ubuntu 14.04 (Trusty Tahr) para un servidor remoto (misma LAN) para puertos cerrados (se agotó el tiempo de espera después de unos 127 segundos), por lo que no es muy adecuado en los scripts. Sin embargo, funcionó para un servicio que tenía un puerto abierto, que retornaba 0. El uso de la opción "-w2" podría ser la solución. - Peter Mortensen
creo -G 2 sería más apropiado para el tiempo de espera de TCP - A B


El método más simple, sin hacer uso de 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 quería, 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 quieres envolver el echo > /dev/... entre paréntesis como este, (echo > /dev/...) es porque si no lo hace, entonces con las pruebas de las conexiones que están 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 ser simplemente redirigidos a /dev/null ya que provienen del intento de escribir datos en el dispositivo /dev/tcp. Entonces capturamos toda esa salida dentro de un sub comando, es decir (...cmds...) y redirigir la salida del subcomando.


48



Esto es excelente. Ojalá se votara hasta la cima. Solo leo esto hasta el final de la página porque accidentalmente me desplacé antes de cerrarlo. - Still.Tony
@ Okuma.Tony - sí, eso siempre es un problema con las Q que tienen muchas respuestas 8-). Gracias por los comentarios, es apreciado. - slm


encontre eso curl puede hacer el trabajo de una manera similar a telnety curl incluso te 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 curl se puede conectar, informará una discrepancia de protocolo y saldrá (si el oyente no es un servicio web). Si curl no se puede conectar, se apagará.

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 oyente 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 fracaso fue porque curl no se pudo conectar al puerto. El segundo fracaso es una prueba de éxito, aunque curl esperado un oyente HTTP en lugar de un oyente AMQP.


35



Si curl no está disponible, wget podría estarlo. wget -qS -O- http://ip.add.re.ss:port debería efectivamente hacer lo mismo. - Michael Kjörling
Esto incluso funciona con un nombre de host, ej. curl myhost:22. - 에이바
Esto puede ser incorrecto Tengo un servicio de tomcat en ejecución, pero obtengo el error 404. # curl -k 192.168.194.4:6443 <html> <head> <title> Apache Tomcat / 7.0.34 - Informe de errores </ title> <style> <! - H1 --- HR {color: # 525D76;} -> </ style> </ head> <body> <h1> HTTP Status 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 tamaño = "1" noshade = "noshade"> <h3> Apache Tomcat / 7.0.34 </ h3> </ body> </ html> - Mohammad Shahid Siddiqui
Mira mi enviar con un enfoque similar. - kenorb


[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 :)


8



Sí, esto es mejor: se agota el tiempo casi de inmediato para puertos cerrados. - Peter Mortensen
¿Esto siempre usa TCP o hay una forma de hacerlo verificar UDP? - kmoe


Aquí hay un trazador de líneas:

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

usando la sintaxis de Bash explicada en @lornix respuesta.

Para más información, verifique: Guía Avanzada de Bash-Scripting: Capítulo 29. /dev y /proc.


7





Estuve luchando todo el día porque ninguna de estas respuestas pareció funcionar para mí. El problema es que la versión más reciente de nc ya no tiene el -z indicador, mientras que el acceso directo a través de TCP (según @lornix y @slm) falla cuando el host no es accesible. 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

    (el -w bandera se ocupa del tiempo de espera, y el </dev/null reemplaza el -z bandera)

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

    (el timeout el comando se ocupa del tiempo de espera, y el resto es de @slm)

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


5





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


2



nmap es una buena herramienta, pero no está disponible en estos sistemas. En lugar de descargar nmap, compilarlo, instalarlo en mi directorio de inicio y luego copiarlo a todos los otros sistemas. Esperaba encontrar la forma de usar las herramientas existentes disponibles en la mayoría de las instalaciones de Linux. - Steve HHH


Combinando las respuestas de @kenorb y @Azukikuru podrías 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 curl para llegar a cualquier puerto

curl telnet://127.0.0.1:22

0