Xray-core: gRPC cannot be proxied with dialerProxy to freedom
Hello I found a quite strange bug in gRPC transport. Take a look at this config:
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": "10808",
"protocol": "socks",
"settings": {
"udp": true
}
},
{
"listen": "127.0.0.1",
"port": "10809",
"protocol": "http"
}
],
"outbounds": [
{
"protocol": "trojan",
"settings": {
"servers": [
{
"address": "example.com",
"port": 443,
"password": "pass"
}
]
},
"streamSettings": {
"network": "gun",
"security": "tls",
"grpcSettings": {
"serviceName": "servername"
},
"sockopt": {
"dialerProxy": "direct"
}
}
},
{
"protocol": "freedom",
"tag": "direct"
}
]
}
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 the sockopt
from the config it works fine. Logs look like this:
2023/06/20 16:13:41 [Warning] core: Xray 1.8.3 started
2023/06/20 16:13:43 [Info] [2221018126] proxy/socks: TCP Connect request to tcp:[2a00:1450:4001:827::200e]:80
2023/06/20 16:13:43 [Info] [2221018126] app/dispatcher: default route for tcp:[2a00:1450:4001:827::200e]:80
2023/06/20 16:13:45 tcp:127.0.0.1:36732 accepted tcp:[2a00:1450:4001:827::200e]:80
2023/06/20 16:13:49 [Info] [2221018126] transport/internet/grpc: creating connection to tcp:104.21.2.133:443
2023/06/20 16:13:49 [Debug] transport/internet/grpc: using gRPC tun mode service name: `...` stream name: `Tun`
2023/06/20 16:13:49 [Info] [2221018126] transport/internet: redirecting request tcp:104.21.2.133:443 to fragment
2023/06/20 16:13:49 [Info] [2221018126] transport/internet/tcp: dialing TCP to tcp:104.21.2.133:443
2023/06/20 16:13:49 [Debug] transport/internet: dialing to tcp:104.21.2.133:443
2023/06/20 16:13:49 [Info] [2221018126] proxy/freedom: connection opened to tcp:104.21.2.133:443, local endpoint 172.16.0.2:48020, remote endpoint 104.21.2.133:443
2023/06/20 16:13:54 [Info] [2221018126] proxy/trojan: tunneling request to tcp:[2a00:1450:4001:827::200e]:80 via 104.21.2.133:443
multi read transport/internet/grpc/encoding: failed to fetch hunk from gRPC tunnel > rpc error: code = Unavailable desc = error reading from server: EOF
transport/internet/grpc/encoding: failed to send data over gRPC tunnel > EOF
2023/06/20 16:14:36 [Info] [2221018126] app/proxyman/outbound: failed to process outbound traffic > proxy/trojan: connection ends > transport/internet/grpc/encoding: failed to fetch hunk from gRPC tunnel > rpc error: code = Unavailable desc = error reading from server: EOF
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 the dokedemo-door
address as the outbound address. Consider following config file:
{
"log": {
"loglevel": "debug"
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": "10808",
"protocol": "socks",
"settings": {
"udp": true
}
},
{
"listen": "127.0.0.1",
"port": "10809",
"protocol": "http"
},
{
"listen": "127.0.0.1",
"port": "28111",
"protocol": "dokodemo-door",
"settings": {
"address": "104.21.2.133",
"port": 443,
"network": "tcp"
},
"tag": "fragmentedinbound"
}
],
"outbounds": [
{
"protocol": "trojan",
"settings": {
"servers": [
{
"address": "127.0.0.1",
"port": 28111,
"password": "password"
}
]
},
"streamSettings": {
"network": "gun",
"security": "tls",
"grpcSettings": {
"serviceName": "..."
},
"tlsSettings": {
"serverName": "..."
}
}
},
{
"protocol": "freedom",
"settings": {
"fragment": {
"length": "1-2",
"interval": "0-1",
"packets": "1"
}
},
"tag": "fragment"
},
{
"protocol": "freedom",
"tag": "direct"
}
],
"routing": {
"domainMatcher": "mph",
"domainStrategy": "IPIfNonMatch",
"rules": [
{
"domain": [
"regexp:.*\\.ir$",
"ext:iran.dat:ir",
"ext:iran.dat:other"
],
"outboundTag": "direct",
"type": "field"
},
{
"ip": [
"geoip:private",
"geoip:ir"
],
"outboundTag": "direct",
"type": "field"
},
{
"inboundTag": [
"fragmentedinbound"
],
"outboundTag": "fragment",
"type": "field"
}
]
}
}
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.
About this issue
- Original URL
- State: closed
- Created a year ago
- Comments: 18 (17 by maintainers)
感谢你的测试,可能不是 gRPC 内部的问题,而是 Xray 调用 gRPC 的问题
dialerProxy
和 gRPC 传输层是 Xray-core v1.4.0 同时引入的,可能它们之间没适配,你可以检查一下代码,然后发个 PR