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

242 天前
 yyy134341

我想实现以下目标任务

  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 ,再虚拟一个路由系统做负载均衡,缺点是性能开销大而且可能有性能损失

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

2172 次点击
所在节点    宽带症候群
16 条回复
vcn8yjOogEL
242 天前
可以给 WG 出站包打标签, 然后再按标签走不同的路由表
pagxir
242 天前
要么走二层的链路集合比如 bond ,要么用 mptcp
maybeonly
242 天前
用单个 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
242 天前
OP 这个需求和户外直播使用的多卡聚合的功能类似,使用一台聚合服务来实现多条公网链路的聚合打到带宽叠加,故障冗余的效果。
https://www.openmptcprouter.com/

B 端的服务器可以直接运作聚合服务,不需要额外的聚合服务器了。不过这个并不能达到 1+1=2 的效果,最多也就是 1+1=1.7
MFWT
241 天前
为 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
241 天前
启动个 clash-meta (可配置出口网口),配置四个 DIRECT 分别走四个 wg 网口,然后这个策略组使用 loadblance 就可以了

为什么不直接在 clash 里面配置 wg? => 效率低,慢
yyy134341
241 天前
@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
241 天前
我先梳理一下上面各层大佬提出的 solution ,有好多技术我还是第一次接触到、、如果有什么没弄懂的还烦请各位帮忙解答、、感谢各位大佬 :)
yyy134341
241 天前
@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
241 天前
@MFWT #5
原来回复不支持 Markdown 的么、、
那我换成文字版
PC -------> ServerA (proxy server) -----链路 a-----> speedtest.net
PC -------> ServerB --- Port forward ---> ServerA -----链路 a---> speediest.net
也就是说最终 serverA 都是使用同一个方式进行对 speedtest 进行访问(也就是 proxy server 发出请求),为什么这种方式可以实现绕过 30Mbps 的作用呢?
Kinnice
241 天前
@yyy134341 #7
1. B 机器看起来应该是可以搞到多个 ipv6 地址的(一般国内 ipv6 给的还是富足的),然后 A 机器就可以设置路由让指定的目的 ip 走指定网口(very Easy), 接着就可以了
2. A 机器如果性能还不错,可以试试直接 clash 上面配置 wg 和出口网口,全在 clash 里面做,但是缺点可能是性能不太高。(或许可以换一个协议比如 ss/vless 之类的)
MFWT
241 天前
@yyy134341

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

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

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

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

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

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

所以这也就是我提到,为什么是 SS:像是 SS 这种代理协议和 VPN 不同,他提前终结了 TCP ,只是拿着数据跑来跑去,这就比 VPN 那种单纯的三层路由要好得多。我可能描述得不太准确,但大概就是这个意思
MFWT
241 天前
@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
240 天前
@Kinnice #11
1. 这个是个好思路,确实可以试试实现看看
2. Openwrt 里面有支持多网卡分流的 Clash 插件吗,在用的 OpenClash 好像不支持通过 interface-name 绑定多网卡 [Openclash 开启后多线多拨下行速度无法叠加]( https://github.com/vernesong/OpenClash/issues/301)
Kinnice
240 天前
@yyy134341 使用 meta 内核,使用策略组内的 interface-name

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1027091

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX