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

虚心请教,如何充分利用低速率网口带宽聚合代理上网

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

    我想实现以下目标任务

    1. 用 4in6 的形式,使用异地机器 B 代理机器 A 所有流量(即 A 访问 v4 服务器的时候先使用 AB 之间 ipv6 传输通道传输到 B ,再由 B 的 v4 地址发出到服务器的请求)(已实现)
    2. 以实现宽带聚合,在 A 机器上利用多网口以异地机器 B 作为中转代理机器 A 所有流量

    目前解决方案

    使用 wireguard ,分别在 A 与 B 作为 Peer 相互通信,并将 A 机器的 default_route 设置为 wg 网口,拓扑如下,其中 A 、B 均为 Openwrt

                       |       Internet(v6)    |        
    [ A: gateway ]     |                       |   [ B: Server ]
                       |                       | 
       (wg0) <-----> (ens1_100M) < - - - - > (ens1_1G) <----> (wg0)
    

    在不考虑 Internet 带宽下(假设 Internet 速率为 1G ,B 的接口速率亦为 1G ),由于 A 的接口速率只有 100m ,这种方案可以实现 100m 的数据传输。 目前方案存在的问题: Gateway 提供了有 4 个 100M 的网口(有着不一样的四个公网 iPv6 地址),按照以上方案只能利用一个网口进行对外通信,也就是仅能提供 100M 的带宽,剩下 3 个 100M 的网口无法充分发挥作用。如何在一台配置不高(成本、物理空间有限)的设备上实现充分利用剩下 3 个 100M 的网口达到 400M 的上网冲浪速率? 感觉应该不需要考虑应用粘滞、各种应用会在两个宽带上面来回跳的问题,因为最终出到互联网全部都是以 B 的 ip 作为出口 ip ,所以不会出现说一个 app 发出通信对端服务器收到两个 incoming ip 的问题。

    尝试过的解决方案

    在 A 机器上部署多个 wg 网口,每个网口的 peer 都指向 B 机器,拓扑如下图 目前存在的问题是wg 似乎会从默认网口进行出口,这就导致了所有 wg client 全都只会从一个网口出站,搜寻一下互联网发现这篇文章 How do I configure a Wireguard Interface to connect to a remote peer through a specific network interface? ,采用的是 IP 路由表分流的方案,这篇文章可以解决 B 机器有多 IP 的分流。但是在本情景下,由于 B 机器只有一个 IP ,无法采用这种方案

                       |       Internet        |        
    [ A: gateway ]     |                       |   [ B: Server ]
                       |                       | 
       (wg0) <-----> (ens1_100M) < - - - - > (ens1_1G) <----> (wg0)
                       |               / /     | 
                       |             /  /      |        
       (wg1) <-----> (ens2_100M) < -   /       |
         ·             |              /        | 
         · (省略若干 wg)|             |         | 
         ·             |             /         | 
       (wg3) <-----> (ens3_100M) < -           |
    
    

    想到的可能的解决方案

    虚拟机方案,将 4 个网口分别虚拟 4 个 openwrt 分别架设 wg client ,再虚拟一个路由系统做负载均衡,缺点是性能开销大而且可能有性能损失

    来问问大佬们有没有什么低成本方法可以解决这个问题 谢谢大家喵

    16 条回复    2024-03-29 08:34:23 +08:00
    vcn8yjOogEL
        1
    vcn8yjOogEL  
       247 天前
    可以给 WG 出站包打标签, 然后再按标签走不同的路由表
    pagxir
        2
    pagxir  
       247 天前 via Android
    要么走二层的链路集合比如 bond ,要么用 mptcp
    maybeonly
        3
    maybeonly  
       247 天前
    用单个 wg 的话
    给自己发 4 个配置文件,然后起 4 个 wg 隧道
    假如四个 wg 客户端 ip 分别是 198.51.100.1-198.51.100.4 ,接口分别是 wg1-wg4
    那么可以加路由
    ip r a default dev wg1 table 1001
    ...
    ip r a default dev wg4 table 1004
    然后加规则
    ip ru a f 198.51.100.1 table 1001
    ...
    ip ru a f 198.51.100.4 table 1004
    然后加出口 nat 规则(可能需要适当调整一下,比如结合默认路由的 srcip )
    iptables -t nat -A POSTROUTING -m statistic --mode random --probability 0.25 -j SNAT --to 198.51.100.1
    iptables -t nat -A POSTROUTING -m statistic --mode random --probability 0.33 -j SNAT --to 198.51.100.2
    iptables -t nat -A POSTROUTING -m statistic --mode random --probability 0.5 -j SNAT --to 198.51.100.3
    iptables -t nat -A POSTROUTING -j SNAT --to 198.51.100.4
    然后就可以把不同的连接丢到不同的 wg 上了……
    必要时调整 rp_fillter 。

    如果用多个 wg ,或者其他 vpn ,可以考虑类似 ecmp 的实现,或者分别随机打标签……
    单个 wg 不能这么做是因为客户端地址是同一个的话,wg 这种三层 vpn 没办法路由到不同的客户端去。
    gregy
        4
    gregy  
       246 天前   ❤️ 1
    OP 这个需求和户外直播使用的多卡聚合的功能类似,使用一台聚合服务来实现多条公网链路的聚合打到带宽叠加,故障冗余的效果。
    https://www.openmptcprouter.com/

    B 端的服务器可以直接运作聚合服务,不需要额外的聚合服务器了。不过这个并不能达到 1+1=2 的效果,最多也就是 1+1=1.7
    MFWT
        5
    MFWT  
       246 天前
    为 OP 的提问方式先点个赞,清晰明了

    我贡献一下我自己之前的一个研究吧,就是我手头的机器还是比较富裕的时候
    当时我手头有两台香港良心云的轻量,内网互通,单机上行(出站) 30Mbps

    我当时做的一个实验是:

    1. A 机安装 SS ,B 机不装
    2. B 机做一个端口转发,**通过内网地址**,转发到 A 机的 SS 服务
    3. 我这边用 v2 做一个客户端,用他的负载均衡(其实就是轮询各个服务器,顺序发包)建立连接,分别填上两台服务器的地址
    4. 去 speedtest 测速,多线程模式,测出来 60Mbps ( 30+30 )

    要点是:
    1. SS 的特性是:无连接。换句话说只要数据包到了(当然要满足校验规则什么的)就能直接建立连接,可以看作是 state-less 的代理服务
    2. 多线程测速就保证了『产生多个 HTTP 连接』,这样客户端就可以轮流给两个服务器上强度,实现均衡的效果
    3. 最后流量还是走内网聚合(保证延迟低,以及稳定)到一台机器上,走一个机器的出口,这就是 OP 提到的『 IP 不乱跳』
    4. 类似 SS 这样的四层代理,是把数据『抠』出来再处理的,在实操中比直接搞三层流量要方便些

    以上应该可以作为参考
    Kinnice
        6
    Kinnice  
       246 天前   ❤️ 1
    启动个 clash-meta (可配置出口网口),配置四个 DIRECT 分别走四个 wg 网口,然后这个策略组使用 loadblance 就可以了

    为什么不直接在 clash 里面配置 wg? => 效率低,慢
    yyy134341
        7
    yyy134341  
    OP
       246 天前
    @Kinnice #6 确实可以利用 clash 去做 load-balance ,但是问题出在 wg 出口。 理想情况下 4 个 WG client 应该沿着 4 个 WAN 口出站,即 wg1 -> wan1 -> serverB, wg2 -> wan2 -> serverB, 以此类推,但是我在问题描述的时候提过,「 wg 似乎会从默认网口进行出口」,也就是说所有 wg client (wg1,wg2,wg3,wg4) 全部都会走默认网口出站(比如 wan1 ),所以即使 load-balance 到四个 wg 网口去,由于四个 wg 网口最终都只使用 wan1 出站,所以最终只能够实现 100m 的数据传输
    yyy134341
        8
    yyy134341  
    OP
       246 天前
    我先梳理一下上面各层大佬提出的 solution ,有好多技术我还是第一次接触到、、如果有什么没弄懂的还烦请各位帮忙解答、、感谢各位大佬 :)
    yyy134341
        9
    yyy134341  
    OP
       246 天前
    @MFWT #5 我和你的 case 似乎不太一样,应该是刚好反过来,你的是在本地端拥有 1 个 IP 地址,远端有多个 IP 地址;我的是在本地端有多个 IP 地址,需要连接同一个远端服务器 IP 并将请求平均分配到本地的数个 IP 进行出口,其实有点像多宽带聚合的场景。只不过在我的场景是一个环境更复杂的多宽带分流( iPv6 + 4in6 )

    你的实验也挺有趣的,但是我对这个实验发现有个问题,我理解的实验设计如下面拓扑所示,
    ```

    PC ----> serverA (proxy server) --> speedtest.net
    \ ^
    | | port forward
    \ |
    --> serverB --

    ```
    最终发送到互联网请求连接的是 serverA ,那这样子的话最终访问互联网的速度应该仍然受限于 serverA <----> speedtest.net 的 30Mbps 限制才对啊,为什么可以跑得到 60Mbps 呢
    yyy134341
        10
    yyy134341  
    OP
       246 天前
    @MFWT #5
    原来回复不支持 Markdown 的么、、
    那我换成文字版
    PC -------> ServerA (proxy server) -----链路 a-----> speedtest.net
    PC -------> ServerB --- Port forward ---> ServerA -----链路 a---> speediest.net
    也就是说最终 serverA 都是使用同一个方式进行对 speedtest 进行访问(也就是 proxy server 发出请求),为什么这种方式可以实现绕过 30Mbps 的作用呢?
    Kinnice
        11
    Kinnice  
       246 天前   ❤️ 1
    @yyy134341 #7
    1. B 机器看起来应该是可以搞到多个 ipv6 地址的(一般国内 ipv6 给的还是富足的),然后 A 机器就可以设置路由让指定的目的 ip 走指定网口(very Easy), 接着就可以了
    2. A 机器如果性能还不错,可以试试直接 clash 上面配置 wg 和出口网口,全在 clash 里面做,但是缺点可能是性能不太高。(或许可以换一个协议比如 ss/vless 之类的)
    MFWT
        12
    MFWT  
       245 天前
    @yyy134341

    首先需要明白一个点(其实我描述中也漏了一点):我提到的测试中的速度,实际上是『下行速度』,其具体实现是:浏览器请求一个文件,并统计接收该文件的速度。换句话说,实际上测试下行速度的时候,流量的流向是:

    Speedtest 服务器 =( 1 )=> 良心云服务器 =( 2 )=> 我的客户机

    良心云的限速 30Mbps ,其实是限制出站方向 30Mbps ,对于入站方向则限制不大(至少大于等于 100Mbps ),也就是说,1 号段相当于是没有限速,2 号段本来应该是 30Mbps 的,但是因为两台机器分开了多个请求的流量,所以可以叠加加速
    MFWT
        13
    MFWT  
       245 天前
    @yyy134341

    其实你的 case 和我的本质上还是一样的,主要就是谁主动连接谁的问题

    这其实就是流量聚合的一个难点:以目前网络中比较常用的 TCP 协议为例,如果不是对端配合,他『并不能』在实现多路径传输(不然就不会有 MPTCP 之类的玩意出现了),在这个情况下,链路聚合能体现加速的一般就以下几个场景:

    1. 多个 TCP 同时使用(比如说,多机使用,多线程下载)
    2. 多用户从不同链路进来

    所以这也就是我提到,为什么是 SS:像是 SS 这种代理协议和 VPN 不同,他提前终结了 TCP ,只是拿着数据跑来跑去,这就比 VPN 那种单纯的三层路由要好得多。我可能描述得不太准确,但大概就是这个意思
    MFWT
        14
    MFWT  
       245 天前
    @yyy134341

    就目前而言,据我所知,WireGuard 的官方版本并没有实现指定出口的功能,而且对于对等点的认证也没有想象中的那么快捷(至少如果某个 Peer 有新的对端地址(此处地址指代『地址:端口 二元组』,下同)连入,那么原先的连接似乎会被放弃,也就是说两个接口会不停地等到超时之后重新握手,也就是说可能是同时也就一条链路被用上)

    我有个稍微显得 dirty 的解决方法,同样是类似于『把数据抠出来』的思路,这就需要双方配合:

    1. 你的 B 机上面,安装 gost (或者其他 UDP 端口转发软件,不能是 iptables 的 REDIRECT ,必须是不保留源地址的转发工具),监听一个端口,并把数据转发到 WG 的监听端口
    2. 你的 A 机上面,用 gost 监听某个端口,配合虚拟节点功能(或者选择其他有负载均衡功能的 UDP 端口转发软件),注意指定不同出口,但是填一样的地址(就是刚刚 B 机 gost 监听那个端口)实现负载均衡功能
    3. 你的 A 机的 WG ,指定对端地址为你本机的 GOST

    画图就是:
    A 机 WG -------> A 机 GOST -----(多网卡出线)-----> B 机 GOST ----> B 机 WG

    核心思想还是:保持两端 WG 所看到的对端地址不变(都是 127.0.0.1 + 固定端口),然后中间偷梁换柱
    yyy134341
        15
    yyy134341  
    OP
       244 天前
    @Kinnice #11
    1. 这个是个好思路,确实可以试试实现看看
    2. Openwrt 里面有支持多网卡分流的 Clash 插件吗,在用的 OpenClash 好像不支持通过 interface-name 绑定多网卡 [Openclash 开启后多线多拨下行速度无法叠加]( https://github.com/vernesong/OpenClash/issues/301)
    Kinnice
        16
    Kinnice  
       244 天前 via Android
    @yyy134341 使用 meta 内核,使用策略组内的 interface-name
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   6074 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 27ms · UTC 06:18 · PVG 14:18 · LAX 22:18 · JFK 01:18
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.