BakaCai
MPTCP in GRE完美叠加轻量云上行带宽和流量

access_time
brush 2031个字
whatshot 1181 ℃

Youtube已经全面普及AV1了, 然而有部分"极其先进"的OTT平台还在用H264. 30M的带宽Youtube可以看到8K30, 而H264编码的就只能看到1080P60...想要流畅播放4K30的H264需要50M的带宽, 每个月也要花费比AV1更多的流量.

云计算大厂为了防止自家VPS被用来开"国际机场", 推出了一系列上行带宽只有30M的轻量云服务.
其中阿里云是30M对等一点都不给大家薅, Ucloud 50M/30M, 腾讯云 100M/30M...
价格便宜, 稳定性超强, 就是连流畅看个高清视频的带宽都不够.

传统的PCC负载均衡, 单个线程无法切割只能通过其中一条线路送到对面. 出现一条线路满载, 另一条线路空载是日常.
而MPTCP可以均匀分配单个线程的数据, 完美解决了PCC在流媒体收看与推流无法平分流量的痛点.

只要轻量云下行比上行带宽大, 同区域虚拟机内网可互联且流量不计费, 那我们就可以用MPTCP愉快的叠加上行带宽, 将其中一台作为出口即可. 反正那些轻量云都是单向流量计费, 只算入网部分.


本案例虚拟机配置方式如下

PROCESS.png
国内部分采用RouterOS作为主路由, 同一个二层内有一台Debian 12 6.10内核已编译BBRv3, VPS作为 Xray 客户端(旁路由).
海外部分采用2台surfercloud(Ucloud)轻量云VPS, 带宽均为50/30M, 系统Debian 11.7.

Part 1 - 配置系统环境

首先进控制面板开2台Debian虚拟机, 其中一台内核用xanmod 升级到 6.10, 并开启BBRv3+fq.
推荐这个一键脚本

wget -O tcpx.sh "https://github.com/ylx2016/Linux-NetSpeed/raw/master/tcpx.sh" && chmod +x tcpx.sh && ./tcpx.sh

TCPX.png
先选32 安装核心, 重启后选11 或者 12 启动 BBRv3+FQ.

另一台直接DD成RouterOS方便起隧道:

wget --no-check-certificate https://download.mikrotik.com/routeros/6.45.8/chr-6.45.8.img.zip -O chr.img.zip && \
gunzip -c chr.img.zip > chr.img && \
mount -o loop,offset=512 chr.img /mnt && \
ADDRESS=`ip addr show eth0 | grep global | cut -d' ' -f 6 | head -n 1` && \
GATEWAY=`ip route list | grep default | cut -d' ' -f 3` && \
echo "/ip address add address=$ADDRESS interface=[/interface ethernet find where name=ether1]
/ip route add gateway=$GATEWAY
" > /mnt/rw/autorun.scr && \
umount /mnt && \
echo u > /proc/sysrq-trigger && \
dd if=chr.img bs=9216 of=/dev/vda && \
reboot

DD 完成后把RouterOS 更新到6.49最新版, 别忘了登录Mikrotik账号配置License.

Part 2 : 配置网络环境

三台虚拟机GRE隧道互连打通内网.

GRE1 : 国内RouterOS动态IP - 海外Debian VPS
GRE2.png
RouterOS侧需关闭KeepAlive功能.

海外Debian 使用这样的命令起GRE:

ip tunnel add gre1 mode gre remote 58.32.32.1 local 10.41.120.57 ttl 255
ip addr add 10.13.2.1/24 dev gre1
ip link set gre1 up
ip link set gre1 mtu 1418

Remote Address 先根据实际填写, 第二行 10.13.2.1/24 改成自己喜欢的内网IP段.
需要注意的是 MTU不会自动协商, 取国内PPPoe后的MTU 手动设定.

互ping一下 , 通了之后我们配置ssh-exec通过RouterOS 遥控Linux修改GRE隧道的 Remote Address.
先在Debian下生成密钥对:

ssh-keygen -t rsa -m PEM

GRE2-2.png
目录就用默认的, 然后自己设个喜欢的密码.
编辑 /etc/ssh/sshd_config

AuthorizedKeysFile    .ssh/id_rsa.pub
PubkeyAuthentication yes

完事后service ssh restart, 这台VPS就开启了密钥登录, 此类教程网上很多, 根据系统不同方法略有差异.

把刚才生成的 id_rsa 和 id_rsa.pub 通过自己喜欢的方式下载到本地, 用Winbox上传到RouterOS:
GRE2-3.png
System - Users 菜单里导入私钥用户名这里写RouterOS的管理员账号, 一般默认admin不用改.
GRE2-4.png

Winbox 里开个Terminal使用以下命令进行测试:

/system ssh-exec address=DebianVPS的IP user=root command="ifconfig"

Terminal里返回对端的网卡配置那说明ssh服务端配置正确, 开始配置RouterOS脚本:

:global ipaddr [/ip address get [/ip address find interface=PPPoe名称] address]
:set ipaddr [:pick $ipaddr 0 ([len $ipaddr] -3)]

/system ssh-exec address=对端IP user=root command="ip tunnel change gre1 remote $ipaddr"

这个脚本的工作流程详细为大家讲解一下:
第一步 : 找到PPPoe拨号的公网IP
第二步 : 把那个IP地址定义为$ipaddr
第三步 : 通过ssh-exec 发送修改隧道对端IP的指令
脚本根据自己的实际情况编辑一下放到 System - Script里:
GRE2-6.png

你可以把这个脚本用Scheduler几分钟执行一次, 也可以在PPPoe Profile里, 每次拨号成功后执行.
GRE2-5.png
我这里用了delay, 8秒后重新执行一次, 确保指令发到对面.
修改相同的IP地址, 系统自动判定无须修改, 网络不中断, 所以我们可以放心的重复执行.

/system script run RemoteGRE
:delay 8000ms;
/system script run RemoteGRE

先把最复杂的一条GRE隧道配好了, 接下来的2条很简单.

GRE2 : 国内RouterOS动态IP - 海外RouterOS VPS
两头RouterOS, 这是最简单的, 用DDNS做Remote Address即可:
GRE1.png
使用DDNS的方法有很多, 自行参考网络教程即可. 或者可以硬核一些, 采用与GRE相同的ssh-exec遥控方式.

两头分别给一个内网IP地址:
GRE1-1.png
互ping一下, 通了就配下一条~

GRE3 : 最后还有一条2台VPS之间内网互联的GRE隧道(可根据实际情况省略)
有群友反馈, Ucloud可以2层直接 next-hop 另一个内网IP(设为网关).
不一定每家IDC都能二层互联, 大家可以先尝试, 不通的话再打一条GRE隧道也让费不了多少系统资源.

RouterOS那一头直接写Debian VPS的内网IP, 关闭KeepAlive, 别忘了配个内网地址~
GRE3.png
Debian 那头通过命令行配置:

ip tunnel add gre3 mode gre remote 10.41.126.91 local 10.41.120.57 ttl 255
ip addr add 10.13.1.1/24 dev gre3
ip link set gre3 up

互ping一下 , 通了之后GRE隧道配置工作结束.

Part 3 : 配置静态路由

很多人都注
海外Debian那台修改loopback地址. 大家都是127.0.0.1, 当然要换一个识别度比较高的地址:

ifconfig lo 11.4.5.14 up

我们要让国内的那台RouterOS分别经由GRE1访问这个IP, 在另一张路由表中经由GRE2-GRE3访问这个IP~
先到IP-Route建路由表(以tw1 和 tw2 两张路由表为例):
ROUTE1.png
分别为2个GRE隧道配置SRC-NAT:
ROUTE1-1.png

接下来要配置国内作为MPTCP客户端的Debian虚拟机~
这里需要2个网络出口, 以eth0 和 eth0.235为例.

首先配置一个VLAN interface, 编辑 /etc/network/interfaces . 这一步根据系统不同方法会有区别, 请自行查找网络教程. 在eth0上配VLAN 235:

auto eth0.235
iface eth0.235 inet static
        address 192.168.235.112/24

