Appearance
CDN 资源加载失败 — /etc/hosts 硬编码 IP 失效问题
归类:网络排查 / CDN / 本地环境配置
发生时间:2026-03-06
涉及域名:assets.example-cdn.com
状态:✅ 已修复
一、问题现象
浏览器访问内部系统(如 portal.example-internal.com)时,页面白屏或样式/脚本全部加载失败。打开 DevTools → Network 面板,可以看到以下资源的请求状态均为红色错误:
https://assets.example-cdn.com/static/theme/index.css
https://assets.example-cdn.com/static/...(多个 JS/CSS/字体)错误特征:
- 请求状态均为失败(无 HTTP 状态码)
- DevTools 提示
net::ERR_CONNECTION_RESET或请求超时
二、排查过程
第一步:确认是否代理问题
查看系统代理配置(macOS):
bash
networksetup -getsecurewebproxy "Wi-Fi"
# Enabled: Yes
# Server: 127.0.0.1
# Port: 7897系统代理开启(clash 等工具监听 127.0.0.1:7897)。
尝试绕过代理直连:
bash
curl --noproxy "*" -v "https://assets.example-cdn.com/..."
# 结果:LibreSSL SSL_connect: SSL_ERROR_SYSCALL — TLS 握手失败结论:绕过代理后依然失败,排除代理干扰。
第二步:排查 DNS 解析
bash
nslookup assets.example-cdn.com # 默认 DNS
nslookup assets.example-cdn.com 114.114.114.114 # 公共 DNS
nslookup assets.example-cdn.com 8.8.8.8 # Google DNS三个 DNS 全部解析到同一个 IP:203.0.113.10
结论:DNS 解析本身没有问题,也没有被污染。
第三步:发现 /etc/hosts 硬编码
bash
grep "example-cdn" /etc/hosts
# 203.0.113.10 assets.example-cdn.com
/etc/hosts第 31 行存在一条历史记录,将assets.example-cdn.com硬绑定到203.0.113.10。
第四步:验证该 IP 是否可达
bash
ping -c 3 assets.example-cdn.com
# 100% packet loss — IP 完全不响应 ICMP
openssl s_client -connect assets.example-cdn.com:443 -servername assets.example-cdn.com </dev/null
# no peer certificate available
# SSL handshake has read 0 bytes — TLS 握手阶段直接被中断结论:203.0.113.10 这个 CDN 节点已下线/失效,TCP 可以建立连接(端口打开),但 TLS 握手阶段服务端直接断开,导致所有 HTTPS 资源无法加载。
根本原因链路
1. /etc/hosts 硬编码旧 IP
↓
2. 所有 DNS 查询被绕过,强制走 203.0.113.10
↓
3. 该节点 TLS 握手失败(服务端无证书响应)
↓
4. 浏览器资源全部加载失败 → 页面白屏三、影响范围
| 受影响项 | 说明 |
|---|---|
| 浏览器资源加载 | 所有来自 assets.example-cdn.com 的 CSS / JS / 字体全部失败 |
| curl / wget | 命令行工具下载同域名资源也失败 |
| 系统代理 | 代理无法解决,因为 IP 在 hosts 层面已被覆盖 |
| 其他 CDN 子域 | 只影响 hosts 中硬编码的域名,其他 CDN 域名不受影响 |
四、修复方式
方案:删除 hosts 中的硬编码记录
bash
# 删除 /etc/hosts 中的硬编码记录(需要 sudo 权限)
sudo sed -i '' '/assets.example-cdn.com/d' /etc/hosts
# 验证已删除
grep "example-cdn" /etc/hosts || echo "记录已删除"
# 验证 CDN 是否恢复可用
curl -I "https://assets.example-cdn.com/static/theme/index.css"修复后响应结果(正常):
HTTP/2 200
server: Tengine
content-type: text/css
cdn-from: edge
content-length: 509150五、为何 hosts 中会出现这条记录
常见原因:
| 原因 | 说明 |
|---|---|
| 历史手动绑定 | 开发或调试阶段为加速 CDN 访问,手动将当时的 CDN IP 写入 hosts |
| 工具自动写入 | 部分抓包/代理工具(如 SwitchHosts、Charles)会自动修改 hosts |
| CDN 节点轮换 | CDN 服务商节点 IP 会定期变更,旧 IP 逐渐下线 |
核心风险:hosts 中的 IP 与 CDN 动态调度机制冲突——CDN 会根据用户位置、节点健康状态自动切换 IP,但 hosts 硬编码绕过了 DNS,导致始终访问同一个(可能已失效的)节点。
六、预防建议
- 不要在 /etc/hosts 中硬编码 CDN 域名,CDN 节点 IP 是动态的,绑死 IP 有失效风险。
- 使用 SwitchHosts 等工具时,定期清理不再需要的 hosts 规则。
- 遇到 CDN 资源加载失败时,排查顺序建议:
/etc/hosts 检查 → DNS 解析检查 → IP 连通性检查 → 代理配置检查 → CDN 服务端检查- 快速排查命令:
bash
# 一键检查 /etc/hosts 中是否有该域名的硬编码
grep "<域名关键词>" /etc/hosts
# 检查 IP 是否可达
ping -c 3 <域名>
# 检查 TLS 握手是否正常
openssl s_client -connect <域名>:443 -servername <域名> </dev/null 2>&1 | head -10七、参考信息
| 项目 | 值 |
|---|---|
| 故障域名 | assets.example-cdn.com |
| 失效 IP | 203.0.113.10 |
| CDN 服务商 | 某 CDN 服务商 |
| Node.js 环境 | v20.20.0 |
| 操作系统 | macOS |
| 修复耗时 | < 5 分钟 |