TCP 통신과 3-way,4-way handshake 그리고 time_wait 소켓의 개념

TCP 통신과 3-way,4-way handshake 그리고 time_wait 소켓의 개념
  • TCP 통신과 3-way handshake와 4-way handshake
  • 내가 사용하는 서버의 기본 time_wait 시간확인

모든 코드는 깃헙에 작성되어 있습니다.



1.TCP 통신과 3-way-handshake, 4-way-handshake에 대해 알아보자.

우리가 개발할 때 사용하는 네트워크 통신에 대해 들어가기게 앞서 알아두어야 할 기본 지식들이 있다.

TCP는 한번씩 들어봤을거다.TCP(Transmission Control Protocol)는 쉽게 말하자면 인터넷상에서 데이터를 메세지의 형태로 보내기 위해 IP와 함께 사용하는 규약이다. 브라우저에서 클라이언트가 우리가 배포한 서버로 접근하는것도, 리버스 프록시인 엔진엑스에서 WAS로 보내는 네트워크 통신도 TCP 통신의 일종이다.


HTTP 통신과 TCP 통신은 다른게 아닌가요?
HTTP 통신도 TCP 통신을 기반으로 만들어져 있다. 그렇기에 아래에 설명할 3-way handshake, 4-way handshake 과정을 TCP 통신 뿐만이 아니라, HTTP 통신도 똑같이 거치게 된다. 아래에 3-way handshake와 4-way handshake를 보고나면 이해가 더 잘 될것이다.
HTTP통신과 TCP통신


TCP란 무엇인가


그럼 TCP 통신에 대해 알았으니, 그 과정에 대해 보도록 하겠다. 클라이언트와 서버단에서 서로 TCP 통신을 하기 위해서는 여러 과정을 거친다. 우선 클라이언트단에서 서버단에 최초의 연결을 맺으려 할 때 3-way handshake라는 과정을 거치게 된다.

3-way handshake란,
1.클라이언트는 서버로 통신을 시작하겠다는 SYN을 보내고,
2.서버는 그에 대한 응답으로 SYN+ACK를 보낸다.
3.마지막으로 클라이언트는 서버로부터 받은 패킷에 대한 응답으로 ACK를 보낸다.
이렇게 3-way-handshake를 정상적으로 마친 다음 클라이언트는 서버에 데이터를 요청한다.

3-Way Handshake를 하는 이유는 클라이언트, 서버 모두 데이터를 전송할 준비가 되었다는 것을 보장하기 위한 것이다.


3-way handshake에 관하여 (1)
3-way handshake에 관하여 (2)


그 다음, 데이터를 주고 받은 뒤에 해당 연결을 끊어야 하는데 이 또한 4가지 과정을 거쳐야 한다. 이를 4-way handshake라 한다. 아래 순서를 보겠다.

4-way handshake란
1.클라이언트는 응답을 주고 연결을 끊기 위해 FIN패킷을 보낸다.
2.서버는 클라이언트에서 보낸 패킷에 대한 응답으로 ACK 패킷을 보낸다.
3.서버는 자신이 사용한 소켓을 정리하며 통신을 완전히 끝내도 된다는 의미로 FIN 패킷을 보낸다.
4.클라이언트는 서버 패킷에 대한 응답으로 ACK패킷을 보낸다.

4-way handshake과정을 거치고 나면 클라이언트와 서버단의 네트워크는 종료가 된다.


연결을 맺을 때는 연결을 맺고자 하는 쪽에서 먼저 SYN를 보내며, 연결을 끊을 때는 연결을 끊으려는 쪽에서 먼저 FIN을 보낸다.


4-way handshake에 관하여


위에서 본 TCP 통신은 모두 TCP Socket 통신이다. TCP Socket 통신은 소켓(socket)을 이용하여 클라이언트단과 서버단이 각각 소켓에 명시된 자신의 포트를 통해 통신해야만 한다. 즉, 클라이언트과 서버가 연결을 할 때도 데이터를 교환할 때도 해당 소켓의 포트를 이용해야한다.

즉, 3-way handshake, 4-way handshake 모두 클라이언트단과 서버단에 소켓(socket)이 생성되어야만 이 소켓을 연결부로 사용하여 통신을 할 수 있게 되는것이다.


소켓(Socket)은 프로토콜, IP주소, 포트로 정의되며, 네트워크상에서 동작하는 프로그램 간 통신의 종착점(Endpoint)이다. (정확히는 엔드포인트의 연결부이다.) 즉, 데이터를 통신할 수 있도록 해주는 연결부이기 때문에 통신할 두 프로그램(Client, Server) 모두에 소켓이 생성되야 한다.
소켓(socket)이란 (1)
소켓(socket)이란 (2)


Endpoint : IP Address와 port 번호의 조합을 뜻하며 최종 목적지를 나타낸다. 예시로 최종목적지는 사용자의 디바이스(PC, 스마트폰 등) 또는 Server가 될 수 있다.
엔드포인트(Endpoint)란


