透明代理搭建记录

一开始家里直接使用OpenWrt作为主路由,优点是可折腾性强,什么都可以往上部署,缺点就是稳定性差,经常性会出现一些不明故障,排查花时间不说,主要在这期间影响网络使用。
所以后来直接将主路由切换成专业的硬路由,网络基本稳定了,看来还是专业的事交给专业的设备来处理比较好。但是头疼的是原来软路由可以做的事情,很多都没法做了,所以就想搞一个旁挂的网关,来代替原来OpenWrt做的时候。
主要需要实现以下几个目的:

  1. ddns:针对阿里的域名解析
  2. 科学上网:只对有需要的设备进行代理
  3. wiregurad:虚拟组网

本文介绍科学上网

科学上网

这里直接将原来OpenWrt软路由刷成了ubuntu系统,采用xray做透明代理,这里参考了Xray TProxy 透明代理配置教程,根据实际情况做了一些调整。
所以后续描述都基于ubuntu 22.04.1 LTS,采用iptables转发操作入口。

所以需要安装 # sudo apt install iptables ip6tables

安装xray
直接使用xray官方的脚本

1
# bash -c "$(curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh)" @ install

或者将脚本install-release.sh和安装包Xray-linux-64.zip下载下来之后,使用本地安装

1
2
# chmod 700 install-release.sh
# ./install-release.sh --local Xray-linux-64.zip

安装完成之后,修改xray的配置文件,根据实际情况配置

1
# sudo vim /usr/local/etc/xray/config.json
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
{
"log": {
"loglevel": "warning"
},
"inbounds": [
{
"tag": "all-in",
"port": 12345,
"protocol": "dokodemo-door",
"settings": {
"network": "tcp,udp",
"followRedirect": true
},
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
},
"streamSettings": {
"sockopt": {
"tproxy": "tproxy",
"mark": 255
}
}
},
{
"port": 10808,
"protocol": "socks",
"sniffing": {
"enabled": true,
"destOverride": ["http", "tls", "quic"]
},
"settings": {
"auth": "noauth",
"udp": true
}
}
],
"outbounds": [
{
//此为默认outbound,路由(routing)模块若未匹配到任何规则,则默认走此 proxy 出口,如果你希望直连国内优先请将下面 direct 出口放到 outbound 第一,看不懂可忽略
"tag": "proxy",
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "yourdomain.domain", //改为你自己的域名,直接填写ipv4或ipv6地址也可以
"port": 443,
"users": [
{
"id": "uuid", //填写uuid,可通过在终端中输入 xray uuid 生成;此处也支持任意字符串(https://xtls.github.io/config/inbounds/vless.html#clientobject)
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"sockopt": {
"mark": 255
},
"network": "tcp",
"security": "tls", //注意使用 xtls-rprx-vision 流控此处需为 tls
"tlsSettings": {
//注意使用 xtls-rprx-vision 流控此处需为 tlsSettings
"allowInsecure": false,
"serverName": "yourdomain.domain", //改为你自己的域名
"fingerprint": "chrome" //此设置建议先看下Release, https://github.com/XTLS/Xray-core/releases/tag/v1.7.3
}
}
},
{
"tag": "direct",
"protocol": "freedom",
"settings": {
"domainStrategy": "UseIP"
},
"streamSettings": {
"sockopt": {
"mark": 255
}
}
},
{
"tag": "block",
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
}
},
{
"tag": "dns-out",
"protocol": "dns",
"streamSettings": {
"sockopt": {
"mark": 255
}
}
}
],
"dns": {
"hosts": {
"domain:googleapis.cn": "googleapis.com",
"dns.google": "8.8.8.8",
"你的VPS域名": "你的VSP IP" //如果 outbound 的 proxy 里 address 填的域名:希望代理走ipv4,这里 VPS IP 填VPS的ipv4, 希望代理走ipv6,这里VPS IP 填VPS的ipv6;outbound 的 proxy 里 address 填的 IP,这行不用写。
},
"servers": [
"https://1.1.1.1/dns-query",
{
"address": "119.29.29.29",
"domains": ["geosite:cn"],
"expectIPs": ["geoip:cn"]
},
"https://dns.google/dns-query",
"223.5.5.5",
"localhost"
]
},
"routing": {
"domainMatcher": "mph",
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": ["geosite:category-ads-all"],
"outboundTag": "block"
},
{
"type": "field",
"inboundTag": ["all-in"],
"port": 123,
"network": "udp",
"outboundTag": "direct"
},
{
"type": "field",
"inboundTag": ["all-in"],
"port": 53,
"network": "udp",
"outboundTag": "dns-out"
},
{
"type": "field",
"ip": ["119.29.29.29", "223.5.5.5"],
"outboundTag": "direct"
},
{
"type": "field",
"protocol": ["bittorrent"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["geoip:private", "geoip:cn"], //此处可加入 VPS IP 避免 ssh 时被代理
"outboundTag": "direct"
},
{
"type": "field",
"domain": ["geosite:cn"],
"outboundTag": "direct"
},
{
"type": "field",
"ip": ["1.1.1.1", "8.8.8.8"],
"outboundTag": "proxy"
},
{
"type": "field",
"domain": [
"geosite:geolocation-!cn",
"domain:googleapis.cn",
"dns.google"
],
"outboundTag": "proxy"
}
]
}
}

