network

서버 관리자를 위한 network 지식- netstat

Hello World Study 2022. 6. 27. 23:44

8080 포트로 서버로 접속하려고 하면 timeout 오류가 납니다.  서버 살아있는거 맞나요?

접속이 되었다가 안되었다가 합니다. 뭐가 문제죠?

서버 관리자라면 위와 같은 질문을 종종 받게 됩니다.

 

여러분은 이때 어떤 일을 하시나요?

저는 가장 먼저 netstat 명령어를 이용해서 네트워크 상태부터 확인하길 권장 드립니다. 

netstatnetwork status 확인용 명령어라고 생각하면 됩니다. 약간의 옵션이 다르긴 합니다만 window와 linux 모두 netstat 사용이 가능하며, 여기서는 리눅스 환경을 기준으로 설명드리겠습니다.   뒤에 윈도우와의 차이점 약간 설명하겠니다.

 

 

기본 지식

우선 리눅스서버에 접속해서 좀 더 자세히 살펴보겠습니다.

netstat 이라는 명령어로 네트워크 상태를 알수 있으며 -ant 는 TCP 정보를 알 수 있게 해주는 옵션입니다.

 

$ netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 172.31.22.162:39806     169.254.169.254:80      TIME_WAIT  
tcp        0    384 172.31.22.162:22        13.209.1.56:53874       ESTABLISHED
tcp        0      0 172.31.22.162:22        13.209.1.57:48444       ESTABLISHED
tcp6       0      0 :::22                   :::*                    LISTEN

-help 옵션을 쓰면 사용할 수 있는 옵션들의 상세 설명이 나옵니다. 

아래를 보니

-n 은 포트번호를 숫자 그대로 보여주지 그걸 ssh, http 와 같이 프로토콜 명으로 치환하지 말라는 뜻입니다.

-a 는 모든 소켓들을 보여달라. 

-t 는 tcp 패킷을 보여달라 입니다.

-ant 는 위 -a, -n, -t 를 조합한 것입니다. 

$ netstat -help
usage: netstat [-vWeenNcCF] [<Af>] -r         netstat {-V|--version|-h|--help}
       netstat [-vWnNcaeol] [<Socket> ...]
       netstat { [-vWeenNac] -i | [-cnNe] -M | -s [-6tuw] }       
        -n, --numeric            don't resolve names       
        -p, --programs           display PID/Program name for sockets       
        -a, --all                display all sockets (default: connected)
        ( 중략 )
<Socket>={-t|--tcp} {-u|--udp} {-U|--udplite} {-S|--sctp} {-w|--raw}
           {-x|--unix} --ax25 --ipx --netrom

 

 

 

 

netstat 결과에서 중요한건 Local Address, Foregine Address , state 값입니다. 아래 코드블럭에 한글로 표시해두었습니다.

$ netstat -ant
Active Internet connections (servers and established)
               현재컴퓨터의 ip,port 정보   연결된 외부 컴퓨터 정보   소켓 상태
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 172.31.22.162:39806     169.254.169.254:80      TIME_WAIT  
tcp        0    384 172.31.22.162:22        13.209.1.56:53874       ESTABLISHED
tcp        0      0 172.31.22.162:22        13.209.1.57:48444       ESTABLISHED
tcp6       0      0 :::22                   :::*                    LISTEN

하나씩 의미를 살펴보겠습니다.

 

아래는 현재 컴퓨터의 모든 ip 주소(0.0.0.0:22)로 LISTEN 중이다. 연결할 수 있는 외부 컴퓨터는 아무 ip와 포트가 가능하다(0.0.0.0:*)  라는 뜻입니다. 0.0.0.0 은 any 를 나타냅니다. Foreign Address 에 0.0.0.0 이라고 적혀있으니 외부에서 접속할 경우 외부 클라이언트의 주소는 아무거나 가능하다 라는 뜻입니다. 즉 특정 ip만 접속이 가능한게 아니라 아무나 접속가능하다 라는 뜻이며, 보통 이렇게 LISTEN 상태의 소켓은 foreign address 는 0.0.0.0:* 을 나타냅니다.

Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN

