Passa al contenuto principale
La tua applicazione segnala problemi nel raggiungere il server di database back-end all'indirizzo 172.16.1.116, oppure stai per configurare una nuova applicazione e vuoi assicurarti che riesca a raggiungere il server di database back-end. Il primo strumento che viene in mente è ping, ma molti host non rispondono più alle richieste ICMP echo (ping) e, tra quelli che lo fanno, c'è un'alta probabilità che i loro firewall di rete blocchino le tue richieste ping o le loro risposte. Se ping va in timeout (figura 1), ci sono altri modi per testare la connettività di rete.
ping 172.16.1.116
Pinging host 172.16.1.116 : 172.16.1.116
ping: No reply. Time Out !!
ping: No reply. Time Out !!
ping: No reply. Time Out !!
ping: No reply. Time Out !!
Host 172.16.1.116 replied to 0 of the 4 pings
ready 12:26:32
Figura 1 – Scadenza del ping
Supponendo che l'host che si sta cercando di raggiungere esegua un servizio basato su TCP (anziché su UDP), è sufficiente collegarsi all'host tramite Telnet e specificare il numero di porta del servizio. Sono possibili quattro tipi di risposta: una connessione (figura 2), un rifiuto (figura 6), un'indicazione di un errore (figure 7 e 8) o un timeout (figura 9).
telnet 172.16.1.116 1830
Trying...
Connected to 172.16.1.116.
Escape character is '^]'.
Figura 2 – collegamento
Il messaggio «Connesso» indica che sei connesso all'host – probabilmente. Alcuni acceleratori WAN intercettano la connessione e la completano, fungendo da proxy. Se ti connetti e poi, pochi secondi dopo, ti disconnetti, è possibile che tu ti sia connesso all'acceleratore e che quest'ultimo non sia riuscito a connettersi alla destinazione finale, quindi si sia disconnesso da te. Naturalmente potrebbe anche essere che ti sia connesso all'host effettivo e che l'applicazione si sia bloccata. Vale la pena sapere se stai utilizzando un hardware acceleratore e come funziona esattamente.
Per disconnettersi, digitare Ctrl-] e «quit» al prompt telnet>.
telnet 172.16.1.116 1830
Trying...
Connected to 172.16.1.116.
Escape character is '^]'.
telnet> quit
Figura 3 – Disconnessione di una sessione attiva
L'unico modo per essere assolutamente certi di aver raggiunto il servizio corretto in esecuzione sull'host di destinazione è che tale servizio risponda alla richiesta di connessione con un messaggio di benvenuto. Ad esempio, una schermata di accesso che identifichi l'host. Se si ha accesso all'host di destinazione e su di esso è installato Perl, è possibile eseguire lo script Perl tcplisten, che invierà un messaggio di benvenuto specificato quando accetta una connessione.
On target system (Linux)
[ndav@phx-lab-lnx64 ~]$ perl tcplisten.pl -p 1830 -m 'Connection has been accepted'
perl tcplisten.pl -port 1830 -message 'Connection has been accepted'
On OpenVOS client
stp -ttp ascii
ready 12:16:34
telnet 164.152.77.155 1830
Trying...
Connected to 164.152.77.155.
Escape character is '^]'.
Connection has been accepted
Escape character is '^]'.Connection closed by forei.
Ready 12:16:40
Figura 4: esecuzione di tcplisten.pl su un sistema Linux con client OpenVOS
Poiché il client Telnet di OpenVOS azzera la finestra del terminale alla chiusura della connessione, probabilmente dovrai impostare il tipo di terminale su ASCII per visualizzare il messaggio di connessione.
È inoltre possibile eseguire tcplisten su OpenVOS (a condizione che sia installata la libreria gnu_library).
On OpenVOS target system
perl tcplisten.pl -p 1830 -m 'made it to m16'
perl tcplisten.pl -port 1830 -message 'made it to m16'
On Linux client
[ndav@phx-lab-lnx64 ~]$ telnet 164.152.77.128 1830
Trying 164.152.77.128...
Connected to rigel.az.stratus.com (164.152.77.128).
Escape character is '^]'.
made it to m16
Connection closed by foreign host.
[ndav@phx-lab-lnx64 ~]$
Figura 5: esecuzione di tcplisten.pl su un sistema OpenVOS con client Linux
Un messaggio di "rifiuto" indica che hai raggiunto l'host di destinazione, ma che probabilmente su quella porta non era in ascolto alcun servizio.
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: The connection was refused.
ready 12:31:28
Figura 6 – Rifiuto
Alcuni firewall potrebbero inviare un comando di reset in risposta a una richiesta di connessione non autorizzata. È molto difficile, se non impossibile, capire quale delle due situazioni si stia verificando, almeno dal lato del client.
Se Telnet riceve un'indicazione che la rete (figura 7) o l'host (figura 8) sono irraggiungibili, lo segnalerà. Il messaggio "network … unreachable" indica che OpenVOS non dispone di un percorso verso la rete di destinazione oppure che un router intermedio non è riuscito a raggiungere la rete di destinazione. Il messaggio "No route to host" indica che il router collegato alla rete di destinazione non è riuscito a raggiungere l'host di destinazione. Molto probabilmente ciò significa che l'host di destinazione è inattivo.
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: Network trying to be reached is unreac
+hable.
ready 12:54:34
Figura 7 – Il client Telnet di OpenVOS segnala che la rete è irraggiungibile.
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: No route to host.
ready 12:55:44
Figura 8 – Il client Telnet di OpenVOS segnala che l'host è irraggiungibile
Telnet non segnala l'origine di questi errori. Lo script Perl tuc.pl (test di connessione UDP), eseguito sullo stesso indirizzo IP e numero di porta, segnalerà l'indirizzo IP di origine (vedere la discussione seguente sui test UDP)
Un timeout indica che non è possibile raggiungere l'host – probabilmente. La maggior parte degli host risponde con l'accettazione o il rifiuto della connessione, ma se un host dispone di un firewall a livello di host, potrebbe semplicemente ignorare la richiesta senza rispondere. Allo stesso modo, anche un firewall di rete potrebbe semplicemente ignorare la richiesta senza rispondere; e, naturalmente, qualsiasi messaggio ICMP inviato da un router o da un host potrebbe essere ignorato da un altro router o firewall.
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: The operation timed out.
Figura 9 – Client Telnet OpenVOS che segnala un timeout
In sintesi, ci sono 5 possibili risultati
Messaggio
Significato
Connesso (con banner)
È possibile raggiungere l'host e l'applicazione
Connesso (senza banner)
È possibile raggiungere l'host e l'applicazione – probabilmente
Rifiutato
Riesco a collegarmi al server ma non all'applicazione – probabilmente
Irraggiungibile
Impossibile raggiungere l'host
Timeout
Impossibile raggiungere l'host – probabilmente
Figura 10 – Riepilogo dei risultati e delle interpretazioni relative alle connessioni TCP
Se l'applicazione utilizza una porta UDP, la situazione si complica. Innanzitutto, su OpenVOS non esistono utilità standard per l'invio di un datagramma UDP. In secondo luogo, la risposta può arrivare sotto forma di datagramma UDP o di messaggio ICMP. Lo script Perl tuc.pl (test UDP connection) invierà un datagramma contenente la data e l'ora correnti all'host e alla porta specificati. Attenderà quindi un datagramma UDP o un messaggio ICMP. Idealmente, l'applicazione restituirà un messaggio che verrà poi visualizzato. La Figura 11 mostra che l'applicazione in ascolto ha ripetuto il messaggio inviato dallo script.
perl tuc.pl -i 172.16.1.116 -p 1830
Reply received on UDP socket from 164.152.77.128 message: echoed by udpecho.pl:
+sent by tuc.pl at Mon Aug 30 13:31:34 2010
ready 13:31:34
Figura 11 – L'applicazione server UDP ripete il messaggio ricevuto
Se il server non è in ascolto sulla porta di destinazione, dovrebbe restituire un messaggio del tipo «porta di destinazione non raggiungibile». Supponendo che il messaggio provenga dall'indirizzo IP di destinazione, ciò significa che sei riuscito a raggiungere il server, ma nessuna applicazione era in ascolto.
perl tuc.pl -i 172.16.1.116 -p 1830
ICMP Destination port unreachable message received from 172.16.1.116
ready 11:40:12
Figura 12 – Host di destinazione che invia un messaggio di porta non raggiungibile
Come nei test Telnet, è possibile ricevere messaggi ICMP che segnalano problemi di rete e relativi agli host e, come ho spiegato in precedenza, si ottiene l'indirizzo IP del mittente, il che fornisce un punto di partenza più preciso per avviare le indagini.
perl tuc.pl -i 172.16.1.116 -p 1830
ICMP Destination network unreachable message received from 164.152.77.171
ready 11:43:50
perl tuc.pl -i 172.16.1.116 -p 1830
ICMP Destination host unreachable message received from 164.152.77.171
ready 11:44:54
Figura 13 – Messaggi di rete e host non raggiungibili
Gli errori sopra indicati sono probabilmente due dei più comuni. Un altro segnala un loop di instradamento
perl tuc.pl -i 172.16.1.116 -p 1830
ICMP Time exceeded , TTL expired in transit message received from 164.152.77.34
ready 11:45:39
Figura 14 – Messaggio ICMP che segnala un loop di instradamento
Ci sono molti altri errori, alcuni dei quali indicano un intervento amministrativo volto a impedire il passaggio dei pacchetti. Si può essere abbastanza certi che questi messaggi indichino che un firewall sta bloccando i pacchetti.
Tuttavia, molte applicazioni richiedono un messaggio formattato in modo specifico. In tal caso, probabilmente non riceverai alcuna risposta. Per impostazione predefinita, lo script scadrà dopo 5 secondi e segnalerà «nessuna risposta».
perl tuc.pl -i 172.16.1.116 -p 1830
No response was received from 172.16.1.116
ready 16:43:26
Figura 15 – nessuna risposta
Se vuoi impostare un tempo di attesa più lungo (o più breve), puoi usare l'opzione «-t»
perl tuc.pl -i 172.16.1.117 -p 1830 -t 10
No response was received from 172.16.1.117
ready 12:06:26
perl tuc.pl -i 172.16.1.117 -p 1830 -t 1
No response was received from 172.16.1.117
ready 12:06:32
Figura 16 – Modifica del timeout predefinito
Il silenzio non è necessariamente un male. Potrebbe significare che hai raggiunto l'host di destinazione, che è in ascolto sulla porta di destinazione, ma che semplicemente non ha gradito il messaggio di prova inviato. Purtroppo, potrebbe anche significare che il pacchetto di test non è mai arrivato all'host di destinazione e che eventuali messaggi ICMP inviati per segnalarlo sono stati bloccati. Se hai accesso al server, puoi eseguire lo script Perl udpecho.pl che aggiungerà la propria intestazione e poi ripeterà qualsiasi cosa gli sia stata inviata (figura 11).
In sintesi
Messaggio
Significato
Messaggio del banner dell'applicazione
È possibile raggiungere l'host e l'applicazione
Messaggio ICMP di rete/host
Impossibile raggiungere l'host
Messaggio ICMP relativo alla porta proveniente dall'host
Riesco a raggiungere il server ma non l'applicazione
Nessuna risposta, l'applicazione invia un messaggio di avviso
Impossibile raggiungere l'host
Nessuna risposta, l'applicazione non invia il messaggio di avviso
Potrebbe essere possibile o meno raggiungere l'host
Figura 17 – Riepilogo dei risultati e delle interpretazioni relative ai collegamenti UCP

