96

As far as I've been able to work out, the official process for changing which DNS server is used by WSL2 on Windows 10 is as detailed below. (WSL2 is the new release of the Windows Subsystem for Linux, which runs an actual Linux kernel in a lightweight VM on Windows 10.)

However, this process doesn't work for me - I end up with a system that simply times out and can't resolve any addresses whatsoever.

What am I doing wrong?

Here's the process as I've pieced it together so far:

1. Turn off generation of /etc/resolv.conf

Using your Linux prompt, (I'm using Ubuntu), modify (or create) /etc/wsl.conf with the following content

[network]
generateResolvConf = false

(Apparently there's a bug in the current release where any trailing whitespace on these lines will trip things up.)

2. Restart the WSL2 Virtual Machine

Exit all of your Linux prompts and run the following Powershell command

wsl --shutdown

3. Create a custom /etc/resolv.conf

Open a new Linux prompt and cd to /etc

If resolv.conf is soft linked to another file, remove the link with

rm resolv.conf

Create a new resolv.conf with the following content

nameserver 1.1.1.1

4. Restart the WSL2 Virtual Machine

Same as step #2

5. Start a new Linux prompt.

Profit!

Update March 18, 2020

My /etc/hosts file contains this:

# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateHosts = false
127.0.0.1       localhost
127.0.1.1       [redacted]  bearps-desktop

10.168.244.140  host.docker.internal
10.168.244.140  gateway.docker.internal
127.0.0.1       kubernetes.docker.internal

# The following lines are desirable for IPv6 capable hosts
::1     ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters

The file /etc/switch.conf does not exist.

The tool resolvectl is not on my path; it doesn't exist at /usr/bin/resolvectl.

Likewise systemd-resolve is not on my path; it doesn't exist at /usr/bin/systemd-resolve.

2
  • Out of curiosity, what are the contents of /etc/host, /etc/switch.conf and the results of either resolvectl status or systemd-resolve status? Mar 17, 2020 at 9:35
  • It works perfectly on Fedora 35 on WSL2 on Windows 11. Mar 9, 2022 at 11:46

5 Answers 5

46

The process I documented above is correct - this is how you change the DNS settings under WSL2.

My mistake was in using the well known public DNS Servers for CloudFlare (1.1.1.1) and Google (8.8.8.8 & 8.8.4.4) for testing purposes. It turns out that my local network blocks me from using public DNS.

When I tested the above process with the correct internal DNS server IP address, everything worked properly.

4
  • Thanks for these steps (in the question), is was good to see how all of these work together. My issue ended up being no DNS settings in my WSL-created network adapter. Once I updated that to an acceptable value, it worked for me.
    – ps2goat
    Oct 15, 2020 at 22:22
  • Update: It appears that WSL2 is reverting my DNS settings to empty on a reboot.
    – ps2goat
    Oct 16, 2020 at 17:02
  • 2
    One minor fix - you don't need to reboot for changes to /etc/resolv.conf to take effect. May 18, 2021 at 12:01
  • @ps2goat I had the problem initially but it's Bevan's instructions that did the trick. removing the symlink and creating a local file worked. The file stuck through a wsl --shutdown cycle. @mikemaccana yes, but do it anyway to check the persistence.
    – ADTC
    Jun 17, 2021 at 3:08
9

Adding to other answers here you also want to set resolv.conf immutable.

sudo chattr +i /etc/resolv.conf

In my case it was being deleted on every boot, even with wsl.conf.

For that reason, I created this small program that automates everything with one shell:

https://github.com/epomatti/wsl2-dns-fix-config

4
  • Actually, I had to start with chattr -i or it wouldn't let me save changes to the file... Thanks! Apr 11, 2023 at 10:30
  • Used your script to resolve the issue. However I have to add more DNS. How do I do it ?
    – Gupta
    Nov 25, 2023 at 7:45
  • @Gupta add to /etc/resolv.conf Nov 25, 2023 at 14:26
  • 1
    Love it! We're periodically onboarding new devs and half the time WSL just works out of the box and half the time we have to do this dance. Having a script is so handy! Mar 20 at 16:56
4

I had to do this from home (coronavirus) and ultimately ended up writing a Powershell Admininstrator Prompt script to launch my distro (debian). Also note this launches the default distro specified by WSL, you'll need to change the last line if that's not the case. Look for the \\wsl$\[distro name] if yours isn't also called Debian, just type the first part in a Windows Explorer path to reach WSL2, i.e. in the explorer top bar enter \\wsl$\ and it will list your distributions.

This will pull the DNS server from the Windows host, create a new resolv.conf, and write it in Unix format to the WSL2 instance. So you do need to edit /etc/wsl.conf to:

[network]
generateResolvConf = false

So a super user tried to change that to resolv.config; if that file exists because you are using a different Linux distribution, well then I suppose it's the file you want instead. So modify accordingly. Although I've never seen that file in any documentation, and I'm not sure the edit of my post was correct.

Then kick off PowerShell Admin Prompt and run like ./debian.ps1 (if that's what you name the file):

# Filename: debian.ps1
# 
# Get the DNS server of the Windows machine, save into variable nameserver
$nameserver = Get-WmiObject -Namespace root\cimv2 -Query "Select dnsserversearchorder from win32_networkadapterconfiguration" | where {$_.DNSServerSEarchOrder -ne $null} | select -ExpandProperty DNSServerSearchOrder
# Convert nameserver object into a string
$nameserver = Out-String -InputObject $nameserver
# Run Set-Contents (sc) to write the resolv.conf file in a public location as it has DOS formatted line endings written by PowerShell, not readable by Linux
sc -Path 'c:\Users\Public\Documents\resolv.conf' -Value ('nameserver ' + $nameserver) -Encoding utf8
# Convert the DOS formatted file into UNIX format for WSL2 and write it in the proper place (\etc\resolv.conf, its primary location is \\wsl$\[distro_name] from Windows)
[string]::Join( "`n", (gc 'c:\Users\Public\Documents\resolv.conf')) | sc '\\wsl$\debian\etc\resolv.conf'
# Launch the default WSL2 distribution - if you want to use another one, specify in the line below
wsl.exe

This has been tested under Debian Buster and a Zscaler (corporate) VPN. It's a good starting point, hope it saves someone the headaches I encountered getting DNS access on my corporate PC's WSL2 instance!

2
  • \\wsl$\[distro name] does not exist for me :/
    – zfogg
    Aug 5, 2021 at 1:17
  • Just type \\wsl$\ in an Explorer menu as the path and see what it's registered as, it will take you to your distros. I added it to my answer above as well to be more clear.
    – Matt
    Aug 10, 2021 at 16:01
3

When creating/editing /etc/resolv.conf I kept getting errors like this one:

cat: /etc/resolv.conf: No such file or directory

I was able to resolve these issues by removing and recreating it from scratch. Both operations require running as root (using sudo didn't work for me)

rm /etc/resolv.conf
echo nameserver 8.8.8.8 > /etc/resolv.conf
2
  • Sounds like you were logged into your normal account, you likely needed to use sudo. When you created the file under your user account, it automatically gives your normal account ownership of the file. This can always be changed with a simple: sudo chown [username]:[username] /etc/resolv.conf. If you just put your user name once root will also have ownership, which doesn't really give any issues in my experience. By the way, this works on a personal PC, but behind a corporate firewall, I had to use my solution posted above....
    – Matt
    Aug 10, 2021 at 16:08
  • 1
    in my experience the issue is that when you ask WSL2 to not generate /etc/resolv.conf, after the reboot you find a /etc/resolv.conf that is no more a file, but a link a to /run/resolvconf/resolv.conf, which (the link) you get rid of with the above sudo rm command. Subsequent command create a real file
    – mrq
    May 30, 2022 at 9:48
2

Very detailed answers about changing it. I just wanted to use the default and get on with it. Followed a few guides like the first answer, didn't work for me. I only changed /etc/wsl.conf and it works again.

sudo nano /etc/wsl.conf

Insert or change in this file:

[network]
generateResolvConf = true

Insert in Powershell/CMD:

wsl --shutdown

or:

wsl --terminate <<Linux distro>>

Done and done. Let me know if this worked for you.

My setup was messed up because Tailscale changed it when i started it. Now it's working again.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .