Verifica se è possibile raggiungere una porta su un sistema remoto (senza telnet)


353

Ai vecchi tempi, telnetvedevamo se una porta su un host remoto era aperta: telnet hostname porttentava di connettersi a qualsiasi porta su qualsiasi host e ti dava accesso al flusso TCP grezzo.

In questi giorni, i sistemi su cui lavoro non hanno telnet installato (per motivi di sicurezza) e tutte le connessioni in uscita a tutti gli host sono bloccate per impostazione predefinita. Nel tempo, è facile perdere traccia di quali porte sono aperte a quali host.

Esiste un altro modo per verificare se una porta su un sistema remoto è aperta, utilizzando un sistema Linux con un numero limitato di pacchetti installati e telnetnon è disponibile?



Stavo avendo lo stesso problema. La risposta di @Subhranath Chunder di seguito è stata di aiuto. Tuttavia, ho scoperto che l'installazione di Telnet era una piccola questione di esecuzione brew install telnet. Quindi mi aspetto che gli utenti Linux possano fare lo stesso con yume apt-get.
Mig82,

Risposte:


277

Bash è stato in grado di accedere alle porte TCP e UDP per un po '. Dalla pagina 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.

Quindi potresti usare qualcosa del genere:

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

Taa Daa!


Anche questo sembra funzionare in MinGW . Ad esempio, un server VNC remoto su 192.168.2.100 risponde con "RFB 003.008" utilizzando "cat </dev/tcp/192.168.2.100/5900".
Peter Mortensen,

1
@lornix, ok, ma in questo caso devo ottenere lo stesso risultato con l'uso di nc senza l'opzione -z, ma non funziona ancora: # nc -v -w5 127.0.0.1 18080 Connessione alla porta 127.0.0.1 18080 [tcp /*] successo! # cat </dev/tcp/127.0.0.1/18080 Si blocca semplicemente senza alcun risultato. Voglio solo capire quando posso usare l'opzione "/ dev / tcp / host / port"
Alexandr

5
@Alexandr ... in realtà, "si blocca senza alcun risultato" è un comportamento praticamente previsto. cat è in attesa di input. nc ha ulteriori risorse per consentirgli di rilevare la mancanza di dati in sospeso e smette di provare. gatto non è abbastanza intelligente. Prova cat < /dev/tcp/localhost/22, dovresti ottenere la tua intestazione sshd. Evidentemente, il tuo processo sulla porta 18080 attende che arrivi qualcosa prima di inviare qualcosa. Port 22 ( ssh ) ti saluta con la sua versione e quant'altro. Provalo!
Lornix,

1
@lornix, grazie mille per la spiegazione! Ora la restrizione è chiara. Penso che usare nc dovrebbe essere un modo preferito per controllare le porte.
Alexandr,

2
Ciò è stato incredibilmente utile quando si lavora con un contenitore docker su cui non è installato nulla. È stato in grado di verificare rapidamente che il contenitore avesse accesso a DB non containerizzato tramite DNS. Esempio: cat </ dev / tcp / hostname / 5432
Michael Hobbs,

404

Bello e prolisso! Dalle pagine man.
Porta singola:

nc -zv 127.0.0.1 80

Porte multiple:

nc -zv 127.0.0.1 22 80 8080

Gamma di porte:

nc -zv 127.0.0.1 20-30

6
Sembra essere di gran lunga la risposta migliore, grazie. ;-)
lpapp il

6
Ciò si è bloccato quando provato su Ubuntu 14.04 (Trusty Tahr) per un server remoto (stessa LAN) per porte chiuse (è scaduto dopo 127 secondi) - quindi non molto adatto negli script. Ha funzionato però per un servizio con una porta aperta. L'uso dell'opzione "-w2" potrebbe essere la soluzione.
Peter Mortensen,

6
Utilizzare l'opzione -u per le porte UDP.
Efren,

8
Sulla versione 6.4 di ncat -z non è riconosciuto. Sono stato in grado di fare a meno di z
smishra il

5
Puoi controllare più intervalli con: nc -zv 127.0.0.1 22,80,8080,20-30,443-446(nc Versione: 1.107-4).
Bob

102

Netcat è uno strumento utile:

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

Verrà emesso 0se la porta 123 è aperta e 1se è chiusa.


Questa è una risposta molto più elegante e gestibile dalla mia. È una sfortuna per me che anche gli amministratori di sistema attenti alla sicurezza che telnethanno rifiutato nc(anche se - stranamente - non lo fanno curlo no wget).
Steve HHH,

Sì, è completamente arbitrario e sciocco.
giovedì

3
Che le FORdichiarazioni abbiano inizio!
Chad Harrison,

1
Ciò si è bloccato quando provato su Ubuntu 14.04 (Trusty Tahr) per un server remoto (stessa LAN) per porte chiuse (è scaduto dopo circa 127 secondi) - quindi non molto adatto negli script. Ha funzionato però per un servizio che aveva una porta aperta, restituendo 0. L'uso dell'opzione "-w2" potrebbe essere la soluzione.
Peter Mortensen,

1
Penso che -G 2sarebbe più appropriato per il timeout TCP
AB

58

Il metodo più semplice, senza utilizzare un altro strumento, come ad esempio socat, è come descritto nella risposta di @lornix sopra. Questo è solo per aggiungere un esempio reale di come si farebbe uso del psuedo-dispositivo /dev/tcp/...all'interno di Bash se si volesse, per esempio, verificare se un altro server aveva una determinata porta accessibile tramite la riga di comando.

