Skip to content

Instantly share code, notes, and snippets.

@coltenkrauter
Last active May 29, 2025 14:20
Show Gist options
  • Save coltenkrauter/608cfe02319ce60facd76373249b8ca6 to your computer and use it in GitHub Desktop.
Save coltenkrauter/608cfe02319ce60facd76373249b8ca6 to your computer and use it in GitHub Desktop.
Fix DNS resolution in WSL2

Permanent WSL DNS Fix (WSL 2.2.1+)

If you're encountering ping github.com failing inside WSL with a Temporary failure in name resolution, you're not alone — this has been a long-standing issue, especially when using VPNs or corporate networks.

This issue is now fixed robustly with DNS tunneling, which preserves dynamic DNS behavior and avoids limitations like WSL’s former hard cap of 3 DNS servers in /etc/resolv.conf.

DNS tunneling is enabled by default in WSL version 2.2.1 and later, meaning that if you're still seeing DNS resolution issues, the first and most effective fix is simply to upgrade WSL. Upgrading WSL updates the WSL platform itself, but does not affect your installed Linux distributions, apps, or files.

To upgrade WSL, follow these steps,

# Run all of the following in a Windows terminal (PowerShell, Command Prompt, etc.)

# 1. Check your current WSL version
wsl --version

# 2. Close all open *WSL windows* — any Linux terminals running via WSL (Ubuntu, Debian, etc.)

# 3. Shut down the WSL subsystem
wsl --shutdown

# 4. Upgrade WSL
wsl --upgrade

# 5. Verify the upgrade was successful (version should now be >= 2.2.1)
wsl --version

# 6. Open your WSL terminal and test
ping github.com

# 🎉 If it works, drop a comment on this Gist and tell us how happy you are.

If needed, explicitly enable tunneling by creating (source):

# C:\Users\<YourUsername>\.wslconfig
[wsl2]
dnsTunneling=true

That’s it. No more messing with /etc/resolv.conf. No more weird hacks!


🧟 Previous Workarounds (for WSL < 2.2.1 or locked-down systems)

Preserved for historical transparency and for users unable to upgrade WSL.

# In WSL
cd /etc
echo "[network]" | sudo tee wsl.conf
echo "generateResolvConf = false" | sudo tee -a wsl.conf

# Back in Windows
wsl --terminate <DistroName>  # or use wsl --shutdown

# Back in WSL
sudo rm -f /etc/resolv.conf
echo "nameserver 1.1.1.1" | sudo tee /etc/resolv.conf
echo "nameserver 8.8.8.8" | sudo tee -a /etc/resolv.conf
sudo chattr +i /etc/resolv.conf

If you're using a VPN like Cisco AnyConnect:

Get-NetAdapter | Where-Object { $_.InterfaceDescription -Match "Cisco AnyConnect" } | Set-NetIPInterface -InterfaceMetric 6000

🙌 Credit & Sources

Big thanks to,


If you're still using manual resolv.conf hacks in 2024+, you're solving a problem that's already been solved.

@coltenkrauter
Copy link
Author

coltenkrauter commented Aug 30, 2022

Awesome, thanks for sharing.
I am no longer using WSL2 – please let me know if you'd like me to update the gist or add any comments that might help others out.

@plawson
Copy link

plawson commented Aug 31, 2022

[boot]
command = "printf 'nameserver 8.8.8.8\nnameserver 4.4.4.4' > /etc/resolve.conf"

This worked for me on Windows 11

@chujiangke
Copy link

Add this to the /etc/wsl.conf file:

[boot]
command = "printf 'nameserver 8.8.8.8\nnameserver 4.4.4.4' > /etc/resolve.conf"

This worked for me on Windows 11

@giumax87
Copy link

The solution proposed works but I prefere to leave the resolv.conf self generated and add a rule to firewall.
Using powershell:
New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

To get the InterfaceAlias use ipconfig /all

@nikzanda
Copy link

nikzanda commented Oct 9, 2022

Original resolution worked for on Windows 11

@jamezrin
Copy link

The solution proposed works but I prefere to leave the resolv.conf self generated and add a rule to firewall. Using powershell: New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

To get the InterfaceAlias use ipconfig /all

This worked for me

@dpraul
Copy link

dpraul commented Oct 19, 2022

The solution proposed works but I prefere to leave the resolv.conf self generated and add a rule to firewall. Using powershell: New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

