본문 바로가기
응용 프로그램이 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 시간 초과
연결하려는 호스트가 UDP가 아닌 TCP 기반 서비스를 실행 중이라고 가정할 때, 해당 호스트에 telnet으로 접속하여 서비스의 포트 번호를 지정하기만 하면 됩니다. 네 가지 가능한 응답이 있습니다: 연결 성공(그림 2), 연결 거부(그림 6), 오류 발생 표시(그림 7 및 8), 또는 시간 초과(그림 9).
telnet 172.16.1.116 1830
Trying...
Connected to 172.16.1.116.
Escape character is '^]'.
그림 2 – 연결
"연결됨" 메시지는 호스트에 연결되었음을 나타냅니다 – 아마도. 일부 WAN 가속기는 연결을 가로채서 프록시 역할을 하며 연결을 완료합니다. 연결된 후 몇 초 후에 연결이 끊어졌다면, 가속기에 연결된 후 가속기가 최종 목적지에 연결하지 못해 사용자와의 연결을 끊었을 수 있습니다. 물론 실제 호스트에 연결되었으나 애플리케이션이 충돌했을 가능성도 있습니다. 가속기 하드웨어를 사용 중인지, 그리고 그 작동 방식을 정확히 파악하는 것이 중요합니다.
연결을 끊으려면 telnet> 프롬프트에서 Ctrl+] 키를 누르고 "quit"을 입력하십시오.
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: OpenVOS 클라이언트가 있는 Linux 시스템에서 tcplisten.pl 실행
OpenVOS 텔넷 클라이언트는 연결이 종료될 때 터미널 창을 지우므로, 연결 메시지를 보려면 터미널 유형을 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: Linux 클라이언트가 있는 OpenVOS 시스템에서 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 – 거부
일부 방화벽은 승인되지 않은 연결 요청에 대해 리셋을 보낼 수 있습니다. 어떤 시나리오가 발생하는지, 적어도 클라이언트 측에서는 구분하기가 매우 어렵거나 불가능합니다.
텔넷이 네트워크(그림 7) 또는 호스트(그림 8)에 접근할 수 없다는 신호를 수신하면 이를 보고합니다. "네트워크 …에 연결할 수 없음" 메시지는 OpenVOS가 대상 네트워크로 가는 경로를 가지고 있지 않거나 네트워크 중간에 있는 일부 라우터가 대상 네트워크에 도달할 수 없음을 나타냅니다. "호스트에 대한 경로 없음" 메시지는 대상 네트워크에 연결된 라우터가 대상 호스트에 도달할 수 없음을 나타냅니다. 이는 대부분 대상 호스트가 다운되었음을 의미합니다.
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 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: No route to host.
ready 12:55:44
그림 8 – OpenVOS 텔넷 클라이언트가 호스트에 연결할 수 없다고 보고하는 화면
텔넷은 이러한 오류의 원인을 보고하지 않습니다. 동일한 IP 주소와 포트 번호로 전송된 tuc.pl(UDP 연결 테스트) Perl 스크립트는 원본 IP 주소를 보고합니다(UDP 테스트에 관한 다음 설명 참조).
타임아웃은 호스트에 연결할 수 없음을 나타냅니다 – 아마도. 대부분의 호스트는 연결 응답 또는 연결 거부 응답을 반환하지만, 호스트 기반 방화벽이 있는 호스트는 응답 없이 요청을 차단할 수 있습니다. 마찬가지로 네트워크 기반 방화벽도 응답 없이 요청을 차단할 수 있습니다. 물론 라우터나 호스트가 전송한 ICMP 메시지도 다른 라우터나 방화벽에 의해 차단될 수 있습니다.
telnet 172.16.1.116 1830
Trying...
telnet: Unable to connect to remote host: The operation timed out.
그림 9 – 시간 초과를 보고하는 OpenVOS 텔넷 클라이언트
요약하면 5가지 가능한 결과가 있습니다
메시지
의미
연결됨 (배너 포함)
호스트 및 애플리케이션에 접근할 수 있음
연결됨 (배너 없음)
호스트와 애플리케이션에 도달할 수 있음 – 아마도
거절됨
호스트에는 연결 가능하지만 애플리케이션에는 연결 불가 – 아마도
연락 불가
호스트에 연결할 수 없습니다
타임아웃
호스트에 연결할 수 없음 – 아마도
그림 10 – TCP 연결에 대한 결과 요약 및 해석
애플리케이션이 UDP 포트를 사용하는 경우 상황이 더 복잡해집니다. 첫째, OpenVOS에는 UDP 데이터그램을 전송하는 표준 유틸리티가 없습니다. 둘째, 응답은 UDP 데이터그램이나 ICMP 메시지 형태로 돌아올 수 있습니다. tuc.pl(UDP 연결 테스트) Perl 스크립트는 지정된 호스트와 포트로 현재 날짜-시간을 포함한 데이터그램을 전송합니다. 이후 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 – 대상 호스트가 포트에 접근할 수 없다는 메시지를 전송하는 모습
텔넷 테스트와 마찬가지로, 네트워크 및 호스트 문제를 나타내는 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