현재 컴퓨터의 모든 ip 주소란 아래처럼 ifconfig 로 현재 컴퓨터의 ip 주소를 가져왔을때 나오는 주소들입니다.

아래에서는 172.31.22.162 와 127.0.0.1 이라는 ip 주소가 있네요. 

$ ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 9001
        inet 172.31.22.162  netmask 255.255.240.0  broadcast 172.31.31.255
        ( 중략 )

lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        ( 중략 )

그래서 local address 에 0.0.0.0:22 이라고 적혀있다면, 클라이언트에서는 172.31.22.162:22 으로 접속할수도 있고, 127.0.0.1:22 로도 접속할 수 있다는 뜻입니다. 127.0.0.1 은 특수용도이므로, 결국 외부 클라이언트에서 접속하려면 172.31.22.162:22 으로 접속해야 한다는걸 말합니다.

 

아래 값은 13.209.1.57 이라는 ip address 를 가진 외부 컴퓨터에서 이 컴퓨터의 172.31.22.162 번 ip 주소에 연결되어 있다. 그리고 외부 컴퓨터는 48444 라는 포트번호를 사용중이고, 현재 컴퓨터는 22번 포트를 사용중이다. 라는 걸 뜻합니다.

22번 포트 즉 ssh 서비스에 13.209.1.57번 ip address 를 가진 컴퓨터가 현재 ssh 연결중이다. 라는걸 뜻합니다. 

Proto Recv-Q Send-Q Local Address           Foreign Address         State     
tcp        0      0 172.31.22.162:22        13.209.1.57:48444       ESTABLISHED

 

아래는 IP v6 에 대한 정보입니다. Proto 에 tcp6 이라고 적혀있는데 이게 IP v6 이라는 겁니다.

주소체계가 기존과 다르기에 0.0.0.0 대신에 ::: 와 같이 사용될 뿐 의미적으로는 아무 ip 주소에서 접속 가능하고, 현재 컴퓨터가 소유한 ip 주소 아무거나로 접속하면 된다 라는 뜻입니다. 

Proto Recv-Q Send-Q Local Address           Foreign Address         State  
tcp6       0      0 :::22                   :::*                    LISTEN

 

 

아래는 특수용도로 열려있는 소켓인데, 127.0.0.53 ip 주소로 listen 중이며 53번 포트로 열려있다. 외부에서 접속은 아무 ip, 아무 port 모두 가능하다. 라는 뜻입니다. 

Proto Recv-Q Send-Q Local Address           Foreign Address         State  
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN

혹시 이 특수용도에 대해 궁금하다면 아래를 참고하세요

https://ko.ipshu.com/ipv4/127.0.0.53

 

127.0.0.53 예약된 IP 주소

127.0.0.53는 IP 주소 관리 대행사가 예약한 예약 IP 주소이며 공용 또는 개인 IP로 할당되지 않습니다. 예약된 IP는 일반적으로 소프트웨어, 개인 네트워크, 호스트, 서브넷, 문서, 변환, 멀티 캐스트,

ko.ipshu.com

 

실전 응용

위 기본 지식을 바탕으로 실전에서 응용할 케이스 몇개를 살펴봅시다.

 

localhost 전용 소켓(=외부에서 접근못하는 소켓)

아래처럼 Local Address 에 127.0.0.1 이라고 적혀있다면, 22번 포트로는 컴퓨터 내부에서만 접근가능하고 외부 컴퓨터에서는 접근 불가능합니다. 왜냐면 127.0.0.1 은 특수용도로 현재 컴퓨터의 주소를 나타내는데, 외부에서 127.0.0.1:22 로 접속하면 원하는 서버가 아니라 자기자신에게 접속시도를 하기 때문입니다.

보안을 위해 일부 서비스는 디폴트로 아래처럼 127.0.0.1 로 설정되어 있기도 하니, 외부에서 접근가능해야 한다면 이를 0.0.0.0 으로 변경되도록 해당 서비스의 config 를 변경해야 합니다. 

Proto Recv-Q Send-Q Local Address           Foreign Address         State  
tcp        0      0 127.0.0.1:22           0.0.0.0:*               LISTEN

 

