用树莓派做透明代理网关加速 Switch 游戏 -- 怪物猎人xx

之前折腾过的游戏方案都需要路由器支持,但普通路由器跑个 KCP 都能炸。即便是 AC68U也不令人满意:科学上网插件中的访问控制虽然能让单独的游戏设备使用游戏模式达到 FullCone 的效果,但 Nat Type 时不时会掉到 F,十分影响游戏体验,于是乎又折腾起了树莓派,发现做成一个透明代理网关完全符合需求。

此方案同样适用于 PS4 等游戏主机,只需要连上树莓派的 WIFI 或单独设置网关地址为树莓派 IP 就能达到无污染上网、流畅玩游戏的效果。
如果只是想加速 PC 游戏的话可以关注 [Netch] 这个项目,比 SSTAP 和 Sockscap 之类的好用太多了,以后要是更新了局域网代理加速的功能的话,是游戏加速方案首选。
[Netch]:https://github.com/NetchX/Netch

环境

服务器:阿里云深圳小鸡,像怪物猎人这种 P2P 的联机游戏,选国内的服务器相当合适。

树莓派系统:2016-03-18-raspbian-jessie
http://ftp.jaist.ac.jp/pub/raspberrypi/raspbian/images/

替换USTC源前请备份:

sudo nano /etc/apt/sources.lis
#修改源
deb http://mirrors.ustc.edu.cn/raspbian/raspbian/ stretch main contrib non-free rpi
# 更新
sudo apt-get update -y

烧录工具:
https://www.alexpage.de/usb-image-tool/download/

拓容: sudo rpi-config --> Expand FileSystem

BBR

没错,树莓派也能用 BBR 了 hhh。

sudo rpi-update
sudo reboot
# 内核版本大于 4.9 即可
uname -r
    输出:4.19.46-v7+
sudo bash -c 'echo "net.core.default_qdisc=fq" >> /etc/sysctl.conf'
sudo bash -c 'echo "net.ipv4.tcp_congestion_control=bbr" >> /etc/sysctl.conf'
sudo sysctl -p
sudo reboot
# 重启后检查一下有没有 bbr 模块即可
sysctl net.ipv4.tcp_available_congestion_control
    输出:net.ipv4.tcp_available_congestion_control = bbr cubic reno
lsmod | grep bbr
    输出:tcp_bbr                20480  1

热点

如果游戏设备在同一个局域网内,可以直接设置网关为树莓派 IP,不需要额外折腾热点。

带 rtl871xdrv 补丁的 hostapd

3B+内置的网卡信号太感人,外接个 USB 带天线的网卡会好很多,8192CUS 驱动请参考最后的链接来配置。

sudo apt install -y libnl-3-dev libnl-genl-3-dev libssl-dev
wget https://w1.fi/releases/hostapd-2.6.tar.gz
wget https://raw.githubusercontent.com/pritambaral/hostapd-rtl871xdrv/hostapd_2_6/rtlxdrv.patch
tar zxf hostapd-2.6.tar.gz
cd hostapd-2.6
patch -p1 < ../rtlxdrv.patch
cd hostapd
cp defconfig .config
echo CONFIG_LIBNL32=y >> .config
echo CONFIG_DRIVER_RTW=y >> .config
make -j
sudo make install

create_ap

想自行设置热点请参考官方文档:https://www.raspberrypi.org/documentation/configuration/wireless/access-point.md

这里一步到位用了 create_ap,热点不设置密码也是可以的。
eth0、wlan0 为树莓派默认网卡名,不同的话请自行修改。

sudo apt-get install -y haveged dnsmasq iproute2 iptables
git clone https://github.com/oblique/create_ap
cd create_ap
sudo make install
# 启动热点
sudo create_ap wlan0 eth0 $ap_name $ap_password --no-virt

打开路由转发

sudo vim /etc/sysctl.conf
//取消net.ipv4.ip_forward=1的注释
sudo sysctl -p
输出:
    net.ipv4.ip_forward = 1
    net.core.default_qdisc = fq
    net.ipv4.tcp_congestion_control = bbr

此时客户端连接上 WIFI 可以上网就可以进行下一步了

SS

  • no-install-recommends参数来避免安装非必须的文件,从而减小镜像的体积。

  • 只有 C 语言版的 Shadowsocks-libev才支持 UDP 转发,且更新频率最高、CPU内存占用率最小,所以推荐使用。

各种有的没的依赖

sudo apt-get install -y --no-install-recommends vim git gettext libssl-dev build-essential autoconf libtool libpcre3-dev asciidoc xmlto libev-dev libc-ares-dev automake libcurl4-openssl-dev ipset rng-tools screen

Libsodium