tcplisten.pl

# tcplisten.pl begins here

#

# Versione 1.00 30-07-2010

# Questo script è stato testato su

# Open VOS 17.0.2ah con Perl v5.8.0 compilato per i686-vos

# Microsoft Windows XP Service Pack 3 in esecuzione

# ActiveState Perl v5.10.0 compilato per MSWin32-x86-multi-thread

# Red Hat 4AS-5.5 in esecuzione

# Perl v5.8.5 compilato per x86_64-linux-thread-multi

#

#stratus

#

usa IO::Socket;

use Getopt::Long;

usa Sys::Hostname;

use strict;

my ($result);

my ($localPort, $message, $peerAddr);

my ($newSock, $data);

$result = GetOptions (‘port=s’ => $localPort,

‘message=s’ => $message);

se (($result != 1) || !(defined($localPort)))

{

stampa “nnUso:n”;

stampa “tperl tcplisten.pl -port NUMERO-PORTA [-message MESSAGGIO]nn”;

esci;

}

se (!defined($message))

{

stampa “Nessun messaggio specificato – creazione del messaggio”;

$message = “Connessione accettata da tcplisten in esecuzione su ” . hostname;

}

stampa “perl tcplisten.pl -port $localPort -message ‘” . $message . “‘n”;

my $sock = IO::Socket::INET->new(

Proto => ‘tcp’,

LocalPort => $localPort,

LocalAddr => ‘0.0.0.0’,

Ascolta => 1,

) oppure "Impossibile creare il socket per la porta $localPort: $!n";