# 이 스크립트는 다음 환경에서 테스트되었습니다.

# Open VOS 17.0.2ah 실행 중, i686-vos용으로 빌드된 Perl v5.8.0

# Microsoft Windows XP 서비스 팩 3 실행 중

# ActiveState Perl v5.10.0, MSWin32-x86-멀티스레드용으로 빌드됨

# Red Hat Linux 4AS-5.5 실행 중

# x86_64-linux-thread-multi용으로 빌드된 Perl v5.8.5

#

# [email protected]

#

use IO::Socket;

use Getopt::Long;

use Sys::Hostname;

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 "nn사용법:n";

print "tperl tcplisten.pl -port 포트번호 [-message 메시지]";

종료;

}

define($message)가 정의되지 않은 경우

{

print "메시지가 지정되지 않았습니다 – 메시지를 생성 중입니다";

$message = "tcplisten이 실행 중인 " . 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',

듣기 => 1,

) 또는 종료됨 “포트 $localPort에 대한 소켓을 생성할 수 없음: $!n”;

while (1)

{

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

print “연결 요청 수락됨: ” . $newSock->peerhost .

" at " . 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

# 이 스크립트는 다음 환경에서 테스트되었습니다.

# Open VOS 17.0.2ah 실행 중, i686-vos용으로 빌드된 Perl v5.8.0

# Microsoft Windows XP 서비스 팩 3 실행 중

# ActiveState Perl v5.10.0, MSWin32-x86-멀티스레드용으로 빌드됨

# Red Hat Linux 4AS-5.5 실행 중

# x86_64-linux-thread-multi용으로 빌드된 Perl v5.8.5

#

# [email protected]

#

use IO::Socket;

use IO::Select;

use Getopt::Long;

use strict;

my ($result);

my ($목적지IP, $목적지포트, $타임아웃, $결과, $메시지, $플래그);

my ($ready, $socket);

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

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

‘port=s’ => $destPort,

‘timeout=s’ => $timeout);

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

{

print "nn사용법:n";

"tperl tuc.pl -ip 대상 IP 주소" 출력.

“-포트 대상-포트-번호nn”;

종료;

}

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

elsif ($timeout > 15) { print "OK, 하지만 " . $timeout .

"불합리하게 길어 보인다."; }

$message = "tuc.pl에 의해 전송됨: " . localtime();

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

Proto => ‘udp’,

PeerPort => $destPort,

PeerAddr => $destIP

) 또는 종료됨 “대상 $destIP에 대한 소켓을 생성할 수 없음: $!n”;

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

Proto => 'icmp');

$sock->send($message) or die "전송 오류: $!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 = "UDP 소켓에서 수신된 응답: ";

$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”; }

}

}

else # icmp 메시지 수신