그렇다면, 4-way handshake에 대해 더 자세히보고 4-way handshake를 사용하는 이유를 보도록 하겠다. 위의 과정에서 왼쪽이 A, 오른쪽이 B라하면 A에서 먼저 연결을 끊는것으로 볼 수 있다. (A가 FIN을 B로 보내고 있으니) 그 이후 마지막으로 A가 ACK를 B로 보내고 time_wait상태로 빠진다. B는 A에게서 마지막 ACK를 받고 소켓을 종료시킨다. 하지만, A는 time_wait로 인해 일정시간이 지나고 나서야 소켓이 닫힌다.

여기서, A가 time_wait시간을 갖는 이유는, 만약 B가 마지막 ACK를 받지못하면 위에서 보이는 바와같이 B가 A에게 다시한번 FIN(위의 그림에서 위에서 세번째 화살표)을 보내게된다. 그런데, 만약 A가 time_wait없이 종료된 상태면 B가 원활한 종료를 하지 못하는것이다. 그렇기에, 마지막 A가 B에게 ACK를 보낼때 A는 time_wait상태에 빠지고, B는 해당 ACK를 받으면 정상적으로 소켓이 닫히고, A 소켓은 정해진 time 후에 자동으로 닫힌다.


위의 그림에서는 계속해서 클라이언트단이 연결을 먼저 끊어서 FIN을 서버단에 보낸다고 나와있는데, 클라이언트뿐만 아니라 서버단에서도 먼저 끊을 수 있다. 즉, 클라이언트라해서 꼭 연결을 먼저 끊는것은 아니며 서버단이라고 연결이 끊어질 때 FIN을 먼저 받기만하지 않는다. 반대로도 일어날 수 있는거다. 서버단에서 먼저 연결을 끊으면 서버단에서 먼저 FIN을 클라이언트단으로 보내고 위와같은 과정이 똑같이 일어나지만 서버단과 클라이언트단의 역활만 바뀔 뿐이다. 그렇기에, 연결을 먼저 끊는 쪽을 active closer라하고 그 반대를 passive closer라 한다. 클라이언트,서버 둘다 active closer passive closer가 될 수 있는거다.
active closer와 passive closer에 대하여


active closer와 passive closer의 소켓 반환 시기 (1)
active closer와 passive closer의 소켓 반환 시기 (2)
4-way handshake와 time_wait 소켓 (1)
4-way handshake와 time_wait 소켓 (2)


2.내가 사용하는 서버의 time_wait는 몇분일까?

RFC 793(국제 인터넷 표준화 기구에서 기술한 핵심 프로토콜)에 따르면, time_wait의 시간을 2MSL(Maximum Segment Lifetime)로 설정해 놓았다. 하지만, 이 2MSL은 운영체제나 혹은 운영체제 버전(linus의 경우 Centos의 버전)에 따라서도 다르게 지정될 수 있다.(통상 MSL하나당 30초 ~ 2분) 하지만, 보통의 경우 OS에서는 최적화를 위하여 2MSL을 1분으로 설정하여 사용하도록 구현되어 있다. 실제 Centos6의 경우는 60초로 설정되어있다.


RFC 793 이란?
MSL은 운영체제 혹은 운영체제의 버전에 따라서 다르게 지정 가능 (1)
MSL은 운영체제 혹은 운영체제의 버전에 따라서 다르게 지정 가능 (2)
CentOS 6버전에서의 TIme_wait 시간


그렇다면, 우리가 AWS EC2 인스턴스를 생성하는 경우(이 글에서는 aws 리소스를 예시로 설명하겠다.) 우리가 사용하는 서버의 time_wait를 어떻게 알 수 있을까?

이걸 알아가기에 앞서 우리는 리눅스 커널의 개념, 센토스와 우분투는 무엇인지 에 대해 보도록 하고, 리눅스 버전마다 time_wait이 다르니 EC2에서 리눅스버전(CentOS 버전) 그리고 리눅스커널 버전을 보는 방법에 대해서도 알도록 하겠다.


우선 센토스와 우분투에 대해서 보도록 하겠다.
리눅스는 공개 운영체제여서 오픈소스로 누구나 자유롭게 수정이 가능하다. 그렇기에 무수히 많은 버전의 리눅스가 있는데, 보통 레드햇계열과 데비안계열의 리눅스를 많이 사용한다. 레드햇이 센토스OS이고 데비안이 우분투OS이다.

센토스
리눅스에서 서버용 운영체제로써 제일 인기가 많으며, 실제로도 서버용으로 리눅스를 운영할 목적이라면 센토스OS를 대부분 추천한다.

우분투
센토스에 비해서 성능이 딸리거나 부족하지는 않으나 서버용으로는 점유율로 볼때 센토스에 많이 밀린다. 하지만, 개인용 데스크톱 운영체제에서 많이 사용되고 있다.

이렇기에, 개인이 익숙한 리눅스 계열을 사용해도되고, 처음이라면 센토스로 시작해도 나쁘지않다. (우리가 aws에서 사용하는 EC2의 경우는 센토스 계열이다.)


