跳转至主要内容
你的应用程序报告说在到达172.16.1.116的后端数据库服务器时出现了问题,或者你正准备建立一个新的应用程序,你想确保它能到达后端数据库服务器。首先想到的工具是ping,但许多主机不再响应ICMP回声(ping)请求,而那些响应的主机,他们的网络防火墙很可能会阻止你的ping请求或他们的回复。如果ping超时(图1),还有其他方法可以测试网络连接性。
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
图1 - ping定时输出
假设你要连接的主机运行的是基于TCP(而不是UDP)的服务,你可以直接telnet到主机,并指定服务的端口号。有4种可能的响应,一个连接(图2),一个拒绝(图6),一个错误的指示(图7和8)或超时(图9)。
telnet 172.16.1.116 1830
Trying...
Connected to 172.16.1.116.
Escape character is '^]'.
图2 - 连接
一条"已连接"的消息表明你已经连接到了主机--很可能。有些WAN加速器会拦截连接并完成连接,充当代理。如果你连接上了,然后几秒钟后又断开了,可能是你连接到加速器上,然后加速器无法连接到最终目的地,所以与你断开了连接。当然也可能是你连接到了实际的主机上,应用程序崩溃了。了解你是否使用了任何加速器硬件,以及它的具体工作原理是有好处的。
要断开连接,请在telnet>提示下输入control-]和"退出"。
telnet 172.16.1.116 1830
Trying...
Connected to 172.16.1.116.
Escape character is '^]'.
telnet> quit
图3 - 断开已连接的会话
唯一可以确定你已经到达目标主机上运行的正确服务的方法是,如果该服务用某种横幅消息来响应连接请求。例如,一个识别主机的登录提示。如果你可以访问目标主机,并且该主机安装了Perl,你可以运行tcplisten Perl脚本,它将在接受连接时发送一条指定的横幅消息。
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
图4在Linux系统上使用OpenVOS客户端运行tcplisten.pl。
因为OpenVOS telnet客户端会在连接关闭时清除终端窗口,你可能需要将终端类型设置为ascii才能看到连接信息。
你也可以在OpenVOS上运行tcplisten(假设你安装了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 ~]$
图5在OpenVOS系统上使用Linux客户端运行tcplisten.pl。
一个"拒绝"的消息表明你到达了目标主机,但它没有一个服务在该端口上监听 - 可能。
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: The connection was refused.
ready 12:31:28
图6 - 拒绝
有些防火墙可能会在响应未经批准的连接请求时发送复位。至少从客户端来看,很难甚至无法判断是哪种情况发生。
如果telnet收到网络(图7)或主机(图8)无法到达的提示,它就会报告。"网络......无法到达"消息表明,要么是OpenVOS没有通往目标网络的路由,要么是网络中间的某个路由器无法到达目标网络。"No route to host"消息表示连接到目标网络的路由器无法到达目标主机。更有可能这意味着目标主机已经宕机。
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
图7 - OpenVOS telnet客户端报告网络无法到达。
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: No route to host.
ready 12:55:44
图 8 - OpenVOS telnet 客户端报告主机无法到达。
Telnet不会报告这些错误的来源。tuc.pl(测试UDP连接)Perl脚本指向相同的IP地址和端口号,将报告源IP地址(参见下面关于UDP测试的讨论)
超时表示你无法联系到主机--很可能。大多数主机会以连接或拒绝的方式回应,但如果主机有基于主机的防火墙,它可能只是放弃请求而不回应。同样,基于网络的防火墙也可能不做响应就直接放弃请求;当然,路由器或主机发送的任何ICMP消息也可能被另一个路由器或防火墙放弃。
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: The operation timed out.
图9 - OpenVOS telnet客户端报告超时情况
综上所述,有5种可能的结果
留言内容
意思
已连接(带横幅)
可达到主机和应用
已连接(无横幅
可以接触到主机和应用程序--可能
拒绝
可以到达主机,但不能到达应用程序--可能
无法到达
无法到达主机
超时
无法联系到主机--可能
图10 - TCP连接的结果和解释摘要
如果应用程序使用UDP端口,事情就比较棘手了。首先,OpenVOS上没有发送UDP数据报的标准工具。其次,响应可以以UDP数据报或ICMP消息的形式返回。tuc.pl (test UDP connection) Perl 脚本会发送一个包含当前日期时间的数据报到指定的主机和端口,然后等待UDP数据报或ICMP消息的回复。然后它将等待UDP数据报或ICMP消息。理想情况下,你的应用程序将返回一个消息,然后显示出来。图11显示了监听应用程序对脚本发送的消息进行了呼应。
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
图11--UDP服务器应用程序对收到的消息进行回声处理
如果服务器没有在目标端口上监听,它应该发回一条"目标端口无法到达"的消息。假设消息是从目标IP地址收到的,这意味着你到达了服务器,但没有应用程序在监听。
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
图12 - 目标主机发送端口不可达消息
就像telnet测试一样,你可以得到ICMP信息,表明网络和主机的问题,正如我上面所讨论的,你可以得到发送者的IP地址,这样你就有了一个更明确的起点来开始你的调查。
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
图13 - 网络和主机无法到达的消息
以上错误可能是最常见的两种。另一个表示路由环路
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
图14 - 显示路由环路的ICMP消息
还有许多其他的错误,有些错误表明管理行动阻止了数据包的流动。你可以很肯定的是,这些信息表明防火墙阻止了你的数据包。
然而,许多应用程序希望得到一个特定格式的信息。在这种情况下,你可能会遇到沉默。默认情况下,脚本会在5秒后超时,并报告"无响应"。
perl tuc.pl -i 172.16.1.116 -p 1830
No response was received from 172.16.1.116
ready 16:43:26
图15----无答复
如果你想等待更长的时间(或更短),你可以使用"-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
图16 - 更改默认超时
沉默不一定是坏事。它可能意味着你已经到达了目标主机,它正在目标端口上监听,但它只是不喜欢发送的测试消息。不幸的是,这也可能意味着测试数据包从来没有到达目标主机,并且任何ICMP消息发送回来表示被阻止了。如果你能访问服务器,你可以运行udpecho.pl Perl脚本,它将附加自己的报头,然后呼应发送到它的任何东西(图11)。
总的来说
留言内容
意思
申请横幅信息
可达到主机和应用
ICMP网络/主机信息
无法到达主机
来自主机的ICMP端口信息
可以到达主机,但不能到达应用程序
无响应,应用程序发送横幅消息
无法到达主机
无响应,应用程序不发送横幅信息。
可能会或可能无法联系到主机
图17 - UCP连接的结果和解释摘要

tcplisten.pl

# tcplisten.pl begins here

#

# 版本1.00 10-07-30

# 这个脚本已经在

# 打开VOS 17.0.2ah,运行i686-vos的Perl v5.8.0。

# Microsoft Windows XP Service Pack 3运行

# ActiveState Perl v5.10.0,适用于MSWin32-x86多线程。

# Red Hat Linux 4AS-5.5运行。

# #Perl v5.8.5,为x86_64-linux-thread-multi而建。

#

# noah.davids@stratus.com

#

使用IO::Socket。

使用 Getopt::Long。

使用Sys::Hostname。

严格使用。

我的($result)。

我的 ($localPort, $message, $peerAddr);

我的($newSock, $data)。

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

'message=s' => $message)。

