Zum Hauptinhalt springen
Ihre Anwendung meldet Probleme beim Zugriff auf den Backend-Datenbankserver unter 172.16.1.116, oder Sie sind dabei, eine neue Anwendung einzurichten, und möchten sicherstellen, dass diese auf den Backend-Datenbankserver zugreifen kann. Das erste Tool, das einem in den Sinn kommt, ist Ping, aber viele Hosts reagieren nicht mehr auf ICMP-Echo-Anfragen (Ping), und bei denen, die dies tun, ist die Wahrscheinlichkeit hoch, dass ihre Netzwerk-Firewalls entweder Ihre Ping-Anfragen oder deren Antworten blockieren. Wenn Ping zeitlich ausläuft (Abbildung 1), gibt es andere Möglichkeiten, die Netzwerkkonnektivität zu testen.
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
Abbildung 1 – Ping-Zeitüberschreitung
Angenommen, der Host, den Sie erreichen möchten, führt einen TCP-basierten Dienst (im Gegensatz zu UDP) aus, können Sie sich einfach per Telnet mit dem Host verbinden und die Portnummer des Dienstes angeben. Es gibt vier mögliche Antworten: eine Verbindung (Abbildung 2), eine Ablehnung (Abbildung 6), einen Hinweis auf einen Fehler (Abbildungen 7 und 8) oder eine Zeitüberschreitung (Abbildung 9).
telnet 172.16.1.116 1830
Trying...
Connected to 172.16.1.116.
Escape character is '^]'.
Abbildung 2 – Anschluss
Die Meldung „Verbunden“ zeigt an, dass Sie mit dem Host verbunden sind – wahrscheinlich. Einige WAN-Beschleuniger fangen die Verbindung ab und schließen sie ab, indem sie als Proxy fungieren. Wenn Sie verbunden werden und dann einige Sekunden später die Verbindung unterbrochen wird, kann es sein, dass Sie mit dem Beschleuniger verbunden wurden und dieser dann keine Verbindung zum endgültigen Ziel herstellen konnte, sodass er die Verbindung zu Ihnen unterbrochen hat. Natürlich kann es auch sein, dass Sie eine Verbindung zum eigentlichen Host hergestellt haben und die Anwendung abgestürzt ist. Es lohnt sich, zu wissen, ob Sie Beschleuniger-Hardware verwenden und wie diese genau funktioniert.
Um die Verbindung zu trennen, geben Sie „control-]“ und „quit“ an der Eingabeaufforderung „telnet>“ ein.
telnet 172.16.1.116 1830
Trying...
Connected to 172.16.1.116.
Escape character is '^]'.
telnet> quit
Abbildung 3 – Trennen einer verbundenen Sitzung
Die einzige Möglichkeit, absolut sicher zu sein, dass Sie den richtigen Dienst auf dem Zielhost erreicht haben, besteht darin, dass dieser Dienst auf die Verbindungsanfrage mit einer Art Banner-Meldung antwortet. Zum Beispiel mit einer Anmeldeaufforderung, die den Host identifiziert. Wenn Sie Zugriff auf den Zielhost haben und auf diesem Host Perl installiert ist, können Sie das Perl-Skript tcplisten ausführen, das eine bestimmte Banner-Meldung sendet, wenn es eine Verbindung akzeptiert.
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
Abbildung 4: Ausführung von tcplisten.pl auf einem Linux-System mit OpenVOS-Client
Da der OpenVOS-Telnet-Client das Terminalfenster beim Schließen der Verbindung löscht, müssen Sie Ihren Terminaltyp wahrscheinlich auf ASCII einstellen, um die Verbindungsmeldung zu sehen.
Sie können tcplisten auch unter OpenVOS ausführen (vorausgesetzt, Sie haben die gnu_library installiert).
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 ~]$
Abbildung 5: Ausführung von tcplisten.pl auf einem OpenVOS-System mit Linux-Client
Eine „refused“-Meldung bedeutet, dass Sie den Zielhost erreicht haben, dieser jedoch wahrscheinlich keinen Dienst auf diesem Port bereitgestellt hat.
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: The connection was refused.
ready 12:31:28
Abbildung 6 – Ablehnung
Einige Firewalls senden möglicherweise als Antwort auf eine nicht genehmigte Verbindungsanfrage einen Reset. Es ist sehr schwierig bis unmöglich zu sagen, welches Szenario vorliegt, zumindest vom Client aus gesehen.
Wenn Telnet eine Meldung erhält, dass das Netzwerk (Abbildung 7) oder der Host (Abbildung 8) nicht erreichbar ist, wird dies gemeldet. Die Meldung „Netzwerk … nicht erreichbar” bedeutet, dass OpenVOS entweder keine Route zum Zielnetzwerk hat oder dass ein Router in der Mitte des Netzwerks das Zielnetzwerk nicht erreichen konnte. Die Meldung „Keine Route zum Host” bedeutet, dass der an das Zielnetzwerk angeschlossene Router den Zielhost nicht erreichen konnte. Dies bedeutet höchstwahrscheinlich, dass der Zielhost ausgefallen ist.
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
Abbildung 7 – OpenVOS-Telnet-Client meldet, dass das Netzwerk nicht erreichbar ist.
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: No route to host.
ready 12:55:44
Abbildung 8 – OpenVOS-Telnet-Client meldet, dass der Host nicht erreichbar ist
Telnet meldet die Ursache dieser Fehler nicht. Das Perl-Skript tuc.pl (Test der UDP-Verbindung), das an dieselbe IP-Adresse und Portnummer gerichtet ist, meldet die Quell-IP-Adresse (siehe die folgende Erläuterung zum UDP-Test).
Eine Zeitüberschreitung bedeutet, dass Sie den Host wahrscheinlich nicht erreichen können. Die meisten Hosts antworten entweder mit einer Verbindung oder einer Ablehnung, aber wenn ein Host über eine hostbasierte Firewall verfügt, kann er die Anfrage einfach ablehnen, ohne zu antworten. Ebenso kann eine netzwerkbasierte Firewall die Anfrage einfach ablehnen, ohne zu antworten; und natürlich können auch alle ICMP-Nachrichten, die von einem Router oder Host gesendet werden, von einem anderen Router oder einer anderen Firewall abgelehnt werden.
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: The operation timed out.
Abbildung 9 – OpenVOS-Telnet-Client meldet eine Zeitüberschreitung
Zusammenfassend gibt es 5 mögliche Ergebnisse
Nachricht
Bedeutung
Verbunden (mit Banner)
Kann Host und Anwendung erreichen
Verbunden (kein Banner)
Kann Host und Anwendung erreichen – wahrscheinlich
Abgelehnt
Host erreichbar, aber Anwendung nicht – wahrscheinlich
Nicht erreichbar
Host kann nicht erreicht werden
Zeitüberschreitung
Host kann nicht erreicht werden – wahrscheinlich
Abbildung 10 – Zusammenfassung der Ergebnisse und Interpretationen für TCP-Verbindungen
Wenn die Anwendung einen UDP-Port verwendet, ist die Sache etwas komplizierter. Erstens gibt es unter OpenVOS keine Standard-Dienstprogramme zum Senden eines UDP-Datagramms. Zweitens kann eine Antwort entweder als UDP-Datagramm oder als ICMP-Nachricht zurückkommen. Das Perl-Skript tuc.pl (test UDP connection) sendet ein Datagramm mit dem aktuellen Datum und der aktuellen Uhrzeit an den angegebenen Host und Port. Anschließend wartet es entweder auf ein UDP-Datagramm oder eine ICMP-Nachricht. Im Idealfall gibt Ihre Anwendung eine Nachricht zurück, die dann angezeigt wird. Abbildung 11 zeigt, dass die empfangende Anwendung die vom Skript gesendete Nachricht wiederholt hat.
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
Abbildung 11 – UDP-Serveranwendung gibt empfangene Nachricht zurück
Wenn der Server nicht auf dem Zielport lauscht, sollte er eine Meldung „Zielport nicht erreichbar“ zurücksenden. Angenommen, die Meldung wird von der Ziel-IP-Adresse empfangen, bedeutet dies, dass Sie den Server erreicht haben, aber keine Anwendung lauschte.
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
Abbildung 12 – Zielhost sendet eine Meldung, dass der Port nicht erreichbar ist
Wie bei den Telnet-Tests können Sie ICMP-Meldungen erhalten, die auf Netzwerk- und Hostprobleme hinweisen, und wie oben beschrieben, erhalten Sie die IP-Adresse des Absenders, sodass Sie einen genaueren Ausgangspunkt für Ihre Untersuchungen haben.
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
Abbildung 13 – Meldungen „Netzwerk und Host nicht erreichbar“
Die oben genannten Fehler sind wahrscheinlich zwei der häufigsten. Ein weiterer Fehler weist auf eine Routing-Schleife hin.
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
Abbildung 14 – ICMP-Meldung, die eine Routing-Schleife anzeigt
Es gibt viele weitere Fehlermeldungen, von denen einige auf administrative Maßnahmen zur Verhinderung des Paketflusses hinweisen. Sie können davon ausgehen, dass diese Meldungen darauf hindeuten, dass eine Firewall Ihre Pakete blockiert.
Viele Anwendungen erwarten jedoch eine speziell formatierte Nachricht. In diesem Fall werden Sie wahrscheinlich keine Antwort erhalten. Standardmäßig läuft das Skript nach 5 Sekunden ab und meldet „keine Antwort“.
perl tuc.pl -i 172.16.1.116 -p 1830
No response was received from 172.16.1.116
ready 16:43:26
Abbildung 15 – keine Antwort
Wenn Sie länger (oder kürzer) warten möchten, können Sie die Option „-t“ verwenden.
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
Abbildung 16 – Ändern der Standard-Zeitüberschreitung
Stille ist nicht unbedingt schlecht. Es könnte bedeuten, dass Sie den Zielhost erreicht haben, dieser auf dem Zielport lauscht, aber die gesendete Testnachricht einfach nicht gefallen hat. Leider kann es auch bedeuten, dass das Testpaket den Zielhost nie erreicht hat und dass alle zurückgesendeten ICMP-Nachrichten, die dies anzeigen sollten, blockiert wurden. Wenn Sie Zugriff auf den Server haben, können Sie das Perl-Skript udpecho.pl ausführen, das seinen eigenen Header anhängt und dann alles wiedergibt, was an ihn gesendet wurde (Abbildung 11).
Zusammenfassend
Nachricht
Bedeutung
Anwendungsbanner-Meldung
Kann Host und Anwendung erreichen
ICMP-Netzwerk-/Host-Meldung
Host kann nicht erreicht werden
ICMP-Port-Nachricht vom Host
Host kann erreicht werden, Anwendung jedoch nicht
Keine Antwort, Anwendung sendet Banner-Meldung
Host kann nicht erreicht werden
Keine Antwort, Anwendung sendet keine Banner-Nachricht
Möglicherweise kann der Host erreicht werden oder auch nicht.
Abbildung 17 – Zusammenfassung der Ergebnisse und Interpretationen für UCP-Verbindungen

