应用情景
由于 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; }
评论区