finché (1)

{

my $newSock = $sock->accept ();

stampa “Connessione accettata da ” . $newSock->peerhost .

” a ” . localtime() . “n”;

stampa $newSock $message . “n”;

$newSock -> shutdown(2);

$sock->read($data, 1024); # attendi l'indicazione di chiusura */

$newSock->close();

}

#

# tcplisten.pl finisce qui

tuc.pl

# tuc.pl begins here

#

# Versione 1.00 30-07-2010

# Questo script è stato testato su

# Open VOS 17.0.2ah con Perl v5.8.0 compilato per i686-vos

# Microsoft Windows XP Service Pack 3 in esecuzione

# ActiveState Perl v5.10.0 compilato per MSWin32-x86-multi-thread

# Red Hat 4AS-5.5 in esecuzione

# Perl v5.8.5 compilato per x86_64-linux-thread-multi

#

#stratus

#

usa IO::Socket;

usa IO::Select;

use Getopt::Long;

use strict;

my ($result);

my ($destIP, $destPort, $timeout, $result, $message, $flags);

my ($ready, $socket);

my ($x, $c, $icmpAlready);

$result = GetOptions (‘ip=s’ => $destIP,

‘port=s’ => $destPort,

‘timeout=s’ => $timeout);

se (($result != 1) || !(defined($destIP) && defined($destPort)))