export LIBSODIUM_VER=1.0.16
wget https://download.libsodium.org/libsodium/releases/libsodium-$LIBSODIUM_VER.tar.gz
tar xvf libsodium-$LIBSODIUM_VER.tar.gz
pushd libsodium-$LIBSODIUM_VER
./configure --prefix=/usr && make -j
sudo make install
popd
sudo ldconfig

Mbedtls

export MBEDTLS_VER=2.6.0
wget https://tls.mbed.org/download/mbedtls-$MBEDTLS_VER-gpl.tgz
tar xvf mbedtls-$MBEDTLS_VER-gpl.tgz
pushd mbedtls-$MBEDTLS_VER
make SHARED=1 CFLAGS=-fPIC
sudo make DESTDIR=/usr install
popd
sudo ldconfig

Obfs

git clone https://github.com/shadowsocks/simple-obfs.git
cd simple-obfs
git submodule update --init --recursive
./autogen.sh && ./configure && make -j
sudo make install
cd ~

Shadowsocks-libev

git clone https://github.com/shadowsocks/shadowsocks-libev.git
cd shadowsocks-libev
git submodule update --init --recursive
./autogen.sh && ./configure --prefix=/usr && make -j
sudo make install 
cd ~

v2ray-plugin

obfs 混淆不再更新了,这里换成 [v2ray-plugin]
[v2ray-plugin]: https://github.com/shadowsocks/v2ray-plugin

服务器端配置文件

{
    "server": ["0.0.0.0"],
    "server_port": 8388,
    "password": "test",
    "user": "nobody",
    "fast_open": true,
    "method": "aes-256-gcm",
    "plugin": "v2ray-plugin",
    "plugin_opts": "server"
    "mode": "tcp_and_udp",
    "workers": 2
}

Dns Over Https

UPDATE
cloudflared 的解析延迟还是不太能接受,这里推荐红鱼 DNS OVER HTTPS。
配置参考:https://aliyun5.rubyfish.cn/dnscrypt-proxy-on-raspberrypi

cloudflared 同样是监听 0.0.0.0 端口设置为 15353 防止占用系统端口。

wget https://bin.equinox.io/c/VdrWdbjqyF/cloudflared-stable-linux-arm.tgz
tar -xvf cloudflared-stable-linux-arm.tgz
chmod +x cloudflared
nohup /home/pi/ss/cloudflared proxy-dns --address 0.0.0.0 --port 15353  2>&1 > /dev/null &

Dnsmasq

sudo vim /etc/dnsmasq.conf

no-resolv # 不让 dnsmasq 以 /etc/resolve.conf 中的服务器为上游服务器
no-poll    # 不让 dnsmasq 向 /etc/resolve.conf 中的服务器发起查询请求
server=127.0.0.1#15353 # ip 是 cloudflared 监听的 IP,一般是本地 IP;port 是 cloudflared 监听的端口
conf-dir=/etc/dnsmasq.d/,*.conf # dnsmasq-china-list 的配置文件将要存放在 dnsmasq.d 中,引入配置文件

dnsmasq-china-list

之前用 chinadns 不稳定,还要配合 dnsforwarder 使用。
dnsmasq-china-list项目维护了一张国内常用但是通过国外DNS会解析错误的网站域名的列表,保证List中的国内域名全部走国内DNS服务器解析。

wget https://raw.githubusercontent.com/felixonmars/dnsmasq-china-list/master/install.sh
chmod +x install.sh
sudo ./install.sh
# 启动
sudo systemctl restart dnsmasq

iptables

UDP 转发不能像转发 TCP 一样,需要借助 TPROXY 模块。
关于 NAT 这一块,感兴趣的可以看这篇:https://vvl.me/2018/06/09/from-ss-redir-to-linux-nat/

# 清空iptables
sudo su
iptables -F
iptables -X
iptables -t nat -F
iptables -t nat -X
iptables -t mangle -F
iptables -t mangle -X
iptables -P INPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -P OUTPUT ACCEPT

# SS-REDIR TCP
iptables -t nat -N SSREDIR_TCP

# Bypass ssserver and LAN
iptables -t nat -A SSREDIR_TCP -d $Server_IP -j RETURN
iptables -t nat -A SSREDIR_TCP -d 0.0.0.0/8 -j RETURN
iptables -t nat -A SSREDIR_TCP -d 10.0.0.0/8 -j RETURN
iptables -t nat -A SSREDIR_TCP -d 127.0.0.0/8 -j RETURN
iptables -t nat -A SSREDIR_TCP -d 169.254.0.0/16 -j RETURN
iptables -t nat -A SSREDIR_TCP -d 172.16.0.0/12 -j RETURN
iptables -t nat -A SSREDIR_TCP -d 192.168.0.0/16 -j RETURN
iptables -t nat -A SSREDIR_TCP -d 224.0.0.0/4 -j RETURN
iptables -t nat -A SSREDIR_TCP -d 240.0.0.0/4 -j RETURN
# Redirect TCP
iptables -t nat -A SSREDIR_TCP -p tcp -j REDIRECT --to-ports 60080