{

$icmpAlready = 1;

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

if (length($message) > 98)

{ print "예상보다 긴 (" . length($message) .

“) ICMP 메시지 발신자 ” . $socket->peerhost .

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

elsif (length ($message) < 52)

{ print "예상보다 짧음(" . length($message) .

“) ” . $socket->peerhost . “에서 보낸 ICMP 메시지입니다.”; }

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

$port가 $destPort와 다를 경우

{ print "예상치 못한 ICMP 메시지를 다음 주소로부터 수신했습니다: " .

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

“n”; }

else # icmp 메시지는 정상입니다

{

if ($type == 3)

{

if ($code == 0) { print "ICMP 목적지 네트워크 " .

"접속 불가한 메시지를 수신했습니다."

$socket->peerhost . "n"; }

elsif ($code == 1) { print “ICMP 대상 호스트 ” .

"접속 불가한 메시지를 수신했습니다."

$socket->peerhost . "n"; }

elsif ($code == 3) { print "ICMP 대상 포트 " .

"접속 불가한 메시지를 수신했습니다."

$socket->peerhost . "n"; }

elsif ($code == 6) { print "ICMP 목적지 네트워크 " .

"알 수 없는 발신자로부터 메시지를 수신했습니다."

$socket->peerhost . "n"; }

elsif ($code == 7) { print "ICMP 대상 호스트 알 수 없음 " .

“” . $socket->peerhost . “” . “에서 메시지 수신됨”; }

elsif ($code == 8) { print “ICMP 소스 호스트 격리됨 ” .

"에서 수신된 메시지"

$socket->peerhost . "n"; }

elsif ($code == 9) { print “ICMP 네트워크 관리상 ” .

"에서 금지된 메시지를 수신했습니다."

$socket->peerhost . "n"; }

elsif ($code == 10) { print “ICMP 호스트 관리상 ” .

"에서 금지된 메시지를 수신했습니다."

$socket->peerhost . "n"; }

elsif ($code == 11) { print “ICMP 네트워크에 도달할 수 없음: ” .

"TOS 메시지 수신됨"

$socket->peerhost . "n"; }

elsif ($code == 12) { print “ICMP 호스트에 연결할 수 없음: ” .

"TOS 메시지 수신됨"

$socket->peerhost . "n"; }

elsif ($code == 13) { print “ICMP 통신 ” .

"행정적으로 금지된 메시지를 수신했습니다."

$socket->peerhost . "n"; }

else { print "예상치 못한 ICMP 메시지 수신 유형 = " .

$type . “, 코드 = ” . $code . ” 출처 ” .

$socket->peerhost . "n"; }

} # if ($type == 3)

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

{ print "ICMP 시간 초과, 전송 중 TTL 만료" .

“” . $socket->peerhost . “” . “에서 메시지 수신됨”; }

else { print "예상치 못한 ICMP 메시지 수신 유형 = " .

$type . “, 코드 = ” . $code . ” 출처 ” .

$socket->peerhost . "n"; }

} # 그렇지 않으면 # icmp 메시지가 정상입니다

} # 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

# 이 스크립트는 다음 환경에서 테스트되었습니다.

# Open VOS 17.0.2ah 실행 중, i686-vos용으로 빌드된 Perl v5.8.0

# Microsoft Windows XP 서비스 팩 3 실행 중

# ActiveState Perl v5.10.0, MSWin32-x86-멀티스레드용으로 빌드됨

# Red Hat Linux 4AS-5.5 실행 중

# x86_64-linux-thread-multi용으로 빌드된 Perl v5.8.5

#

# [email protected]

#

use IO::Socket;

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

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

{

print "nn사용법:n";

print "tperl udpecho.pl -port 로컬 포트 번호 [-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 = "";

while (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: " . $message . "\n"; }

$socket->send("udpecho.pl에 의해 에코됨: " . $message) or die("전송 오류: $!")

+n”;

}

}

#

# udpecho.pl 여기서 끝

© 2024 Stratus Technologies.