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

谷歌 FCM 还是建议不要走直连

  •  
  •   pagxir · 2023-08-27 21:44:40 +08:00 · 2794 次点击
    这是一个创建于 413 天前的主题,其中的信息可能已经有所发展或是发生改变。
    周末看了手机*#*#426#*#*的 FCM 诊断信息,心跳一直保持在 230 秒。手机是一台备用老手机,很多年了,,一般都是冲完电放一边,电池续航很差了。

    心跳一直在 230 秒感觉很费电,很影响续航。一开始以为是 wifi 网络问题,以为是 NAT 时间过短,就试着在路由器上转发一下增加一下 tcp 的 keepalive 。

    于是在路由器上执行:
    iptables -t nat -A PREROUTING -p tcp --dport 5228 -i wlan0 --to DNAT 192.168.1.1:5222
    socat TCP-LISTEN:5222,fork,reuseaddr TCP:64.233.189.188,keepcnt=3,keepidle=300,keepintvl=60
    然而半天测试下来,并没有啥用。

    从抓包看,最后的断开地方,看到手机有发送 client heart beat, 但是收不到应用层的 ACK (但是看到 TCP 的 ACK 是有的,偶尔还看到 client heart beat 后还有接收到 server heart beat )。

    初步觉得国内虽然 mtalk.google.com 没有直接阻断,但是还是有干扰,要么是靠近国内的 FCM 服务器不太稳定。

    最后,尝试在路由器上建立 ipsec 隧道,然后让连接美国的 FCM 服务器 mtalk.google.com/74.125.137.188, 然后 ipsec 是走 udp 封装,所以就一直 ping 避免 UDP 的 NAT 失效。 目前测试下来,FCM 连接 7 个小时没有断开,并且心跳已经能够从 230 升到了 770,并且感觉手机电量也不再崩的那么快了。

    所以,我觉得路由器上通过 UDP(udp2raw)转发 TCP/5228 流量应该是个不错的方案,比起直连好很多。

    至于,移动数据网络上,我测试把 mtalk.google.com 域名解释道国内的机器上,然后在国内机器通过 UDP 把 TCP/5228 转发出去,测试下来心跳时间可以稳定到 1100 秒。

    结论:不要在国内放任 FCM 直连,否则会影响续航以及推送的及时性。
    13 条回复    2024-10-13 18:08:35 +08:00
    PowerDi
        1
    PowerDi  
       2023-08-28 08:40:46 +08:00
    直接开代理就行了吗
    elechi
        2
    elechi  
       2023-08-28 09:05:50 +08:00
    用 4G 咋办?
    pagxir
        3
    pagxir  
    OP
       2023-08-28 09:16:21 +08:00 via Android
    @elechi 我现在办法是,挂代理( ss/ray 等),然后在代理中 hook DNS ,将 mtalk.google.com 解析到国内的 VPS/挂机宝,然后在那个挂机宝/VPS 上作中转( UDP/udp2raw )处理。也就是 mtalk.google.com 既不走代理也不走直连,而是单独中转。
    pagxir
        4
    pagxir  
    OP
       2023-08-28 09:20:11 +08:00 via Android
    @PowerDi 可能 TCP 承载的代理不会很稳定,可以在路由器上用 gost 走 quic/kcp 类的承载转发一下。如果确认 TCP 承载是稳定的直接走代理也可以。
    ParanoidAndroid
        5
    ParanoidAndroid  
       136 天前
    @pagxir 你好,请教一下这里为什么是做 UDP 中转呢?使用 Haproxy 来转发 TCP:5228 的流量可以吗?
    pagxir
        6
    pagxir  
    OP
       136 天前 via Android
    这个问题的原因是一是某些 ISP 的 NAT 时间过短,二是 gcm 服务器位于海外收众所周知的干扰。要解决这两问题即可以,NAT 问题可以用不需要 nat 的 ipv6 来解决(不过国内大部分的 ISP 提供 DNS 没有提供 ipv6 接入/不是 ipv6 优先,所以不会解释 mtalk.google.com 到 AAAA 记录,所以需要改用 8.8.8.8 的或者手动设置 mtalk.google.com 的 AAAA 记录), 而这里建议用 UDP 原因是没有 TCP RST 的干扰,并且可以自动重新而 tunnel 不断。自己可以根据自己情况测试,用 haproxy 进行 v4 转 v6 应该也是可行的。我后来试过,路由器上用 socat 并且将 keepalive 设置成 120 秒,实际上也是可以的,也就是我的宽带的 nat 时间过短(毕竟是移动的宽带)
    pagxir
        7
    pagxir  
    OP
       136 天前 via Android
    @ParanoidAndroid #5 国内有 ipv6 的话可以将 mtalk.google.com 绑定到 2404:6800:4008:c06::bc
    ParanoidAndroid
        8
    ParanoidAndroid  
       135 天前
    @pagxir 也就是说远端的 mtalk.google.com:5228 可以通过 quic 与中转服务器交互数据,之后中转服务器再通过 TCP 返回给手机客户端吗?新手刚接触这里,理解可能不到位,请见谅😂
    laod911
        9
    laod911  
       9 天前
    @pagxir 大佬,尝试了绑定 ipv6 地址 ,WiFi 下也不行,我遇到了和你类似的情况,可以详细说说 udp 转发 tcp5228 吗
    laod911
        10
    laod911  
       9 天前
    @pagxir 断开的原因我估计是因为在 nat 下没法保持 tcp 长连接吧,这样做端口转发的话 手机→vps 的连接不还是 tcp 连接吗,怎么能保持长连接呢,不太懂,望大佬教教
    pagxir
        11
    pagxir  
    OP
       9 天前 via Android
    ipv6 没有 nat ,理论上不需要改动,但是毕竟经过了 GFW ,所以可能受到干扰。至于 ipv4 ,某些网络的 nat 会话保持时间比较短,比如只有 2 分钟,所以通过 tcp 转发并且在路由器上打开 keepalive 可以让 nat 会话刷新,避免失效。当然了,这时候刷新 nat 会话一部分从手机转移到路由器,耗电也只是从手机转到路由器,不过一般路由器直接插电,所以问题不大。
    @laod911
    laod911
        12
    laod911  
       1 天前
    @pagxir 没用软路由,比较关注你说的移动网络下的解决办法,感觉是一劳永逸。是手机→vps (通过 tcp 协议)的 5228 端口,vps 的通过 udp 监控转发来自 5228 端口的 tcp 流量→fcm 服务器,吗? 那这样手机→vps 还是 tcp 协议,不是仍然无法保持长连接吗?(* ̄︶ ̄)
    pagxir
        13
    pagxir  
    OP
       1 天前 via Android
    @laod911 #12 那样做没有意义,因为虽然 fcm 没有断,但是 UDP 的会话保持时间比较短,导致为了维持会话有效需要缩短发送保活包的时间这会影响功耗。所以还是直接使用 TCP ,所以应该是 TCP/ipv6, 连不上然后是 TCP/ipv4 ,最后试试 UDP/ipv6 。因为 ipv6 不需要 nat
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   4233 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 30ms · UTC 10:14 · PVG 18:14 · LAX 03:14 · JFK 06:14
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.