{

stampa “nnUso:n”;

stampa “tperl tuc.pl -ip INDIRIZZO-IP-DI-DESTINAZIONE ” .

“-porto NUMERO-DEL-PORTO-DI-DESTINAZIONE-nn”;

esci;

}

if (!defined($timeout)) { $timeout = 5; }

altrimenti (se $timeout > 15) { stampa “OK, ma ” . $timeout .

” sembra eccessivamente lungo.n”; }

$message = “inviato da tuc.pl alle ” . localtime();

my $sock = IO::Socket::INET->new(

Proto => ‘udp’,

Porta di origine => $destPort,

PeerAddr => $destIP

) oppure "Impossibile creare il socket per la destinazione $destIP: $!n";

my $isock = IO::Socket::INET->new(

Proto => ‘icmp’);

$sock->send($message) oppure die “Errore di invio: $!n”;

$message = “”;

my $read_set = new IO::Select();

$read_set->add($sock);

$read_set->add($isock);

($ready) = IO::Select->select($read_set, undef, undef, $timeout);

$icmpAlready = 0;

$c = 0;

foreach $socket (@$ready)

{

$c = $c + 1;

se ($socket == $sock)

{

$x = “Risposta ricevuta sul socket UDP da “;

$socket->recv($message, 100, $flags);

se ($icmpAlready == 0)

{

se (length($message) > 0)

{ print $x . $socket->peerhost . ” message: ” . $message . “n”; }

else { print $x . $socket->peerhost . “n”; }

}

}

altrimenti # messaggio ICMP ricevuto

{

$icmpAlready = 1;

$socket->recv($message, 100, $flags);

se (length($message) > 98)

{ stampa “Inaspettatamente lungo (” . lunghezza($message) .

“) Messaggio ICMP proveniente da ” . $socket->peerhost .

"messaggio: " . $message . "\n"; }

elsif (length ($message) < 52)

{ stampa “Inaspettatamente breve (” . lunghezza($message) .

“) Messaggio ICMP proveniente da ” . $socket->peerhost . “n”; }

altrimenti # elabora il messaggio ICMP

{

my $type = ord(substr($message, 20, 1));

my $code = ord(substr($message, 21, 1));

my $port = ord (substr ($message, 50, 1)) * 256 +

ord(substr($message, 51, 1));

se ($port != $destPort)

{ stampa “Messaggio ICMP inatteso ricevuto da ” .

$socket->peerhost . ” messaggio: ” . substr($message, 20) .

“n”; }

altrimenti # il messaggio ICMP è corretto

{

se ($type == 3)

{

if ($code == 0) { print “Rete di destinazione ICMP ” .

«Messaggio non recapitabile ricevuto da » .

$socket->peerhost . “n”; }

altrimenti ($code == 1) { stampa “ICMP Host di destinazione ” .

«Messaggio non recapitabile ricevuto da » .

$socket->peerhost . “n”; }

altrimenti ($code == 3) { stampa “Porta di destinazione ICMP ” .

«Messaggio non recapitabile ricevuto da » .

$socket->peerhost . “n”; }

altrimenti ($code == 6) { stampa “Rete di destinazione ICMP ” .

«Messaggio sconosciuto ricevuto da » .

$socket->peerhost . “n”; }

altrimenti (se $code == 7) { stampa “ICMP: host di destinazione sconosciuto ” .

“Messaggio ricevuto da ” . $socket->peerhost . “n”; }

altrimenti (se $code == 8) { stampa “Host di origine ICMP isolato ” .

“messaggio ricevuto da ” .

$socket->peerhost . “n”; }

altrimenti ($code == 9) { stampa “ICMP: rete bloccata per motivi amministrativi ” .

«Messaggio non autorizzato ricevuto da » .

$socket->peerhost . “n”; }

altrimenti ($code == 10) { stampa “Host ICMP amministrativamente ” .

«Messaggio non autorizzato ricevuto da » .

$socket->peerhost . “n”; }

altrimenti ($code == 11) { stampa “Rete ICMP non raggiungibile per ” .

“Messaggio TOS ricevuto da ” .

$socket->peerhost . “n”; }

altrimenti (se $code == 12) { stampa “Host ICMP non raggiungibile per ” .

“Messaggio TOS ricevuto da ” .

$socket->peerhost . “n”; }

altrimenti ($code == 13) { stampa “Comunicazione ICMP ” .

«Messaggio con divieto amministrativo ricevuto da » .

$socket->peerhost . “n”; }

else { stampa “Ricevuto messaggio ICMP inatteso di tipo = ” .

$type . “, codice = ” . $code . ” da ” .

$socket->peerhost . “n”; }

} # se ($type == 3)

altrimenti se (($type == 11) e ($code == 0))

{ stampa “Tempo ICMP scaduto, TTL scaduto durante il transito” .

“Messaggio ricevuto da ” . $socket->peerhost . “n”; }

else { stampa “Ricevuto messaggio ICMP inatteso di tipo = ” .

$type . “, codice = ” . $code . ” da ” .

$socket->peerhost . “n”; }

} # altrimenti # il messaggio ICMP è corretto

} # altrimenti # elabora il messaggio ICMP

} # altrimenti # messaggio ICMP ricevuto

} # foreach $socket (@$ready)

