Closed HirbodBehnam closed 1 year ago
感谢你的测试,可能不是 gRPC 内部的问题,而是 Xray 调用 gRPC 的问题
dialerProxy
和 gRPC 传输层是 Xray-core v1.4.0 同时引入的,可能它们之间没适配,你可以检查一下代码,然后发个 PR
请问修好了吗
请问修好了吗
@RPRX
I checked this with xray v1.8.3 and I can confirm that as @HirbodBehnam mentioned, it doesn't work with gRPC. On the other hand, WS works fine.
I was able to reproduce the problem, but couldn't figure out the root cause either. It seems to be a real problem, it is dropping the outbound connection somewhere inside freedom proxy.
@cty123 分享些经验?
解决这个问题应该不难,插一些 log 看一下哪里断了就发现了
我已经试过了,最早是在freedom 这里断的https://github.com/XTLS/Xray-core/blob/main/proxy/freedom/freedom.go#L205, 显示的错误就是 use of closed network connection
,但是不是很清楚为什么connection会断开。我看了grpc文档https://github.com/grpc/grpc-go, 根据说明打开了所有logging, 服务端这边显示是客户端先关闭的连接,但是客户端的grpc显示关闭的原因是EOF, 所以目前并不知道断连的根本原因。
以前有个 bug 是若 cancel gRPC 某一子连接的 ctx,会 cancel 整个 gRPC 连接,这个 EOF 可能是类似的原因
h2 同理,如果 h2 加 dialerProxy 也有这问题,基本上可以确定就是它了
这我倒是可以试试看
那就交给你啦,你的反馈很有帮助,“服务端这边显示是客户端先关闭的连接,但是客户端的grpc显示关闭的原因是EOF”这个症状很符合那个 bug,解决办法就是不传原始 ctx,只复制一些关键的信息(若有必要),参考:
以前有个 bug 是若 cancel gRPC 某一子连接的 ctx,会 cancel 整个 gRPC 连接,这个 EOF 可能是类似的原因
修正一下这个描述,应该是把原始 ctx 传给了子连接,子连接结束时调用了 cancel,结果整个 gRPC 连接都断开了(表现为断流)
以前有个 bug 是若 cancel gRPC 某一子连接的 ctx,会 cancel 整个 gRPC 连接,这个 EOF 可能是类似的原因
但这次这个 bug 盲猜符合这个描述,应该是 gRPC 把第一个子连接的 gctx 传给了 dialerProxy,然后这个 gctx 被 cancel。。。
还真的跟你说的一样,我debug了好几天了都。就是你说的这个地方 https://github.com/XTLS/Xray-core/blob/10d6b065784efd3f33a02d6d5ad2a1fa162ff346/transport/internet/grpc/dial.go#L100-L102 我创了个新的context传进去马上就好了,完美使用
以前有个 bug 是若 cancel gRPC 某一子连接的 ctx,会 cancel 整个 gRPC 连接,这个 EOF 可能是类似的原因
修正一下这个描述,应该是把原始 ctx 传给了子连接,子连接结束时调用了 cancel,结果整个 gRPC 连接都断开了(表现为断流) 但这次这个 bug 盲猜符合这个描述,应该是 gRPC 把第一个子连接的 gctx 传给了 dialerProxy,然后这个 gctx 被 cancel。。。
再次修正 & 总结:
这么说的话其实 gRPC + dialerProxy 一直都是不可用的状态
我在写增强版 XUDP 时遇到了“只想让原始 ctx 控制 dial 超时,不想让它 cancel Copy,但又想让 outbound 自身的超时策略生效”的极其复杂需求,做了一些尝试,留了两处彩蛋,最终方案是给原始 ctx 标记 TimeoutOnly,并且改造了各个 outbound:https://github.com/XTLS/Xray-core/commit/be23d5d3b741268ef86f27dfcb06389e97447e87
所以直接拿来用就行了,@cty123 你试一下给 gctx 标记 TimeoutOnly,没问题的话发个 PR,记得带上 H2
我改好了,请测试 https://github.com/XTLS/Xray-core/commit/d92002ad127f64bc1e740cb350eafd693ffadd6d 的 gRPC 能否使用 dialerProxy
原本 H2 应该是没这个问题的,因为它原本是 context.Background(),这次改成了 DialTLSContext,需要测试有没有引入新问题
此前传给 REALITY UClient 的 ctx 实际上没被用到,一直想改,这次顺便改成了 uConn.HandshakeContext(ctx)
,需要测试有没有引入新问题。但是这个超时时间,以后应当参考浏览器来设置一下,否则 GFW 故意让某次握手超时就精准识别了。
以前有个 bug 是若 cancel gRPC 某一子连接的 ctx,会 cancel 整个 gRPC 连接,这个 EOF 可能是类似的原因
再再次修正:记混了,不是 gRPC,是 H2 以前出现过的 bug https://github.com/XTLS/Xray-core/issues/289#issuecomment-783337941 ,修复见 https://github.com/XTLS/Xray-core/issues/289#issuecomment-787060604
Hello I found a quite strange bug in gRPC transport. Take a look at this config:
This config should just route gRPC traffic via a freedom outbound and thus have no difference between adding
dialerProxy
and not. However, I couldn't get this config to work. If I remove thesockopt
from the config it works fine. Logs look like this:And wiresharks shows that my own PC sends a FIN to server: I tried digging into Xray and Google's gRPC source code with debugging and watching when the pipes get closed but I couldn't figure it out. HOWEVER, I found an alternative way to forward any traffic to a specific outbound. This method involves using
dokodemo-door
with a specific routing and using thedokedemo-door
address as the outbound address. Consider following config file:This is basically the config which I'm currently using to connect. I'm not expecting this to be fixed anytime soon considering that there is a neat workaround.