Mor*_*ten 15 linux dns vpn windows-subsystem-for-linux
我已经使用 WSL Bash/Ubuntu 好几年了,但由于某种原因,这个问题最近出现了。
DNS 无法解析任何名称,包括内部名称和外部名称。我第一次重新安装 WSL 时,我认为它可以工作一天……但现在不行了,即使我重新安装。
从 Windows Store 全新安装 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:~$
Run Code Online (Sandbox Code Playgroud)
修改后/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:~$
Run Code Online (Sandbox Code Playgroud)
如您所见,一旦我断开 VPN 连接,我的名称解析就会完美无缺。但是,我全天都与 VPN 保持连接,这显然是因为它需要连接到公司资源。
我不依赖于 WSL 上的内部 DNS,虽然理想情况下也应该工作,但我确实需要外部 DNS 工作。
DNS 在本地按预期工作。我可以从 VPN NIC ping DNS 服务器,但不能从 wi-fi NIC ping DNS 服务器。我试过重新安装 WSL,也试过在/etc/resolv.conf. 尚未根据aptDNS 要求更新 WSL ...
Windows 10,版本 1909
Ubuntu 18.04,来自 Windows Store
Cisco AnyConnect VPN(选中“连接时允许访问本地 LAN”)
谁有想法?从哪儿开始?
小智 17
请参阅此处基于与 IPv6 DNS 服务器观察到的冲突的解决方法:
https://github.com/microsoft/WSL/issues/1350#issuecomment-742454940
请注意一个重要事实和解决方法:
/etc/resolv.conf当另一个网络适配器使用IPv6 DNS 服务器时,不会添加来自 VPN 连接的 DNS 服务器,这似乎会导致某种冲突(其他 IPv4 DNS 服务器被丢弃)。
检查使用 IPv6 DNS 服务器的适配器:
Get-DnsClientServerAddress -AddressFamily IPv6 | Where-Object ServerAddresses -NE "{}" | Select-Object -ExpandProperty InterfaceAlias
Run Code Online (Sandbox Code Playgroud)
获取其相关的适配器绑定
Get-NetAdapterBinding -ComponentID ms_tcpip6 | Where-Object Name -In (Get-DnsClientServerAddress -AddressFamily IPv6 | Where-Object ServerAddresses -NE "{}" | Select-Object -ExpandProperty InterfaceAlias)
Run Code Online (Sandbox Code Playgroud)
使用具有管理员权限的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
Run Code Online (Sandbox Code Playgroud)
或者,只需使用 Windows UI禁用以太网/wifi 适配器上的 IPv6 :

