XTLS / Xray-core

Xray, Penetrates Everything. Also the best v2ray-core, with XTLS support. Fully compatible configuration.
https://t.me/projectXray
Mozilla Public License 2.0
24.39k stars 3.82k forks source link

[疑似Bug]当使用Nginx前置SNI分流且开启PROXY protocol时,Android浏览器中出现ERR_SSL_BAD_RECORD_MAC_ALERT报错 #1873

Open xiaomage2000 opened 1 year ago

xiaomage2000 commented 1 year ago

如题,我在Android设备上浏览网页时,会间歇性的出现ERR_SSL_BAD_RECORD_MAC_ALERT错误。具体表现是,点击一个网页,很长时间没有反应,网页进度条不动。再次点击网页链接时,报"ERR_SSL_BAD_RECORD_MAC_ALERT"错误。电脑端基本没有遇到过。

服务端Core版本:1.7.5 Android V2RayNG版本:1.7.38(Core版本1.7.5) 协议:Vision 尝试过1.8.0版本,同样有这个问题,因为要兼容小火箭上的旧版Vision,故退回1.7.5

使用Nginx Stream模块进行SNI分流,与网站共享443端口,Nginx和Xray之间使用PROXY protocol传递访客IP。如果使用PROXY protocol则会出现上述问题,关闭(Nginx注释proxy_protocol on,Xray注释acceptProxyProtocol)则不会出现问题。

Nginx分流配置:

stream {
  map $ssl_preread_server_name $xray {
    vision.example.com vision;
    example.com web;
    default web;
  }

  upstream vision {
    server unix:/dev/shm/vision.sock;
  }
  upstream web {
    server unix:/dev/shm/web.sock;
  }

  server {
    listen 443 reuseport so_keepalive=on;
    proxy_pass $xray;
    ssl_preread on;
    proxy_protocol on;
  }
}

