避坑xray “xver:1″这个参数

配置好后不能代理,问了ai下面是回复


问题:xray 开了 PROXY Protocol,但 nginx 没配对应支持
在 config.json 里:
Json
xver: 1 表示 xray 转发流量给 nginx 时,会在真实TLS数据前面插入一段 PROXY Protocol v1 的头(用来告诉 nginx 真实客户端IP是什么)。
但你 nginx.conf 里对应的监听是:
Nginx
没有加 proxy_protocol 这个参数——这样 nginx 完全不知道流量前面还带了一段PROXY协议头,会把这段头也当成TLS握手数据去解析,直接导致握手失败。
这个问题的直接后果:任何没通过 Reality 验证被转发到”伪装网站”(disk.uyuy.net)的连接,nginx 那边会连不上/报错——也就是说,如果有人用浏览器直接访问你这个伪装域名,或者GFW/审查方做主动探测时,网站会显示异常,反而暴露了”这不是一个正常网站”,削弱了伪装效果。
修复方法——在 nginx.conf 里加上

server {
    listen 127.0.0.1:5000 ssl http2 proxy_protocol;
    server_name disk.uyuy.net;

    # 如果想让nginx日志/后端也能看到真实客户端IP
    set_real_ip_from 127.0.0.1;
    real_ip_header proxy_protocol;

    ssl_certificate /data/minio/config/certs/public.crt;
    ssl_certificate_key /data/minio/config/certs/private.key;
    …
}

proxy_protocol 在 nginx 里其实是”监听socket级别”的参数,不是”server块级别”的参数。
原理
当多个 server 块都写了完全相同的 listen 127.0.0.1:5000 …(同一个IP:端口),nginx 底层其实只会创建一个真实的监听socket,然后根据TLS握手阶段的 SNI(客户端想访问哪个域名)在同一个端口上分流到不同的 server 块(这就是所谓的”虚拟主机”机制)。
而像 ssl、http2、proxy_protocol 这类参数,是绑定在这个共享的监听socket本身上的,而不是绑定在某个具体的 server{} 配置块上。所以只要任意一个 server 块的 listen 行里声明了 proxy_protocol,nginx 就会对这整个 127.0.0.1:5000 socket启用 PROXY Protocol 解析——在流量还没走到SNI分流、还不知道具体是哪个server块之前,这一层解析就已经统一生效了。

潜在风险提醒
虽然现在能跑,但这属于一种隐式依赖,不建议长期这样放着,原因:
可读性差:以后维护这份配置的人(包括未来的你)看到哪吒/openclaw的 server{} 块,会误以为它们没处理PROXY Protocol,容易踩坑
脆弱:如果哪天你把 minio 那个 server{} 块删掉、注释掉、或者改了监听地址,proxy_protocol 这个设置可能会跟着消失,届时哪吒和openclaw会突然失效,而且报错现象会让人摸不着头脑(因为表面上”我没改这两个配置啊”)
建议:为了配置的健壮性和可维护性,还是在这几个 server{} 块的 listen 行都显式加上 proxy_protocol,哪怕功能上重复也没关系:
Nginx
这样每个 server{} 块自身的配置就是”自洽”的,不用依赖其他块的隐式设置,以后拆分、迁移配置都更安全。


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注