Netfilter 配置

设置路由策略
直接将命令复制到终端执行即可

1
2
3
4
5
6
7
# 设置策略路由 v4
ip rule add fwmark 1 table 100
ip route add local 0.0.0.0/0 dev lo table 100

# 设置策略路由 v6
ip -6 rule add fwmark 1 table 106
ip -6 route add local ::/0 dev lo table 106

使用 iptables

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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# 代理局域网设备 v4
iptables -t mangle -N XRAY
iptables -t mangle -A XRAY -d 127.0.0.1/32 -j RETURN
iptables -t mangle -A XRAY -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A XRAY -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A XRAY -d 192.168.0.0/16 -p tcp -j RETURN
iptables -t mangle -A XRAY -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN
iptables -t mangle -A XRAY -j RETURN -m mark --mark 0xff
iptables -t mangle -A XRAY -p udp -j TPROXY --on-ip 127.0.0.1 --on-port 12345 --tproxy-mark 1
iptables -t mangle -A XRAY -p tcp -j TPROXY --on-ip 127.0.0.1 --on-port 12345 --tproxy-mark 1
iptables -t mangle -A PREROUTING -j XRAY

# 代理局域网设备 v6
ip6tables -t mangle -N XRAY6
ip6tables -t mangle -A XRAY6 -d ::1/128 -j RETURN
ip6tables -t mangle -A XRAY6 -d fe80::/10 -j RETURN
ip6tables -t mangle -A XRAY6 -d fd00::/8 -p tcp -j RETURN
ip6tables -t mangle -A XRAY6 -d fd00::/8 -p udp ! --dport 53 -j RETURN
ip6tables -t mangle -A XRAY6 -d 2400::/8 -p tcp -j RETURN
ip6tables -t mangle -A XRAY6 -d 2400::/8 -p udp ! --dport 53 -j RETURN
ip6tables -t mangle -A XRAY6 -j RETURN -m mark --mark 0xff
ip6tables -t mangle -A XRAY6 -p udp -j TPROXY --on-ip ::1 --on-port 12345 --tproxy-mark 1
ip6tables -t mangle -A XRAY6 -p tcp -j TPROXY --on-ip ::1 --on-port 12345 --tproxy-mark 1
ip6tables -t mangle -A PREROUTING -j XRAY6

