应用情景
由于 XTLS,Xray 需要监听 443 端口,这导致如果之前有网站运行在服务器上,那么此时网站无法运行或需要运行在其他端口上,这显然是不合理的。有以下三种方案可以解决这个问题:
Xray 监听其他常用端口(如 22、3389、8443)
这个方案是最简单的,但不够完美。
Nginx 或 HAProxy 监听 443 端口,通过 SNI 分流做 L4 反向代理,实现端口复用
这个方案比较复杂,需要对 Nginx 或 HAProxy 的使用有一定了解,此处不作过多解释。
Xray 监听 443 端口,通过 Fallbacks 功能 SNI 分流将网站流量回落到 Nginx 或 Caddy
这个方案难度适中,也是此教程接下来想要演示的方案。
思路
从 443 端口接收到流量后,Xray 会把 TLS 解密后首包长度 < 18、协议版本无效或身份认证失败的流量通过对 name、path、alpn 的匹配转发到 dest 指定的地址。
Xray 配置
{
log: {
loglevel: "warning",
},
inbounds: [
{
port: 443,
protocol: "vless",
settings: {
clients: [
{
id: "UUID",
flow: "xtls-rprx-direct",
},
],
decryption: "none",
fallbacks: [
{
name: "example.com",
path: "/vmessws",
dest: 5000,
xver: 1,
},
{
dest: 5001,
xver: 1,
},
{
alpn: "h2",
dest: 5002,
xver: 1,
},
{
name: "blog.example.com",
dest: 5003,
xver: 1,
},
{
name: "blog.example.com",
alpn: "h2",
dest: 5004,
xver: 1,
},
],
},
streamSettings: {
network: "tcp",
security: "xtls",
xtlsSettings: {
alpn: ["h2", "http/1.1"],
certificates: [
{
certificateFile: "/etc/ssl/xray/cert.pem",
keyFile: "/etc/ssl/xray/privkey.key",
},
],
},
},
},
{
listen: "127.0.0.1",
port: 5000,
protocol: "vmess",
settings: {
clients: [
{
id: "UUID",
},
],
},
streamSettings: {
network: "ws",
wsSettings: {
acceptProxyProtocol: true,
path: "/vmessws",
},
},
},
],
outbounds: [
{
protocol: "freedom",
},
]
}以上配置针对于 Nginx,以下是需要注意的一些细节。
有关 Proxy Protocol
Proxy Protocol 是 HaProxy 开发的一种旨在解决代理时容易丢失客户端信息问题的协议,常用于链式代理和反向代理。传统的处理方法往往较为复杂且有诸多限制,而 Proxy Protocol 非常简单地在传输数据时附带上原始连接四元组信息的数据包,解决了这个问题。
凡事皆有利弊,Proxy Protocol 也是如此。
在遇到异常时,请考虑配置是否符合上述条件。
此处,我们使用 Proxy Protocol 让被回落到的目标获取到客户端的真实 IP。
另外,当 Xray 的某个入站配置存在
"acceptProxyProtocol": true时,ReadV 将失效。有关 HTTP/2
首先,
inbounds.streamSettings.xtlsSettings.alpn有顺序,应将h2放前,http/1.1放后,在优先使用 HTTP/2 的同时保证兼容性;反过来会导致 HTTP/2 在协商时变为 HTTP/1.1,成为无效配置。在上述配置中,每条回落到 Nginx 的配置都要分成两个。这是因为 h2 是强制 TLS 加密的 HTTP/2 连接,这有益于数据在互联网中传输的安全,但在服务器内部没有必要;而 h2c 是非加密的 HTTP/2 连接,适合该环境。然而,Nginx 不能在同一端口上同时监听 HTTP/1.1 和 h2c,为了解决这个问题,需要在回落中指定
alpn项(是fallbacks而不是xtlsSettings里面的),以尝试匹配 TLS ALPN 协商结果。建议
alpn项只按需用两种填法:[4]如果使用 Caddy 就大可不必如此繁杂了,因为它可以在同一端口上同时监听 HTTP/1.1 和 h2c,配置改动如下:
省略
"h2"
"fallbacks": [
{
"name": "example.com",
"path": "/vmessws",
"dest": 5000,
"xver": 1
},
{
"dest": 5001,
"xver": 1
},
{
"name": "blog.example.com",
"dest": 5002,
"xver": 1
}
]Nginx 配置
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
server {
listen 127.0.0.1:5001 proxy_protocol default_server;
listen 127.0.0.1:5002 proxy_protocol default_server http2;
location / {
root /srv/http/default;
}
}
server {
listen 127.0.0.1:5003 proxy_protocol;
listen 127.0.0.1:5004 proxy_protocol http2;
server_name blog.example.com;
location / {
root /srv/http/blog.example.com;
}
}
server {
listen 80;
return 301 https://$host$request_uri;
}
评论区