# SS_REDIR UDP
ip rule add fwmark 0x02/0x02 table 100
ip route add local 0.0.0.0/0 dev lo table 100
iptables -t mangle -N SSREDIR_UDP
iptables -t mangle -A SSREDIR_UDP -d $Server_IP -j RETURN
iptables -t mangle -A SSREDIR_UDP -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A SSREDIR_UDP -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A SSREDIR_UDP -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A SSREDIR_UDP -d 169.254.0.0/16 -j RETURN
iptables -t mangle -A SSREDIR_UDP -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A SSREDIR_UDP -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A SSREDIR_UDP -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A SSREDIR_UDP -d 240.0.0.0/4 -j RETURN
# Redirect UDP
iptables -t mangle -A SSREDIR_UDP -p udp -j TPROXY --on-port 60080 --tproxy-mark 0x02/0x02

# Enable
iptables -t nat -A PREROUTING -p tcp -j SSREDIR_TCP
iptables -t mangle -A PREROUTING -j SSREDIR_UDP
exit

写进开机启动自动恢复已保存的路由

保存

sudo sh -c "iptables-save > /etc/iptables/rules.v4"

开机恢复

sudo sh -c "iptables-restore < /etc/iptables/rules.v4"

ss-redir

Kcptun

事实上 kcptun 在游戏加速里面更像个“减速器”,不建议使用。

UDPSpeeder

服务器

./speederv2_amd64 -s -l0.0.0.0:2001 -r127.0.0.1:1080 -f2:4 -k "test" --mode 0 -q 1

客户端

./speederv2_arm -c -l127.0.0.1:1080 -r0.0.0.0:2001 -f2:4 -k "test" --mode 0 -q 1

Udp2raw

贵校 Qos 水平远超我想象,UDP 包稍稍发送频繁一些都会做丢包处理,所以服务器端开两个 udp2raw tunnel 来伪装流量。
如果当地 ISP 干扰不严重,可以不用开。
如果当地 ISP 干扰不严重,可以不用开。
如果当地 ISP 干扰不严重,可以不用开。

# TCP
./udp2raw_arm -c -l127.0.0.1:2000 -r$Server_IP:28900 -k "test" --raw-mode faketcp --sock-buf 4096 --force-sock-buf

# UDP
./udp2raw_arm -c -l127.0.0.1:2001 -r$Server_IP:28901 -k "test" --raw-mode faketcp --sock-buf 4096 --force-sock-buf

串联

最终脚本

这里没有使用 kcptun 和 udp2raw,各位请根据实际情况使用,1+1 不一定大于 2。
普通环境下建议 ss-redir 分离 TCP 和 UDP,UDP 单独用 udpspeeder 加速就行。
ss-redir 和 create_ap 都需要 root 权限

#!/bin/bash

# kill process
killall ss-redir
killall udp2raw_arm
killall speederv2_arm
killall dnscrypt-proxy_arm
killall v2ray-plugin
killall create_ap
systemctl restart dnsmasq

# iptables
/bin/sh /path/iptables.sh
#dns over https
nohup /path/dnscrypt-proxy_arm 2>&1 > /path/dns.log &

# TCP
nohup /usr/bin/ss-redir -s $SS_Server_IP -p $SS_PORT -m aes-256-gcm -k test12345 -b 0.0.0.0 -l 60080 --no-delay --fast-open --plugin v2ray-plugin    -v >/path/ss_tcp.log 2>&1 &
# UDP
nohup /usr/bin/ss-redir -s 127.0.0.1 -p $LOCAL_PORT -m aes-256-gcm -k test12345 -b 0.0.0.0 -l 60080 --no-delay --fast-open --plugin v2ray-plugin    -U -v >/path/ss_udp.log 2
>&1 &

# udpspeeder
nohup /path/speederv2_arm -c -r$SS_Server_IP:$udpspeeder_port -l127.0.0.1:$LOCAL_PORT -f2:4 -k passwd --mode 0 -q 1 >/path/udpspeeder.log 2>&1 &

# AP
nohup /usr/bin/create_ap wlan0 eth0 $AP_Name $AP_Password --no-virt 2>&1 > /dev/null &

效果

连上树莓派的 WIFI 或者将 Switch 的网关和 DNS 设置成树莓派 IP 就能将 Nat Type 升到 A,其他游戏设备同理。
Switch网关设置

Switch连接树莓派WIFI
最后,如果有采集卡的朋友,建议弄个有线网卡和小型的散热底座。
一来联机稳定,二是 Switch 原生底座散热太感人,一旦发热起来录制就掉帧,有点害怕屏幕会变形。

Have Fun~
代理游戏效果