DNS: Avoid passing domain to WriteTo func#6163
Conversation
There was a problem hiding this comment.
Pull request overview
Fixes a WireGuard outbound UDP regression where per-packet destinations may still be domain names (causing RawNetAddr() to be nil and WriteTo to fail), by resolving domain UDP destinations before writing.
Changes:
- Refactors DNS lookup into a
lookupIPhelper and applies it to the initial outbound destination resolution. - Adds per-packet UDP destination domain resolution (with caching) in
udpConnClient.WriteMultiBuffer. - Adds unit tests covering per-packet destination resolution, default destination resolution, and case-insensitive caching.
Reviewed changes
Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| proxy/wireguard/client.go | Adds a DNS lookup helper and resolves/caches domain UDP destinations before WriteTo. |
| proxy/wireguard/client_test.go | Adds tests verifying domain resolution behavior for UDP packet destinations and caching semantics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
自从为freedom添加这个缓存后我一直在想什么客户端会产生 writeTo domain 这种行为看起来极其诡异 |
|
This was reproduced on {
"log": {
"access": "none",
"loglevel": "debug",
"dnsLog": false
},
"dns": {
"hosts": {
"dns.cloudflare.internal": [
"162.159.36.1",
"162.159.46.1"
]
},
"servers": [
{
"address": "dns",
"port": 5353,
"skipFallback": true
},
{
"address": "dns.cloudflare.internal",
"domains": [
"domain:example.com"
],
"skipFallback": true
},
{
"address": "localhost",
"domains": [
"full:dns"
],
"skipFallback": true
}
],
"queryStrategy": "UseIPv4",
"disableFallback": true,
"disableFallbackIfMatch": true,
"tag": "dns_inbound"
},
"routing": {
"domainStrategy": "AsIs",
"rules": [
{
"type": "field",
"domain": [
"full:dns.cloudflare.internal"
],
"inboundTag": [
"dns_inbound"
],
"outboundTag": "warp"
},
{
"type": "field",
"domain": [
"domain:example.com"
],
"inboundTag": [
"inbound-vless"
],
"outboundTag": "warp"
}
]
},
"inbounds": [
{
"listen": "0.0.0.0",
"port": 10808,
"protocol": "socks",
"settings": {
"auth": "noauth",
"udp": true
},
"tag": "inbound-vless",
"sniffing": {
"enabled": true,
"destOverride": [
"http",
"tls",
"quic"
]
}
}
],
"outbounds": [
{
"protocol": "freedom",
"settings": {
"domainStrategy": "ForceIPv4"
},
"tag": "direct"
},
{
"protocol": "wireguard",
"settings": {
"secretKey": "***",
"address": [
"172.16.0.2/32",
"***/128"
],
"noKernelTun": false,
"mtu": 1280,
"reserved": [
*,
*,
*
],
"peers": [
{
"endpoint": "engage.cloudflareclient.com:2408",
"publicKey": "bmXOC+F1FxEMF9dyiK2H5/1SUtzH0JuVo51h2wPfgyo=",
"keepAlive": 0,
"allowedIPs": [
"0.0.0.0/0",
"::/0"
]
}
],
"domainStrategy": "ForceIPv4"
},
"tag": "warp"
}
]
}Request: curl -v --max-time 30 --socks5-hostname 127.0.0.1:10808 http://example.com/Relevant log excerpt: |
|
似乎来源于xray dns模块内部一个自以为是的修复 |
c91f439 to
28196b7
Compare
|
Updated the PR to use a smaller fix. After checking the DNS UDP path, the packet-level UDP destination override in the DNS nameserver turned out to be unnecessary here because the same destination is already passed to |
|
这样看起来就行了 |
|
@Fangliding 是因为 WG 不支持 UDP domain 吗?那好像不止这一处吧,QUIC sniffer 应该也会弄出来这种 |
本来就不支持 这里面传的标准IP包 就不存在目标是一个domain的情况 domain都会被预解析 被sniffer造出来 udp domain 也会 只是遇到writeTo里是domain会错乱 我问这东西哪来的 然后发现是xray dns模块里被误加的 |
|
|
|
反正core里造不出来(更新之后) 不知道其他人会是什么情况 writeto doamin 是极其奇怪的 我还没听说过 |
|
理论上支持 FullCone 的代理协议都能被客户端构造出 UDP WriteTo domain 然后传给服务端,不过 Xray 的 freedom 支持它 |
|
但是 Freedom 从被代理的目标 UDP ReadFrom 后目前只有第一个包的 domain 解析出的 IP 会被换回 domain 如果 redirect 的话那个 InitUnchangedAddr 似乎是 redirect 后的,破坏了客户端的 cone,这两点可以修一下
|
|
Test failure looks like a race/flake inside the Sudoku E2E test harness rather than something related to the WireGuard/DNS fix. The failing case is Could you please rerun the test? |
|
|
I think these can be fixed in the outbound UDP handling. |
|
* commit '94ffd50060f1cfd5d7482ec90a23a92bdefdff68': (107 commits) Xray-core v26.6.1 Burst observatory: Fix init check (XTLS#6221) DNS outbound: Replace "reject" with "return" (`rCode` is 0 by default) (XTLS#6214) uTLS: Update `ModernFingerprints` map and `OtherFingerprints` map (XTLS#6181) Realm finalmask: Fix client punch peers (XTLS#6213) GitHub Action CI: Add Go source file format check (XTLS#6090) Burst observatory: Fix time compare, cancel pending ping on instance close or new schedule started (XTLS#6106) Finalmask: Add mkcp-legacy (UDP) to replace mkcp-* and legacy header-* (XTLS#6201) Sudoku finalmask: Harden UDP ReadFrom() against invalid packets (XTLS#6185) XICMP finalmask: Refactor & Speed up; Add multi `ips` and `dgram` mode (client) (XTLS#6168) Salamander finalmask: Support `packetSize` (Gecko in Hysteria v2.9.2) (XTLS#6198) Finalmask: Add Realm (UDP hole punching in Hysteria v2.9.1) (XTLS#6137) README.md: Add flutter_vless to Xray Wrapper in Others (XTLS#6197) DNS: Avoid panic on domain too long (XTLS#6207) header-custom finalmask: Remove headerConnMode headerReadAddrAware interface (XTLS#6193) noise finalmask: Better `reset` (XTLS#6188) DNS: Avoid passing domain to WriteTo func (XTLS#6163) Bump golang.org/x/net from 0.54.0 to 0.55.0 (XTLS#6192) Socks5 server: More standard UDP ASSOCIATE (RFC 1928) (XTLS#6149) Hysteria server: `tls.WithNextProto("h3")` by default (XTLS#6186) ... # Conflicts: # core/core.go
XTLS#6163 (comment) --------- Co-authored-by: 风扇滑翔翼 <Fangliding.fshxy@outlook.com>
doamin是什么 |
Fix a WireGuard outbound UDP regression when the destination is still a domain name.
After the UDP FullCone fix in #5858,
udpConnClient.WriteMultiBuffermay useb.UDPas the packet destination. If that destination contains a domain,RawNetAddr()returns nil andWriteTofails with errors like: