V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
feng32
V2EX  ›  程序员

实现 NAT (Masquerade) TCP 状态管理的极简方案

  •  
  •   feng32 · 2020-03-20 19:57:01 +08:00 · 1394 次点击
    这是一个创建于 1690 天前的主题,其中的信息可能已经有所发展或是发生改变。
    如果要自己实现一个 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 并没有多少区别,最多放一些错误的包进来,而最终这些错误的包会被底层的设备以正确的方式处理掉
    1 条回复    2020-03-21 10:37:28 +08:00
    qakito
        1
    qakito  
       2020-03-21 10:37:28 +08:00   ❤️ 1
    NAT 表对于 TCP 和 UDP 的表项维持时间是不同的; UDP 表项通常维持在 2 分钟-5 分钟; TCP 表项通常维持在 30 分钟-60 分钟。
    通过 TCP 状态(比如 RST 标识等),能够较及时的清除已经断开的 TCP NAT 表项;否则的话,要么失效的 TCP 表项会长时间残留,要么一段时间空闲的 TCP 会话会因中间的 NAT 表项超时断开。

    UDP 会话没有状态,只要看到一来一回,conntrack 就是 establish 状态了;对于一个需要长时间保持的 UDP 会话(比如 IPSec ESP 穿越 NAT),如果一段时间内没有流量,NAT 表失效就意味着 UDP 会话断开,因此对于这种情况,通常靠协议发送 keepalive 来维持 NAT 表

    TCP 会话有状态,如果没有开启 keepalive 选项,且会话闲置了一段时间,NAT 表超时就会导致 TCP 会话断开(比如 ssh 连接)
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3349 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 23ms · UTC 10:56 · PVG 18:56 · LAX 02:56 · JFK 05:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.