Raspberry Pi透明代理

前一段时间后在Raspberry Pi层开启了HTTP代理,Switch再连接HTTP代理服务器。进入商店下载游戏再也不卡了,正窃喜可以好好的玩乌贼的时候,然而一直提示「NAT穿越失败」。

NAT穿越失败

这个错误很奇怪:

  • 大厅可以正常进入,正常购买武器
  • 进入「格斗模式」进行匹配是会出现「NAT穿越失败」

一开始以为是网络不太好,更换了路由器之后还是提示NAT穿越失败。重新复习了一下「计算机网络」这本书之后一想因为Switch只能连接HTTP代理,而HTTP代理只能转发TCP数据包的,所以应该是乌贼2开始匹配是使用的UDP协议,此时UDP包在HTTP协议下是不能转发的。

知道了原因之后还是考虑如何才能把UDP数据包转发出去。目前使用的是v2ray,v2ray的ss协议是可以支持UDP转发的:

  • 支持 TCP 和 UDP 数据包转发,其中 UDP 可选择性关闭;
  • 支持OTA;
    • 客户端可选开启或关闭;
    • 服务器端可强制开启、关闭或自适应;

所以使用透明代理把Raspberry Pi当作一个网关就可以把Switch上的TCP数据包和UDP数据包都可以转发出去了。

v2ray配置

v2ray需要增加一个inbounds,使用Dokodemo-door(任意门)协议。

Dokodemo door(任意门)是一个入站数据协议,它可以监听一个本地端口,并把所有进入此端口的数据发送至指定服务器的一个端口,从而达到端口映射的效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
{
"log": {
"error": "/etc/v2ray/log/error.log",
"loglevel": "error",
"access": "/etc/v2ray/log/access.log"
},
"inbounds": [
// http 或 socks 协议
{
"port": 12345,
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true
},
"sniffing": {
"enabled": false,
"destOverride": ["http", "tls"]
}
}],
"outbounds": [],
"policy": {
"levels": {
"0": {
"uplinkOnly": 2
}
}
}
}

network需要选择tcp,udpfollowRedirect必须为true

当值为true时,dokodemo-door 会识别出由 iptables 转发而来的数据,并转发到相应的目标地址。

Raspberry Pi配置

设置静态IP

作为一个网关需要知道它的IP是多少,虽然现在路由大部分都已经开启了DHCP,但是为了保险一点还需要在Raspberry Pi上设置。

编辑/etc/dhcpcd.conf,添加:

1
2
3
4
interface wlan0
static ip_address=192.168.2.128/24 # 子网掩码为255.255.255.0
static rounters=192.168.2.1 # 路由器地址
static domain_name_servers=192.168.2.1 # DNS地址

之后重启,Raspberry Pi就绑定了 一个静态的IP。

设置转发

编辑/etc/sysctl.conf,添加:

1
net.ipv4.ip_forward=1 # 开启转发

之后使设备生效:

1
sysctl -p

iptables配置

之后需要使用iptables将入网的流量通过12345端口转发出去:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
# 创建新的chain
iptables -t nat -N V2RAY
iptables -t mangle -N V2RAY
iptables -t mangle -N V2RAY_MASK

iptables -t nat -A V2RAY -d 192.168.2.128 -j RETURN # 拒绝本机转发 直连

iptables -t nat -A V2RAY -d 0.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 10.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 127.0.0.0/8 -j RETURN
iptables -t nat -A V2RAY -d 169.254.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 172.16.0.0/12 -j RETURN
iptables -t nat -A V2RAY -d 192.168.0.0/16 -j RETURN
iptables -t nat -A V2RAY -d 224.0.0.0/4 -j RETURN
iptables -t nat -A V2RAY -d 240.0.0.0/4 -j RETURN

# 配置tcp转发
iptables -t nat -A V2RAY -p tcp -j RETURN -m mark --mark 0xff # 直连 SO_MARK 为 0xff 的流量(0xff 是 16 进制数,数值上等同与上面配置的 255),此规则目的是避免代理本机(网关)流量出现回环问题
iptables -t nat -A V2RAY -p tcp -j REDIRECT --to-ports 12345 # 转发流量到12345端口

iptables -t nat -A OUTPUT -p tcp -j V2RAY
iptables -t nat -A PREROUTING -p tcp -j V2RAY

# 配置udp转发
ip rule add fwmark 1 table 100
ip route add local default dev lo table 100

iptables -t mangle -A V2RAY_MASK -d 0.0.0.0/8 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 10.0.0.0/8 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 127.0.0.0/8 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 169.254.0.0/16 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 172.16.0.0/12 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 192.168.0.0/16 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A V2RAY_MASK -d 240.0.0.0/4 -j RETURN

iptables -t mangle -A V2RAY_MASK -d 192.168.2.128 -j RETURN # 拒绝本机转发

iptables -t mangle -A V2RAY_MASK -p udp -j TPROXY --on-port 12345 --tproxy-mark 0x01/0x01
iptables -t mangle -A PREROUTING -j V2RAY_MASK

如果需要删除,可以执行:

1
2
3
4
5
iptables -t nat -F # 清空NAT
iptables -t nat -X # 清空自定义规则

iptables -t mangle -F
iptables -t mangle -X

Switch配置

在手动配置IP时需要记录此时的IP,之后手动配置IP:

  1. 手动配置IP为直连路由的IP
  2. 网关为Raspberry Pi的静态IP
  3. DNS为路由器的IP

之后测试一下连接,NAT类型终于变成了A:

这样,Switch就可以通过Raspberry Pi网关转发TCP和UDP数据包,可以愉快的联机乌贼了!

🥳 加载Disqus评论