Git SSH 连接异常:WSL2 DNS 劫持导致的 github.com 解析错误
Git SSH 连接异常:WSL2 DNS 劫持导致的 github.com 解析错误
问题现象
在 Windows 环境下使用 Git 通过 SSH 推送代码到 GitHub 时,突然遇到连接重置错误:
1 | $ git push |
更奇怪的是,前一天还能正常推送,今天却突然失败。
问题排查
初步诊断
首先测试 SSH 连接:
1 | $ ssh -T [email protected] |
检查远程仓库配置:
1 | $ git remote -v |
远程地址配置正确,问题不在这里。
DNS 解析异常
尝试 ping GitHub:
1 | $ ping github.com |
问题暴露:github.com 被解析到了一个内网 IP 地址(127.x.x.x 段),而不是 GitHub 的真实公网 IP(应该是 x.x.x.x 段)。
排除常见原因
按照常规思路,逐一排查:
hosts 文件:
1
type C:\Windows\System32\drivers\etc\hosts | findstr github
结果:无相关记录 ✓
端口占用:
1
netstat -ano | findstr xxx.xxx.x.x
结果:无进程监听 ✓
VPN/代理配置:
- 检查 Proxifier 规则:正常
- 检查 Git 配置:无异常
定位根本原因:WSL2
注意到系统后台运行着 WSL2(Windows Subsystem for Linux),这是一个关键线索。
WSL2 的网络架构:
- WSL2 使用虚拟网络适配器(Hyper-V 虚拟交换机)
- 有独立的虚拟 IP 地址段(通常是
172.x.x.x或127.x.x.x) - 可能拦截并重定向 Windows 的 DNS 查询
验证假设:
1 | # 关闭 WSL |
结果:github.com 被正确解析到 140.82.x.x,问题确认!
解决方案
根本原因分析
WSL2 默认会自动生成 /etc/resolv.conf 文件,其中的 DNS 配置可能与 Windows 主机冲突,导致:
- WSL 内部的 DNS 查询被转发到 Windows
- Windows 的 DNS 查询被 WSL 拦截
- 某些域名(如
github.com)被错误解析到 WSL 的虚拟网络地址
永久修复步骤
步骤 1:禁用 WSL 的自动 DNS 生成
在 WSL 终端中执行:
1 | # 编辑 WSL 配置文件 |
添加以下配置:
1 | [network] |
保存并退出(Ctrl+X → Y → Enter)。
这一步告诉 WSL 不要自动生成 DNS 配置,避免与 Windows 冲突。
步骤 2:手动配置 WSL 的 DNS
1 | # 删除自动生成的 resolv.conf |
写入可靠的公共 DNS 服务器:
1 | nameserver 1.1.1.1 |
锁定文件,防止被自动覆盖:
1 | sudo chattr +i /etc/resolv.conf |
步骤 3:重启 WSL 使配置生效
在 Windows PowerShell(管理员权限)中:
1 | wsl --shutdown |
等待几秒后,重新启动 WSL:
1 | wsl |
步骤 4:验证修复
在 WSL 中验证 DNS:
1 | cat /etc/resolv.conf |
在 Windows 中验证:
1 | ipconfig /flushdns |
技术原理
WSL2 网络模型
WSL2 与 WSL1 的网络实现完全不同:
| 特性 | WSL1 | WSL2 |
|---|---|---|
| 网络实现 | 共享 Windows 网络栈 | 独立的虚拟网络(Hyper-V) |
| IP 地址 | 与 Windows 相同 | 独立的虚拟 IP |
| DNS 解析 | 直接使用 Windows DNS | 自动生成 /etc/resolv.conf |
DNS 劫持的触发条件
- WSL2 的 DNS 服务(
systemd-resolved或类似服务)启动 - Windows 网络适配器优先级配置不当
- WSL 虚拟网络适配器的 Metric 值低于物理网卡
- DNS 查询被路由到 WSL 的虚拟 IP
为什么 generateResolvConf = false 有效?
默认情况下,WSL2 会根据 Windows 的网络配置自动生成 /etc/resolv.conf,这可能导致:
- 循环引用:WSL 的 DNS 指向 Windows,Windows 的 DNS 查询又被 WSL 拦截
- 缓存污染:错误的解析结果被缓存,持续影响后续查询
禁用自动生成后,WSL 使用固定的公共 DNS(1.1.1.1),彻底切断与 Windows DNS 的耦合。
总结
这次问题的教训:
- WSL2 是一个完整的虚拟机环境,有独立的网络栈,可能与 Windows 主机产生冲突
- DNS 劫持问题难以察觉,因为错误的解析结果看起来”合理”(能 ping 通本地地址)
- 昨天能用、今天不能用的问题,往往是系统配置变化(如 WSL 更新、网络适配器顺序变化)导致的
- 排查网络问题的正确顺序:DNS 解析 → 路由跟踪 → 防火墙规则 → 应用层配置
通过禁用 WSL 的自动 DNS 生成并手动配置可靠的公共 DNS,可以彻底解决此类问题,同时保持 WSL 和 Windows 主机的网络独立性。