tcplisten.pl

# tcplisten.pl begins here

#

# Version 1.00 30.07.2010

# Dieses Skript wurde getestet auf

# Öffnen Sie VOS 17.0.2ah mit Perl v5.8.0, erstellt für i686-vos.

# Microsoft Windows XP Service Pack 3 läuft

# ActiveState Perl v5.10.0, entwickelt für MSWin32-x86-Multi-Thread

# Red Hat 4AS-5.5 läuft

# Perl v5.8.5, kompiliert für x86_64-linux-thread-multi

#

#stratus

#

IO::Socket verwenden;

use Getopt::Long;

Sys::Hostname verwenden;

use strict;

my ($result);

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

my ($newSock, $data);

$result = GetOptions ('port=s' => $localPort,

'message=s' => $message);

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

{

print „nnVerwendung:n“;

print „tperl tcplisten.pl -port PORT-NUMBER [-message MESSAGE]nn”;

Beenden;

}

if (!defined ($message))

{

print „Keine Nachricht angegeben – Nachricht erstellen“;

$message = „Verbindung akzeptiert von tcplisten, ausgeführt auf “ . hostname;

}

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

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

Proto => „tcp“,

LocalPort => $localPort,

LocalAddr => '0.0.0.0',

Hören => 1,

) oder sterben „Socket für Port $localPort konnte nicht erstellt werden: $!n”;

während (1)

{

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

print „Verbindung akzeptiert von “ . $newSock->peerhost .

„bei“ . localtime () . „n“;

print $newSock $message . „n“;

$newSock -> shutdown(2);

$sock->read($data, 1024); # warten, bis ein Schließungshinweis vorliegt */

$newSock->close();

}

#

# tcplisten.pl endet hier

tuc.pl

# tuc.pl begins here

#

# Version 1.00 30.07.2010

# Dieses Skript wurde getestet auf

# Öffnen Sie VOS 17.0.2ah mit Perl v5.8.0, erstellt für i686-vos.

# Microsoft Windows XP Service Pack 3 läuft

# ActiveState Perl v5.10.0, entwickelt für MSWin32-x86-Multi-Thread

# Red Hat 4AS-5.5 läuft

# Perl v5.8.5, kompiliert für x86_64-linux-thread-multi

#

#stratus

#

IO::Socket verwenden;

IO::Select verwenden;

use Getopt::Long;

use strict;

my ($result);

my ($ZielIP, $ZielPort, $Zeitlimit, $Ergebnis, $Meldung, $Flags);

my ($bereit, $Socket);

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

$result = GetOptions ('ip=s' => $destIP,

'port=s' => $destPort,

'timeout=s' => $timeout);

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

{

print „nnVerwendung:n“;

print „tperl tuc.pl -ip ZIEL-IP-ADRESSE “ .

„-port ZIELPORTNUMMERnn”;

Beenden;

}

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

elsif ($timeout > 15) { print „OK, aber “ . $timeout .

„scheint unangemessen lang zu sein.n”; }

$message = „gesendet von tuc.pl um “ . localtime ();

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

