个人网络配置方案 提到过,之前我的 PS4 代理方案是在 OpenWrt 路由器上通过 LuCI 配置 shadowsocks-libev 来完成的。 此方案理论上并没有什么问题或者不妥,但是在实际游戏中,常常会遇到无法和好友使用 PS4 内置的 Party 进行语音的问题,甚至还会出现彻底无法加入好友的集会所的情况。 这些问题出现时 PS4 大概率会提示说:Cannot use voice chat with the following player: xxxxx. This might be because of NAT type limitations。 考虑到 Monster Hunter World: IceBorne 发售日临近,这个问题若是不解决恐怕又要出现和好基友花半小时开任务十分钟掉线的尴尬画面了。

使用 WireGuard 进行加速

首先是换掉 shadowsocks,改用 WireGuard 提供 VPN 方案。具体来说的话,shadowsocks 本身是对 socks5 代理进行加密传输来实现代理,本质上是一个应用层代理。而透明代理是对设备的 IP Packet 进行代理,需要额外的工作才能实现,目前主要的两种方式是 ss-redir 和 iptables 流量重定向,或者是使用移动平台上常见的 tun2socks 来完成 L5 转 L3。WireGuard 那边呢,因为这玩意本身就是一个 L3 VPN,在两个 peer 上都会创建一个 tun 接口,并使用 UDP 来完成 tun 接口中流量的传递,对操作系统等来说这就是一个常规的 L3 隧道,也就避免了不必要的麻烦。

我们分别在代理服务器和家里的路由器上创建 WireGuard 接口,这些步骤网上已经有大量的内容可供参考,就不再描述了。假定服务器的 IP 为 172.16.150.16/24,路由器的 IP 为 172.16.150.1/24。和正常的 VPN 使用场景不同,我们需要让远程服务器提供 NAT 服务,因此需要在服务器端的 iptables 上动一些手脚,在 WireGuard 的配置文件的 [Interface] 部分增加以下内容:

PostUp = iptables -A FORWARD -i %i -j ACCEPT; iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -D FORWARD -i %i -j ACCEPT; iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

OpenWrt 那一侧呢就很简单了,直接安装 luci-proto-wireguard 和其他你需要的管理工具,然后去 LuCI 中创建 WireGuard 接口并添加 Peer 配置。创建完成之后启动接口,WireGuard 应该就顺利启动运行了。

为 PS4 创建路由规则

既然是为 PS4 提供游戏加速,这个 VPN 承载的数据也只应该是 PS4 的连接,子网内的其他设备仍然应该使用运营商的默认路由访问互联网(主要是付不起这个流量费 QAQ),也就是需要做一下简单的策略路由。第一步,在 /etc/iproute2/rt_tables 文件内追加一些内容:

echo '200     ps4' >> /etc/iproute2/rt_tables

然后,在 iptables mangle 表上创建规则,并插入到 PREROUTING 链上,给所有来自 PS4 的流量打上一个 mark(这里没有直接在 PREROUTING 里插规则是为了后面的需要):

iptables -N PS4_PREROUTING -t mangle
iptables -A PS4_PREROUTING -t mangle -j MARK --set-mark 100

iptables -A PREROUTING -t mangle -m mac --mac-source F8:46:1C:4F:8E:75 -j PS4_PREROUTING # Plash Speed 4

并给之前创建的名为 ps4 的路由表添加默认路由,将默认路由指向 WireGuard VPN 中的服务端 IP:

ip route add default via 172.16.150.16 dev wg_vpn table ps4

最后添加规则,让带有 mark 100 的流量走 ps4 路由表即可:

ip rule add fwmark 100 table ps4

完成这些操作之后,打开 PS4 上的网络浏览器,访问任意一个能查看到自己 IP 的网站(例如 https://ipinfo.io/)来验证是否生效。

排除 PS4 的下载流量

和之前一样,现在这年头游戏动辄五六十 GB,走 VPN 下载显然不妥,因此依然需要对这些流量进行处理。

第一步,先使用 ipset 命令创建好一个 IP set,准备接收来自 dnsmasq 的解析结果:

ipset create ps4cdn hash:ip

随后,编辑 dnsmasq 的配置文件,添加以下内容,确保使用境内 DNS 解析这些域名,并自动将解析得到的 IP 加入 set 中:

server=/ares.dl.playstation.net/223.5.5.5
server=/gs.ww.np.dl.playstation.net/223.5.5.5
server=/gs2.ww.prod.dl.playstation.net/223.5.5.5
server=/poseidon.dl.playstation.net/223.5.5.5
server=/zeus.dl.playstation.net/223.5.5.5
server=/dcn01.ps4.update.playstation.net/223.5.5.5
ipset=/ares.dl.playstation.net/ps4cdn
ipset=/gs.ww.np.dl.playstation.net/ps4cdn
ipset=/gs2.ww.prod.dl.playstation.net/ps4cdn
ipset=/poseidon.dl.playstation.net/ps4cdn
ipset=/zeus.dl.playstation.net/ps4cdn
ipset=/update.playstation.net/ps4cdn

之后,再在 iptables 上动一些手脚:

iptables -I PS4_PREROUTING -t mangle -m set --match-set ps4cdn dst -j RETURN

这样就大功告成了!原理的话大概是这样:PS4 下载游戏之前会去解析域名拿到 IP 地址,在这一过程中 DNS 服务器(也就是路由器)会将解析到的 IP 添加到内核中名为 ps4cdn 的 set 中。与此同时, 后续连接在抵达路由器之后,匹配到 PREROUTING 链,进入 PS4_PREROUTING 链。在 PS4_PREROUTING 链上有两个规则:

  1. 目标地址(dst)在 ps4cdn 这个集合中存在,则执行 RETURN,返回上一个链
  2. 目标地址不在 ps4cdn 中,那么就说明这个是需要进行路由的数据,那么打上 mark 然后放行就好了

之后,如果遇到带有 mark 100 的流量,内核会自动把它安排到 ps4 路由表中,该表的默认路由是 WireGuard VPN 的另一侧,就顺顺利利的完成了所有工作了。

服务器的选择

考虑到 WireGuard 是一个 UDP 为主的 VPN 协议,选择服务器比选择日常使用的代理服务器要麻烦很多。服务器方面,我个人比较建议去选择一些能“不过墙”的方案,比如某阿里云深圳机房和香港机房经典网络的某些网段能内网互通,只要交两倍的流量费和两倍的服务器费就能蹭上专线访问外网。当然还有其他的一些方法,这些我就不多说了。家庭宽带这一侧的话,就还是尽可能选正经运营商吧,截至目前我自己的上海电信宽带依然拥有公网 IPv4 地址,UDP 好像也没遇到什么特别激进的 QoS,可以说是非常感谢了(


2019 年 9 月 12 日更新:

Iceborne 已经打通好几天了,真好玩建议大家都来玩一玩,这一整套加速方案也在过去的几十个小时的游戏时间里保证了几乎完美的游戏体验:Party 完全没有出现过 NAT 警告,游戏本身也从未发生过掉线等问题。