SSL 세션을 서버가 먼저 정리하고나면 클라이언트가 보내온 FIN에 대해서 ACK가 나가질 않습니다.
예전에 개발하여 납품한 장비에 있는 코드가 문제가 있는 것 같습니다.
구조는 TCP 또는 SSL 세션을 연결했다가 데이터를 송수신하고 연결을 끊는... 극히 단순한 구조인데요...
문제는 서버가 먼저 세션을 종료해야 합니다. 논블럭 소켓으로 구현했고요.
서버의 종료절차가
shutdown (fd, SHUT_WR);
nbyte = read(fd, ...);
if (nbyte == 0) close (fd);
이렇게 구성되어 있습니다. 서버가 먼저 종료절차를 시작하기 위해 shutdown()을 호출해서 FIN을 client로 보내고요, client는 ACK를 전송하고, close() 호출하여 역시 FIN을 보냅니다. 거기에 서버가 다시 ACK를 내보내 정상적을 종료가 됩니다.
그런데, 이 서버가 TCP 세션 뿐만 아니라 TLS 세션도 허용하고 있는데요.. 역시 종료절차는
SSL_shutdown (...);
SSL_free (...);
shutdown (fd);
nbyte = read(fd, ...);
if (nbyte == 0) close (fd);
이렇게 되어 있습니다. TCP 세션을 정리하기 전에 SSL_shutdown과 SSL_free를 순차적으로 불러 주는데요..
문제는 이경우 서버가 FIN 내보내고 client가 ACK와 FIN을 전송하는 것 까지는 정상적으로 수행이 되는데요, 서버가 최종적인 ACK를 내보내지 않아서 client에서 FIN을 재전송하는 경우가 자주 발생합니다. 재전송되어 수신된 FIN에 대해서도 ACK를 내보내지 않습니다.
종료절차를 수행하기 전에 논블러킹으로 동작하는 소켓을 블러킹으로 바꿔보고, shutdown없이 바로 close를 호출해보기도 했는데, 영 답을 찾기가 어렵습니다.
쉽게 풀릴 것 같았던 문제가 늪이되어 일주일째 허우적대고 있습니다.
문제가 없을 수도 있을 것 같습니다.
TCP를 후킹하여 필요한 조작을 하는 커널모듈을 같이 구현하여 사용하고 있는데요.. 아마도 그 커널모듈에서 오류가 있었던 것 같습니다. SSL과 TCP 소켓관련한 상위 application의 문제는 아닌 것 같습니다. ㅡㅡ;
댓글 달기