To get the InterfaceAlias use ipconfig /all

Another vote for this one! This method is necessary if you have local DNS rules that you want to share with WSL - if you change the nameserver to an external DNS like 8.8.8.8, it will bypass your local DNS entirely. By using the Windows network interface as a nameserver, WSL will share the local DNS with Windows.

@pauloch8
Copy link

The solution proposed works but I prefere to leave the resolv.conf self generated and add a rule to firewall. Using powershell: New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

To get the InterfaceAlias use ipconfig /all

Worked for internet domains, but not for intranet when connected into VPN. Does anyone know why?

@andi-blafasl
Copy link

The solution proposed works but I prefere to leave the resolv.conf self generated and add a rule to firewall. Using powershell: New-NetFirewallRule -DisplayName "WSL" -Direction Inbound -InterfaceAlias "vEthernet (WSL)" -Action Allow

To get the InterfaceAlias use ipconfig /all

Thist work for me for internet and internal corporate names over VPN. But you have to use FQDNs inside WSL2 because the distribution does not know a dns search domain.

@apodworny
Copy link

The "recent solution" worked for me, thanks!

@gavinn212
Copy link

Is there any way to automate that? Now I need to run Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "Cisco AnyConnect"} | Set-NetIPInterface -InterfaceMetric 6000 every time I connect VPN. Thanks for helping.

@amegbor
Copy link

amegbor commented Nov 4, 2022

Is there any way to automate that? Now I need to run Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "Cisco AnyConnect"} | Set-NetIPInterface -InterfaceMetric 6000 every time I connect VPN. Thanks for helping.

see this https://gist.github.com/pyther/b7c03579a5ea55fe431561b502ec1ba8

@mikeblakeuk
Copy link

Warning. I cloned the wsl2-dns-fix-config repo in windows so the script had windows line endings. After running the run.sh, i ended up in a right mess
image

@johnorourke
Copy link

Disabling and Re-enabling the WiFi adapter in Windows worked for me - there must be something which refreshes WSL2's networking state after a change of network in Windows. Like other commenters, this only seemed to happen after some mix of VPN connect/disconnect and wifi connect/disconnect.

@janban-outlook
Copy link

This works, as long as I stay home. But my DNS settings are different in the office.
Of course I could use 1.1.1.1 or 8.8.8.8, but then I am going around my Pihole at home.

@BDisp
Copy link

BDisp commented Dec 2, 2022

The first solution work well to me. I would like give my opinion about this. On Ubuntu I did all as the instruction.
On Debian I created the wsl.conf file with only the bellow, as suggested in the resolv.conf comments:

[network]
generateResolvConf = false

In the resolv.conf file I only changed the nameserver and added a secondary nameserver.
After restart Debian I tried do a sudo apt update which run very fast but with error return by the debian site. I tried to open the resolv.conf file but it's not exist anymore. So my tought is despite it not recreating the resolv.conf file, WSL need him to get the dns server. The sudo chattr -f +i /etc/resolv.conf command do the trick by avoiding the resolv.conf file been deleted.
But I didn't done the last command at bellow and it also working well as expected.
Get-NetAdapter | Where-Object {$_.InterfaceDescription -Match "Cisco AnyConnect"} | Set-NetIPInterface -InterfaceMetric 6000
So I would to ask what the above command really do?
By the way, in my machine the InterfaceMetric is 5000 and not 6000.
*Edit
Sorry, I made confusion about this. I see that is only to list the connections where having "Cisco AnyConnect".

Edit:
In pwsh the command to get the ip's address is:
(Get-NetAdapter | Get-DnsClientServerAddress).ServerAddresses

@TR0N-ZEN
Copy link

TR0N-ZEN commented Dec 6, 2022

I fixed it by setting my network in windows to private isntead of public.

@MiguelAnia
Copy link

MiguelAnia commented Dec 7, 2022

Using wsl-vpnkit is a better solution: https://github.com/sakai135/wsl-vpnkit
It resolves the DNS resolution shenanigans, while also allowing connectivity from the WSL distros through VPN, + between Windows host and distros.

@ttigori
Copy link

ttigori commented Jan 12, 2023

The recent solution works perfectly, Thanks !

@izznfkhrlislm
Copy link

