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

开个脑洞想了一个结合软硬路由优点的方案

  •  
  •   s82kd92l · 350 天前 · 2161 次点击
    这是一个创建于 350 天前的主题,其中的信息可能已经有所发展或是发生改变。

    TLDR 一句话: 硬路由利用 nfqueue 把关键包的处理逻辑外包给软路由

    硬路由在专用芯片加持下,网络处理上的稳定性与性能上限是远高于软路由的,但我们很多人还是选择软路由当主力路由,不过是因为 x86 系统特别灵活,玩法很多。但仔细分析网络里的各个流程就可以发现,无论是软硬路由,灵活玩法大多来自于对各连接建立的包的处理,即 linux 里面的 iptables/nftables nat 表里的那些包。软硬路由都通过 cpu 处理这些包,其余的绝大部分包硬路由走专用芯片,软路由用 cpu 硬扛。

    现在路由器大多基于 linux, linux 里面有各叫 nfqueue 的东西,可以把 iptables/nftables 里面感兴趣的包发到用户态进程里面,然后用户态可以进行一些操作,比如通过、丢包、拒绝、打 mark 、SNAT/DNAT. 但硬路由上由于 arm/mips 架构难搞、cpu 内存紧张等原因,这个机制像螺蛳壳里做道场,很鸡肋。

    所以我在想是不是能在路由器上写个最轻量化的 nfqueue-agent, 把所有收到的包通过 tcp 转发到软路由的用户态 nfqueue-controller ,然后在 x86 上就可以 java/golang/python 爱怎么玩都行了?

    应用场景:

    1. ip 段分流/wireguard/zerotier

      静态 ip 段路由表管理挺繁,要是 BGP 级别的话,ip 段文件不小,很多老古董 nand 甚至存不下。复杂一点的动态路由要搭建 bird/frr 服务,很麻烦。而我的方案里,nfqueue-controller 可以根据包的内容直接给包打上 mark, 再通过策略路由就很简单实现了分流。x86 可以搭建 wireguard/zerotier ,灵活度有保证。

    2. 无污染 dns 服务/fakedns/根据域名分流

      传统域名分流很多是搞 ipset/nftables set ,要是路由器内核不支持就很难搞。nfqueue-controller 可以强行把所有 udp53 的包通过 mark 路由到自己 x86 节点,自己走 doh/dot. 也可以把 fakedns/vpn 的 IP 段通过 mark 路由到自己节点.根据请求域名的判断可以在 x86 端用户态维护一个 ipset,在下一次 tcp 请求中自动分流。

    3. fullcone nat

      可以把硬路由器自己的 nftables/iptables masquerade 都干掉,在 nfqueue 里进行 snat/dnat.不过这个我不太确定会和 linux conntrack 系统有什么化学反应

    4. multiwan 负载均衡

      用户态控制逻辑,想怎么分配就怎么分配

    5. 软路由节点 down 后 fallback

      一旦硬路由上的 nfqueue agent 发现软路由超时未回复,立刻断开 nfqueue 绑定, 则所有网络设置恢复到单硬路由状态,不会引起断网。

    6. 大量新连接、路由表很长很复杂

      这时候每个新连接的包都要经过网络给 controller 处理,可能会造成一些压力,不过可以在硬路由里利用 nftables 里面自定义 set/map 的功能可以缓存处理结果 mark ,例如连接五元组 30 分钟有效期内复用上次的 mark. 如果路由器只有 iptables 且没有 ipset, 也可以在路由器的 nfqueue-agent 里缓存结果。 不需要所有的都经过控制服务器,

    这样只要支持 nfqueue 的硬路由器有可能这样来控制,可能很多官方固件也能玩,有点 sdn 的意思。

    实现需要的具体工作:

    1. agent: 收到什么就转发什么,类似 socat , 只不过是 netlink socket -> tcp socket.

    2. controller: 用户态的 firewall 处理逻辑,最好是能复用 nftables/iptables 的语法与代码,这样学习、迁移成本更低,但把内核的代码在用户态用上应该是非常难的。或者把这个封装成 python/golang/java 库,用户可以写简单脚本控制, 也可以让社区继续发挥。

    大家看看价值与可行性如何?

    9 条回复    2024-04-22 14:55:44 +08:00
    tomczhen
        1
    tomczhen  
       350 天前 via Android
    dpdk 好像都快 10 年了。
    icy37785
        2
    icy37785  
       350 天前 via iPhone
    你是在找 RouterOS 吗?
    s82kd92l
        3
    s82kd92l  
    OP
       350 天前
    @tomczhen
    @icy37785 这俩都是 x86 世界的啊,dpdk 还要专用硬件支持,得花不少银子把。我这个方案是想把硬路由价值最大化,不刷固件也好用那种。
    RecursiveG
        4
    RecursiveG  
       350 天前
    多此一举,不如想想怎么提升你软路由的稳定性。
    icy37785
        5
    icy37785  
       349 天前 via iPhone
    @s82kd92l #3 RouterOS 怎么就成 x86 的世界了。算了,你自己瞎琢磨去吧。
    sentivcn
        6
    sentivcn  
       349 天前
    三层交换机 ospf 线速分流,路由器只拨号
    huoshen
        7
    huoshen  
       349 天前
    你是否在查找: FPGA
    好吧不开玩笑的说, 这个已经有在搞的, 思科有相当多的交换机就是 ASIC+FPGA, 然后部分包剩下的交给 cpu 处理, 只是个人用户想搞一个可能有点难, 毕竟各个厂家路由设计都不太一样, 现有固定的硬件上是否可行也有待商榷
    povsister
        8
    povsister  
       194 天前
    <来自楼主的召唤链接>

    我看你描述的这个操作,其实和 dae 思路是一样的。
    可以看看这里,其实你想的大部分操作 dae 都已经实现了 https://github.com/daeuniverse/dae/blob/main/docs/zh/how-it-works.md

    不过不存在“路由器大多基于 linux”,“外包 nfqueue 这个说法“,同机器上用户态处理尚可接受,跨机器甚至要 RPC 的情况下,复杂度和可用性都会爆炸的。
    而且高性能的路由器例如 ROS 这种,其都是使用的裁剪+高度定制化的 linux 内核,定制程度达不到你说的这么高。
    s82kd92l
        9
    s82kd92l  
    OP
       194 天前
    @povsister 其实只是最初几个包需要跨机器 ipc, 也就是 iptables nat table 要处理的那些包,其他都是硬件转发。 内网的 rtt 一般 1ms 左右,比起访问公网服务器基本 20+ms 的 rtt ,这个延迟是可以忽略不计的吧。

    > 定制程度达不到你说的这么高。

    这个现状是真的,但支持硬件转发的 openwrt 最近越来越多了,尤其 mtk 的机子,还是有一定潜在应用空间的。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   1492 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 19ms · UTC 17:17 · PVG 01:17 · LAX 10:17 · JFK 13:17
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.