从 Trojan 迁移到 Xray

从 Trojan 迁移到 Xray

RayAlto OP

Xray/XTLS 一开始给我一种很难用的印象,因为它的配置文件看起来又臭又长虽然 Clash 更臭更长,所以一直没敢从 Trojan 换到 Xray ,但上次找到的 Trojan 的一个 Fork最近的几个 Release 的客户端有奇怪的 DNS 问题,所以下定决心迁移到 Xray ,详细看了看他们的文档 之后觉得其实 Xray 的配置文件并不是那么复杂,这次配置的模式为相对传统的 VLESS-TCP-XTLS-Vision ,至于为啥不用 REALITY 是因为我觉得某个冷门 IP 突然出现了几个驴唇不对马嘴的 SNI 也是一个挺明显的特征。

1. Xray 服务端

和 Trojan 类似, Xray 也是服务端&客户端一体的。

1.1. JupyterLab 安装

这一步不是必需的,我安装 JupyterLab 的目的是通过 JupyterLab 的 Terminal 进行下一步配置,避免长时间 SSH 引起 GFW 怀疑

之前一直在用 root 通过 pip 装 Python 包因为 Debian 的包实在太少了,但最近学到了 venv ,这可真是方便啊:

1
2
3
python3 -m venv Pyenv
source ./Pyenv/bin/activate
pip install jupyterlab

给 JupyterLab 写一个配置文件,可以先生成:

1
jupyter lab --generate-config

我写了这些:

1
2
3
4
5
6
7
c.ServerApp.allow_origin = '*'
c.ServerApp.allow_remote_access = True
c.ServerApp.allow_root = True
c.ServerApp.port = 8443
c.ServerApp.port_retries = 0
c.ServerApp.root_dir = '/root/.jupyter/'
c.ServerApp.trust_xheaders = True

再生成一个密码替代 Token :

1
jupyter server password

~/.jupyter/jupyter_server_config.json 里的 hashed_password 复制到 JupyterLab 配置里:

1
c.PasswordIdentityProvider.hashed_password = 'argon2:$argon2id$v=19$m=10240,t=10,p=8$...'

使用 Systemd 进行管理:

1
systemctl edit --full --force jupyterlab.service

随便写了一个 Service Unit :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[Unit]
Description=JupyterLab
After=syslog.target network.target

[Service]
Type=simple
PIDFile=/run/jupyter.pid
User=root
Group=root
ExecStart=/root/Pyenv/bin/jupyter-lab
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

目前配置的 JupyterLab 运行在 http://127.0.0.1:8443 ,申请一个免费的 SSL 证书:

1
2
apt install certbot python3-certbot-nginx
certbot certonly -d your.domain

然后为了方便,用 Nginx 处理 SSL 细节:

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
map $http_upgrade $connection_upgrade {    
default upgrade;
'' close;
}

server {
listen 80;
server_name your.domain;

# Redirect the request to HTTPS
return 302 https://$host$request_uri;
}

server {
listen 10086 ssl;

server_name your.domain;

ssl_certificate /etc/letsencrypt/live/your.domain/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your.domain/privkey.pem;

location / {
proxy_pass http://127.0.0.1:8443;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header X-Scheme $scheme;

proxy_buffering off;
}
}

之后更新 SSL 证书时可以借助 certbot-nginx :

1
certbot renew --nginx

现在 Nginx 监听 HTTP 80 转到 HTTPS 443 (目前 443 上还没有东西)、监听 HTTPS 10086 用来看 JupyterLab ,现在可以用 JupyterLab 里的 Terminal 进行进一步配置了。

1.2. Xray 安装

我的 VPS 是 Debian12 ,我不打算用他们的 xray-install 脚本 ,因为它把 /usr/local 作为 Prefix ,实在是脱裤子放屁,因为除了 ArchLinux 有 AUR 算是半个官方打包,其他发行版几乎没有给 xray 打包,所以我觉得用 /usr 作 Prefix 一般不会造成冲突。

手动安装:

