我已经使用 WSL Bash/Ubuntu 几年了,但由于某种原因,最近出现了这个问题。
DNS 无法解析任何内部和外部名称。我第一次重新安装 WSL 时,我认为它有效,一天......但不再有效,即使我重新安装。
从 Windows 应用商店全新安装 Ubuntu 18.04:
user@hostname:~$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, remove this line.
nameserver <DNS server from wi-fi NIC 1>
nameserver <DNS server from wi-fi NIC 2>
nameserver <DNS server from ethernet 2 (VPN) NIC 1>
search anyconnect.local
user@hostname:~$ ping google.com -c 1
ping: google.com: Name or service not known
user@hostname:~$ ping 8.8.8.8 -c 1
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=16.1 ms
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 16.197/16.197/16.197/0.000 ms
user@hostname:~$ dig +short google.com
user@hostname:~$ dig +short @8.8.8.8 google.com
user@hostname:~$
修改后/etv/resolv.conf
:
user@hostname:~$ dig +short google.com
user@hostname:~$ cat /etc/resolv.conf
search <internal-domain>.local
search anyconnect.local
nameserver <DNS server from wi-fi NIC 1>
nameserver <DNS server from wi-fi NIC 2>
nameserver <DNS server from ethernet 2 (VPN) NIC 1>
nameserver <DNS server from ethernet 2 (VPN) NIC 2>
nameserver 8.8.8.8
nameserver 8.8.4.4
user@hostname:~$ ls -la /etc/resolv.conf
-rw-r--r-- 1 root root 167 May 28 09:18 /etc/resolv.conf
user@hostname:~$ ping google.com -c 1
ping: google.com: Name or service not known
user@hostname:~$ ping 8.8.8.8 -c 1
PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.
64 bytes from 8.8.8.8: icmp_seq=1 ttl=54 time=17.0 ms
--- 8.8.8.8 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 17.045/17.045/17.045/0.000 ms
# disconnected VPN
user@hostname:~$ dig +short google.com
172.217.21.142
user@hostname:~$ ping google.com -c 1
PING google.com (172.217.21.142) 56(84) bytes of data.
64 bytes from arn11s02-in-f14.1e100.net (172.217.21.142): icmp_seq=1 ttl=53 time=17.4 ms
--- google.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 17.445/17.445/17.445/0.000 ms
user@hostname:~$ dig +short google.com
172.217.21.142
# connected VPN
user@hostname:~$ dig +short google.com
user@hostname:~$ ping google.com -c 1
ping: google.com: Name or service not known
user@hostname:~$
正如您所看到的,一旦我断开 VPN,名称解析就可以完美运行。然而,我一整天都保持连接到 VPN,显然是因为它需要连接到公司资源。
我不依赖于 WSL 上的内部 DNS,尽管理想情况下这也应该起作用,但我确实需要外部 DNS 工作。
DNS 在本地按预期工作。我可以从 VPN 网卡 ping 通 DNS 服务器,但不能从 wi-fi 网卡 ping 通 DNS 服务器。我尝试过重新安装 WSL,也尝试过仅使用 Google 的名称服务器/etc/resolv.conf
。尚未更新 WSL,因为apt
需要 DNS...
Windows 10 版本 1909
Ubuntu 18.04(来自 Windows 应用商店)
Cisco AnyConnect VPN(选中“连接时允许访问本地 LAN”)
有人有主意吗?从哪儿开始?
答案1
解决。
Ubuntu 子系统 (WSL) 在打开或关闭 VPN 时无法解析公司和非公司域。
固定的。
必须创建 /etc/wsl.conf 文件并添加一个条目以终止重新启动时自动生成的 resolv.conf 文件。将代码块添加到/etc/wsl.conf:
[network]
generateResolvConf = false
然后以管理员身份打开 powershell 并运行命令来重新启动 ubuntu 子系统:
wsl --shutdown
现在,重新打开 ubuntu 子系统
按顺序使用这些命令:
cd /etc
ls
该目录应显示“resolv.conf”文件(这是一个符号链接)。该链接现在应该是红色的,表明该链接没有通向任何地方。删除resolv.conf链接并创建新的/etc/resolv.conf文件
在新的resolv.conf文件中,写入以下代码块
search your.domain.com
nameserver x.x.x.x
nameserver x.x.x.x
nameserver y.y.y.y
其中 X 是 Cisco Anyconnect VPN 适配器中配置的 DNS 地址。在网络设置中找到 Cisco VPN 适配器,右键单击 Cisco VPN 适配器并单击“属性”,现在突出显示 IPv4 并单击“属性”。然后记下首选 DNS 和备用 DNS 并将其复制到 resolv.conf 文件中。
Y 是您的普通 IPv4 DNS 地址
现在再次从 Powershell 重新启动子系统。注意:如果这不起作用,则意味着 resolv.conf 文件再次被子系统吹走。为了使其工作,系统必须读取 wsl.conf 文件。如果未读取,请尝试重新安装子系统或升级到 20.04。
答案2
请参阅此处根据与 IPv6 DNS 服务器观察到的冲突提出的解决方法:
https://github.com/microsoft/WSL/issues/1350#issuecomment-742454940
请注意一个重要事实和解决方法:
/etc/resolv.conf
当另一个网络适配器正在使用时,不会添加来自 VPN 连接的 DNS 服务器IPv6 DNS 服务器,这似乎会导致某种冲突(额外的 IPv4 DNS 服务器被丢弃)。
检查使用 IPv6 DNS 服务器的适配器:
Get-DnsClientServerAddress -AddressFamily IPv6 | Where-Object ServerAddresses -NE "{}" | Select-Object -ExpandProperty InterfaceAlias
获取其相关的适配器绑定
Get-NetAdapterBinding -ComponentID ms_tcpip6 | Where-Object Name -In (Get-DnsClientServerAddress -AddressFamily IPv6 | Where-Object ServerAddresses -NE "{}" | Select-Object -ExpandProperty InterfaceAlias)
使用 Powershell 为每个适配器绑定(或直接为所有适配器)禁用 IPv6具有管理员权限:
Disable-NetAdapterBinding -Name "Wi-Fi" -ComponentID ms_tcpip6 -PassThru
Disable-NetAdapterBinding -Name "Network Bridge" -ComponentID ms_tcpip6 -PassThru
...
Disable-NetAdapterBinding -Name "*" -ComponentID ms_tcpip6 -PassThru
或者,简单地在以太网/wifi 适配器上禁用 IPv6使用 Windows 用户界面:
现在,启用 VPN 连接时可以正确添加名称服务器,禁用 VPN 时可以正确删除名称服务器。
连接 VPN 后:
$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 192.168.1.1
nameserver xx.xx.xx.x1 # obfuscated company dns
nameserver xx.xx.xx.x2 # obfuscated company dns
search home
VPN 断开连接时:
$ cat /etc/resolv.conf
# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 192.168.1.1
search home
答案3
过去几天我遇到了这个问题,这让我发疯。对于我的口味来说,周围的解决方案都太老套了。我创建了一个非常简单的wsl-resolv-handler.ps1
(请参阅本消息后面的脚本块),它可以根据 InterfaceMetric 自动设置正确的名称服务器顺序,创建正确的搜索行。
基本上,您可以为 VPN 接口设置较低(==较高优先级)的 InterfaceMetric,如下所示(以管理员身份启动 powershell):
# Get a list of interfaces, Note the InterfaceIndex and InterfaceMetric for your VPN adapter
> Get-NetIpInterface
# For example, if your VPN adapter has InterfaceIndex 12, we're setting
# the InterfaceMetric to 10, making sure 10 is lower than whatever your
# WiFi or Ethernet adapter has
> Set-NetIPInterface -InterfaceIndex 12 -InterfaceMetric 10
设置好接口指标后,您可以使用下面脚本块中的脚本。脚本的顶部包含如何使用的完整说明以及一些需要正确的设置(WslDistroName 和 ResolvConfFile)。
# Before attempting to run this script, review and/or follow the
# following steps.
#
# 0. Make sure you can execute powershell scripts. Start Powershell as an
# administrator and execute:
#
# Set-ExecutionPolicy RemoteSigned
# 1. Make sure you disable wsl's broken resolv.conf handler.
# Create /etc/wsl.conf with the following 2 lines (without the pound signs):
#
# [network]
# generateResolvConf = false
#
# After that, make sure you issue a wsl.exe --shutdown.
#
# 2. Configure your WSL distro name in $WslDistroName below and make sure we're
# pointing at your resolv.conf file in $ResolvConfFile. Also make sure we can write
# to the resolv.conf file. I had to set permissions pretty broadly at 666.
#
# 3. Schedule this script with Task Scheduler:
#
# * Click Action –> Create Task…
# * Give your task a name in the General tab
# * Click on the Triggers tab and then click New…
# * In the "Begin the task" menu, choose “On an event.” Then, choose:
#
# Log: Microsoft-Windows-NetworkProfile/Operational
# Source: NetworkProfile
# Event ID: 10000
#
# * Event ID 10000 is logged when you connect to a network. Add another
# one when a disconnect would occur (Event ID 10001):
#
# Log: Microsoft-Windows-NetworkProfile/Operational
# Source: NetworkProfile
# Event ID: 10001
#
# * Go to the Conditions tab. Make sure it runs regardless of AC adapter
# connected/disconnected, peruse the other options there.
#
# * Go to the Actions tab. Add a run script action and then:
#
# Program/script: powershell.exe
# Arguments: -noprofile -file "c:\where\you\stored\wsl-resolv-handler.ps1"
#
$WslDistroName = "Debian"
$ResolvConfFile = [string]::Format("\\wsl$\{0}\etc\resolv.conf", $WslDistroName)
function Convert-To-UnixLineEndings($path) {
$oldBytes = [io.file]::ReadAllBytes($path)
if (!$oldBytes.Length) {
return;
}
[byte[]]$newBytes = @()
[byte[]]::Resize([ref]$newBytes, $oldBytes.Length)
$newLength = 0
for ($i = 0; $i -lt $oldBytes.Length - 1; $i++) {
if (($oldBytes[$i] -eq [byte][char]"`r") -and ($oldBytes[$i + 1] -eq [byte][char]"`n")) {
continue;
}
$newBytes[$newLength++] = $oldBytes[$i]
}
$newBytes[$newLength++] = $oldBytes[$oldBytes.Length - 1]
[byte[]]::Resize([ref]$newBytes, $newLength)
[io.file]::WriteAllBytes($path, $newBytes)
}
Function Pause ($message)
{
# Check if running Powershell ISE
if ($psISE)
{
Add-Type -AssemblyName System.Windows.Forms
[System.Windows.Forms.MessageBox]::Show("$message")
}
else
{
Write-Host "$message" -ForegroundColor Yellow
$x = $host.ui.RawUI.ReadKey("NoEcho,IncludeKeyDown")
}
}
$NetworkInterfaces = Get-NetIPInterface -AddressFamily IPv4 | Where-Object ConnectionState -EQ 'Connected' | Where-Object NlMtu -LT 9001
$DNSServerAddresses = Get-DnsClientServerAddress -AddressFamily IPv4
$DNSClients = Get-DnsClient
$Entries = $NetworkInterfaces | ForEach-Object {
[PSCustomObject]@{
'InterfaceAlias' = $_.InterfaceAlias
'InterfaceIndex' = $_.InterfaceIndex
'InterfaceMetric' = $_.InterfaceMetric
'DNSServerAddresses' = ($DNSServerAddresses | Where-Object InterfaceIndex -EQ $_.InterfaceIndex | Where-Object AddressFamily -EQ 2).ServerAddresses
'DNSSuffixes' = @(($DNSClients | Where-Object InterfaceIndex -EQ $_.InterfaceIndex).ConnectionSpecificSuffix) + @(($DNSClients).ConnectionSpecificSuffixSearchList | Out-Null)
}
} | Sort-Object InterfaceMetric -Unique
$CommentLine = [string]::Format("# Generated by wsl-resolv-handler.ps1.")
Write-Output $CommentLine | Set-Content -Path $ResolvConfFile
$SearchLine = [string]::Format("search {0}", ($Entries.DNSSuffixes -join " "))
Write-Output $SearchLine | Add-Content -Path $ResolvConfFile
$Entries | ForEach-Object {
$_.DNSServerAddresses | ForEach-Object {
$NameServerLine = [string]::Format("nameserver {0}", $_)
Write-Output $NameServerLine | Add-Content -Path $ResolvConfFile
}
}
Convert-To-UnixLineEndings $ResolvConfFile
Pause "Press any key to continue..."
将上述脚本保存为wsl-resolv-handler.ps1
并按照注释中的说明进行操作。祝你好运 + 玩得开心(注意,这种方法应该适用于任何类型的 VPN 或网络拓扑更改,只要您正确配置它并在 Windows 任务管理器中正确设置任务,它就可以在没有手动愚蠢的情况下工作。您不需要提升权限才能运行它,只要脚本可以写入/etc/resolv.conf
)!
注意:我还在此处发布了对此最相关的 github 问题的答案(有大量关于 wsl 的 resolv.conf 生成器损坏的 github 问题):https://github.com/Microsoft/WSL/issues/2884#issuecomment-928299305
答案4
这对我有用,所以希望它能减轻其他人的挫败感。
创建/etc/wsl.conf
[network]
generateResolvConf = false
删除或备份 /etc/resolv.conf
sudo rm -f /etc/resolv.conf
从命令提示符重新启动 wsl
wsl --shutdown
启动一个新的 bash 会话,DNS 解析应该与主机上完全一样。