如果(($result !=1) || !(定义($localPort)))

{

print "nnUsage:n"。

print "tperl tcplisten.pl -port PORT-NUMBER [-message MESSAGE]nn"。

退出。

}

如果(!定义($message))

{

print "No message specified - creating messagen"。

$message = "tcplisten运行在"上的连接已被接受。

}

print "perl tcplisten.pl -port $localPort -message '" 。$message ."“‘n”;

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

Proto => 'tcp',

LocalPort => $localPort,

LocalAddr => '0.0.0.0'。

听 => 1,

)或die "Could not create socket for port $localPort: $!n";

而(1)

{

我的$newSock = $sock->accept ();

print "Connected accepted from " . $newSock->peerhost .

"在".localtime() ."“n”;

print $newSock $message ."“n”;

$newSock -> shutdown(2);

$sock->read($data, 1024); # 等待获得关闭指示 */。

$newSock->close()。

}

#

# tcplisten.pl 到此为止。

tuc.pl

# tuc.pl begins here

#

# 版本1.00 10-07-30

# 这个脚本已经在

# 打开VOS 17.0.2ah,运行i686-vos的Perl v5.8.0。

# Microsoft Windows XP Service Pack 3运行

# ActiveState Perl v5.10.0,适用于MSWin32-x86多线程。

# Red Hat Linux 4AS-5.5运行。

# #Perl v5.8.5,为x86_64-linux-thread-multi而建。

#

# noah.davids@stratus.com

#

使用IO::Socket。

使用IO::Select。

使用 Getopt::Long。

严格使用。

我的($result)。

我的($destIP, $destPort, $timeout, $result, $message, $flags)。

我的($ready, $socket)。

我的($x, $c, $icmpAlready)。

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

'port=s' => $destPort,

'timeout=s' => $timeout)。

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

{

print "nnUsage:n"。

print "tperl tuc.pl -ip DESTINATION-IP-ADDRESS" 。

"-port DESTINATION-PORT-NUMBERnn"。

退出。

}

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

elsif ($timeout > 15) { print "OK, but " . $timeout .

"似乎不合理的长.n"; }。

