V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX 提问指南
palemoky
V2EX  ›  问与答

公网数据包如何通过 NAT 传递给内网的程序?

  •  
  •   palemoky · 2021-09-11 23:57:53 +08:00 · 1331 次点击
    这是一个创建于 1179 天前的主题,其中的信息可能已经有所发展或是发生改变。

    NAT 为了减缓 IPv4 的消耗而被广泛应用,比如最常见的家庭局域网。

    假设我 192.168.5.5 访问 43.1.1.1 的公网资源,请求数据包经过 NAT 的时候我理解会改写 IP 层的源主机 IP 地址,将内网 IP 改为公网 IP, 此时 NAT 维护了 192.168.5.5:54321 <==> 43.1.1.1:443 这样的映射关系,然后数据包就在公网传递。现在的问题是,响应数据包到了 NAT 是如何处理的?是通过查询到响应报文中有 43.1.1.1:443,再去 NAT 映射关系中查到 192.168.5.5:54321,然后通过 ARP 再查到对应主机的 MAC 地址交付数据包吗?如果是这样,就会有一个问题,假设另一个设备 192.168.5.9 也访问了 43.1.1.1:443,恰巧客户端端口号也是 54321,那此时 NAT 中就有这样的两个映射关系:

    • 192.168.5.5:54321 <==> 43.1.1.1:443
    • 192.168.5.9:54321 <==> 43.1.1.1:443

    那 43.1.1.1:443 的响应报文此时 NAT 如何正确投递呢?当连接释放时,NAT 也会删除对应的映射关系吗?还是通过有效期等淘汰机制清理呢?

    第 1 条附言  ·  2023-07-21 11:57:15 +08:00
    今天在看《 TCP/IP 详解:卷 1 》(第二版),在 7.3.1 节提到了我的疑惑。普通的 NAT 确实会存在不同主机相同端口映射冲突的问题,所以现在都用 NAPT 来解决
    https://i.postimg.cc/L80r5n3W/NAT-vs-NAPT.png
    15 条回复    2021-09-13 13:28:44 +08:00
    miyuki
        1
    miyuki  
       2021-09-12 00:09:03 +08:00 via iPhone
    在上层网关 192.168.1.1 (假设)会被继续 NAT
    比如 192.168.1.1 的上级 ip 是 1.2.3.4,192.168.5.5 的数据包 NAT 到从 1.2.3.4:5000 出去到 43.1.1.1:443,195.68.5.9 从 1.2.3.4:5001 出去到 43.1.1.1:443
    weyou
        2
    weyou  
       2021-09-12 00:10:40 +08:00 via Android   ❤️ 1
    现在讲到 NAT 大多数是 NAPT(Network Address Port Translation),就是加入端口映射的 NAT 。所以你例子中的映射关系里会有一个外部端口,当发生你所说的内网有多台设备用相同的源端口出去的话,会发生 NAT 外部源端口的改变,比如:
    192.168.5.5:54321 <=>ext port 54321<=>43.1.1.1:443
    192.168.5.9:54321 <=> ext port 54322<=>43.1.1.1:443
    这样对于响应包如何进来的就一目了然了
    sujin190
        3
    sujin190  
       2021-09-12 00:19:12 +08:00
    源地址变换,自然是源地址映射,你这源地址和目的地址映射看起来当然不对,不同源地址端口映射到公网之后 ip 相同但是端口不同啊,相应的时候目的地址端口就是映射的公网地址端口,一查就知道对应的是哪个内网地址端口了
    Tianao
        4
    Tianao  
       2021-09-12 00:34:02 +08:00 via iPhone
    首选楼主问的源 NAT ( NAPT ),那我们只讨论源 NAT 。

    转换后的源端口可以作为标识,比如 5.5 转出去是源端口还是 54321,5.9 转出去就是 54322 了(具体是多少取决于源端口保持策略),这样就不存在源端口复用的情况。至于转换后的源端口标识的是特定的内网主机呢,还是的特定连接呢,这取决于 NAPT 策略(完全锥形、对称型等)。部分特殊应用( SIP 、FTP 等)还有 ALG 辅助。

    映射关系释放、老化问题,会以 TCP FIN ALG 等作为老化时机和时间的参照和辅助(加速老化等),也有针对半连接等情况的兜底老化(不然就相当于内存泄漏了),但具体都取决于软件实现和参数配置,没有协议规范。

    ARP 查 MAC 什么的都有没关系,处理到 IP 层就够了,如果是在硬件路由器上做的,涉及到 CEF 快转、各种硬件 offload 、FIB 及 TCAM 工作原理,就不要乱猜了。
    echo1937
        5
    echo1937  
       2021-09-12 00:37:33 +08:00
    @weyou #2 2 楼的说法是正确的。

    你说的这种情况叫做 PAT ( port-address-translation )是端口地址转换。
    具体内容可以查看 https://zh.wikipedia.org/wiki/%E7%BD%91%E7%BB%9C%E5%9C%B0%E5%9D%80%E8%BD%AC%E6%8D%A2
    palemoky
        6
    palemoky  
    OP
       2021-09-12 00:57:02 +08:00
    @miyuki
    @weyou
    @sujin190
    @Tianao
    @echo1937
    理解各位说的都映射到同一 IP 的不同端口上,但我同时有另一个疑问,这种方式下,我不确定映射的 IP 是不是只有一个,如果是一个 IP,那可映射的端口号只有 65535-2 个,也就是说只能同时处理 65533 个连接,但局域网内电脑+手机可能有几十台设备,每台设备又会发很多的网络请求,65533 个够用吗?
    miyuki
        7
    miyuki  
       2021-09-12 01:04:26 +08:00 via iPhone
    @palemoky 如果足够多的设备都去请求同一个外网端口的话,确实存在这个问题
    Tianao
        8
    Tianao  
       2021-09-12 01:08:53 +08:00 via iPhone
    @palemoky #6 可以是一个,也可以是多个(一个池)。即使只有一个外网 IP,给几百台终端也是够用的。此外,你可以选择更激进的老化策略,也可以使用完全锥形节省源端口。
    FieldFarmer
        9
    FieldFarmer  
       2021-09-12 02:01:15 +08:00 via Android
    @palemoky 对于拥有一个 ipv4 地址的客户机来说,的确是最大不能超过 65535 同时去连某一个服务器的端口,只能通过增加 ip 的方式来解决这类问题,不过日常生活中很少会遇到在一个 ipv4 的公网 ip 下,需要这么多的长连接去访问同一个服务器的端口,大多数时间都是短连接,用完马上释放。
    你这个问题类比于 ipv4 不够用了怎么办。
    echo1937
        10
    echo1937  
       2021-09-12 02:08:33 +08:00 via iPhone
    @palemoky 楼上几位已经做了进一步解释,比如增加 ip 成为 ip 池,调整老化时间等等。

    实际日常过程中普通设备能保持的 nat 会话数很有限,一般三四千个就到头了,反倒这个问题是先遇到的。
    FieldFarmer
        11
    FieldFarmer  
       2021-09-12 02:09:59 +08:00 via Android
    @Tianao 同一 ip 区域下的 5 万多台终端在同一段时间使用了 tcp 连接同一服务器的同一端口,才会出现不够用的情况。
    这种概率会有多大?即便真的出现了,也不过是出现拥塞现象,待其他的设备释放连接,网络即可恢复。
    相反服务端出现这种情况次数更多,比如某博炸了,某宝卡了,这种没办法大多数情况下只能增加服务器数量。
    FieldFarmer
        12
    FieldFarmer  
       2021-09-12 02:13:41 +08:00 via Android
    @echo1937 从来都只有服务器考虑并发情况连接太多处理不过来,没见过客户端担心客户端太多导致自己排不上队的。。。。
    palemoky
        13
    palemoky  
    OP
       2021-09-12 08:33:58 +08:00 via iPhone
    @FieldFarmer 所以说访问 43.1.1.1:443 会在 NAT 新增映射 192.168.5.5:54321 <==> 43.1.1.14:569,访问 44.2.2.2:443 会新增 192.168.5.5:49856 <==> 44.2.2.2:1443 ?如果这样,确实局域网内同时访问同一 IP 的同一端口是极端情况。
    我尝试直接看华硕路由器和 FriendlyWRT 的 NAT 表,但查了半天资料都没找到怎么看
    FieldFarmer
        14
    FieldFarmer  
       2021-09-12 11:20:07 +08:00
    @palemoky 普通的路由上面,应该是没有查看的功能的,一些软路由上面应该可以,关键字:linux 查看 nat 映射表
    zemul
        15
    zemul  
       2021-09-13 13:28:44 +08:00
    ngrok
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3961 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 10:21 · PVG 18:21 · LAX 02:21 · JFK 05:21
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.