[DNS] v1.14.0-alpha.48 复用已被上游关闭的 TCP DNS 连接时导致间歇性 EOF
Nobody has claimed this yet.
- Dominant language
- Go
- Stars
- 38.2k
- Forks
- 4.6k
- Avg merge
- 19d 15h
- Merged PRs (30d)
- 1
Description
操作系统
iOS
系统版本
IOS 26.5.2 本地最小复现环境:Ubuntu 26.04 LTS,Linux 7.0.0-22-generic x86_64。
安装类型
sing-box for iOS 图形客户端程序
如果您使用图形客户端程序,请提供该程序版本。
No response
版本
sing-box version unknown
Environment: go1.24.7 linux/amd64
Revision: fa36eb769a200e9558c414a36eb16da9a2446ea9
CGO: disabled
上述本地二进制从 `v1.14.0-alpha.48` 标签对应的 revision 自行编译。作为对照,也使用 `v1.14.0-alpha.47`(revision `37b4386b`)运行了完全相同的复现环境。
描述
升级到 v1.14.0-alpha.48 后,使用 TCP DNS 且通过 Shadowsocks detour 连接远端 DNS 时,会间歇性出现:
dns: exchange failed for example.com. IN AAAA: EOF
该问题不需要高并发。只要 TCP DNS 服务端在返回一次响应后延迟关闭连接,而客户端恰好在关闭前把下一个查询写入 alpha.48 复用的连接,下一个查询就会收到 EOF,且不会在新连接上重试。
本地最小复现中,alpha.48 连续 10 轮结果为 10 次成功、10 次 EOF;alpha.47 使用完全相同的客户端配置、服务端配置、DNS 服务和查询步骤,两次查询均成功。
初步定位为 commit 3d2461f3bae3fab6537656173ab65965c41ea0a8(refactor: Async DNS)引入的 TCP DNS 单连接复用回归:
- alpha.47 的 TCP DNS 每次查询都会新建并关闭连接。
- alpha.48 的
TCPTransport改为使用queryMultiplexer共享连接。 ExchangeAsync只会在写入失败时重试一次。recvLoop读到 EOF 后仅使连接失效并返回;已经成功写入该连接的 pending query 会直接收到 EOF,不会在新连接上重试。
预期行为:对于可安全重试的 DNS 查询,如果复用连接在读取响应时返回 EOF,应在新 TCP 连接上重试一次;或者在能够正确处理这种关闭竞态前不要复用 TCP DNS 连接。
重现方式
复现完全在本机进行,不依赖远程服务器、TUN、图形客户端或私有配置。附件包含完整文件:
- client.json
{
"log": {
"level": "trace",
"timestamp": true
},
"dns": {
"servers": [
{
"type": "tcp",
"tag": "remote-dns",
"server": "127.0.0.1",
"server_port": 2053,
"detour": "ss-out"
}
],
"rules": [
{
"action": "evaluate",
"server": "remote-dns"
},
{
"action": "respond",
"match_response": {}
}
],
"final": "remote-dns"
},
"inbounds": [
{
"type": "direct",
"tag": "dns-in",
"listen": "127.0.0.1",
"listen_port": 15353,
"network": "udp",
"override_address": "1.0.0.1",
"override_port": 53
}
],
"outbounds": [
{
"type": "shadowsocks",
"tag": "ss-out",
"server": "127.0.0.1",
"server_port": 12000,
"method": "2022-blake3-aes-128-gcm",
"password": "MTIzNDU2Nzg5MDEyMzQ1Ng=="
},
{
"type": "direct",
"tag": "direct"
}
],
"route": {
"rules": [
{
"port": 53,
"action": "hijack-dns"
}
],
"final": "direct"
}
}
- server
{
"log": {
"level": "trace",
"timestamp": true
},
"inbounds": [
{
"type": "shadowsocks",
"tag": "ss-in",
"listen": "127.0.0.1",
"listen_port": 12000,
"method": "2022-blake3-aes-128-gcm",
"password": "MTIzNDU2Nzg5MDEyMzQ1Ng=="
}
],
"outbounds": [
{
"type": "direct",
"tag": "direct"
}
]
}
- dns_server.py
#!/usr/bin/env python3
import socket
import struct
import threading
import time
def handle(conn):
with conn:
header = conn.recv(2)
if not header:
return
length = struct.unpack("!H", header)[0]
query = b""
while len(query) < length:
part = conn.recv(length - len(query))
if not part:
return
query += part
response = (
query[0:2]
+ b"\x81\x80"
+ query[4:6]
+ b"\x00\x00\x00\x00\x00\x00"
+ query[12:]
)
conn.sendall(struct.pack("!H", len(response)) + response)
time.sleep(0.2)
server = socket.socket()
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(("127.0.0.1", 2053))
server.listen()
while True:
client, _ = server.accept()
threading.Thread(target=handle, args=(client,), daemon=True).start()
四个终端分别执行:
# 终端 1:本地 TCP DNS。每条连接回答一次,等待 200ms 后关闭。
python3 dns_server.py
# 终端 2:本地 Shadowsocks 2022 服务端。
sing-box run -c server.json
# 终端 3:本地 sing-box 客户端。
sing-box run -c client.json
# 终端 4:两个普通顺序查询,无需并发。
dig @127.0.0.1 -p 15353 example.com A +time=1 +tries=1 +short
dig @127.0.0.1 -p 15353 example.com AAAA +time=1 +tries=1 +short
alpha.48 中,第一个查询成功,第二个查询在约 180–200ms 后出现 EOF。重复执行时稳定表现为一个成功、下一个 EOF。
alpha.47 中,两个查询均成功,并且日志显示每个查询分别创建 Shadowsocks/TCP DNS 连接。
日志
+0800 2026-07-20 08:53:48 INFO network: updated default interface ens3, index 2
+0800 2026-07-20 08:53:48 INFO inbound/direct[dns-in]: udp server started at 127.0.0.1:15353
+0800 2026-07-20 08:53:48 INFO sing-box started (0.00s)
+0800 2026-07-20 08:54:24 INFO [225664907 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:36834
+0800 2026-07-20 08:54:24 INFO [225664907 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:24 DEBUG [225664907 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:24 DEBUG [225664907 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:24 DEBUG [225664907 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:24 INFO [225664907 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:24 DEBUG [225664907 4ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:24 DEBUG [225664907 4ms] dns: match[1] => respond
+0800 2026-07-20 08:54:24 INFO [1319074720 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:38401
+0800 2026-07-20 08:54:24 INFO [1319074720 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:24 DEBUG [1319074720 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:24 DEBUG [1319074720 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:24 DEBUG [1319074720 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:24 ERROR [1319074720 181ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:24 DEBUG [1319074720 181ms] dns: match[1] => respond
+0800 2026-07-20 08:54:25 INFO [2804382732 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:43839
+0800 2026-07-20 08:54:25 INFO [2804382732 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:25 DEBUG [2804382732 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:25 DEBUG [2804382732 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:25 DEBUG [2804382732 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:25 INFO [2804382732 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:25 DEBUG [2804382732 3ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:25 DEBUG [2804382732 3ms] dns: match[1] => respond
+0800 2026-07-20 08:54:25 INFO [3445958183 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:43547
+0800 2026-07-20 08:54:25 INFO [3445958183 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:25 DEBUG [3445958183 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:25 DEBUG [3445958183 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:25 DEBUG [3445958183 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:25 ERROR [3445958183 186ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:25 DEBUG [3445958183 186ms] dns: match[1] => respond
+0800 2026-07-20 08:54:26 INFO [1592300138 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:59836
+0800 2026-07-20 08:54:26 INFO [1592300138 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:26 DEBUG [1592300138 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:26 DEBUG [1592300138 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:26 DEBUG [1592300138 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:26 INFO [1592300138 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:26 DEBUG [1592300138 2ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:26 DEBUG [1592300138 2ms] dns: match[1] => respond
+0800 2026-07-20 08:54:26 INFO [2368381551 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:54610
+0800 2026-07-20 08:54:26 INFO [2368381551 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:26 DEBUG [2368381551 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:26 DEBUG [2368381551 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:26 DEBUG [2368381551 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:26 ERROR [2368381551 183ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:26 DEBUG [2368381551 183ms] dns: match[1] => respond
+0800 2026-07-20 08:54:27 INFO [4197815466 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:56053
+0800 2026-07-20 08:54:27 INFO [4197815466 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:27 DEBUG [4197815466 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:27 DEBUG [4197815466 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:27 DEBUG [4197815466 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:27 INFO [4197815466 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:27 DEBUG [4197815466 2ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:27 DEBUG [4197815466 2ms] dns: match[1] => respond
+0800 2026-07-20 08:54:27 INFO [3389798323 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:46090
+0800 2026-07-20 08:54:27 INFO [3389798323 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:27 DEBUG [3389798323 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:27 DEBUG [3389798323 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:27 DEBUG [3389798323 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:27 ERROR [3389798323 188ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:27 DEBUG [3389798323 188ms] dns: match[1] => respond
+0800 2026-07-20 08:54:28 INFO [434615175 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:40035
+0800 2026-07-20 08:54:28 INFO [434615175 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:28 DEBUG [434615175 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:28 DEBUG [434615175 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:28 DEBUG [434615175 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:28 INFO [434615175 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:28 DEBUG [434615175 1ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:28 DEBUG [434615175 1ms] dns: match[1] => respond
+0800 2026-07-20 08:54:28 INFO [3977516575 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:60620
+0800 2026-07-20 08:54:28 INFO [3977516575 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:28 DEBUG [3977516575 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:28 DEBUG [3977516575 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:28 DEBUG [3977516575 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:28 ERROR [3977516575 186ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:28 DEBUG [3977516575 186ms] dns: match[1] => respond
+0800 2026-07-20 08:54:29 INFO [1304790072 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:41298
+0800 2026-07-20 08:54:29 INFO [1304790072 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:29 DEBUG [1304790072 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:29 DEBUG [1304790072 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:29 DEBUG [1304790072 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:29 INFO [1304790072 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:29 DEBUG [1304790072 1ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:29 DEBUG [1304790072 1ms] dns: match[1] => respond
+0800 2026-07-20 08:54:29 INFO [2250143740 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:37998
+0800 2026-07-20 08:54:29 INFO [2250143740 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:29 DEBUG [2250143740 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:29 DEBUG [2250143740 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:29 DEBUG [2250143740 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:29 ERROR [2250143740 187ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:29 DEBUG [2250143740 187ms] dns: match[1] => respond
+0800 2026-07-20 08:54:30 INFO [1343518884 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:51992
+0800 2026-07-20 08:54:30 INFO [1343518884 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:30 DEBUG [1343518884 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:30 DEBUG [1343518884 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:30 DEBUG [1343518884 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:30 INFO [1343518884 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:30 DEBUG [1343518884 2ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:30 DEBUG [1343518884 2ms] dns: match[1] => respond
+0800 2026-07-20 08:54:30 INFO [1368409676 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:36625
+0800 2026-07-20 08:54:30 INFO [1368409676 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:30 DEBUG [1368409676 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:30 DEBUG [1368409676 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:30 DEBUG [1368409676 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:30 ERROR [1368409676 185ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:30 DEBUG [1368409676 185ms] dns: match[1] => respond
+0800 2026-07-20 08:54:31 INFO [3985661459 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:53789
+0800 2026-07-20 08:54:31 INFO [3985661459 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:31 DEBUG [3985661459 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:31 DEBUG [3985661459 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:31 DEBUG [3985661459 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:31 INFO [3985661459 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:31 DEBUG [3985661459 1ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:31 DEBUG [3985661459 1ms] dns: match[1] => respond
+0800 2026-07-20 08:54:31 INFO [1556909890 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:34634
+0800 2026-07-20 08:54:31 INFO [1556909890 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:31 DEBUG [1556909890 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:31 DEBUG [1556909890 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:31 DEBUG [1556909890 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:31 ERROR [1556909890 187ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:31 DEBUG [1556909890 187ms] dns: match[1] => respond
+0800 2026-07-20 08:54:32 INFO [229990985 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:47374
+0800 2026-07-20 08:54:32 INFO [229990985 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:32 DEBUG [229990985 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:32 DEBUG [229990985 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:32 DEBUG [229990985 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:32 INFO [229990985 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:32 DEBUG [229990985 1ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:32 DEBUG [229990985 1ms] dns: match[1] => respond
+0800 2026-07-20 08:54:32 INFO [3732143038 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:57086
+0800 2026-07-20 08:54:32 INFO [3732143038 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:32 DEBUG [3732143038 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:32 DEBUG [3732143038 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:32 DEBUG [3732143038 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:32 ERROR [3732143038 185ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:32 DEBUG [3732143038 185ms] dns: match[1] => respond
+0800 2026-07-20 08:54:33 INFO [3456443664 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:33812
+0800 2026-07-20 08:54:33 INFO [3456443664 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:33 DEBUG [3456443664 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:33 DEBUG [3456443664 0ms] dns: exchange example.com. IN A
+0800 2026-07-20 08:54:33 DEBUG [3456443664 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:33 INFO [3456443664 0ms] outbound/shadowsocks[ss-out]: outbound connection to 127.0.0.1:2053
+0800 2026-07-20 08:54:33 DEBUG [3456443664 1ms] dns: exchanged example.com NOERROR 0
+0800 2026-07-20 08:54:33 DEBUG [3456443664 1ms] dns: match[1] => respond
+0800 2026-07-20 08:54:33 INFO [769956142 0ms] inbound/direct[dns-in]: inbound packet connection from 127.0.0.1:39560
+0800 2026-07-20 08:54:33 INFO [769956142 0ms] inbound/direct[dns-in]: inbound packet connection to 1.0.0.1:53
+0800 2026-07-20 08:54:33 DEBUG [769956142 0ms] router: match[0] port=53 => hijack-dns
+0800 2026-07-20 08:54:33 DEBUG [769956142 0ms] dns: exchange example.com. IN AAAA
+0800 2026-07-20 08:54:33 DEBUG [769956142 0ms] dns: match[0] => evaluate(remote-dns)
+0800 2026-07-20 08:54:33 ERROR [769956142 183ms] dns: exchange failed for example.com. IN AAAA: EOF
+0800 2026-07-20 08:54:33 DEBUG [769956142 183ms] dns: match[1] => respond
+0800 2026-07-20 08:54:53 TRACE close http-client
+0800 2026-07-20 08:54:53 TRACE close http-client completed (0.00s)
支持我们
- 我已经 赞助
完整性要求
- 我保证阅读了文档,了解所有我编写的配置文件项的含义,而不是大量堆砌看似有用的选项或默认值。
- 我保证提供了可以在本地重现该问题的服务器、客户端配置文件与流程,而不是一个脱敏的复杂客户端配置文件。
- 我保证提供了可用于重现我报告的错误的最简配置,而不是依赖远程服务器、TUN、图形界面客户端或者其他闭源软件。
- 我保证提供了完整的配置文件与日志,而不是出于对自身智力的自信而仅提供了部分认为有用的部分。
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by reading the TCPTransport, queryMultiplexer, ExchangeAsync, and recvLoop paths introduced by commit 3d2461f3bae3fab6537656173ab65965c41ea0a8. Run the provided client.json, server.json, and dns_server.py reproduction with two sequential dig queries, then verify that the second query no longer fails with EOF and that the alpha.47 comparison remains successful.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- go, python
- Domain
- networking
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100