$message = "由tuc.pl发送,时间为".localtime()。

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

Proto => 'udp',

PeerPort => $destPort,

PeerAddr => $destIP

)或die "Could not create socket for destination $destIP: $!n";

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

Proto => 'icmp')。

$sock->send($message) or die "Send error: $!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。

如果($socket == $sock)

{

$x = "在UDP套接字上收到来自"的回复。

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

如果 ($icmpAlready == 0)

{

如果 (长度 ($message) > 0)

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

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

}

}

否则 # 收到ICMP信息

{

$icmpAlready = 1;

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

如果 (长度 ($message) > 98)

{ print "Unexpectedly long (" . length ($message) .

") 来自". $socket->peerhost"的ICMP消息。

"信息。". $message ."“n”; }

elsif (length ($message) < 52)

{ print "短得不能再短(" . length ($message) .

") 来自". $socket->peerhost的ICMP消息 ."“n”; }

否则 # 处理icmp信息

{

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

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

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

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

如果($port !=$destPort)

{ print "收到来自" 的意外ICMP消息。

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

"“n”; }

否则 # icmp信息是好的

{

如果 ($type == 3)

{

if ($code == 0) { print "ICMP Destination network " .

"收到来自"的无法联系的信息"。

$socket->peerhost ."“n”; }

elsif ($code == 1) { print "ICMP Destination host " .

"收到来自"的无法联系的信息"。

$socket->peerhost ."“n”; }

elsif ($code == 3) { print "ICMP 目标端口 " .

"收到来自"的无法联系的信息"。

$socket->peerhost ."“n”; }

elsif ($code == 6) { print "ICMP Destination network " .

"收到来自"的未知信息。

$socket->peerhost ."“n”; }

elsif ($code == 7) { print "ICMP Destination host unknown " .

"收到来自" . $socket->peerhost ."“n”; }

elsif ($code == 8) { print "ICMP Source host isolated " .

"收到的信息来自" .

$socket->peerhost ."“n”; }

elsif ($code == 9) { print "ICMP网络管理" .

"收到来自"的违禁信息。

$socket->peerhost ."“n”; }

elsif ($code == 10) { print "ICMP Host administratively " .

"收到来自"的违禁信息。

$socket->peerhost ."“n”; }

elsif ($code == 11) { print "ICMP Network unreachable for " .

"收到来自"的TOS信息。

$socket->peerhost ."“n”; }

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

"收到来自"的TOS信息。

$socket->peerhost ."“n”; }

elsif ($code == 13) { print "ICMP Communication " .

"从"收到"管理上禁止的信息"。

$socket->peerhost ."“n”; }

else { print "收到的意外ICMP消息类型 = " .

$type .", 代码 = ". $code ."从" .

$socket->peerhost ."“n”; }

}# if ($type == 3)

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

{ print "ICMP Time exceeded , TTL expired in transit " .

"收到来自" . $socket->peerhost ."“n”; }

else { print "收到的意外ICMP消息类型 = " .

$type .", 代码 = ". $code ."从" .

$socket->peerhost ."“n”; }

}# else # icmp message is good

}# else # 处理icmp信息

}# else #icmp消息已收到

}# foreach $socket (@$ready)

if ($c == 0) { print "没有收到来自" .

$sock->peerhost ."“n”; }

#

# tuc.pl 到此为止

udpecho.pl

# udpecho.pl begins here

#

# 版本1.00 10-07-30

# 这个脚本已经在

# 打开VOS 17.0.2ah,运行i686-vos的Perl v5.8.0。

# Microsoft Windows XP Service Pack 3运行

# ActiveState Perl v5.10.0,适用于MSWin32-x86多线程。

# Red Hat Linux 4AS-5.5运行。

# #Perl v5.8.5,为x86_64-linux-thread-multi而建。

#

# noah.davids@stratus.com

#

使用IO::Socket。

使用IO::Select。

使用 Getopt::Long。

严格使用。

我的($result)。

我的($localPort, $debug, $result, $message, $flags)。

我的($ready, $socket)。

我的($x, $c);

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

'debug' => $debug)。

如果(($result !=1) || !(定义($localPort)))

{

print "nnUsage:n"。

print "tperl udpecho.pl -port LOCAL-PORT-NUMBER [-debug]nn"。

退出。

}

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

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

Proto => 'udp',

LocalPort => $localPort

)或死于"无法创建套接字$!n"。

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

$read_set->add($sock)。

$message = "";

而(1)

{

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

foreach $socket (@$ready)

{

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

if (defined ($debug)) { print "Message from " . $socket->peerhost .

"信息。". $message ."“n”; }

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

+n”;

}

}

#

# udpecho.pl 到此为止

© 2020 Stratus Technologies.