Disabling and Re-enabling the WiFi adapter in Windows worked for me - there must be something which refreshes WSL2's networking state after a change of network in Windows. Like other commenters, this only seemed to happen after some mix of VPN connect/disconnect and wifi connect/disconnect.

Surprisingly, this one's worked for me. After some desperate attempt to edit /etc/resolv.conf and adding new firewall rule in PowerShell like what @giumax87 suggests 😅

@yiqiangjizhang
Copy link

sudo touch /etc/resolv.conf
chmod 777 /etc/resolv.conf
printf 'nameserver 8.8.8.8\nnameserver 4.4.4.4' > /etc/resolv.conf

This worked for me

@jangrewe
Copy link

jangrewe commented Feb 3, 2023

That's all you need:

echo -e "[network]\ngenerateResolvConf = false\n" | sudo tee /etc/wsl.conf
echo -e "nameserver 8.8.8.8\n" | sudo tee /etc/resolv.conf

No reboots, no restarts, no line-by-line appending, no messing with non-existent Cisco AnyConnect interfaces. Just those two lines and you're good to go.

Again, this is Linux, not Windows. You don't need to reboot/restart just because you changed your nameserver...

@itsTyrion
Copy link

no change, name resolution still takes like 5 SECONDS. WSL1 AND 2

@kingofwe86
Copy link

After usual windows 11 update:
KB2267602 (1.381.3293.0)

custom resolv.conf solution with Google DNS configured worked for me.
firewall solution (that i preferred in order not to alter the configuration of the wsl) didn't work.

@yiqiangjizhang
Copy link

echo -e "[network]\ngenerateResolvConf = false\n" | sudo tee /etc/wsl.conf
echo -e "nameserver 8.8.8.8\n" | sudo tee /etc/resolv.conf

I used this in the terminal and it worked like a charm! Thanks. I hope I do not have to execute this command every time I use github. Do you know if it is one-time use? or should I run it after executing whenever I reboot my machine?

@BDisp
Copy link

BDisp commented Feb 10, 2023

echo -e "[network]\ngenerateResolvConf = false\n" | sudo tee /etc/wsl.conf
echo -e "nameserver 8.8.8.8\n" | sudo tee /etc/resolv.conf

I used this in the terminal and it worked like a charm! Thanks. I hope I do not have to execute this command every time I use github. Do you know if it is one-time use? or should I run it after executing whenever I reboot my machine?

After the above command is needed to run sudo chattr -f +i /etc/resolv.conf, otherwise the resolv.conf file will be deleted after reboot. See my comment above.

@yiqiangjizhang
Copy link

echo -e "[network]\ngenerateResolvConf = false\n" | sudo tee /etc/wsl.conf
echo -e "nameserver 8.8.8.8\n" | sudo tee /etc/resolv.conf

I used this in the terminal and it worked like a charm! Thanks. I hope I do not have to execute this command every time I use github. Do you know if it is one-time use? or should I run it after executing whenever I reboot my machine?

After the above command is needed to run sudo chattr +i resolv.conf, otherwise the resolv.conf file will be deleted after reboot. See my comment above.

I have the following error when using that command: chattr: No such file or directory while trying to stat resolv.conf then I used this sudo chattr -f +i /etc/resolv.conf and somehow worked. Not sure if it is the correct way

@BDisp
Copy link

BDisp commented Feb 10, 2023

Sorry I didn't write the correct path. Without the -f option it didn't worked?

Edit:
The -f (force) flag is really needed if we want to make all the process at once in the same instance, otherwise this error is raised chattr: Operation not supported while reading flags on /etc/resolv.conf. The -f isn't needed if we exit the distro without executing the chattr command and reopen again, we will find that the /etc/resolv.conf was deleted. Then we must recreate it again with the nameserver and in this case the -f isn't needed. So, my advice is doing all this at once before close the distro by using the -f flag.

@yiqiangjizhang
Copy link

Sorry I didn't write the correct path. Without the -f option it didn't worked?

With the '-f it seem to have worked. Ihave to confirm once I reboot my PC if it still works.

@jangrewe
Copy link

jangrewe commented Feb 10, 2023

Do you know if it is one-time use?

The first line ensures that the resolv.conf does not get generated by WSL - which is kinda obvious from the name of the variable, isn't it? ;-)
The second line is the actual change to Google's DNS servers.
So yes, it's a one-time thing.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment