更换DNS后还是被污染?可能是本地缓存没清干净!
遇到DNS污染,很多人的第一反应是把DNS服务器换成公共DNS——8.8.8.8、1.1.1.1、223.5.5.5。换完之后满怀期待地刷新页面,结果发现该打不开还是打不开,该跳广告还是跳广告。
这时候大部分人开始怀疑“是不是换的DNS也被污染了”,然后陷入反复换DNS的死循环。其实问题往往出在一个被忽略的环节:本地缓存没有清理干净。你的电脑、路由器、甚至浏览器里,可能还存着之前被污染的错误解析记录。换了DNS,系统还是在用旧缓存,新DNS根本没机会发挥作用。
这篇文章把DNS缓存的分布层级和清理流程讲清楚,解决“换了DNS还是被污染”的问题。
先理解:DNS缓存存在哪些地方
DNS解析结果不是只存在一个地方。从你的浏览器到目标服务器,中间每一个环节都可能缓存解析记录:
浏览器缓存:Chrome、Edge、Firefox都会缓存DNS解析结果,有自己的TTL机制。浏览器缓存优先级高于操作系统缓存。
操作系统缓存:Windows的DNS Client服务、macOS的mDNSResponder、Linux的systemd-resolved或nscd,都会缓存解析结果。
路由器缓存:家用路由器通常内置DNS转发功能,也会缓存解析结果。如果路由器本身用的就是被污染的DNS,换电脑DNS也没用。
运营商递归DNS缓存:运营商的DNS服务器会缓存解析结果。如果上游权威记录更新了,运营商的缓存可能还没过期。
应用级缓存:Java应用、Node.js程序、Docker容器内部都可能维护自己的DNS缓存。
关键点是:换DNS只改变了“查询路径”,但没有清掉之前已经缓存的错误结果。 系统在缓存有效期内,根本不会去查新DNS,直接返回旧结果。
第一步:确认问题——换DNS后到底是谁在解析
在清理缓存之前,先用工具确认当前解析到底走的是哪条路。
在Windows上:
nslookup 你的域名.com
输出会显示当前使用的DNS服务器和解析结果。如果显示的服务器地址还是你换之前的旧DNS,说明系统没有更新DNS配置;如果服务器地址是新DNS但结果依然是错误IP,说明缓存没清。
在Linux/macOS上:
dig 你的域名.com
查看输出中的SERVER字段,确认实际使用的是哪个DNS服务器。同时对比dig @8.8.8.8 你的域名.com +short的结果。如果两者不一致,说明本地DNS还在返回缓存中的旧记录。
判断标准:如果你的系统在换了DNS之后,仍然返回与公共DNS不同的结果,那么大概率是缓存问题,而不是新DNS被污染。
第二步:清理浏览器缓存
浏览器缓存是DNS缓存的第一道关卡,也是最容易被忽略的。
Chrome/Edge:
打开设置 → 隐私和安全 → 清除浏览数据,勾选“缓存的图片和文件”,时间范围选择“所有时间”,点击清除。
但浏览器还有一个隐藏的DNS缓存,需要用特殊方式清理:
在Chrome地址栏输入:
chrome://net-internals/#dns
点击“Clear host cache”按钮。这个操作专门清空Chrome内部的DNS缓存,比清浏览数据更精准。
在Edge地址栏输入:
edge://net-internals/#dns
同样点击“Clear host cache”。
Firefox:Firefox的DNS缓存可以通过about:networking#dns页面查看,但没有直接清空按钮。最简单的方法是重启浏览器,或者关闭DNS缓存功能(在about:config里把network.dnsCacheExpiration设为0)。
第三步:清理操作系统DNS缓存
浏览器缓存清完后,再清系统的。
Windows
打开命令提示符(以管理员身份运行):
ipconfig /flushdns
输出 Successfully flushed the DNS Resolver Cache 表示清理成功。
但Windows还有一个隐藏的缓存——NetBIOS缓存。如果ipconfig /flushdns后问题依旧,再执行:
nbtstat -R
这会清空NetBIOS名称缓存。
macOS
根据macOS版本不同,命令略有差异:
macOS 10.11及以上:
sudo dscacheutil -flushcache
sudo killall -HUP mDNSResponder
macOS 10.10:
sudo discoveryutil mdnsflushcache
sudo discoveryutil udnsflushcaches
执行后系统会提示mDNSResponder被重启,说明缓存已清。
Linux
Linux的DNS缓存取决于你用的解析服务:
使用systemd-resolved(Ubuntu 18.04+默认):
sudo systemd-resolve --flush-caches
验证缓存是否已清空:
sudo systemd-resolve --statistics
输出中Cache部分的Current Cache Size应该为0。
使用nscd:
sudo systemctl restart nscd
使用dnsmasq:
sudo systemctl restart dnsmasq
第四步:清理路由器缓存
如果你用的是家用路由器,它同样会缓存DNS解析结果。这一步经常被忽略,但恰恰是“换电脑DNS没用”的罪魁祸首。
方法一:重启路由器
最简单粗暴但有效。拔掉电源等30秒再插上,路由器缓存会被清空。
方法二:登录路由器管理后台
通常地址是192.168.1.1或192.168.0.1。登录后在系统工具或高级设置里找到“清除DNS缓存”或“重启DNS服务”选项。
关键操作:在路由器后台把DNS服务器地址改成你想要的公共DNS(比如8.8.8.8和1.1.1.1)。这样路由器自己也会用新DNS,而不是继续用运营商默认的。
注意:部分光猫自带路由功能,DNS也在光猫层面缓存。如果重启路由器无效,尝试重启光猫。
第五步:清理应用级缓存
如果你的问题出现在特定应用里,而不是所有上网场景,那问题可能出在应用自己的DNS缓存上。
Docker容器:容器内部的DNS解析走的是Docker的嵌入式DNS服务器,默认会缓存解析结果。重启容器可以清空:
docker restart 容器名
如果容器使用的是自定义网络,可以重建网络:
docker network disconnect 网络名 容器名
docker network connect 网络名 容器名
Java应用:Java的InetAddress类会缓存DNS解析结果,默认TTL是永久(-1),除非设置了networkaddress.cache.ttl。修改$JAVA_HOME/jre/lib/security/java.security文件,设置:
networkaddress.cache.ttl=60
networkaddress.cache.negative.ttl=10
Node.js应用:Node.js默认不缓存DNS,但如果用了dns.lookup的cache选项或第三方库,需要重启应用来清缓存。
第六步:如果还是不行——更深层的排查
如果浏览器、系统、路由器、应用缓存全部清理完毕,换了DNS还是被污染,那问题可能不在本地缓存,而是以下几种情况:
1. 新DNS确实也被污染
部分公共DNS在某些网络环境下同样会被污染。测试方法:用dig @8.8.8.8 域名和dig @1.1.1.1 域名对比结果。如果多个公共DNS返回的IP也不一致,说明污染发生在更上游的网络层。
2. hosts文件里有静态绑定
检查C:\Windows\System32\drivers\etc\hosts(Windows)或/etc/hosts(Linux/macOS),看里面有没有写死目标域名的IP。hosts文件的优先级高于DNS,即使换了DNS也会被hosts里的记录覆盖。
3. 系统或路由器被篡改
某些恶意软件会修改系统的DNS设置或路由器的DNS配置。检查系统DNS设置是否被改回了运营商DNS,检查路由器后台的DNS配置有没有被篡改。
4. 使用加密DNS(DoH/DoT)
如果污染持续存在,可以考虑使用加密DNS。DoH(DNS over HTTPS)和DoT(DNS over TLS)把DNS查询加密,中间节点无法篡改。Chrome、Firefox都内置了DoH功能,可以在设置里开启。
完整清理流程总结
换DNS后仍被污染的排查顺序:
- 清浏览器缓存:Chrome/Edge用chrome://net-internals/#dns清host cache
- 清系统缓存:Windows用ipconfig /flushdns,macOS用dscacheutil+killall,Linux用systemd-resolve --flush-caches
- 清路由器缓存:重启路由器,并在后台把DNS改成公共DNS
- 清应用缓存:重启Docker容器、Java应用、Node.js服务
- 检查hosts文件:确认没有静态绑定覆盖DNS
- 验证清理效果:用nslookup或dig对比本地和公共DNS的解析结果
- 如果还不行:检查新DNS是否被污染、系统是否被篡改,考虑启用DoH
缓存清理的核心逻辑是:DNS解析结果在多个层级都有缓存,只改一个地方不够,需要从浏览器到系统到路由器逐层清理。很多时候不是新DNS不生效,而是旧缓存还在“挡路”。把缓存清干净,问题往往就解决了。
CN
EN