影评周公子 2026-02-15 05:35 采纳率: 98.9%
浏览 0
已采纳

多次失败(>5次)IP常因DNS缓存污染或本地hosts误配导致解析异常

常见问题: 某业务系统频繁出现“连接超时”或“无法访问目标服务”,经抓包发现客户端反复尝试向多个不同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 outFailed 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.114 vs @223.5.5.5 vs @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.ttlnetworkaddress.cache.negative.ttl
    系统服务resolvectl query api.example.com && resolvectl statistics查看 Cache hitsCache misses 比值是否异常高
    静态配置getent hosts api.example.com(绕过DNS,直查hosts+DNS)若返回结果与 dig 不一致,即证明 /etc/hosts 干扰

    五、解决层:分阶段清除策略与长效防护

    1. 立即止血:执行 sudo systemd-resolve --flush-caches(systemd)或 sudo systemctl restart dnsmasq(dnsmasq);Windows 运行 ipconfig /flushdns
    2. 应用隔离:JVM 启动参数强制刷新策略:-Dnetworkaddress.cache.ttl=30 -Dnetworkaddress.cache.negative.ttl=5
    3. 基础设施加固:将 resolv.conf 指向可信DNS(如 nameserver 1.1.1.1),并启用 DNSSEC(resolvectl dnssec example.com 返回 supported
    4. 自动化监控:部署 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 插件记录异常响应码(如 REFUSEDSERVFAIL)。

    ```
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

问题事件

  • 已采纳回答 2月16日
  • 创建了问题 2月15日