常见问题:
某业务系统频繁出现“连接超时”或“无法访问目标服务”,经抓包发现客户端反复尝试向多个不同IP(>5次)发起TCP连接,但均失败;进一步排查发现,这些IP与服务真实地址不符。典型表现为:`nslookup` 与 `dig` 返回结果不一致、`curl -v` 显示解析到异常IP、重启应用后短暂恢复但数小时后复现。根本原因多为——本地DNS缓存遭受污染(如运营商劫持、恶意中间设备伪造响应),或开发/运维人员误在 `/etc/hosts`(Linux/macOS)或 `C:\Windows\System32\drivers\etc\hosts`(Windows)中静态绑定过期/错误IP,且未及时清理。由于系统级DNS缓存(如systemd-resolved、dnsmasq)及应用层缓存(如JVM的`networkaddress.cache.ttl`默认永久)叠加,导致错误解析持续生效,形成“多次失败—重试—再失败”的恶性循环。
1条回答 默认 最新
远方之巅 2026-02-15 05:35关注```html一、现象层:识别“连接超时”背后的异常DNS行为
业务系统日志持续报错
Connection timed out或Failed to connect to [host]: No route to host;Wireshark/tcpdump 抓包显示客户端在3–5秒间隔内向6+个不同IP(如 192.0.2.101、203.0.113.44…)发起SYN,全部无SYN-ACK响应;curl -v https://api.example.com显示解析到非生产网段IP(如 100.64.0.10),而dig api.example.com @8.8.8.8 +short正确返回 203.208.60.123。此为典型“解析漂移”现象——同一域名在毫秒级内被解析为多个错误地址。二、验证层:交叉比对DNS解析链路的五级缓存
- 应用层:JVM 缓存(
networkaddress.cache.ttl=0可禁用,但默认为-1即永久) - 运行时层:glibc
getaddrinfo()的__res_maybe_init缓存(Linux 5.10+ 默认启用,TTL≈30s) - 系统服务层:systemd-resolved(
resolvectl statistics查缓存命中率)、dnsmasq(sudo dnsmasq --test && sudo systemctl status dnsmasq) - OS配置层:/etc/hosts 静态绑定(
grep -i "example.com" /etc/hosts)、/etc/resolv.conf nameserver 顺序 - 网络中间层:运营商DNS劫持(对比
dig @114.114.114.114vs@223.5.5.5vs@8.8.8.8结果差异)
三、根因层:DNS污染与缓存叠加的恶性循环模型
graph LR A[客户端发起HTTP请求] --> B{JVM DNS缓存查询} B -->|命中错误IP| C[直接连接失败] B -->|未命中| D[glibc getaddrinfo调用] D --> E{systemd-resolved缓存?} E -->|是| F[返回污染IP] E -->|否| G[转发至上游DNS] G --> H[遭遇ISP劫持/中间人伪造响应] H --> I[写入systemd-resolved缓存] I --> J[后续JVM/glibc均复用该错误记录] J --> C四、诊断层:标准化排查清单(含命令速查表)
层级 检测命令 关键指标 应用层 java -XshowSettings:properties -version 2>&1 | grep networkaddress确认 networkaddress.cache.ttl和networkaddress.cache.negative.ttl系统服务 resolvectl query api.example.com && resolvectl statistics查看 Cache hits与Cache misses比值是否异常高静态配置 getent hosts api.example.com(绕过DNS,直查hosts+DNS)若返回结果与 dig不一致,即证明 /etc/hosts 干扰五、解决层:分阶段清除策略与长效防护
- 立即止血:执行
sudo systemd-resolve --flush-caches(systemd)或sudo systemctl restart dnsmasq(dnsmasq);Windows 运行ipconfig /flushdns - 应用隔离:JVM 启动参数强制刷新策略:
-Dnetworkaddress.cache.ttl=30 -Dnetworkaddress.cache.negative.ttl=5 - 基础设施加固:将 resolv.conf 指向可信DNS(如
nameserver 1.1.1.1),并启用 DNSSEC(resolvectl dnssec example.com返回supported) - 自动化监控:部署 Prometheus + Blackbox Exporter,对关键域名做
dns_probe_success == 0告警,并关联dns_probe_dns_server标签定位污染源
六、预防层:面向SRE的DNS治理规范
建立《DNS变更双签制》:任何
```/etc/hosts修改需经开发+运维双人审批并提交Git审计;在CI/CD流水线中嵌入dnscheck工具(如 dnscheck),对部署前镜像执行host -t A api.example.com断言;Kubernetes集群统一使用 CoreDNS 配置forward . 1.1.1.1 8.8.8.8并开启log插件记录异常响应码(如REFUSED、SERVFAIL)。本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报- 应用层:JVM 缓存(