외부로 접속하고 있는 소켓

아래는 현재 컴퓨터가 142.251.42.143 ip 주소로 연결되어 있고, 상대방 포트는 443 이라는 걸 말합니다.

443 은 https 포트이므로, 아마도 현재 컴퓨터가 142.251.42.143 ip 주소를 가진 HTTPS 서버에 "클라이언트"로서 접속했음을 알수 있습니다.

172.31.22.162:53484은 서버로 연결시 사용한 소스 ip 주소가 172.31.22.162 라는걸 뜻하며, 보통 클라이언트로 접속시에는 소스포트는 임의의 값으로 결정되기에 53484이라는 포트는 랜덤하게 배정된 값입니다. 

Proto Recv-Q Send-Q Local Address           Foreign Address         State  
tcp        0      0 172.31.22.162:53484     142.251.42.142:443      ESTABLISHED

만약 무조건 서버로만 동작해야 하는(=요청을 받기만 하지, 다른 곳으로 요청하지 않는) 컴퓨터인데, 위와 같이 의심스러운/알지못하는 ip 주소로  접속하고 있다면, 어떤 프로세스가 이 소켓을 소유한 것인지 알 필요가 있습니다. 

 

소켓의 소유자 알아내기

모든 소켓은 프로세스/프로그램에게 소유되어 있습니다. 그러므로 각 소켓의 소유자를 알 수 있는 -p 옵션을 사용하면 됩니다. 보통 super user 권한이 필요하므로 sudo 를 함께 사용해야 아래처럼 제대로 된 소유자 정보가 나옵니다.

아래에서는 18013 이라는 pid 를 가진 telnet 이라는 프로그램을 통해 해당 소켓이 실행되고 있었습니다. 

$ sudo netstat -antp
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name 
tcp        0      0 172.31.22.162:53484     142.251.42.142:443      ESTABLISHED 18013/telnet

사실 제가 설명하기 위해 일부러 아래처럼 구글 서버에 접속시도를 한것입니다.

$ telnet google.com 443
Trying 142.251.42.142...
Connected to google.com.
Escape character is '^]'.

암튼 -p 옵션을 통해 각 소켓의 소유자를 알 수 있습니다. 

 

소켓을 구분짓는 요소들

소켓이란 아래처럼 netstat -ant 와 같은 명령을 내렸을때 나오는 값들이 소켓입니다.

아래에는 3개의 소켓이 있다고 보면 됩니다. 

$ netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN     
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN     
tcp        0      0 172.31.22.162:22        13.209.1.56:64630       ESTABLISHED

소켓을 구분짓는 요소는 어떤게 있을까요? 정답은 아래와 같이 tcp 이면서 소스 ip, 소스 포트, 목적지 ip, 목적지 포트 이렇게 5가지가 모두 동일한게 존재할 수 있을지를 생각하면 됩니다.

 

Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN    
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN

위와 같이 완전 동일한게 2가지가 나오지 않습니다.

즉 소켓은 아래 5가지로 구성됩니다. 아래 5가지가 조합되어 하나의 unique key 를 만든다고 보면 됩니다.

프로토콜(tcp or udp), 소스 ip, 소스 포트, 목적지 ip, 목적지 포트

 

이 말은 상당히 중요한 의미를 가집니다.

웹서버A ---> 웹서버B   와 같이 웹서버A 에서 웹서버 B로 http 요청을 보낸다고 합시다. 웹서버 A는 동시에 몇개의 http 요청을 보낼수 있을까요? 정답은 약 65535개 입니다. 

아마도 아래와 같은 상태일것입니다. 즉 모두 동일하게 local address 의 포트번호만 다를겁니다.

Proto Recv-Q Send-Q Local Address           Foreign Address         State      
tcp        0      0 x.x.x.x:1234              22.22.22.22:80        ESTABLISED    
tcp        0      0 x.x.x.x:1235              22.22.22.22:80        ESTABLISED  
tcp        0      0 x.x.x.x:1236              22.22.22.22:80        ESTABLISED  
tcp        0      0 x.x.x.x:1237              22.22.22.22:80        ESTABLISED  
(생략)

포트번호는 65535까지 가능하므로, 동시에 요청가능한 요청수도 65535 로 제한됩니다. 포트번호중 몇개는 특수용도로 사용되니 실제로는 65535 보다 약간 작을겁니다. 암튼 너무 많은 요청을 하면 포트번호 고갈로 인해 소켓 생성이 되지 않게 되어 통신문제가 발생하는 겁니다.  만약 통신이 안되거나 timeout이 자주 발생하는데, CPU, MEM 등은 문제가 없을 경우 netstat 으로 너무 많은 소켓이 열려있는건 아닌지 확인해봐야 합니다.

 

그외 유사한 툴

netstat 외에도 ss 나 ip 라는 툴이 있으며, netstat 과 유사한 기능을 합니다. 

netstat 의 man 페이지 맨 아래에

This program is mostly obsolete. Replacement for netstat is ss. <-- 이렇게 적혀있습니다. 

그럼에도 불구하고 여전히 많이 사용되고 있습니다. 기능 업데이트가 더 이상 없을뿐인건데 사실 현재 기능 만으로도 꽤 유용하기 때문에 여전히 사용하고 있지 않을까 싶습니다.

$ man netstat
NETSTAT(8)                                                         Linux System Administrator's Manual                                                        NETSTAT(8)

NAME
       netstat - Print network connections, routing tables, interface statistics, masquerade connections, and multicast memberships

SYNOPSIS
      (생략)

NOTES  :  < 이 프로그램은 거의 구식이다. ss 로 대체해서 사용하라. 라고 아래에 적혀있음. >
       This program is mostly obsolete.  Replacement for netstat is ss.  Replacement for netstat -r is ip route.  Replacement for netstat -i is ip -s link.  Replacement
       for netstat -g is ip maddr.

 

windows 에서 사용법

netstat 은 윈도우의 cmd 창에서도 사용가능합니다.

C:\Users\second>netstat -ant

활성 연결

  프로토콜  로컬 주소              외부 주소              상태            오프로드 상태
  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       InHost
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       InHost  
  TCP    127.0.0.1:10809        127.0.0.1:64032        ESTABLISHED     InHost 
  TCP    127.0.0.1:64032        127.0.0.1:10809        ESTABLISHED     InHost
  TCP    172.30.128.1:139       0.0.0.0:0              LISTENING       InHost
  TCP    192.168.0.2:139        0.0.0.0:0              LISTENING       InHost
  TCP    192.168.0.2:2869       192.168.0.1:46319      ESTABLISHED     InHost

리눅스의 netstat 과 거의 동일합니다.

다만 -p 옵션이 process id 를 알려주는 옵션이었는데 windows 에서는 -o 옵션을 써야 하며 pid 만 알려주고 process name을 알려주지 않습니다.

C:\Users\second>netstat -anto

활성 연결

  프로토콜  로컬 주소              외부 주소              상태            PID      오프로드 상태

  TCP    0.0.0.0:135            0.0.0.0:0              LISTENING       1092     InHost
  TCP    0.0.0.0:445            0.0.0.0:0              LISTENING       4        InHost

그래서 아래처럼 "작업 관리자"를 실행한 후 "세부 정보" 탭에서 PID 정보를 참고해서 프로세스 이름을 찾아야 합니다.

리눅스에서는 grep 이라는 명령어를 통해 문자열 필터링이 가능하나 윈도우에서는 findstr 이라는 명령어를 써야 합니다. 

아래는 ESTA 라는 문자열이 있는 것만 필터링 해서 보여줍니다. 보통은 찾길 원하는 ip 주소를 적어서 특정 ip 와의 소켓정보만 확인합니다.

C:\Users\second>netstat -anto | findstr ESTA
  TCP    127.0.0.1:6517         127.0.0.1:6518         ESTABLISHED     4348     InHost
  TCP    127.0.0.1:6518         127.0.0.1:6517         ESTABLISHED     4348     InHost
  TCP    127.0.0.1:10809        127.0.0.1:64032        ESTABLISHED     29268    InHost

* 도움이 되었다면 "좋아요" 부탁드립니다.