1
2
3
4
5
wget https://github.com/XTLS/Xray-core/releases/latest/download/Xray-linux-64.zip
unzip Xray*zip
mkdir -p /usr/share/xray /etc/xray
mv xray /usr/bin/
mv geo*dat /usr/share/xray/

然后用 Systemd 管理:

1
systemctl edit --full --force xray.service

从他们的脚本里抄来的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
[Unit]
Description=Xray Server
Documentation=https://github.com/xtls
After=network.target nss-lookup.target

[Service]
User=root
#CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
#AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE
#NoNewPrivileges=true
ExecStart=/usr/bin/xray run -config /etc/xray/config.json
Restart=on-failure
RestartPreventExitStatus=23
LimitNPROC=10000
LimitNOFILE=1000000

[Install]
WantedBy=multi-user.target

1.3. 配置

传统的 VLESS-TCP-XTLS-Vision 大概像这样:

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
{
"log": {
"loglevel": "warning"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{ // 禁用回国流量
"type": "field",
"ip": [
"geoip:cn"
],
"outboundTag": "block"
}
]
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 443, // 监听 HTTPS 443
"protocol": "vless",
"settings": {
"clients": [
{
"id": "Rand Str 或 UUID ,保证客户端和服务端一致,类似密码",
"flow": "xtls-rprx-vision"
}
],
"decryption": "none",
"fallbacks": [
{
"dest": "8443" // fallback 到 JupyterLab
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"alpn": ["http/1.1"], // JupyterLab 貌似不支持 HTTP2 ,不是很清楚
"rejectUnknownSni": true,
"minVersion": "1.2",
"certificates": [
{
"ocspStapling": 3600,
"certificateFile": "/etc/letsencrypt/live/your.domain/fullchain.pem",
"keyFile": "/etc/letsencrypt/live/your.domain/privkey.pem"
}
]
}
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
],
"policy": {
"levels": {
"0": {
"handshake": 2,
"connIdle": 120
}
}
}
}

然后应该就可以运行了:

1
systemctl enable xray --now

2. Xray 客户端

我的路由器运行 ArchLinux ,有 AUR 可用,所以安装比较方便:

1
paru -S xray-bin

2.1. 配置

客户端配置相对简单:

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
{
"log": {
"loglevel": "warning"
},
"routing": {
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"type": "field",
"domain": [
"geosite:cn", // 国内域名直连
"geosite:private", // 局域网域名直连
"domain:your.domain" // 为了稳妥设置服务端域名直连
],
"outboundTag": "direct"
},
{
"type": "field",
"ip": [
"geoip:cn", // 国内 IP 直连
"geoip:private", // 局域网 IP 直连
"your.ip" // 为了稳妥设置服务端 IP 直连
],
"outboundTag": "direct"
}
]
},
"inbounds": [
{ // socks5://127.0.0.1:10808
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"udp": true
},
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
},
{ // http://127.0.0.1:10809
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls"
]
}
}
],
"outbounds": [
{
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "your.domain",
"port": 443,
"users": [
{
"id": "Rand Str 或 UUID ,保证客户端和服务端一致,类似密码",
"encryption": "none",
"flow": "xtls-rprx-vision"
}
]
}
]
},
"streamSettings": {
"network": "tcp",
"security": "tls",
"tlsSettings": {
"serverName": "",
"allowInsecure": false,
"fingerprint": "chrome"
}
},
"tag": "proxy"
},
{
"protocol": "freedom",
"tag": "direct"
},
{
"protocol": "blackhole",
"tag": "block"
}
]
}

2.2. 国内中转

我家这边的网络非常奇怪,我的北美 VPS 用我家电信 Ping 是这种效果:

1
2
3
4
5
6
7
8
PING your.domain (***) 56(84) bytes of data.
64 bytes from *** (***): icmp_seq=1 ttl=51 time=174 ms
...
64 bytes from *** (***): icmp_seq=30 ttl=51 time=166 ms

