net.lookupip防不了dns污染,因其调用系统resolver(/etc/resolv.conf或windows api),完全受本地dns配置及中间劫持影响;必须用net.resolver显式指定可信dns服务器(如"1.1.1.1:53"),设prefergo:true和dial函数走udp/tcp直连,并配超时与错误判断。

直接用 net.LookupIP 无法防污染——它走系统 resolver,完全受本地 DNS 配置和中间劫持影响;真要绕过污染,必须用 net.Resolver 显式指定可信 DNS 服务器(如 "1.1.1.1:53" 或 "8.8.8.8:53"),并强制走 UDP/TCP 直连,同时配好超时与错误判断。
为什么 net.LookupIP 防不了 DNS 污染
net.LookupIP 底层调的是系统 getaddrinfo(Linux)或 GetAddrInfoW(Windows),完全依赖 /etc/resolv.conf 或网络设置里的 DNS 地址。运营商劫持、路由器 DNS 劫持、局域网中间人,都会在这一层生效——你根本没机会干预。
它不接受自定义服务器,不支持 context 超时,也不区分 UDP/TCP 协议。哪怕你本地 hosts 写了正确 IP,只要系统 resolver 被污染,net.LookupIP 就可能返回错误结果。
- 传
"example.com:443"会报*net.DNSError,Err 字段是"no such host",不是格式错,是系统 resolver 查不到 - 返回的
[]net.IP是纯地址列表,无法溯源是哪个 DNS 返回的,也没法做响应校验 - 查不到 MX/TXT/CNAME 等记录,没法验证 DNSSEC 或做辅助校验
net.Resolver 必须设 PreferGo:true + Dial 才真正生效
net.Resolver 默认不生效:即使你写了 PreferGo: true,但没提供 Dial 函数,Go 还是 fallback 到 cgo 的 getaddrinfo,等于白配。
Dial 必须是函数,不是字符串;必须返回 net.Conn;必须用 net.Dialer{Timeout: ...}.DialContext,否则连接卡死无超时。
免费 DNS 与邮件安全分析(IntoDNS.ai):包括 DNSSEC、SPF、DKIM、DMARC、MTA-STS、BIMI、SMTP STARTTLS、FCrDNS、黑名单、发件人要求及报告。
- UDP 查询公网 DNS:
network = "udp",addr = "1.1.1.1:53" - TCP 查询内网 CoreDNS:
network = "tcp",但得确认服务端允许 TCP 查询(Cloudflare 默认拒收) - 别写
net.Dial("udp", "1.1.1.1:53")——没 context,无法 cancel,goroutine 可能永久阻塞 -
KeepAlive建议设(比如30 * time.Second),长连接复用时避免频繁建连
如何让 HTTP 请求也走防污染 DNS 解析
http.Client 完全不认 net.Resolver,也不能改 http.DefaultClient 或 net.DefaultResolver。唯一办法是接管 http.Transport.DialContext。
关键点:必须用 DialContext(不是旧版 Dial),并在里面调你的 resolver.LookupHost,再用 net.Dialer.DialContext 建连。
-
LookupHost返回的是[]string(IP 字符串),需手动选 IPv4/IPv6;若后端启用 SNI,TLSConfig.ServerName得填原始域名,不能填 IP,否则证书校验失败 - HTTP 连接池默认不缓存 DNS 结果(TTL=0),如需缓存,得自己在
DialContext里加 LRU 或 TTL 控制逻辑 - 别漏
context.WithTimeout包裹LookupHost调用——net.Resolver本身没超时字段
错误判断不能只看 err != nil
DNS 查询失败不等于域名不存在,临时网络问题(UDP 丢包、防火墙拦截、DNS 服务器无响应)也会返回 error,但它是可重试的。
必须类型断言为 *net.DNSError,再用其方法区分:
-
err.(*net.DNSError).IsNotFound()→ 真的域名不存在,不用重试 -
err.(*net.DNSError).IsTemporary()→ 临时失败,建议重试(比如 UDP 查询失败后切 TCP) - 非
*net.DNSError类型的 error(如 context canceled、Dial timeout)按各自逻辑处理
防污染的核心不在“一次查准”,而在“可控路径 + 可重试 + 可验证”——net.Resolver 提供了入口,但每个环节都得亲手拧紧螺丝,漏一个就可能被绕过。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










