DialerProxy: Fix SplitHTTP H3 dialerProxy#3570
Conversation
|
Detailsconn, err := internet.DialSystem(ctx, dest, streamSettings.SocketSettings)
if err != nil {
return nil, err
}
var packetConn net.PacketConn
switch c := conn.(type) {
......
default:
packetConn = &connWrapper{Conn: conn}
}
return quic.DialEarly(ctx, packetConn, conn.RemoteAddr(), tlsCfg, cfg)type connWrapper struct {
net.Conn
}
func (c *connWrapper) ReadFrom(p []byte) (n int, addr net.Addr, err error) {
n, err = c.Read(p)
return n, c.RemoteAddr(), err
}
func (c *connWrapper) WriteTo(p []byte, _ net.Addr) (n int, err error) {
return c.Write(p)
}
func (c *connWrapper) LocalAddr() net.Addr {
// return some random and unique things
}For the warning in https://github.com/quic-go/quic-go/blob/c40d4ccb7fe00974095f06a7eb5ac00dd62b7f5b/sys_conn_buffers_write.go#L19, just ignore it (or implement a dummy |
|
Thanks, this does seem cleaner. Howvever, when using the config files from #3560, I still get the same error as before even for a single connection: removing dialerProxy fixes it |
|
SplitHTTP H3 不支持 dialerProxy 只是我不小心发现的,实际上似乎没有这样的使用场景,有时间可以先实现 #3560 (comment) |
|
For Xray-core/transport/internet/dialer.go Line 129 in 2becdd6 Wrong context used? Maybe using the ctx from getHTTPClient is correct.For a connection issue: I tried with minimal config |
|
It is true that the dialer doesn't work with splithttp h3, but there is another way to send splithttp h3 outbound to another outbound. {
"dns": {
"hosts": {
"domain:googleapis.cn": "googleapis.com"
},
"servers": [
"8.8.8.8"
]
},
"inbounds": [
{
"listen": "127.0.0.1",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true,
"userLevel": 8
},
"sniffing": {
"destOverride": [
"quic",
"http",
"tls"
],
"enabled": true
},
"tag": "socks"
},
{
"listen": "127.0.0.1",
"port": 10809,
"protocol": "http",
"settings": {
"userLevel": 8
},
"tag": "http"
},
{
"listen": "127.0.0.1",
"port": 23451,
"protocol": "dokodemo-door",
"settings": {
"address": "ip or domain", // config domain or ip
"port": 443, // config port
"network": "tcp,udp", // udp is required
"timeout": 0,
"userLevel": 8,
"followRedirect": false
},
"tag": "proxytodirect"
}
],
"log": {
"loglevel": "none"
},
"outbounds": [
{
"mux": {
"concurrency": 8,
"enabled": false,
"xudpConcurrency": 8,
"xudpProxyUDP443": "allow"
},
"protocol": "vless",
"settings": {
"vnext": [
{
"address": "127.0.0.1",
"port": 23451,
"users": [
{
"encryption": "none",
"flow": "",
"id": "your-id", // config id
"level": 8,
"security": "auto"
}
]
}
]
},
"streamSettings": {
"network": "splithttp",
"security": "tls",
"splithttpSettings": {
"host": "your.host", // config host
"path": "/yourpath" // config path
},
"tlsSettings": {
"allowInsecure": false,
"alpn": [
"h3" // quic
],
"fingerprint": "chrome",
"serverName": "your.sni" // config sni
}
},
"tag": "proxy"
},
{
"protocol": "freedom",
"settings": {},
"tag": "direct"
},
{
"protocol": "blackhole",
"settings": {
"response": {
"type": "http"
}
},
"tag": "block"
}
],
"policy": {
"levels": {
"8": {
"connIdle": 300,
"downlinkOnly": 1,
"handshake": 4,
"uplinkOnly": 1
}
},
"system": {
"statsOutboundUplink": true,
"statsOutboundDownlink": true
}
},
"routing": {
"domainStrategy": "AsIs",
"rules": [
// rule to send dokodemo-door to direct.
{
"inboundTag": [
"proxytodirect"
],
"outboundTag": "direct",
"type": "field"
},
// It is important to set DNS and send it to the right outbound (i.e. the second outbound) if you put the domain in the address section of dokodemo-door.
{
"outboundTag": "direct",
"port": "53",
"type": "field"
}
]
},
"stats": {}
}
1- If the second outbound has Mux, it must be xudpProxyUDP443 allow or skip. 2- Pay attention to dns, I explained it in the form of a comment in the code.
|
The discussion is about how to fix it rather than using another way to workaround it. The dialer does work, and dialerProxy will work after applying the changes I mentioned. It is dialer reuse(?) that causes a very basic configuration (without dialerProxy) having connection issues. |
Pay attention to the first paragraph of my comment. I didn't say don't improve dialerproxy! Pay attention to what is written on the xray github page. |
|
I had to delete another comment of mine. Thanks to @dyhkwong's comments I got it working. But I have a different conclusion:
To reproduce this issue with dialerproxy, do this:
this explains why some workarounds worked:
Anyway, this PR now fixes dialerProxy without affecting QUIC connection reuse. I'm not 100% sure if any other uses of dialerProxy are affected though, and maybe it leaks connections in some other scenario now due to I found that changing to |
|
GRPC and HTTP use ctx like this, is that your case? Xray-core/transport/internet/grpc/dial.go Lines 122 to 124 in 96e8b8b Xray-core/transport/internet/http/dialer.go Lines 72 to 74 in 96e8b8b And can you reproduce the connectivity issue? It even happens without |
|
@dyhkwong it's pretty interesting. I tried this code snippet now, it seems that it does not fix http3 client reuse (but patching in I was not able to reproduce the general connectivity issue you described earlier. I am inclined to believe it only happens on some systems because there's also tests for this 😅 |
|
Looks good to me, thanks all! |
* wip * wip * formatting * cnc connection no longer needs to be a Packetconn * dialerProxy: do not cancel connection when Dial context is cancelled
* wip * wip * formatting * cnc connection no longer needs to be a Packetconn * dialerProxy: do not cancel connection when Dial context is cancelled
Summary for users: If you have Fragment turned on in v2rayNG and other clients, splithttp+h3 configs may not connect. With this PR, this bug is fixed.
I implemented the suggestions in #3560, but I ran into some difficulties: