해킹 여부 및 DDOS 공격 여부를 확인하기 위해 unix/linux 서버를 점검할 때 가장 먼저 살펴봐야할 것은 서버의 통신 상태다. 그리고 이때 사용하는 명령어는 netstat 명령이다. 만약 root권한의 탈취가 의심되고 운영체제 파일의 변조까지도 의심스럽다면 서버에 기본적으로 설치되어 있는 netstat 명령보다는 사고가 발생하지 않은 서버에서 netstat 명령어나 lsof 명령어 등을 업로드하여 사용하는 것이 좋겠다.
많은 엔지니어나 운영자들이 TCP 소켓의 상태 중에 3 way handshake 과정에 해당되는 LISTEN이나 SYN_SENT, SYN_RCVD, ESTABLISHED 등의 상태에 대해서는 잘 알고 있지만 FIN_WAIT1이나 FIN_WAIT2 등 통신 종료과정의 상태에 대해서는 어떤 의미인지를 잘 모르고 있는 경우가 많다.
TCP 통신의 종료과정은 일반적으로 4 way handshake라고 불리는 절차에 의해 진행된다. 일단 그 과정을 도식화 하면 다음과 같다.
이 4 way handshake 과정은 다음과 같이 진행된다.
1. 먼저 통신을 종료하고자 하는 클라이언트는 서버에게 FIN 플래그를 세팅한 패킷을 보내고 자신은 FIN_WAIT_1 상태가 된다.2. FIN 을 수신한 서버는 ACK를 클라이언트에게 전송하고 소켓의 상태를 CLOSE_WAIT로 변경한다.3. ACK를 수신한 클라이언트는 서버가 FIN을 잘 받았다고 판단하고 FIN_WAIT_2로 소켓의 상태를 변경한 뒤 다시 FIN 패킷을 기다린다.4. FIN을 클라이언트에게 전송한 서버는 다시 FIN 패킷을 클라이언트로 전송한 뒤 소켓을 LAST_ACK 상태로 변경한다.5. FIN을 수신한 클라이언트는 서버에게 ACK를 전송한 뒤 소켓의 상태를 TIME_WAIT 상태로 변경한다.6. 클라이언트로부터 마지막 ACK를 수신한 서버는 소켓을 CLOSED 한다.
이 4 way handshake 과정이 문제가 되는 경우가 종종 발생한다. 서버와 클라이언트의 통신에서 (이때 클라이언트는 대부분 PC가 아닌 Unix, linux 서버임) 클라이언트 쪽에 FIN_WAIT1, FIN_WAIT2 상태의 소켓이 급격하게 증가하여 소켓관련 메모리가 부족한 상황이 발생하고 더 이상의 소켓을 오픈하지 못하는 경우가 그것이다.(실제로 오래전 서버보안 프로젝트 수행 시 이 문제로 골치를 앓은 경우가 있어 확실하게 기억하고 공부를 하였음. -.-)
이러한 증상의 원인은 대부분 서버나 클라이언트 측 프로그램의 버그이거나 운영체제의 버그인 경우가 많은데 쉽게 원인을 찾지 못하는 경우가 많은 것 같다. 클라이언트에서 서버에게 FIN을 날려 통신을 끊고자 하면 서버가 ACK와 FIN을 순차적으로 클라이언트에게 보내야 하지만 어떤 이유인지 서버측에서 혼자만 소켓을 LAST_ACK나 CLOSED로 바꾸고 ACK와 FIN 전송을 모두 혹은 FIN의 전송을 하지 않는 경우로 보인다.
특히 이러한 경우가 네트워크 부하가 많은 서버에서 종종 발생하는데 세션의 확립과 종료가 대량으로 발생하는 경우가 대부분이다. 원인을 찾아 해결하면 좋겠으나 그 과정이 쉽지 않아 대부분 클라이언트 측에서 FIN_WAIT_1 상태에서 ACK를 기다리는 시간과(Timeout이 걸리면 강제로 닫음.) FIN_WAIT_2 상태에서 FIN을 기다리는 시간을 짧게 설정하여 서버로부터 정상적인 ACK와 FIN을 수신하지 못하면 강제로 소켓을 닫도록 하는 방법으로 문제를 해결하고 있다.
하지만 4 way handshake를 사용하는 한 대량의 빈번한 open과 close를 한다면 timeout의 조정만으로는 문제를 해결하지 못한다. 이때는 4 way가 아닌 3 way로의 변경을 고려해볼 필요가 있다. 4 way 종료에서 3 way 종료로 바꾸기 위해서는 close() 를 호출하는 클라이언트 측의 프로그램 소스를 변경하여야 한다. 이때 사용되는 옵션이 SO_LINGER 옵션이다. 하지만 여러 문제를 야기할 수도 있으므로 신중하게 결정해야 한다고…많은 개발자들이 이야기 하고 있다.
만약 이글을 읽는 이가 개발자라면 자세한 것은 개발자 포럼에서 SO_LINGER로 검색해봐야 할 것이다. (단, 리눅스만 이 옵션을 제공하는 것 같음..)