2013-07-19 16:54:10 +0000 2013-07-19 16:54:10 +0000
369

Probar si un puerto en un sistema remoto es alcanzable (sin telnet)

En los viejos tiempos, usábamos telnet para ver si un puerto en un host remoto estaba abierto: telnet hostname port intentaba conectarse a cualquier puerto en cualquier host y le daba acceso al flujo TCP crudo.

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 a qué hosts.

¿Existe 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?

Respuestas [13]

418
2013-12-03 21:34:41 +0000

¡Lindo y verborreico! De las páginas de manual. Un solo puerto:

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
418
297
2013-07-22 10:37:11 +0000

Bash ha sido capaz de acceder a los puertos TCP y UDP por un tiempo. Desde la página del hombre:

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

Así que 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!

297
104
2013-07-19 18:07:26 +0000

Netcat es una herramienta útil:

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

dará salida a 0 si el puerto 123 está abierto, y a 1 si está cerrado.

104
61
2014-09-02 17:59:36 +0000

El método más simple, sin hacer uso de otra herramienta, como socat, es el que se describe en la respuesta de @lornix arriba. Esto es sólo para añadir un ejemplo real de cómo se haría uso del dispositivo psuedo /dev/tcp/... dentro de Bash si se quisiera, por ejemplo, probar si otro servidor tiene un puerto determinado accesible a través de la línea de comandos.

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 haces, entonces con las pruebas de conexiones que están caídas, obtendrás este tipo de mensajes que aparecen.

$ (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 vienen del intento de escribir datos en el dispositivo /dev/tcp. Así que capturamos toda esa salida dentro de un subcomando, es decir (...cmds...) y redirigimos la salida del subcomando.

61
48
2013-07-19 17:05:30 +0000

Encontré que curl puede hacer el trabajo de manera similar a telnet, e incluso curl le dirá qué protocolo espera el oyente.

Construir una URI HTTP del nombre de host y el puerto como primer argumento para curl. Si curl puede conectarse, reportará un desajuste de protocolo y saldrá (si el oyente no es un servicio web). Si curl no 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 cortafuegos:

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

Sin embargo, desde un sistema diferente, el puerto 5672 en el host 10. 0.0.99 puede ser alcanzado, y parece estar ejecutando un receptor 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 fallo fue porque curl no pudo conectarse al puerto. El segundo fallo es una prueba de éxito, aunque curl esperaba un receptor HTTP en lugar de un receptor AMQP.

48
13
2015-06-02 06:27:59 +0000
[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 esto resuelva tu problema :)

13
8
2017-05-31 08:45:09 +0000

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

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

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

8
6
2018-08-10 12:20:04 +0000

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

timeout 1 bash -c '

Otro enfoque con rizo para llegar a cualquier puerto

curl telnet://127.0.0.1:22
6
4
2019-02-12 20:21:11 +0000

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

# Check_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 "
4
2
2013-07-19 17:01:16 +0000

No debería estar disponible en tu caja, pero prueba con nmap.

2
1
2019-08-07 23:17:13 +0000

para 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 propósitos de demostración)

1
0
2018-10-26 13:49:54 +0000

Si tiene que probar más que en el sistema puede usar nuestra herramienta de pruebas dda-serverspec 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 probar estas expectativas contra el host local o contra hosts remotos (conectar por ssh). Para las pruebas remotas tienes que 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"}}

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

Bajo el capó estamos usando netcat como se indica arriba ...

0