Esempi

Supponiamo di avere un host sulla mia rete chiamato 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

Il motivo per cui vuoi racchiudere le echo > /dev/...parentesi in questo modo (echo > /dev/...)è perché se non lo fai, quindi con i test delle connessioni che sono inattivi, otterrai questi tipi di messaggi.

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

Questi non possono essere semplicemente reindirizzati /dev/nullpoiché provengono dal tentativo di scrivere dati sul dispositivo /dev/tcp. Quindi catturiamo tutto l'output all'interno di un comando secondario, ovvero (...cmds...)reindirizziamo l'output del comando secondario.


Questo è eccellente Vorrei che fosse votato fino in cima. Ho letto solo in fondo alla pagina perché ho accidentalmente scorrere prima di chiuderlo.
Still.Tony,

@ Okuma.Tony - sì, questo è sempre un problema con Q che hanno molte risposte Cool. Grazie per il feedback, è apprezzato.
slm,

46

Ho scoperto che curlpotrebbe svolgere il lavoro in modo simile a telnet, e curlti dirò anche quale protocollo si aspetta l'ascoltatore.

Costruisci un URI HTTP dal nome host e dalla porta come primo argomento a curl. Se curlpuò connettersi, segnalerà una mancata corrispondenza del protocollo e l'uscita (se l'ascoltatore non è un servizio Web). Se curlnon è possibile connettersi, si verificherà il timeout.

Ad esempio, la porta 5672 sull'host 10.0.0.99 è chiusa o bloccata da un firewall:

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

Tuttavia, da un sistema diverso, è possibile raggiungere la porta 5672 sull'host 10.0.0.99 e sembra che stia eseguendo un listener AMQP.

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

È importante distinguere tra i diversi messaggi: il primo errore è stato perché curlnon è stato possibile connettersi alla porta. Il secondo errore è un test di successo, sebbene curlprevisto un listener HTTP anziché un listener AMQP.


5
Se l'arricciatura non è disponibile, potrebbe essere wget. wget -qS -O- http://ip.add.re.ss:portdovrebbe effettivamente fare la stessa cosa.
un CVn

4
Funziona anche con un nome host, ad es. curl myhost:22.
에이 바

Questo potrebbe non essere corretto. Sto eseguendo un servizio Tomcat in esecuzione, ma ricevo un errore 404. # curl -k 192.168.194.4:6443 <html><head> <title> Apache Tomcat / 7.0.34 - Rapporto errori </title> <style> <! - H1 --- HR {color: # 525D76;} -> </style> </head><body> <h1> Stato HTTP 404 - / </h1> <HR size = "1" noshade = "noshade"> <p> <b> type </b> Rapporto sullo stato </p> <p> <b> messaggio </b> <u>/</u></p><p> <b> descrizione </b> <u> La risorsa richiesta non è disponibile. </u> </p> <HR size = "1" noshade = "noshade"> <h3> Apache Tomcat / 7.0.34 </h3> </body> </html>

Vedi il mio post con un approccio simile.
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!

Spero che risolva il tuo problema :)


1
Sì, questo è meglio - timeout quasi immediatamente per le porte chiuse.
Peter Mortensen,

1
Utilizza sempre TCP o c'è un modo per farlo controllare UDP?
Kimmo


6

Ho lottato per un giorno intero perché nessuna di queste risposte sembrava funzionare per me. Il problema è che la versione più recente di ncnon ha più il -zflag, mentre l'accesso diretto via TCP (come secondo @lornix e @slm) fallisce quando l'host non è raggiungibile. Alla fine ho trovato questa pagina , dove finalmente ho trovato non uno ma due esempi funzionanti:

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

    (la -wbandiera si occupa del timeout e </dev/nullsostituisce la -zbandiera)

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

    (il timeoutcomando si occupa del timeout e il resto proviene da @slm)

Quindi, utilizzare semplicemente &&e / o ||(o anche $?) per estrarre il risultato. Speriamo che qualcuno troverà queste informazioni utili.


4

Combinando le risposte di @kenorb e @Azukikuru potresti testare la porta aperta / chiusa / protetta da firewall.

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

Un altro approccio con arricciatura per raggiungere qualsiasi porta

curl telnet://127.0.0.1:22

3

Ecco una funzione che sceglierà uno dei metodi in base a ciò che è installato sul tuo 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

Non dovrebbe essere disponibile sulla confezione, ma prova con nmap.


4
nmapè un buon strumento, ma non disponibile su questi sistemi. Invece di scaricare nmap, compilarlo, installarlo nella mia directory home, quindi copiarlo su tutti gli altri sistemi, speravo di trovare un modo usando gli strumenti esistenti disponibili nella maggior parte delle installazioni Linux.
Steve HHH,

1

come riferimento, espandendo la risposta di @peperunas:

il modo di usare nmap per testare è:

nmap -p 22 127.0.0.1

(l'esempio sopra utilizza localhost a scopo dimostrativo)


0

Se devi testare più che sul sistema, puoi utilizzare il nostro strumento di test dda-serverpec ( https://github.com/DomainDrivenArchitecture/dda-serverspec-crate ) per tali attività. Puoi definire le tue aspettative

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

e testare queste aspettative sia su localhost che su host remoti (connettersi tramite ssh). Per i test remoti devi definire un target:

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

È possibile eseguire il test con java -jar dda-serverspec.jar --targets targets.edn serverspec.edn

Sotto il cofano stiamo usando Netcat come indicato sopra ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.