SYN 쿠키는 SYN flood 공격을 막을 때 사용하는 TCP 초기 시퀀스 값입니다. 이 기법은 1996년 9월에 Daniel J. Bernstein과 Eric Schenk가 고안한 것입니다. 원래 SYN 큐가 가득 차면 서버는 더 이상 접속을 처리하지 못하고 버리게 됩니다. 이렇게 하는 대신에 SYN 쿠키를 사용하면, 서버는 SYN+ACK 응답에 접속 관련 정보를 써넣은 다음 전송하고 SYN 큐에서 삭제합니다. 이후에 클라이언트로부터 ACK 응답을 받았을 때, 서버는 TCP 시퀀스 번호에 인코드된 정보를 이용하여 SYN 큐 접속 정보를 복원할 수 있습니다.
구현
TCP 접속을 시작하려면 클라이언트가 먼저 서버에게 TCP SYN 패킷을 전송해야 합니다. 이에 대한 응답으로 서버는 TCP SYN+ACK 패킷을 클라이언트에게 보냅니다. 이 패킷에 들어있는 값 중 하나가 시퀀스 번호인데, 이 값은 TCP 프로토콜이 데이터 스트림을 재조립하는데 사용합니다. TCP 명세에 따르면, 첫 번째 시퀀스 번호는 전송하는 쪽에서 임의의 값을 사용할 수 있도록 되어있습니다. SYN 쿠키는 아래의 규칙을 따라 만들어진 특별한 초기 시퀀스 번호를 의미합니다:
- t = 64초마다 증가하는 카운터 값
- m = MSS (Maximum Segment Size) 값. 원래 서버의 SYN 큐 안에 들어가는 정보입니다.
- s = 서버 IP 주소와 포트 번호, 클라이언트 IP 주소와 포트 번호, 위의 t 값을 매개변수로 하는 해시 함수. 반환값 s는 반드시 24비트 값이어야 합니다.
초기 TCP 시퀀스 번호 (= SYN 쿠키) 는 아래와 같이 계산됩니다:
- 첫번째 5비트: t mod 32 (t를 32로 나눈 나머지)
- 다음 3비트: m을 인코드한 값
- 마지막 24비트: s
(여기서 m은 3비트 밖에 사용할 수 없으므로, SYN 쿠키를 사용하는 서버는 m 값을 8가지만 사용 가능합니다.)
클라이언트가 서버의 SYN+ACK 패킷에 대응하는 TCP ACK 패킷을 보낼 때에는, TCP 규약대로 반드시 서버가 보낸 초기 시퀀스 번호 n에 1을 더해서 확인 번호(Acknowledgement number)로 사용해야 합니다. 서버는 ACK 패킷을 받아서 1을 빼면 처음에 클라이언트에게 보냈던 SYN 쿠키 값을 확인할 수 있게 됩니다.
이제 서버는 아래와 같은 작업을 수행합니다:
- t 값을 이용하여 접속 대기 시간이 초과되었는지 확인합니다.
- s 값을 재계산하여 SYN 쿠키가 유효한 값인지 확인합니다.
- 3비트 인코딩된 m 값을 디코드하여 SYN 큐 엔트리를 생성합니다.
이후에는 일반 접속 절차가 그대로 진행됩니다.
단점
SYN 쿠키는 프로토콜 명세를 위반하지 않기 때문에 모든 TCP 구현과 호환 가능합니다. 그렇지만 서버가 사용할 수 있는 MSS 값이 8가지로 제한된다는 점과, 모든 TCP 옵션을 거부해야 한다는 단점이 있습니다.
이 때문에 성능이 최적으로 나오지 않을 가능성이 있지만, 사실상 클라이언트에 미치는 영향이 미미한데다 서버가 공격 당하고 있는 상황에서만 이 기법을 적용하는 것도 가능하기 때문에 별다른 문제가 되지는 않습니다. 아예 서비스를 사용할 수 없는 상황보다는 나을테니까요.




