공용 네트워크 서버 또는 클라이언트가 NAT 네트워크인 서버는 tcp_를 동시에 켜지 마십시오.tw_recycle 및 tcp_timestamps
9224 단어 계통
카탈로그
배경 및 현상
서버: 공공 네트워크 서버 클라이언트: 외부 네트워크 모바일 클라이언트 유저 측 현상: 대량의 같은 랜 내의 내부 유저들이 서버에 접속하는 시간이 초과되었지만 4G로 전환된 후에 연결이 원활하다.서비스 사이드 현상:
netstat -s"
"passive connections rejected because of time stamp"수량이 빠르게 증가하고 닫힘tcp_tw_recycle
또는 tcp_timestamps
정상적으로 회복되며 유저 사이드 현상이 사라집니다.문제의 원인
tcp_tw_recycle
의존tcp_timestamps
, 전자는 기본적으로 닫고 후자는 기본적으로 엽니다.둘 다 켜져 있으면 서버가 FIN 패키지를 받을 때 이 FIN 패키지의 타임스탬프 값은 IP에 따라 캐시됩니다(캐시 TCP_PAWS_MSL
, 즉 60s). 캐시 시간 내에 같은 IP의 SYN 패키지 타임스탬프가 이 값보다 작으면 바로 버려집니다.코드 분석은 다음과 같습니다.tcp_v4_conn_request()
/* VJ's idea. We save last timestamp seen
* from the destination in peer table, when entering
* state TIME-WAIT, and check against it before
* accepting new connection request.
*
* If "isn" is not zero, this request hit alive
* timewait bucket, so that all the necessary checks
* are made in the function processing timewait state.
*/
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 ((u32)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;
}
}
peer->tcp_ts_stamp
는 이전에 FIN 패키지를 받았을 때 서버의 시간 스탬프를 기록하기 때문에, peer->tcp_ts
는 FIN 패키지의 시간 스탬프를 기록하고, req->ts_recent
는 현재 SYN 패키지의 시간 스탬프를 표시하기 때문에, (u32)get_seconds() - peer->tcp_ts_stamp < TCP_PAWS_MSL
캐시가 아직 만료되지 않았음을 나타내고, (s32)(peer->tcp_ts - req->ts_recent) > TCP_PAWS_WINDOW
현재 SYN 패키지의 시간 스탬프가 이전 FIN 패키지의 시간 스탬프보다 1s 작음을 나타내기 때문에, 현재 SYN 패키지가 이전에 재전송된 것으로 간주하여 그대로 버린다.req - struct request_sock peer- struct inet_peer, inet_getpeer() get_seconds() - 현재 서버 시간 가져오기
TCP_PAWS_MSL
#define TCP_PAWS_MSL 60 /* Per-host timestamps are invalidated
* after this time. It should be equal
* (or greater than) TCP_TIMEWAIT_LEN
* to provide reliability equal to one
* provided by timewait state.
TCP_PAWS_WINDOW
#define TCP_PAWS_WINDOW 1 /* Replay window for per-host
* timestamps. It must be less than
* minimal timewait lifetime.
*/
tcp_v4_tw_remember_stamp()
int tcp_v4_tw_remember_stamp(struct inet_timewait_sock *tw)
{
struct inet_peer *peer = inet_getpeer(tw->tw_daddr, 1);
if (peer) {
const struct tcp_timewait_sock *tcptw = tcp_twsk((struct sock *)tw);
if ((s32)(peer->tcp_ts - tcptw->tw_ts_recent) <= 0 ||
((u32)get_seconds() - peer->tcp_ts_stamp > TCP_PAWS_MSL &&
peer->tcp_ts_stamp <= (u32)tcptw->tw_ts_recent_stamp)) {
peer->tcp_ts_stamp = (u32)tcptw->tw_ts_recent_stamp;
peer->tcp_ts = tcptw->tw_ts_recent;
}
inet_putpeer(peer);
return 1;
}
return 0;
}
peer->tcp_ts_stamp
동tcptw->tw_ts_recent_stamp
,peer->tcp_ts
동tcptw->tw_ts_recent
,참조tcp_timewait_state_process()
.tcptw - struct tcp_timewait_sock, struct inet_timewait_sock
tcp_timewait_state_process()
/* FIN arrived, enter true time-wait state. */
tw->tw_substate = TCP_TIME_WAIT;
tcptw->tw_rcv_nxt = TCP_SKB_CB(skb)->end_seq;
if (tmp_opt.saw_tstamp) {
tcptw->tw_ts_recent_stamp = get_seconds();
tcptw->tw_ts_recent = tmp_opt.rcv_tsval;
}
/* I am shamed, but failed to make it more elegant.
* Yes, it is direct reference to IP, which is impossible
* to generalize to IPv6. Taking into account that IPv6
* do not understand recycling in any case, it not
* a big problem in practice. --ANK */
if (tw->tw_family == AF_INET &&
tcp_death_row.sysctl_tw_recycle && tcptw->tw_ts_recent_stamp &&
tcp_v4_tw_remember_stamp(tw))
inet_twsk_schedule(tw, &tcp_death_row, tw->tw_timeout,
TCP_TIMEWAIT_LEN);
else
inet_twsk_schedule(tw, &tcp_death_row, TCP_TIMEWAIT_LEN,
TCP_TIMEWAIT_LEN);
return TCP_TW_ACK;
여기서 알 수 있듯이
tcptw->tw_ts_recent_stamp
은 FIN 패키지를 받았을 때 서버의 현재 시간을 기록하고 tcptw->tw_ts_recent
는 FIN 패키지의 양쪽 끝에 있는 시간 스탬프를 기록합니다.결론
대량의 내부 유저가 같은 NAT 네트워크에 있기 때문에 모든 유저의 IP는 같은 출구 IP로 변환되지만 타임 스탬프는 보존되어 있기 때문에 서버에 도착한 패키지의 타임 스탬프 순서와 도착 순서는 일치하지 않습니다.
tcp_tw_recycle
과tcp_timestamps
를 동시에 열 때 한 유저가 연결을 끊으면 다른 유저의 SYN 패키지가 버려질 수 있습니다.실천
tcp_ 구성 방법tw_recycle 및 tcp_timestamps
tcp_timestamp
오픈 권장.tcp_timestamp
는 RFC1323이 정의한 최적화 옵션으로 TCP 연결에서 RTT(Round Trip Time) 계산에 주로 사용되며, 오픈tcp_timestamp
은 시스템 계산에 더욱 정확한 RTT와 TCP 성능 향상에 도움이 된다.tcp_tw_recycle
닫기를 권장합니다.대부분의 시스템의 기본 설정도 마찬가지입니다.
왜 tcp_를 많이 켰는지tw_recycle도 문제가 없어요.
첫째, 현재 네트워크에서 대량의 사용자가 같은 NAT 네트워크에 있고 가방이 NAT 게이트웨이에 전송된 후 순서가 혼란스러워 수량이 적더라도 발생한다.둘째, 일부 클라이언트 시스템에서는 XP 및 대부분의 Windows 7과 같은 타임 스탬프를 사용하지 않습니다.
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
실례를 통해 Nodejs 모듈 시스템 및 require 메커니즘 이해Nodejs에는 간단한 모듈 로딩 시스템이 있습니다.Nodejs에서 파일과 모듈은 하나의 독립된 모듈로 간주됩니다. 이 파일은 JavaScript 코드, JSON 또는 컴파일된 C/C++ 확장자일 수 있습니다. 2....
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.