if ($c == 0) { print “Non è stata ricevuta alcuna risposta da ” .

$sock->peerhost . “n”; }

#

# tuc.pl finisce qui

udpecho.pl

# udpecho.pl begins here

#

# Versione 1.00 30-07-2010

# Questo script è stato testato su

# Open VOS 17.0.2ah con Perl v5.8.0 compilato per i686-vos

# Microsoft Windows XP Service Pack 3 in esecuzione

# ActiveState Perl v5.10.0 compilato per MSWin32-x86-multi-thread

# Red Hat 4AS-5.5 in esecuzione

# Perl v5.8.5 compilato per x86_64-linux-thread-multi

#

#stratus

#

usa IO::Socket;

usa IO::Select;

use Getopt::Long;

use strict;

my ($result);

my ($localPort, $debug, $result, $message, $flags);

my ($ready, $socket);

my ($x, $c);

$result = GetOptions (‘port=s’ => $localPort,

‘debug’ => $debug);

se (($result != 1) || !(defined($localPort)))

{

stampa “nnUso:n”;

stampa “tperl udpecho.pl -port NUMERO-PORTA-LOCALE [-debug]nn”;

esci;

}

if (defined($debug)) { print “local port number is ” . $localPort . “n”; }

my $sock = IO::Socket::INET->new(

Proto => ‘udp’,

LocalPort => $localPort

) oppure "Impossibile creare il socket $!n";

my $read_set = new IO::Select();

$read_set->add($sock);

$message = “”;

finché (1)

{

($ready) = IO::Select->select($read_set, undef, undef, 300);

foreach $socket (@$ready)

{

$socket->recv($message, 100, $flags);

if (defined($debug)) { print “Messaggio da ” . $socket->peerhost .

"messaggio: " . $message . "\n"; }

$socket->send(“riprodotto da udpecho.pl: ” . $message) oppure die “Errore di invio: $!”

+n”;

}

}

#

# udpecho.pl finisce qui