추가로,
리눅스 커널
리눅스 커널은 리눅스 운영체제의 주요 구성 요소이며, 컴퓨터 하드웨어와 프로세스를 잇는 핵심 인터페이스이다. 즉, 우분투와 센토스는 리눅스 그 자체라면 리눅스 커널은 이를 구성하는 요소로 보면된다.


리눅스의 센토스와 우분투에 관하여
리눅스 커널이란


그렇다면, EC2의 리눅스 커널 버전과 센토스(aws ec2는 센토스를 사용한다.) 버전을 확인하는 방법에 대해 보도록 하겠다.


EC2 인스턴스를 이미 생성하고 SSH접속까지 완료됬다는 가정하에 진행한다.


EC2 인스턴스에 ssh접속을 하였으면,
cat /etc/release 명령어를 입력해준다.

그러면,

1
2
3
4
5
6
7
8
9
10
11
12
13
[ec2-user@ip-172-31-1-230 ~]$ cat /etc/*release*
cat: /etc/lsb-release.d: Is a directory
NAME="Amazon Linux"
VERSION="2"
ID="amzn"
ID_LIKE="centos rhel fedora"
VERSION_ID="2"
PRETTY_NAME="Amazon Linux 2"
ANSI_COLOR="0;33"
CPE_NAME="cpe:2.3:o:amazon:amazon_linux:2"
HOME_URL="https://amazonlinux.com/"
Amazon Linux release 2 (Karoo)
cpe:2.3:o:amazon:amazon_linux:2

이와같이 보여지는데, 기존같으면 센토스 몇인지 나와야 하는데, 나오지가 않는다. 그 이유는 현재 필자가 글을 쓰는 시점에는 CentOS8의 경우 2021년 12월 31일부로 종료가 되었고, RHEL로 전환이 되었는데, 이러한 것을 반영한것일수도 있고, 내부적으로 CentOS 7을 사용하는데 보여지지 않는것일수도 있다. 우선은 레드헷 계열의 리눅스를 사용한다는걸 알 수 있다.


RHEL(Red Hat Enterprise Linux)를 설명하자면, 기존의 CentoS가 이 RHEL의 소스를 그대로 갖고와서 Red Hat의 브랜드와 로고만 제거하고 만든 배포본이다. 즉, RHEL의 소스를 거의 수정없이 사용하였기에 센토스의 원본이라고 보아도 된다.
Red Hat이란?


센토스 버전 확인방법 (1)
센토스 버전 확인방법 (2)
CentOS 8 종료와 RHEL로 전환


리눅스 커널의 버전을 보는방법은 두가지다.
하나는, AWS 인스턴스 생성시에 AMI(Amazon Machine Image)를 고르는 과정에서 볼 수 있는 방법이 있고, 다른하나는 ssh 접속하여 명령어로 알아보는 방법이다. 첫번째는 쉬우니 두번째로 알아보도록 하겠다.

아까와 같이 ssh접속을 한 상태에서, uname -r 을 입력해준다.

1
4.14.256-197.484.amzn2.x86_64

라고 뜨는게 보인다. 해당 버전은 커널 4.14버전임을 알 수 있다. 실제로, aws의 AMI 선택란에도 보면 Linux Jernel 4.14버전임을 알 수 있다. (필자가 작성한 날짜 기준이다. 시간이 지나면 버전은 바뀔 수 있다.)

결론적으로, 내가 사용하는 EC2 인스턴스의 리눅스 커널 버전을 알고, redhat계열의 리눅스라는건 알았지만 자세한 버전은 알 수 없었다. 하지만, 기존 OS에서는 time_wait 소켓의 시간이 1분이라는 점과 CentOS 6의 time_wait도 1분이라는 점을 볼때 현재 사용하는 EC2의 time_wait도 1분으로 생각하고 가도 충분할것이다.


후에 정확한 time_wait을 알아야 하는 경우, aws문서나 혹은 ssh접속으로 명령어를 통해 알아보도록 하자.


EC2에서 센토스 버전 확인 (1)
EC2에서 센토스 버전 확인 (2)


🚀 추가로,

앞서, HTTP 통신이 TCP 통신기반이라 얘기했었다. 하지만, HTTP 통신과 TCP 통신의 다른점도 분명히 존재한다.

HTTP 통신

  1. 클라이언트가 요청을 보내는 경우에만 Server가 응답하는 단방향 통신이다.
  2. Server로 부터 응답을 받은 후에는 연결이 바로 종료된다.
  3. 요청을 보내 server의 응답을 기다리는 어플리케이션의 개발에 주로 사용된다.

TCP 소켓통신

  1. Server와 Client가 계속 연결을 유지하는 양방향 통신이다.
  2. Server와 Client가 실시간으로 데이터를 주고받는 상황이 필요한 경우에 사용된다.
  3. 실시간 동영상 Streaming이나 온라인 게임등에 자주 사용된다.


🪁 References


태그 : #포트, #소켓, #3-way handshake, #4-way handshake, #time_wait, #HTTP통신, #TCP통신, #TCP 소켓통신, #리눅스커널, #우분투, #센토스, #RHEL, #RFC 793, #MSL

comments powered by Disqus