커널 파라메터 tcp_tw_recycle 이슈
2024. 2. 7. 16:33ㆍNetwork
요즘 cloud 환경을 많이 사용하는 데, cloud 환경에서 NAT를 거쳐 onPrem 같은 구 환경으로 네트웍을 연결해놓은 상태라면, 구 커널 버전 환경에서 구동 중인 서버라면 해당 이슈가 발생할 수 있다는 걸 알게 되었습니다.
1) TIME WAIT (https://docs.likejazz.com/time-wait/)
- Active close 측에서 만들어지는 Socket status로 Timeout 설정이 끝날때 까지 Socket이 생존한채로 유지됩니다.
- tcp_tw_reuse : TIME WAIT 상태의 Socket 들로 인해서 Outgoing connection시 Socket 부족 현상이오면 Reuse (https://forum.vyos.io/t/linux-tcp-tw-reuse-2-how-is-this-set-and-what-is-the-significance/5286) 하도록 하는 옵션이며 최근에는 국소적인 옵션이 생겨났으며 현재 이 값이 default인 상태입니다.)
- tcp_tw_recycle : TIME WAIT의 유지 시간을 극단적으로 줄이게 되는 옵션이며 문제의 원흉!
- 해당 option은 실제 위험한 NAT 환경에서 위험한 문제를 발생시키며 실제[ https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=4396e46187ca5070219b81773c4e65088dac50cc] 2017년 kernel 버전 4.2 부터(Ubuntu 기준으로는 16.04)는 이미 삭제된 옵션입니다.
- (https://linux.systemv.pe.kr/2015/03/%eb%b2%88%ec%97%ad-%eb%b0%94%ec%81%9c-%eb%a6%ac%eb%88%85%ec%8a%a4-%ec%84%9c%eb%b2%84%ec%97%90%ec%84%9c-tcp-time-wait-%ec%83%81%ed%83%9c-%eb%8c%80%ec%b2%98%ed%95%98%ea%b8%b0/)해당 flag가 on이 되어져있을 경우 동일한 IP에서 온 request에 대해서 Sender측 Timestamp 값과 저장해둔 값의 차를 이용하여 잘못된 패킷이라고 판단 후 drop하는 코드가 존재합니다.
if (tmp_opt.saw_tstamp &&
tcp_death_row.sysctl_tw_recycle &&
(dst = inet_csk_route_req(sk, req)) != NULL &&
(peer = rt_get_peer((struct rtable *)dst)) != NULL &&
peer->v4daddr == saddr) {
if (get_seconds() < peer->tcp_ts_stamp + TCP_PAWS_MSL &&
(s32)(peer->tcp_ts - req->ts_recent) >
TCP_PAWS_WINDOW) {
NET_INC_STATS_BH(sock_net(sk), LINUX_MIB_PAWSPASSIVEREJECTED);
goto drop_and_release;
}
}
- 위의 로직이 문제가 되는 이유는 NAT 환경에서는 모든 Sender가 동일 IP로 들어오게 되며, Client 마다 기준 Timestamp가 각기 다르기 때문입니다. 이로인해 “goto drop_and_release” 해당 코드가 동작하게 되었으며 Client는 지속적으로 SYN에 대한 ACK를 요구하기 위해서 다시 보내오고 Server 측에서는 그냥 버리는 동작이 반복되었습니다.
- Wireshark 레벨에서는 동일한 Source로 부터 반복해서 동일 port로 SYN이 들어온다고만 판단했기에 아래와 같은 메시지를 출력하고 있었습니다.
- “NMIMS side 문제 발생시 TCP dump“
- (https://www.lesstif.com/lpt/linux-chrony-time-synchronizing-82215032.html) 라는 Tool도 존재하지만 실제로 TCP Timestamp 값에는 영향을 미치지 못했습니다. (정확히는 알수 없지만 OS타임과 TCP에서 관리하는 Timestamp라는 값은 별개로 판단됩니다.)
2) Linger option (http://egloos.zum.com/rucaus/v/237240)
- C에서 제공되는 Socket 옵션
struct linger
{
int l_onoff; ⁄* option on⁄off *⁄
int l_linger; ⁄* linger time *⁄
};
- Socket 생성시 l_onoff를 on으로 활성화할 경우 linger time을 함께 설정하게 되고, 해당 값 동안만 TIME WAIT 역할을 수행하고 바로 RST를 이용하여 TIME WAIT STATE로 전환하지 않는 방법입니다.
- 활성화시 socket close는 linger time동안 blocking call 이 됩니다. (Return이 되지 않음)
- 비동기에서는 쓰지 않을 이유가 없는 방식으로 보이고 실제 Netty 기반의 Spring cloud gateway의 경우에는 TIME WAIT가 남지 않기기에 linger를 활용하고 있는 것으로 보입니다.
'Network' 카테고리의 다른 글
Connection reset by peer 이슈 (1) | 2023.01.24 |
---|