--- your.domain ping statistics ---
30 packets transmitted, 30 received, 0% packet loss, time 29036ms
rtt min/avg/max/mdev = 162.453/167.700/174.026/3.587 ms

用我的上海的一个国内 VPS Ping 是这种效果:

1
2
3
4
5
6
7
8
PING your.domain (***) 56(84) bytes of data.
64 bytes from *** (***): icmp_seq=1 ttl=48 time=186 ms
...
64 bytes from *** (***): icmp_seq=30 ttl=48 time=186 ms

--- your.domain ping statistics ---
30 packets transmitted, 30 received, 0% packet loss, time 29036ms
rtt min/avg/max/mdev = 172.273/183.198/189.639/6.016 ms

但用我手机的移动 5G Ping 是这种效果:

1
2
3
4
5
6
7
8
PING your.domain (***) 56(84) bytes of data.
64 bytes from *** (***): icmp_seq=1 ttl=47 time=632 ms
...
64 bytes from *** (***): icmp_seq=30 ttl=47 time=502 ms

--- your.domain ping statistics ---
30 packets transmitted, 20 received, 33% packet loss, time 30735ms
rtt min/avg/max/mdev = 454.358/592.252/822.797/112.345 ms

这已经比前一天晚上好很多了,前一天晚上丢包高达 50% 总之就是十分离谱,我从 Trojan 换成 Xray 还有一个主要原因是因为我最近在玩碧蓝档案国际服 ᕕ(◠ڼ◠)ᕗ ,在家有路由器可以随便玩,但出了门之后手机就在墙内,因为安卓没有一个比较安全的 Trojan 客户端,换成 Xray 可以用 V2rayNG 。

碧蓝档案里的桃味小孩和猕猴桃味小孩

这样的移动 5G 用 V2rayNG 的表现就是国内网络完全正常,境外的网络 100 次能有 5 次连接成功,去看 V2rayNG 的 Logcat 大概意思就是境外域名要通过 Xray 在我的北美 VPS 进行解析,但因为丢包严重,这个解析结果都发不回来,所以本地的 DNS 就是不可用的状态。

这个现象前一天我排查了一个晚上都没意识到问题这么简单,我一直以为是我的 V2rayNG 配置有问题,还去 V2rayNG 的 TG 群里问了问,群友好像也没有遇到这种问题,实际上就是移动 5G 到我的北美 VPS 线路质量太差了。第二天早上我灵机一动打算用我的上海的 VPS 做中转,想了想用 Nginx 的 stream 模块应该就可以:

1
2
3
4
5
6
7
8
9
stream {
upstream vps_na {
server your.ip:443;
}
server {
listen 10443; # 监听 10443 端口
proxy_pass vps_na; # 反向代理北美 VPS 443 端口
}
}

记得设置防火墙放行 TCP/UDP 10443 端口。现在 V2rayNG 地址设置成国内 VPS 的 IP ,端口设置成 10443 , SNI 为 your.domain 不变,线路就变成了“移动 5G — 国内 VPS — 北美 VPS”,这样基本能用了,最离谱的是这样测出来的延迟比直连“移动 5G — 北美 VPS”更低,可见中国移动优秀的线路规划。

3. 总结

其实我还去 Xray 的 TG 群里问了问只用 Nginx 的 stream 实现中转会不会有安全问题,有个群友说没有,但我的国内 VPS 可能会因为出境流量过多被通报,仔细想想确实没什么安全方面的问题,而且我只有在使用流量玩碧蓝档案时需要中转,所以估计问题不大。

总体来说我对 Xray 还是比较满意的,但他们的 examples 里貌似对 HTTP2 很执着,我的 fallback 是 JupyterLab ,只要开了 HTTP2 ,JupyterLab 就会抱怨 Malformed HTTP version in HTTP Request-Line: 'HTTP/2.0' ,暂时不清楚是 JupyterLab 不支持 HTTP2 还是说我的配置有问题,但只用 HTTP1.1 目前也没遇到什么问题,测速也能跑满我家网络的带宽,所以就这样吧。