如果要自己实现一个 NAT (Masquerade) 服务器,除了分配端口,改字段和校验和,另一个难题可能是 TCP 的状态管理: 一般的技术资料会告诉你,FIN 的发起方需要 TIME_WAIT,而接收方则不需要
比如资料 1:
http://tcpipguide.com/free/t_TCPOperationalOverviewandtheTCPFiniteStateMachineF-2.htm比如资料 2:
https://blog.51cto.com/11859650/1917938于是如果要在一个合适的时候释放掉端口,我原本以为要在程序中大致实现 TCP 状态机,并且跟踪连接状态
今天为了保险起见,看了下 Linux 内核 conntrack 的实现逻辑,却有了个新发现。Linux 内核的 conntrack 虽然实现了完整的状态管理,并且滤掉了一些明显错误的包,但是我发现无论是主动发起 FIN 还是被动发起,conntrack 状态变化的过程都是:
- sES -> sFW (Established -> FinWait)
- sFW -> sCW (FinWait -> CloseWait)
- sCW -> sLA (CloseWait -> LastAck)
- sLA -> sTW (LaskAck -> TimeWait)
最终都是要 TIME_WAIT 的!源代码在这里:
https://elixir.bootlin.com/linux/v2.6.39.4/source/net/netfilter/nf_conntrack_proto_tcp.c#L141为了确认不是自己看走眼了,还找到了一篇描述该现象的提问:
https://unix.stackexchange.com/questions/67479/why-tcp-time-wait-state-is-present-at-both-ends-after-a-connection-termination问题来了:既然无论如何都要 TIME_WAIT 一段时间,NAT TCP 的处理是否可以退化成 NAT UDP 的处理,也就是连接静止一段时间就触发清除?
看起来这个和 Linux 原生的 iptables masquerade 并没有多少区别,最多放一些错误的包进来,而最终这些错误的包会被底层的设备以正确的方式处理掉
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
https://www.v2ex.com/t/654693
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.