V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
huangya
V2EX  ›  宽带症候群

一个电视机顶盒引发的 tcp 路径 mtu 问题

  •  
  •   huangya · 2022-05-02 13:50:57 +08:00 · 3894 次点击
    这是一个创建于 927 天前的主题,其中的信息可能已经有所发展或是发生改变。

    换了一个路由器,用的是自己编译的 OpenWRT 系统,发现一个很奇怪的问题, 电视直播能看,但是其他节目点击需要很久才能进入。比如一些电影,或者电视剧。原来的路由器没有问题。所以我就抓了一下包。

    机顶盒(192.168.5.240) --LAN(192.168.5.50) OpenWRT 路由器--PPPoE-- Internet

    Notes:

    1.打码的 IP 是服务器 IP.

    2.路由器的 LAN IP 是 192 .168.5.50,不是 192.168.5.1

    3.包是在 LAN 这边抓的,所以看不到我的 WAN IP.

    因为是 PPPoE, 所以最佳的 MSS 是 1500-40(IP 头部+tcp 头部)-8 ( PPPoE 头部)=1452. 所以机顶盒多次用服务器通告的 MSS 1460 为依据发包,这个我觉得不对。应该是当收到路由器发给 它的第一个 ICMP destination unreachable(Frangmentation Needed)包就应该缩小自己的包的大小,而 不是一直用 1514 的大小发。我这样理解对吗?如果对的话,就没办法解释以前的路由器为什么可以了。这个可能要仔细抓一下老路由器的包了。

    第 1 条附言  ·  2022-05-02 18:51:00 +08:00
    @LGA1150
    @fvladlpa
    @wwbfred
    确认了,是我用的一个较老的 OpenWRT 没有对入口的 tcp sync 包做 mss clamping 。加入下面的 patch 可以解决。后面有时间的话,我会调查看看为什么老的路由器没有对入口的 tcp sync 包做 mss clamping 也可以。

    bug report:
    https://github.com/openwrt/openwrt/issues/8122

    patch:
    https://git.openwrt.org/?p=project/firewall3.git;a=patch;h=e9b90dfac2225927c035f6a76277b850c282dc9a
    第 2 条附言  ·  2022-05-03 10:37:33 +08:00

    @LGA1150 @fvladlpa @wwbfred @weyou

    本着求索的精神(哈哈),我今天换回老路由器了,发现机顶盒收到路由器发给它的 ICMP destination unreachable(Frangmentation Needed)包后减少了8个size ,重发了包。见下图的816和817号包。tcp payload size 分别为1452 和8。也就是对813号包的重发。这就很奇怪了,不知道为什么新路由器情况下机顶盒没有缩小包发。各位有兴趣的话,欢迎讨论。

    17 条回复    2022-05-22 23:52:55 +08:00
    LGA1150
        1
    LGA1150  
       2022-05-02 13:58:30 +08:00 via Android
    OpenWRT 有没有开 MSS clamping ?这个应该是默认开的
    fvladlpa
        2
    fvladlpa  
       2022-05-02 14:16:32 +08:00
    iptables -I FORWARD 1 -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
    fvladlpa
        3
    fvladlpa  
       2022-05-02 14:16:59 +08:00
    加上这个是试试
    cloudsigma
        4
    cloudsigma  
       2022-05-02 14:33:10 +08:00
    不是 nat 类型,锥形端口?
    cloudsigma
        5
    cloudsigma  
       2022-05-02 14:33:58 +08:00
    iptv 走的是组播吧? udpproxy ?
    wwbfred
        6
    wwbfred  
       2022-05-02 16:13:00 +08:00
    TCP 的包过大还真少见,我觉得更像是机顶盒网卡的 MTU 没设置对。这个问题在其他设备上能复现么?
    另外根据我的记忆你的理解是不正确的。路由中间件认为包过大解决方案是自己分包,而不是通知对端发小包。对端的发包大小就是由网卡的 MTU 决定。
    huangya
        7
    huangya  
    OP
       2022-05-02 16:21:14 +08:00
    @LGA1150
    @fvladlpa
    关于 MSS champing, 我在发帖之前就查过, 发现路由器只对从 WAN(eth0 和基于 eth0 的 pppoe 接口)出去的包做了 champing, 但没对进来的包没有做。我在想如果对进来的包也做了话,就应该能解决问题。老人家要看电视,所以现在又换回老路由器了。现在还没有实验环境。晚上试试看。fvladlpa 提供的命令就没有限制接口。但有个问题是新老路由器都没有做,不知道老路由器为啥可以流畅观看。可能还有某个点我弄错了或者疏忽了,不过现在最需要确定的是先看下对从 wan 进来的包也做一下 MSS champing 看是否能解决。

    老路由器:
    mangle 表里面做的, 其他表没有 grep 到
    root@OpenWrt:~# iptables -t mangle -L -nv
    Chain PREROUTING (policy ACCEPT 2578K packets, 2530M bytes)
    pkts bytes target prot opt in out source destination
    2578K 2530M fwmark all -- * * 0.0.0.0/0 0.0.0.0/0

    Chain INPUT (policy ACCEPT 85635 packets, 7987K bytes)
    pkts bytes target prot opt in out source destination

    Chain FORWARD (policy ACCEPT 2489K packets, 2522M bytes)
    pkts bytes target prot opt in out source destination
    2489K 2522M mssfix all -- * * 0.0.0.0/0 0.0.0.0/0

    Chain OUTPUT (policy ACCEPT 132K packets, 236M bytes)
    pkts bytes target prot opt in out source destination

    Chain POSTROUTING (policy ACCEPT 2622K packets, 2758M bytes)
    pkts bytes target prot opt in out source destination

    Chain fwmark (1 references)
    pkts bytes target prot opt in out source destination

    Chain mssfix (1 references)
    pkts bytes target prot opt in out source destination
    10301 615K TCPMSS tcp -- * pppoe-wan 0.0.0.0/0 0.0.0.0/0 tcp flags:0x06/0x02 /* wan (mtu_fix) */ TCPMSS clamp to PMTU
    0 0 TCPMSS tcp -- * eth0 0.0.0.0/0 0.0.0.0/0 tcp flags:0x06/0x02 /* wan (mtu_fix) */ TCPMSS clamp to PMTU
    root@OpenWrt:~# iptables -t filter -L -nv |grep MSS
    root@OpenWrt:~# iptables -t nat -L -nv |grep MSS
    huangya
        8
    huangya  
    OP
       2022-05-02 16:26:15 +08:00
    @cloudsigma 上海移动的机顶盒不是组播,我抓到的包是单播。这个机顶盒插到路由器后面就可以用。也不需要设置什么 vlan ,相当于一个普通上网设备。从这个角度看,我感觉这不是严格意义上的 iptv 。
    huangya
        9
    huangya  
    OP
       2022-05-02 16:37:23 +08:00
    @wwbfred
    1. 机顶盒没有提供界面设置 MTU,除非你想办法 hack 进它的 shell 。
    2. 其他设备目前还没有测试.
    3. >根据我的记忆你的理解是不正确的。路由中间件认为包过大解决方案是自己分包,而不是通知对端发小包。对端的发包大小就是由网卡的 MTU 决定。

    参考 tcp/ip 详解, 我是这样理解的。
    --------------------------------------------------------------------------------------------------------------------
    T C P 的路径 M T U 发现按如下方式进行:在连接建立时,T C P 使用输出接口或对端声明的
    M S S 中的最小 M T U 作为起始的报文段大小。路径 M T U 发现不允许 T C P 超过对端声明的 M S S 。
    如果对端没有指定一个 M S S ,则默认为 5 3 6 。一个实现也可以按 2 1 . 9 节中讲的那样为每个路由
    单独保存路径 MTU 信息。
    一旦选定了起始的报文段大小,在该连接上的所有被 T C P 发送的 I P 数据报都将被设置 D F
    比特。如果某个中间路由器需要对一个设置了 D F 标志的数据报进行分片,它就丢弃这个数据
    报,并产生一个我们在 11.6 节介绍的 ICMP 的“不能分片”差错。
    如果收到这个 I C M P 差错,T C P 就减少段大小并进行重传。如果路由器产生的是一个较新
    的该类 I C M P 差错,则报文段大小被设置为下一跳的 M T U 减去 I P 和 T C P 的首部长度。如果是一
    个较旧的该类 I C M P 差错,则必须尝试下一个可能的最小 M T U (见图 2 - 5 )。当由这个 I C M P 差
    错引起的重传发生时,拥塞窗口不需要变化,但要启动慢启动。
    由于路由可以动态变化,因此在最后一次减少路径 M T U 的一段时间以后,可以尝试使用
    一个较大的值(直到等于对端声明的 M S S 或输出接口 M T U 的最小值)。RFC 11 9 1 推荐这个时
    间间隔为 10 分钟(我们在 11.8 节看到 Solaris 2.2 使用一个 30 分钟的时间间隔)。
    在对非本地目的地,默认的 M S S 通常为 5 3 6 字节,路径 M T U 发现可以避免在通过 M T U 小
    于 5 7 6 (这非常罕见)的中间链路时进行分片。对于本地目的主机,也可以避免在中间链路
    (如以太网)的 M T U 小于端点网络(如令牌环网)的情况下进行分片。但为了能使路径 M T U
    更加有用和充分利用 M T U 大于 5 7 6 的广域网,一个实现必须停止使用为非本地目的制定的 5 3 6
    的 MTU 默认值。MSS 的一个较好的选择是输出接口的 MTU (当然要减去 IP 和 TCP 的首部大小)
    (在附录 E 中,我们将看到大多数的实现都允许系统管理员改变这个默认的 MSS 值)。
    ----------------------------------------------------------------------------------------------------------------------
    wwbfred
        10
    wwbfred  
       2022-05-02 17:01:22 +08:00
    @huangya
    "在该连接上的所有被 TCP 发送的 IP 数据报都将被设置 DF",OK ,是我记错了。
    最好做一下交叉测试,确定问题是谁的。比如在旧路由器上抓包,看它为什么能正常访问。再到其他设备上抓包,看看发包情况和机顶盒有什么不同。
    wwbfred
        11
    wwbfred  
       2022-05-02 17:04:30 +08:00
    @huangya 而且由于执行这些发包操作的实际上是内核,你贴中的猜测意味着内核出了问题,我觉得这个可能性不大。正常情况下如果更换了一个网络设备出现了问题,那么这个网络设备和原来一定有什么不一样的地方。找到这个不一样的地方就行了。
    cloudsigma
        12
    cloudsigma  
       2022-05-02 17:04:58 +08:00
    @huangya 对,是单播。在拨号上网里,vlan 类型 选择完全锥形 ( hw 光猫拨号)。op 拨号 我不知道怎么设置。我改成完全锥形后,iptv 都是秒开。选择端口受限,iptv 要等 3s 左右才能播放。如果有人知道 op 拨号的情况下,解决 iptv 打开慢的问题,请 @我,谢谢
    huangya
        13
    huangya  
    OP
       2022-05-02 18:03:59 +08:00
    @LGA1150
    @fvladlpa
    @wwbfred
    目前看来是我用的一个较老的 OpenWRT, 没有对入口的 tcp sync 包做 mss clamping 。晚上试试看,如果是,有时间的话,我会调查看看为什么老的路由器没有对入口的 tcp sync 包做 mss clamping 也可以。

    bug report:
    https://github.com/openwrt/openwrt/issues/8122

    patch:
    https://git.openwrt.org/?p=project/firewall3.git;a=patch;h=e9b90dfac2225927c035f6a76277b850c282dc9a
    datocp
        14
    datocp  
       2022-05-02 20:10:11 +08:00 via Android
    # iptables -t mangle -S
    -A PREROUTING -i eth0.2 -j DSCP --set-dscp 0x00
    -A FORWARD -o eth0.2 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1400:1536 -j TCPMSS --clamp-mss-to-pmtu

    太深奥了,当年看了人家的讨论一直就这么设定,好像没遇到问题。mtu 是 1454 。
    weyou
        15
    weyou  
       2022-05-02 21:48:06 +08:00 via Android
    19 版本之前的 openwrt 确实没对 wan 到 lan 的 mss 做 clamping 。但你的机顶盒如果支持 MTU discovery 即使 openwrt 没有 clamping 进来的 mss 也是不会有这个问题的。所以我怀疑你的机顶盒系统的 net.ipv4.ip_no_pmtu_disc 被置成了 1 ,导致 MTU discovery 没有工作。这个功能对于绝大多数 Linux 系统都默认是打开的。
    melsp
        16
    melsp  
       2022-05-03 09:15:50 +08:00 via Android
    mtu 的问题,有一说一,挺不常见的
    MasterMonkey
        17
    MasterMonkey  
       2022-05-22 23:52:55 +08:00 via iPhone
    mtu mss 头疼君路过
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1010 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 21:37 · PVG 05:37 · LAX 13:37 · JFK 16:37
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.