server { //回落伪装站
  listen 80;
  listen unix:/dev/shm/web.sock ssl http2 proxy_protocol;
  listen unix:/dev/shm/fake.sock proxy_protocol;
  listen unix:/dev/shm/fakeh2.sock http2 proxy_protocol;
......

客户端应该是正确配置的,使用的电脑上没有问题的配置导出的二维码。 服务端配置:

    {
      "protocol": "vless",
      "listen": "/dev/shm/vision.sock",
      "settings": {
        "clients": [
          {
            "id": "xxxxxxx",
            "flow": "xtls-rprx-vision"
          }
        ],
        "fallbacks": [
          {
            "dest": "/dev/shm/fake.sock",
            "xver": 1
          },{
            "dest": "/dev/shm/fakeh2.sock",
            "alpn": "h2",
            "xver": 1
          }
        ],
        "decryption": "none"
      },
      "streamSettings": {
        "network": "tcp",
        "security": "tls",
        "tcpSettings": {
          "acceptProxyProtocol": true
        },
        "tlsSettings": {
          "alpn": [
            "h2",
            "http/1.1"
          ],
          "certificates": [
            {
              "ocspStapling": 3600,
              "certificateFile": "/usr/local/nginx/conf/ssl/server.cert.pem",
              "keyFile": "/usr/local/nginx/conf/ssl/server.key.pem"
            }
          ]
        }
      },
      "sniffing": {
        "enabled": true,
        "destOverride": [
          "http",
          "tls"
        ]
      }
    },

服务端日志,约22:02:13报ERR_SSL_BAD_RECORD_MAC_ALERT错误: err.log

V2RayNG 客户端日志: client.log

困扰很长时间了,似乎比较早的版本就有,一直待1.8.0都有这个问题,不知道是Xray本身的问题,还是用到的库的问题,还是V2RayNG的问题了(麻了 实在无解,来发issue吧(

chika0801 commented 1 year ago

我没用过sni分流,有看别人用,没见和你类似现象的反馈。

建议先不用sni分流,直接搭(比如你要用1.7.5)看是否复现。

xiaomage2000 commented 1 year ago

我没用过sni分流,有看别人用,没见和你类似现象的反馈。

建议先不用sni分流,直接搭(比如你要用1.7.5)看是否复现。

直接搭不分流是没事的,SNI分流不用PROXY protocol获取访客IP也没事。偏偏加上acceptProxyProtocol的那一段,用上PROXY protocol就不行了。 另外用旧版Direct试了一下午,似乎也没事,问题可能出在Vision的PROXY protocol处理上了...?(大胆推断 如果需要什么样的更多测试,都可以进行的。

picklefan commented 1 year ago

我也遇到同样的现象, 然而我只是纯粹的 IPv6 问题

同样的现象但是我只是`IPv6` 问题 巧了, 我服务端也是 Nginx Stream 分流, REALITY出现之后过了几天就开始使用REALITY, **之后一直在使用了 `Old soldier's never die` 之前的一个版本直到昨天.** 大概从3天前开始, 电脑端的 `Chrome` (通过 `socks5` 代理, `socks` 入站全 `proxy`) 在 `油管首页` 经常点不进去视频, 现象就是首页点击所有视频都没有任何反应, 打开网页的那个进度条根本不会动, 但是可以右键在新标签中打开视频页面, 但是该 `现象` **无法稳定复现**, disable 所有浏览器插件并把 `Xray` 升级到 `Action` 最新版之后仍然会出现该 `现象`. 但是依旧是 `偶尔出现`, 并 `不能稳定复现` , 有时候过了 `几十秒` 就正常了, 或者重启浏览器之后有 `十几秒` 是正常的, 看完一个几分钟的视频后 `有很大概率` 一切又回复正常. 人比较懒, 没有去查错误信息所以不知道是什么错误. 目前只观察到在 `油管首页` 出现该问题, 并且首次观测到该问题是大概3天前, 出现该 `现象` 的时间点 `前` 最近的的一次改动为: 1. 使用 `nftables` 把客户端(linux旁路由)的 `IPv6` 劫持进 `Xray`. 2. 关闭了服务端的 `sniffing`, (客户端 Tproxy `IPv6` 的时候突然发现服务端开了 `sniffing`, 感觉没什么必要就关了, 只在软路由上保留了 `sniffing`. 看起来跟 `sniffing` 没有任何关系 ~~根据以上判断该 `现象` 可能跟`sniffing` 和 `IPv6` 有关.~~ ~~目前并不想 `enable` 服务端的 `sniffing`, 如果再遇到该现象则会 `enable` 测试, 因为我这边 **出现概率实在很低**~~ ~~你可以看看你服务端开了 `sniffing` 和 `destOverride` 没有, 如果没有可以打开来测试一下~~ >报"ERR_SSL_BAD_RECORD_MAC_ALERT"错误 这个报错我没遇到过, 可我跟你的错误并不完全一样 当然这个问题你更有发言权, 因为我在 `REALITY` 之前从来没用过 `VISION`
xiaomage2000 commented 1 year ago

看起来跟 sniffing 没有任何关系 是的,客户端和服务端的sniffing 都反复开关过,sniffing开启和问题出现没有关系。 因为旧版Direct流控不会出现这个问题,而旧版流控不支持fingerprint,因此还测试了Vision下留空fingerprint,还是不行,跟fingerprint也没有关系。

日志中有大量的failed to close connection > tls: failed to send closeNotify alert (but connection was closed anyway): write unix /dev/shm/vision.sock->@: write: broken pipe报错,即使不使用domain socket,还是会有报错,个人感觉问题在这里。

这个问题很随机,不容易复现,经过测试摸索出了一个相对容易复现的方法:

  1. 打开一个网站,等他加载完毕。
  2. 重启Xray服务端
  3. 点击网站上的一个网页。如果很快加载完成,则复现失败;否则如果加载了10秒还是没有反应,再点击一个网页,就很可能复现。

试了下sing-box上的vision,同样SNI分流,似乎还没有出现这个问题。

picklefan commented 1 year ago

基本上可以确认是 IPv6 的问题, 我刚才又出现了这种 现象, 马上按了 F12 看看什么情况, 发现一堆东西加载不出来, 一看全是 IPv6 地址, 我把 IPv6 一关, 刷新, 全绿了, 而且地址显示的是我的 10808端口 而不是目标实际地址, 说明浏览器 IPv6 根本没有走代理. 不过目前还没有复现, 因为浏览器现在走的v4, 让我看看怎么强制它走V6 至于你说的手机上有毛病, 我早就体验过了, 因为手机上有 IPv6 地址, 你要是开规则分流的话有些应用是直接连接 IP 的, 规则对他无效, 只能全部代理. 你电脑端没遇到是因为你电脑没有 v6 地址

picklefan commented 1 year ago

我这边已经复现了, 就是 IPv6 的问题, 你可以试一下吧全局代理打开(也就是没有分流规则, 全部proxy), 看一下还会有这种情况吗

xiaomage2000 commented 1 year ago

我这边已经复现了, 就是 IPv6 的问题, 你可以试一下吧全局代理打开(也就是没有分流规则, 全部proxy), 看一下还会有这种情况吗

我电脑是有IPv6的,但是电脑上确实没事 刚刚关了本地的IPv6和服务器上的IPv6,正在尝试能不能复现。不能复现的话就是IPv6的锅了。 但个人感觉应该不是,因为我的问题主要是Nginx前置分流+Vision+PROXY protocol下面出现的,破坏任意一个就不能复现了,应该不是IPv6的问题。

picklefan commented 1 year ago

不是你不是手机上出现问题吗, 手机怎么关闭ipv6, 你关服务器没用的, 是你客户端这边的问题. 当然你用vsion比较久估计遇到的bug比我多, 我一直都是nginx 开 proxy_protocol 在前面分流, 但是没有用 vision 所以也没啥发言权.

你手机要排除 v6 直连影响, 只能开全局, root了的话当我没说

xiaomage2000 commented 1 year ago

手机上可以建一个仅IPv4的APN,数据流量就只支持IPv4了。另外刚刚禁用v6还是能复现,说明跟v6没有关系(

picklefan commented 1 year ago

那看起来我们的问题确实不一样, 我跟你服务端结构一样的, 除了我的 VISION 是在 REALITY 里

不过让我想到了这个 issue #1690 不过好像没啥关系

picklefan commented 1 year ago

确实是PROXY protocol 的问题, 我这边又出现了, 关掉就正常了

xiaomage2000 commented 1 year ago

确实是PROXY protocol 的问题, 我这边又出现了, 关掉就正常了

我有了新的发现,也许不能说完全是PROXY protocol的问题,可能问题出在SNI分流上(

我之前只注意到了问题发生时候的日志,现在查看日志,有了新的发现。Nginx前置分流,在没有发生问题时,浏览完毕关闭浏览器时却出现了如下大量报错,直接占据了一个屏幕:

2023/04/02 22:51:33 [Info] [1350649912] app/proxyman/inbound: connection ends > proxy/vless/inbound: connection ends > proxy/vless/inbound: failed to transfer response payload > write unix /dev/shm/@vision.sock->@: write: broken pipe 2023/04/02 22:51:33 [Info] [1350649912] app/proxyman/inbound: failed to close connection > tls: failed to send closeNotify alert (but connection was closed anyway): write unix /dev/shm/@vision.sock->@: write: broken pipe

我又进行了三项测试:

  1. Xray直接监听443
  2. Nginx前置SNI分流 不开启PROXY protocol
  3. Nginx前置SNI分流 开启PROXY protocol

前一项测试没有任何问题。第二项出现了上述的大量错误日志,但是浏览正常。最后一项不但有大量错误日志,还出现偶发ERR_SSL_BAD_RECORD_MAC_ALERT报错。也就是报错只是表象,问题在SNI分流上,有Bug或者我的配置有误。您那边开启SNI分流会有这样的报错吗? @picklefan

picklefan commented 1 year ago

我 proxy_protocol 关了也出现了点击没反应的情况. stream SNI 的话我是一直开的, 以前没用过VISION (我甚至没怎么用过XTLS), 没见过这种情况, 从 REALITY 开始才用的 VISION, 刚开始用 REALITY 也没发现这种情况, 出现问题的版本我都用了一个多月了, 直到前几天才注意到这个问题, 所以这个问题就很诡异, 用了一个月才出问题. SNI 分流的话我就是 stream 直接转发, 难道还需要其他配置?

这个日志不知道在讲什么, 你那边看起来是 fallbacks ,但是我这边就没配置, 我看不懂这个日志, 我这边是这样的, 出现的概率是200万条里面有2000多条

2023/04/02 08:19:19 [Info] [3695363848] app/proxyman/inbound: connection ends > proxy/vless/inbound: connection ends > proxy/vless/inbound: failed to transfer response payload > io: read/write on closed pipe
xiaomage2000 commented 1 year ago

我 proxy_protocol 关了也出现了点击没反应的情况. stream SNI 的话我是一直开的, 以前没用过VISION (我甚至没怎么用过XTLS), 没见过这种情况, 从 REALITY 开始才用的 VISION, 刚开始用 REALITY 也没发现这种情况, 出现问题的版本我都用了一个多月了, 直到前几天才注意到这个问题, 所以这个问题就很诡异, 用了一个月才出问题. SNI 分流的话我就是 stream 直接转发, 难道还需要其他配置?

这个日志不知道在讲什么, 你那边看起来是 fallbacks ,但是我这边就没配置, 我看不懂这个日志, 我这边是这样的, 出现的概率是200万条里面有2000多条

2023/04/02 08:19:19 [Info] [3695363848] app/proxyman/inbound: connection ends > proxy/vless/inbound: connection ends > proxy/vless/inbound: failed to transfer response payload > io: read/write on closed pipe

并不是回落fallbacks。大量错误日志产生的时间点是:Nginx开启SNI分流,Xray在Nginx后面,不管开不开PROXY protocol都会出现这些错误日志:

2023/04/03 14:13:34 [Info] [37353324] app/proxyman/inbound: connection ends > proxy/vless/inbound: connection ends > proxy/vless/inbound: failed to transfer respon
se payload > write unix /dev/shm/@vision.sock->@: write: broken pipe
2023/04/03 14:13:34 [Info] [37353324] app/proxyman/inbound: failed to close connection > tls: failed to send closeNotify alert (but connection was closed anyway):
write unix /dev/shm/@vision.sock->@: write: broken pipe
2023/04/03 14:13:34 [Info] [2960971761] app/proxyman/inbound: connection ends > proxy/vless/inbound: connection ends > proxy/vless/inbound: failed to transfer resp
onse payload > write unix /dev/shm/@vision.sock->@: write: broken pipe
2023/04/03 14:13:34 [Info] [2960971761] app/proxyman/inbound: failed to close connection > tls: failed to send closeNotify alert (but connection was closed anyway)
: write unix /dev/shm/@vision.sock->@: write: broken pipe

这些日志表明,关闭浏览器,Nginx和Xray之间的连接被Nginx打断,日志里面就会报broken pipe的错。也就是说,开启PROXY protocol间歇性报ERR_SSL_BAD_RECORD_MAC_ALERT的错是表象,问题出在Nginx和Xray的交互上,只是开了PROXY protocol让这个问题显现出来了。可能Vision对连接的处理不如Direct,就会报错。

原因应该是这样的,因为我应对这样的原因找到了解决方案,Nginx Stream模块里面加一行proxy_half_close on;就一切正常了,测试了一段时间,没有再出现过了。

但看您那边错误信息和我不太一样,可能不是同一个问题,但是您可以试试 @picklefan

picklefan commented 1 year ago

我们两个问题应该是一样的, 只是你直接用的 vision, 我用的 vision 是在 REALITY 里面. ERR_SSL_BAD_RECORD_MAC_ALERT 这个报错我倒是从来没见过, 浏览器没有, Nginx 和 xray 日志里也没有. 感谢测试并找到了解决方案, 我会尝试你的解决方案

moll33er commented 1 year ago

可以用nginx先代理去除proxy_protocol(如果一定需要使用proxy_protocol直达xray请忽略),配置如下

stream {
    # 第一跳 
    upstream xray_proxy_protocol {
        server 127.0.0.1:7070;
    }
    # 接受proxy_protocol
    server {
        listen 7070 proxy_protocol;
        proxy_pass  xray_proxy;
    }
    # 第二跳
    upstream xray_proxy { 
        # 代理端口
        server 127.0.0.1:30001;
    }
}
AAkira45 commented 3 months ago

2024.6.3 更新: 也遇到了相同的问题,网站随机出现err_ssl_bad_record_mac_alert,哪怕在PC端Chrome也是相同现象。 nginx端口使用proxy_half_close on;配置依旧无法解决问题,在使用此跳转去除proxy_protocol后问题消失,同时xray内也无需开启acceptProxyProtocol.

在此更新一下我个人的解决方案,希望对后来者有所帮助。 PS:另外不知道这个是不是bug,不过总之这样可以解决,缺点是xray因为没有代理协议从而无法得到客户端ip,不过这个对有nginx前置的情况下并不是很重要。

donnyxray commented 1 month ago

@AAkira45 this happens for me too.

It does not matter whether I use NGINX or HAPROXY. As soon as the proxy protocol is enabled, random requests will fail with ERR_SSL_BAD_RECORD_MAC_ALERT.

I suspect the bug is in xray-core, not both nginx and haproxy. But due to it's rare and random character it's very difficult to debug.

AAkira45 commented 1 month ago

@AAkira45 this happens for me too.

It does not matter whether I use NGINX or HAPROXY. As soon as the proxy protocol is enabled, random requests will fail with ERR_SSL_BAD_RECORD_MAC_ALERT.

I suspect the bug is in xray-core, not both nginx and haproxy. But due to it's rare and random character it's very difficult to debug.

这样看起来首先这基本确定应该是一个bug,其次照时间计算这个bug已经存在一年时间尚未在现有版本中得到解决,如有可能需要有人reopen这个issue或者进行修复,只可惜本人对go实在不熟,只能寄希望于开发者们能对这个问题再review一下,在此谢谢各位开发者辛勤付出!

AAkira45 commented 1 month ago

@AAkira45 this happens for me too. It does not matter whether I use NGINX or HAPROXY. As soon as the proxy protocol is enabled, random requests will fail with ERR_SSL_BAD_RECORD_MAC_ALERT. I suspect the bug is in xray-core, not both nginx and haproxy. But due to it's rare and random character it's very difficult to debug.

这样看起来首先这基本确定应该是一个bug,其次照时间计算这个bug已经存在一年时间尚未在现有版本中得到解决,如有可能需要有人reopen这个issue或者进行修复,只可惜本人对go实在不熟,只能寄希望于开发者们能对这个问题再review一下,在此谢谢各位开发者辛勤付出!

我这边使用的配置为nginx前置ssl sni分流,xray为reality vision,具体配置见: https://github.com/XTLS/Xray-core/issues/3548 当不使用此转换配置时便会出现问题 stream {

第一跳

upstream xray_proxy_protocol {
    server 127.0.0.1:7070;
}
# 接受proxy_protocol
server {
    listen 7070 proxy_protocol;
    proxy_pass  xray_proxy;
}
# 第二跳
upstream xray_proxy { 
    # 代理端口
    server 127.0.0.1:30001;
}

}

xiaomage2000 commented 1 month ago

2024.6.3 更新: 也遇到了相同的问题,网站随机出现err_ssl_bad_record_mac_alert,哪怕在PC端Chrome也是相同现象。 nginx端口使用proxy_half_close on;配置依旧无法解决问题,在使用此跳转去除proxy_protocol后问题消失,同时xray内也无需开启acceptProxyProtocol.

在此更新一下我个人的解决方案,希望对后来者有所帮助。 PS:另外不知道这个是不是bug,不过总之这样可以解决,缺点是xray因为没有代理协议从而无法得到客户端ip,不过这个对有nginx前置的情况下并不是很重要。

你的解决方案是可以的,但是Xray无法获取到使用者的IP,虽然不影响使用。 后来我又测试,proxy_half_close on确实不行。 再之后没办法,我就暂时放弃Nginx前置SNI分流了,改成Xray前置。这个Bug到现在还没有修复。 开发者们应该是在忙着开发新协议,Nginx前置这种玩法好像不被重视( 同样希望开发者能再review一下这个问题,我这边也可以再尝试复现一下,提交一些更详细的日志

simplerick-simplefun commented 1 month ago

2024.6.3 更新: 也遇到了相同的问题,网站随机出现err_ssl_bad_record_mac_alert,哪怕在PC端Chrome也是相同现象。 nginx端口使用proxy_half_close on;配置依旧无法解决问题,在使用此跳转去除proxy_protocol后问题消失,同时xray内也无需开启acceptProxyProtocol. 在此更新一下我个人的解决方案,希望对后来者有所帮助。 PS:另外不知道这个是不是bug,不过总之这样可以解决,缺点是xray因为没有代理协议从而无法得到客户端ip,不过这个对有nginx前置的情况下并不是很重要。

你的解决方案是可以的,但是Xray无法获取到使用者的IP,虽然不影响使用。 后来我又测试,proxy_half_close on确实不行。 再之后没办法,我就暂时放弃Nginx前置SNI分流了,改成Xray前置。这个Bug到现在还没有修复。 开发者们应该是在忙着开发新协议,Nginx前置这种玩法好像不被重视( 同样希望开发者能再review一下这个问题,我这边也可以再尝试复现一下,提交一些更详细的日志

可以使用 https://github.com/path-network/go-mmproxy 作为中间件帮助不支持proxy protocol的程序获得分流前的原来源IP。配置略微复杂一些,但是教程很清晰,不难。

berserkBoyi commented 1 month ago

你们测试时是否在网络环境比较好的时候进行? 你们开启sni后,应该会跑一些网页,这些网页的数据库需要占用内存,是否有检查主机内存留有足够内存? 我也整了一个sni,分别为xray和网页设置了证书。一开始因为不会设置,没有开启nginx到xray这段过程的proxy_protocol,最近学会了设置,但发现链接中断的概率提高了。主要表现就是:

safari:“Safari can't open the page because it couldn't establish a secure connection to the server.”

firefox focus:“An SSL error has occurred and a secure connection to the server cannot be made.”

不同浏览器表达不同,但是就是与ssl相关。 这种错误在网络丢包率较高时出现,但我开启了nginx 到 xray 这段proxy_protocol后出现的频率更高了。 我一开始以为是bug,后面试着做一些排除,其中一处是内存不够。因为我的网页时wordpress搭的,mysql占用几百M,使得系统内存只有十几M,后面我的做法是,停用网页相关的数据库部分,让系统有200m内存空余;感觉有所改善。 但我不确定是不是因为内存太小导致网络丢包的概率提升。 希望我回复对你们有帮助。

AAkira45 commented 1 month ago

你们测试时是否在网络环境比较好的时候进行? 你们开启sni后,应该会跑一些网页,这些网页的数据库需要占用内存,是否有检查主机内存留有足够内存? 我也整了一个sni,分别为xray和网页设置了证书。一开始因为不会设置,没有开启nginx到xray这段过程的proxy_protocol,最近学会了设置,但发现链接中断的概率提高了。主要表现就是:

safari:“Safari can't open the page because it couldn't establish a secure connection to the server.”

firefox focus:“An SSL error has occurred and a secure connection to the server cannot be made.”

不同浏览器表达不同,但是就是与ssl相关。 这种错误在网络丢包率较高时出现,但我开启了nginx 到 xray 这段proxy_protocol后出现的频率更高了。 我一开始以为是bug,后面试着做一些排除,其中一处是内存不够。因为我的网页时wordpress搭的,mysql占用几百M,使得系统内存只有十几M,后面我的做法是,停用网页相关的数据库部分,让系统有200m内存空余;感觉有所改善。 但我不确定是不是因为内存太小导致网络丢包的概率提升。 希望我回复对你们有帮助。

过程中并没有观察到内存占用过高,实际上在启动完成以后还有1.5GB的RAM可以使用,且去掉protocol以后问题完全消失,重新加上部分网页问题偶发,并不是每一次打开网页都会触发这个问题。但是频率也不罕见。目前尚不清楚触发必须的条件是什么,且并不会每次都出现,debug需要耗费相当的时间和精力去寻找问题。

lxhao61 commented 1 month ago

特意报告一下:使用 Caddy 前置 SNI 分流且开 PROXY protocol 一样会产生类似问题。

Yochee commented 3 weeks ago

我也遇到同样问题,而且是纯ipv4下桌面chrome报的错。服务端是nginx+sni分流到后端xray