# 代理网关本机 v4
iptables -t mangle -N XRAY_MASK
iptables -t mangle -A XRAY_MASK -d 224.0.0.0/4 -j RETURN
iptables -t mangle -A XRAY_MASK -d 255.255.255.255/32 -j RETURN
iptables -t mangle -A XRAY_MASK -d 192.168.0.0/16 -p tcp -j RETURN
iptables -t mangle -A XRAY_MASK -d 192.168.0.0/16 -p udp ! --dport 53 -j RETURN
iptables -t mangle -A XRAY_MASK -j RETURN -m mark --mark 0xff
iptables -t mangle -A XRAY_MASK -p udp -j MARK --set-mark 1
iptables -t mangle -A XRAY_MASK -p tcp -j MARK --set-mark 1
iptables -t mangle -A OUTPUT -j XRAY_MASK

# 代理网关本机 v6
ip6tables -t mangle -N XRAY6_MASK
ip6tables -t mangle -A XRAY6_MASK -d fe80::/10 -j RETURN
ip6tables -t mangle -A XRAY6_MASK -d fd00::/8 -p tcp -j RETURN
ip6tables -t mangle -A XRAY6_MASK -d fd00::/8 -p udp ! --dport 53 -j RETURN
ip6tables -t mangle -A XRAY6_MASK -j RETURN -m mark --mark 0xff
ip6tables -t mangle -A XRAY6_MASK -p udp -j MARK --set-mark 1
ip6tables -t mangle -A XRAY6_MASK -p tcp -j MARK --set-mark 1
ip6tables -t mangle -A OUTPUT -j XRAY6_MASK

# 新建 DIVERT 规则,避免已有连接的包二次通过 TPROXY,理论上有一定的性能提升 v4
iptables -t mangle -N DIVERT
iptables -t mangle -A DIVERT -j MARK --set-mark 1
iptables -t mangle -A DIVERT -j ACCEPT
iptables -t mangle -I PREROUTING -p tcp -m socket -j DIVERT

# 新建 DIVERT 规则,避免已有连接的包二次通过 TPROXY,理论上有一定的性能提升 v6
ip6tables -t mangle -N DIVERT
ip6tables -t mangle -A DIVERT -j MARK --set-mark 1
ip6tables -t mangle -A DIVERT -j ACCEPT
ip6tables -t mangle -I PREROUTING -p tcp -m socket -j DIVERT

将上述配置写入一个文件(如 iptables.rules),之后将该文件赋予可执行权限

1
2
# sudo chmod 700 ./iptables.rules
# sudo ./iptables.rules

其中,网关地址192.168.0.0/16, fd00::/8等可由

address | grep -w inet | awk '{print $2}'```以及
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
```ip address | grep -w inet6 | awk '{print $2}'```获得,替换对应行

**配置持久化**

iptables相关配置,可以安装netfilter-persistent,安装过程中会提示保存配置,只要保存之后就持久化
或者可以手动执行。
```netfilter-persistent save```

路由相关配置,我们需要使用脚本来处理。
在 /etc/systemd/system/ 目录下创建一个名为 tproxyrules.service 的文件,添加以下内容并保存。
```shell
[Unit]
Description=Tproxy rules

[Service]
Type=oneshot
RemainAfterExit=yes

ExecStartPre=/bin/sh -c 'until ping -c1 网关IP地址; do sleep 1; done;'

ExecStart=/sbin/ip rule add fwmark 1 table 100 ; \
/sbin/ip -6 rule add fwmark 1 table 106 ; \
/sbin/ip route add local 0.0.0.0/0 dev lo table 100 ; \
/sbin/ip -6 route add local ::/0 dev lo table 106

ExecStop=/sbin/ip rule del fwmark 1 table 100 ; \
/sbin/ip -6 rule del fwmark 1 table 106 ; \
/sbin/ip route del local 0.0.0.0/0 dev lo table 100 ; \
/sbin/ip -6 route del local ::/0 dev lo table 106

[Install]
WantedBy=multi-user.target

最后执行 systemctl enable tproxyrules 命令。

局域网设备使用网关

只要手动设置IP,然后将对应的网关设置为刚刚配置的透明代理网关设备即可。当不需要代理的时候,取消对应的网关就行了。