본문 바로가기

카테고리 없음

Backlog Queue와 Accept Queue

Backlog Queue와 Accept Queue

TCP 연결은 3-way handshake 과정을 통해 이뤄진다. 이 과정에서 서버 측 커널은 다음 두 가지 큐를 유지한다.

  • Backlog Queue(SYN Queue): 클라이언트 측이 보낸 SYN 요청에 대해 half-open 요청을 해당 큐에 저장한다.
  • Accept Queue: 3-way handshake가 완료되어 클라이언트로부터 ACK 패킷을 수신하면, 완전히 연결된 요청을 해당 큐에 저장한다.

3-way handshake 과정을 통해 두 큐의 쓰임을 살펴보자.

  1. 클라이언트 측은 연결을 시작하기 위해 서버 측에 SYN을 보낸다. 클라이언트 측은 SYN_SENT 상태가 된다.
  2. 서버 측이 클라이언트 측으로부터 SYN을 수신하면, 서버 측은 SYN_RECV 상태가 된다. 이때 커널은 backlog queue에 연결(half-open connection)을 저장하고 SYN+ACK을 클라이언트 측에 보낸다.
  3. 클라이언트 측이 SYN+ACK을 수신하면, 클라이언트가 ACK을 보내고 ESTABLISHED 상태가 된다.
  4. 서버 측이 ACK을 수신하면, 커널은 SYN 큐에서 연결을 제거하고 accept queue에 연결(fully established connection)을 저장한다. 그리고 서버 측도 ESTABLISHED 상태가 된다.
  5. 서버 측 애플리케이션이 accept 함수를 호출하면, accept queue에서 연결을 가져와 새로운 소켓을 생성하고 이를 애플리케이션에 반환한다. 애플리케이션은 이 소켓을 사용하여 클라이언트와의 통신을 수행한다.

Backlog Queue 사이즈

backlog queue의 사이즈는 서버 애플리케이션이 소켓을 열고 클라이언트의 연결 요청을 대기하기 위해 listen 함수를 호출할 때 지정할 수 있다. listen 함수의 두 번째 인자는 backlog 큐의 크기를 지정하는 파라미터이다. sockfd는 소켓 파일 디스크립터, backlog는 backlog 큐의 크기이다.

int listen(int sockfd, int backlog);

 

실제 큐의 크기는 listen 호출 시 지정한 값과 운영체제의 내부 구현 값 중 더 작은 값으로 설정된다. 스프링 부트를 사용하면 톰캣 서버를 사용하게 되는데 톰캣의 기본 backlog queue 사이즈 설정 값은 100이다. 그리고 server.tomcet.accept-count 속성을 통해 큐 사이즈를 변경할 수 있다.

 

톰캣의 설정은 다음과 같다.

  • accept-count: backlog queue 사이즈
    • 기본 값 = 100 
    • 너무 크게 설정하면, 메모리 자원을 낭비할 수 있다.
    • 너무 작게 설정하면, 요청이 몰렸을 때 들어오는 요청들을 거절할 수 있다. 그리고 DDOS 공격에 취약해진다. SYN Flood Attack은 간략히 말하면 클라이언트가 SYN만 무수히 많이 보내고 ACK를 보내지 않아서 SYN Backlog Queue를 가득차게 만들어서 다른 사람이 연결을 맺지 못하게 만드는 공격이다. 
    • 설정 값 이상의 SYN에 대해서는 연결 요청을 거절하거나 패킷을 드롭한다.
  • max-connections: 서버가 동시에 열 수 있는 클라이언트와의 연결 소켓의 개수
    • 기본 값 = 8192
    • 서버 측 애플리케이션이 accept 함수를 호출하면 accept queue에서 요청을 가져와, 새로운 소켓을 생성한다. 이 소켓의 수를 의미한다.

Reference