Proto => „udp“,

PeerPort => $destPort,

PeerAddr => $destIP

) oder sterben „Socket für Ziel $destIP konnte nicht erstellt werden: $!n”;

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

Proto => „icmp“);

$sock->send($message) oder die „Sendefehler: $!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;

if ($socket == $sock)

{

$x = „Antwort empfangen auf UDP-Socket von “;

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

if ($icmpAlready == 0)

{

if (length($message) > 0)

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

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

}

}

sonst # ICMP-Nachricht empfangen

{

$icmpAlready = 1;

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

if (length ($message) > 98)

{ print „Unerwartet lang (“ . length ($message) .

ICMP-Nachricht von „. $socket->peerhost .

” message: ” . $message . “n”; }

elsif (length ($message) < 52)

{ print „Unerwartet kurz (“ . length ($message) .

") ICMP-Nachricht von " . $socket->peerhost . "n"; }

sonst # ICMP-Nachricht verarbeiten

{

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));

if ($port != $destPort)

{ print „Unerwartete ICMP-Nachricht empfangen von “ .

$socket->peerhost . „Nachricht: “ . substr ($message, 20) .

„n“; }

sonst # icmp-Nachricht ist in Ordnung

{

if ($type == 3)

{

if ($code == 0) { print „ICMP Zielnetzwerk “ .

„Unzustellbare Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 1) { print „ICMP-Zielhost “ .

„Unzustellbare Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 3) { print „ICMP-Zielport “ .

„Unzustellbare Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 6) { print „ICMP-Zielnetzwerk “ .

„Unbekannte Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 7) { print „ICMP Zielhost unbekannt “ .

„Nachricht empfangen von “ . $socket->peerhost . „n”; }

elsif ($code == 8) { print „ICMP-Quellhost isoliert“ .

„Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 9) { print „ICMP Netzwerk administrativ “ .

„Verbotene Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 10) { print „ICMP Host administrativ ” .

„Verbotene Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 11) { print „ICMP Netzwerk für ” nicht erreichbar.

„TOS-Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 12) { print „ICMP Host unreachable for “ .

„TOS-Nachricht empfangen von “.

$socket->peerhost . „n”; }

elsif ($code == 13) { print „ICMP-Kommunikation “ .

„Verwaltungstechnisch gesperrte Nachricht empfangen von “.

$socket->peerhost . „n”; }

else { print „Unerwartete ICMP-Nachricht empfangen Typ = “ .

$type . „, code = “ . $code . „von “ .

$socket->peerhost . „n”; }

} # wenn ($type == 3)

elsif (($type == 11) & ($code == 0))

{ print „ICMP-Zeitüberschreitung, TTL während der Übertragung abgelaufen“ .

„Nachricht empfangen von “ . $socket->peerhost . „n”; }

else { print „Unerwartete ICMP-Nachricht empfangen Typ = “ .

$type . „, code = “ . $code . „von “ .

$socket->peerhost . „n”; }

} # sonst # icmp-Nachricht ist in Ordnung

} # sonst # ICMP-Nachricht verarbeiten

} # sonst #icmp-Nachricht empfangen

} # foreach $socket (@$ready)

if ($c == 0) { print „Keine Antwort von “ .

$sock->peerhost . „n“; }

#

# tuc.pl endet hier

udpecho.pl

# udpecho.pl begins here

#

# Version 1.00 30.07.2010

# Dieses Skript wurde getestet auf

# Öffnen Sie VOS 17.0.2ah mit Perl v5.8.0, erstellt für i686-vos.

# Microsoft Windows XP Service Pack 3 läuft

# ActiveState Perl v5.10.0, entwickelt für MSWin32-x86-Multi-Thread

# Red Hat 4AS-5.5 läuft

# Perl v5.8.5, kompiliert für x86_64-linux-thread-multi

#

#stratus

#

IO::Socket verwenden;

IO::Select verwenden;

use Getopt::Long;

use strict;

my ($result);

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

my ($bereit, $Socket);

my ($x, $c);

$result = GetOptions ('port=s' => $localPort,

'debug' => $debug);

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

{

print „nnVerwendung:n“;

print „tperl udpecho.pl -port LOCAL-PORT-NUMBER [-debug]nn”;

Beenden;

}

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

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

Proto => „udp“,

LocalPort => $localPort

) oder sterben „Socket $!n konnte nicht erstellt werden”;

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

$read_set->add($sock);

$message = „“;

während (1)

{

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

foreach $socket (@$ready)

{

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

if (defined ($debug)) { print „Nachricht von ” . $socket->peerhost .

” message: ” . $message . “n”; }

$socket->send(„echoed by udpecho.pl: ” . $message) or die „Send error: $!

+n";

}

}

#

# udpecho.pl endet hier