RouterOS在与Debian虚拟机同一个二层下的接口创建相同的VLAN接口, 再分配一个IP地址:
ROUTE2.png
互ping一下, 通了之后配路由规则:
ROUTE2-1.png
这样从eth0访问11.4.5.14走tw1, 从eth0.235(vlan235)访问11.4.5.14走tw2.

配置海外RouterOS上到达11.4.5.14的路由:
先为GRE3配置SRC-NAT:
ROUTE3.png
IP - Route, 在Main 表里直创建路由, Gateway即GRE3对端IP:
ROUTE3-1.png

本地分别通过 eth0 与 eth0.35 MTR一下~
直达海外Debian VPS的那个出口只有一跳:
ROUTE4-1.png
绕行RouterOS的那个出口会多一跳:
ROUTE4.png

Part 4 : 配置MPTCP

服务端(海外Debian VPS)这头的规则:

ip mptcp limits set subflows 8
ip mptcp limits set add_addr_accepted 8

limits 无脑全部调到最大值8,与性能无关。MPTCPv1规定最大8个子流。1个出口一个subflow,这是固定的,并不是说这个参数越大同一个出口可以生成的子流更多。
国内这头稍微复杂那么一点点, 先要配置一条路由规则:

ip route add 11.4.5.14 metric 1 nexthop via eth0对端IP dev eth0 weight 1 nexthop via vlan235对端IP dev eth0.235 weight 33

众所周知, 有了路由才能通TCP/UDP/MPTCP...以上这是一整条命令, weight 参数随意写, 不影响MPTCP的带宽的分配比例.

分别配置2个出口的subflow, 这里的IP即本地网卡IP:

ip mptcp endpoint add id 1 subflow fullmesh eth0IP dev eth0
ip mptcp endpoint add id 2 subflow fullmesh vlan235IP dev eth0.235
ip mptcp limits set subflows 8
ip mptcp limits set add_addr_accepted 8

Part 5 : 配置Xray-Core

节约时间, 服务端直接用一键脚本:

bash <(wget -qO- -o- https://github.com/233boy/Xray/raw/main/install.sh)

编辑配置文件 /etc/xray/config.json, listen地址自己修改后的loopback地址:

  "inbounds": [
    {
      "tag": "api",
      "port": 56359,
      "listen": "11.4.5.14",
      "protocol": "dokodemo-door",
      "settings": {
        "address": "11.4.5.14"
      }
    }
  ],

再修改脚本自动创建的出网配置文件, 在/etc/xray/conf文件夹中 ~
"streamSettings": 这一段里加上mptcp相关配置 :

"sockopt": {
                "tcpMptcp": true
            },

之后service xray restart, 成功运行的话, 服务端配置工作已经全部结束.

客户端的选择就多了, 可以用Clash.meta, Sing-box,未来还可以用dae. 只要你的系统支持MPTCP这些Socks类代理服务端就可以用. 比如你用的OpenWRT配的OpenClash, 系统把mptcp模块给阉割了, 就算OpenClash支持了MPTCP那也是毫无卵用的.

或者同样用 Xray做客户端, 方法和服务端一样, "streamSettings"添加和上面一摸一样的MPTCP参数即可.
这里还是提供一个参考配置, 自行根据Xray文档调成自己最喜欢的协议:

"outbounds": [
    {
      "tag": "VLESS-REALITY-52372.json",
      "protocol": "vless",
      "settings": {
        "vnext": [
          {
            "address": "11.4.5.14",
            "port": 52372,
            "users": [
              {
                "id": "7a504caf-06f7-425b-94f0-7f6d6e114514",
                "encryption": "none",
                "flow": "xtls-rprx-vision"
              }
            ]
          }
        ]
      },
      "streamSettings": {
        "network": "tcp",
        "security": "reality",
        "realitySettings": {
          "serverName": "www.amazon.com",
          "fingerprint": "chrome",
          "publicKey": "Nl1atxBfJlCecC8Z3vr6oeTK8ZEc_ogxOwQ2I114514",
          "shortId": "",
          "spiderX": "/"
        },
        "sockopt": {
                    "tcpMptcp": true
                }
      }
    },
    {
      "tag": "direct",
      "protocol": "freedom"
    }
  ]

Part 6 : 验证并保存配置

我这里采用的是不改变原有网络结构的方式, 通过原有的OpenClash旁路由下, 连接那台Debian VPS.
在作为Xray Client的那台VPS上再配一个 inbound 给OpenClash接入 :

"inbounds": [
  {
   "port": 2333,
   "listen": "192.168.1.12",
   "protocol": "shadowsocks",
   "settings": {
     "network": "tcp,udp",
     "method": "none",
 "password": "114514"
   },
   "sniffing": {
     "enabled": true,
     "destOverride": [
       "http",
       "tls"
     ]
   }
 }
],

在Clash里选择这条线路, 访问一下fast.com进行验证测试.
测速开始前在国内那台Debian上使用 ip mptcp monitor 命令:
TEST.png
看到 saddr4= 后面有2个不同的IP, MTCP的状态有 CREATED ESTABLISHED ANNOUNCED SF_ESTABLISHED, 那基本OK了.
本来应该在作为服务端的VPS上查看更直观, 然而Debian 11 没有 ip mptcp monitor这个命令, 要升级到Debian 12才有.

故障排查 :

全部是 CLOSED状态 : 说明Xray-Core 客户端或服务端参数不对.
SF_ESTABLISHED 状态没有 : 说明 MPTCP subflow的 endpoint配置错误, 或者这条线路的路由不通.
什么都没有 : 说明没有数据使用MPTCP. 可能是数据根本没发到这台VPS, 检查Xray的 Inbound参数,也有可能是Outbound部分的MPTCP参数配置错误.

再进RouterOS, 看一下流量是否平分到2条GRE隧道:
TEST2.png

最后我们需要将一切参数保存并在开机时自动添加运行, 可以写在很多不同的地方, 自行参考网络教程.

海外Debian服务端 :

PostUp = ifconfig lo 11.4.5.14 up
PostUp = ip tunnel add gre3 mode gre remote 10.41.126.91 local 10.41.120.57 ttl 255
PostUp = ip addr add 10.13.1.1/24 dev gre3
PostUp = ip link set gre3 up
PostUp = ip tunnel add gre1 mode gre remote 58.32.32.1 local 10.41.120.57 ttl 255
PostUp = ip addr add 10.13.2.1/24 dev gre1
PostUp = ip link set gre1 up
PostUp = ip link set gre1 mtu 1418
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = ip mptcp limits set subflows 8
PostUp = ip mptcp limits set add_addr_accepted 8
PostUp = service xray restart

国内Debian客户端 :

PostUp = ip route add 11.4.5.14 metric 1 nexthop via eth0对端IP dev eth0 weight 1 nexthop via vlan235对端IP dev eth0.235 weight 33
PostUp = ip mptcp endpoint add id 1 subflow fullmesh eth0IP dev eth0
PostUp = ip mptcp endpoint add id 2 subflow fullmesh vlan235IP dev eth0.235
PostUp = ip mptcp limits set subflows 8
PostUp = ip mptcp limits set add_addr_accepted 8
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostUp = iptables -t nat -A POSTROUTING -o eth0.235 -j MASQUERADE

网络配置sysctl 必要参数 :

net.ipv4.ip_forward=1
net.core.default_qdisc=fq
net.ipv4.tcp_congestion_control=bbr

恭喜你完成了地狱般最简单的MPTCP实例配置~

#如无特别声明,该文章均为 BakaCai 原创,转载请遵循 署名-非商业性使用 4.0 国际(CC BY-NC 4.0) 协议,即转载请注明文章来源。
#最后编辑时间为: 2024 年 09 月 10 日





关于 DreamCat

主题名称:DreamCat | 版本:2.8.221001(LTS)

主题开发:HanFengA7 | TeddyNight | Dev-Leo | CornWorld | WhiteBearcn | DFFZMXJ

Designed by HanFengA7 Power by Typecho

Copyright © 2015-2024 by LychApe All rights reserved!

加我的QQ
加我的微博
加我的支付宝
加我的微信