现在,启用 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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
Blu*_*408 13
解决。
打开或关闭 vpn 时,Ubuntu 子系统 (WSL) 无法解析企业和非企业域。
固定的。
必须创建 /etc/wsl.conf 文件并添加一个条目以在重新启动时从自动生成中终止 resolv.conf 文件。将代码块添加到 /etc/wsl.conf:
[network]
generateResolvConf = false
Run Code Online (Sandbox Code Playgroud)
然后通过以管理员身份打开 powershell 并运行命令来重新启动 ubuntu 子系统:
wsl --shutdown
Run Code Online (Sandbox Code Playgroud)
现在,重新打开 ubuntu 子系统
按顺序使用这些命令:
cd /etc
ls
Run Code Online (Sandbox Code Playgroud)
该目录应显示“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
Run Code Online (Sandbox Code Playgroud)
其中 X 是 Cisco Anyconnect VPN 适配器中配置的 DNS 地址。在网络设置中找到 Cisco VPN 适配器,右键单击 Cisco VPN 适配器并单击“属性”,现在突出显示 IPv4 并单击“属性”。然后记下首选 DNS 和备用 DNS 并将它们复制到 resolv.conf 文件中。
Y 是您的普通 IPv4 DNS 地址
现在再次从 Powershell 重新启动子系统。注意:如果这不起作用,则意味着 resolv.conf 文件再次被子系统吹走了。为了使其工作,系统必须读取 wsl.conf 文件。如果没有被读取,请尝试重新安装子系统或升级到 20.04。
过去几天我遇到了这个问题,这让我发疯。对于我的口味来说,周围的解决方案都太老套了。我创建了一个非常简单的wsl-resolv-handler.ps1(请参阅本消息后面的脚本块),它可以根据 InterfaceMetric 自动设置正确的名称服务器顺序,创建正确的搜索行。
基本上,您可以为 VPN 接口设置较低(==较高优先级)的 InterfaceMetric,如下所示(以管理员身份启动 powershell):
\n # Get a list of interfaces, Note the InterfaceIndex and InterfaceMetric for your VPN adapter\n> Get-NetIpInterface\n# For example, if your VPN adapter has InterfaceIndex 12, we\'re setting\n# the InterfaceMetric to 10, making sure 10 is lower than whatever your\n# WiFi or Ethernet adapter has\n> Set-NetIPInterface -InterfaceIndex 12 -InterfaceMetric 10 \nRun Code Online (Sandbox Code Playgroud)\n设置好接口指标后,您可以使用下面脚本块中的脚本。脚本的顶部包含如何使用的完整说明以及一些需要正确的设置(WslDistroName 和 ResolvConfFile)。
\n# Before attempting to run this script, review and/or follow the \n# following steps.\n#\n# 0. Make sure you can execute powershell scripts. Start Powershell as an\n# administrator and execute:\n#\n# Set-ExecutionPolicy RemoteSigned\n\n# 1. Make sure you disable wsl\'s broken resolv.conf handler.\n# Create /etc/wsl.conf with the following 2 lines (without the pound signs):\n#\n# [network]\n# generateResolvConf = false\n#\n# After that, make sure you issue a wsl.exe --shutdown.\n#\n# 2. Configure your WSL distro name in $WslDistroName below and make sure we\'re\n# pointing at your resolv.conf file in $ResolvConfFile. Also make sure we can write \n# to the resolv.conf file. I had to set permissions pretty broadly at 666.\n#\n# 3. Schedule this script with Task Scheduler:\n#\n# * Click Action \xe2\x80\x93> Create Task\xe2\x80\xa6\n# * Give your task a name in the General tab\n# * Click on the Triggers tab and then click New\xe2\x80\xa6\n# * In the "Begin the task" menu, choose \xe2\x80\x9cOn an event.\xe2\x80\x9d Then, choose:\n#\n# Log: Microsoft-Windows-NetworkProfile/Operational\n# Source: NetworkProfile\n# Event ID: 10000\n#\n# * Event ID 10000 is logged when you connect to a network. Add another\n# one when a disconnect would occur (Event ID 10001):\n#\n# Log: Microsoft-Windows-NetworkProfile/Operational\n# Source: NetworkProfile\n# Event ID: 10001\n#\n# * Go to the Conditions tab. Make sure it runs regardless of AC adapter\n# connected/disconnected, peruse the other options there.\n#\n# * Go to the Actions tab. Add a run script action and then:\n#\n# Program/script: powershell.exe\n# Arguments: -noprofile -file "c:\\where\\you\\stored\\wsl-resolv-handler.ps1"\n#\n\n$WslDistroName = "Debian"\n$ResolvConfFile = [string]::Format("\\\\wsl$\\{0}\\etc\\resolv.conf", $WslDistroName)\n\nfunction Convert-To-UnixLineEndings($path) {\n $oldBytes = [io.file]::ReadAllBytes($path)\n if (!$oldBytes.Length) {\n return;\n }\n [byte[]]$newBytes = @()\n [byte[]]::Resize([ref]$newBytes, $oldBytes.Length)\n $newLength = 0\n for ($i = 0; $i -lt $oldBytes.Length - 1; $i++) {\n if (($oldBytes[$i] -eq [byte][char]"`r") -and ($oldBytes[$i + 1] -eq [byte][char]"`n")) {\n continue;\n }\n $newBytes[$newLength++] = $oldBytes[$i]\n }\n $newBytes[$newLength++] = $oldBytes[$oldBytes.Length - 1]\n [byte[]]::Resize([ref]$newBytes, $newLength)\n [io.file]::WriteAllBytes($path, $newBytes)\n}\n\nFunction Pause ($message)\n{\n # Check if running Powershell ISE\n if ($psISE)\n {\n Add-Type -AssemblyName System.Windows.Forms\n [System.Windows.Forms.MessageBox]::Show("$message")\n }\n else\n {\n Write-Host "$message" -ForegroundColor Yellow\n $x = $host.ui.RawUI.ReadKey("NoEcho,IncludeKeyDown")\n }\n}\n\n$NetworkInterfaces = Get-NetIPInterface -AddressFamily IPv4 | Where-Object ConnectionState -EQ \'Connected\' | Where-Object NlMtu -LT 9001\n$DNSServerAddresses = Get-DnsClientServerAddress -AddressFamily IPv4\n$DNSClients = Get-DnsClient\n\n$Entries = $NetworkInterfaces | ForEach-Object {\n [PSCustomObject]@{\n \'InterfaceAlias\' = $_.InterfaceAlias\n \'InterfaceIndex\' = $_.InterfaceIndex\n \'InterfaceMetric\' = $_.InterfaceMetric\n \'DNSServerAddresses\' = ($DNSServerAddresses | Where-Object InterfaceIndex -EQ $_.InterfaceIndex | Where-Object AddressFamily -EQ 2).ServerAddresses\n \'DNSSuffixes\' = @(($DNSClients | Where-Object InterfaceIndex -EQ $_.InterfaceIndex).ConnectionSpecificSuffix) + @(($DNSClients).ConnectionSpecificSuffixSearchList | Out-Null)\n }\n} | Sort-Object InterfaceMetric -Unique\n\n$CommentLine = [string]::Format("# Generated by wsl-resolv-handler.ps1.")\nWrite-Output $CommentLine | Set-Content -Path $ResolvConfFile\n$SearchLine = [string]::Format("search {0}", ($Entries.DNSSuffixes -join " "))\n Write-Output $SearchLine | Add-Content -Path $ResolvConfFile\n$Entries | ForEach-Object {\n $_.DNSServerAddresses | ForEach-Object {\n $NameServerLine = [string]::Format("nameserver {0}", $_)\n Write-Output $NameServerLine | Add-Content -Path $ResolvConfFile\n }\n}\n\nConvert-To-UnixLineEndings $ResolvConfFile\n\nPause "Press any key to continue..."\nRun Code Online (Sandbox Code Playgroud)\n将上述脚本保存为wsl-resolv-handler.ps1并按照注释中的说明进行操作。祝你好运 + 玩得开心(注意,这种方法应该适用于任何类型的 VPN 或网络拓扑更改,只要您正确配置它并在 Windows 任务管理器中正确设置任务,它就可以在没有手动愚蠢的情况下工作。您不需要不需要提升权限来运行它,只要脚本可以写入/etc/resolv.conf)!
注意:我还将此答案发布到了与此最相关的 github 问题(有大量关于 wsl 的 resolv.conf 生成器损坏的 github 问题):https: //github.com/微软/WSL/issues/2884#issuecomment-928299305
\n编辑resolv.conf为仅包含 Cisco Anyconnect VPN NIC 提供的 DNS 服务器:
nameserver X.X.X.X
nameserver X.X.X.X
Run Code Online (Sandbox Code Playgroud)
现在,WSL 中的 DNS 在连接到 VPN 和断开连接时都能完美运行。
这超出了我的想象,但显然它与 Cisco Anyconnect VPN 和(分割)DNS 有关。