WSL2 uses the Windows host’s DNS - so if DNS is working on Windows, normally WSL2 should be fine as well! Unfortunately, DNS in WSL2 just randomly stopped working for me at some point. The /etc/resolv.conf
file generated by WSL2 was still being correctly created but DNS just wouldn’t work.
Luckily there are plenty of ways to work around this, because we can just do DNS ourselves inside the Linux running in WSL2.
Prerequisite: Deactivate auto-generation of /etc/resolv.conf
For any of the following scenarios we need to stop WSL2 from writing to /etc/resolv.conf
first, because we need to persistently modify it.
In WSL2, open a file /etc/wsl.conf
, paste the following content and save:
[network]
generateResolvConf = false
If you also want to stop WSL2 from overwriting your /etc/hosts.conf
, you need to add another line like so:
generateHosts = false
To have these changes take effect, you need to restart WSL2. Close your WSL2 window, start PowerShell as admin and run the following command to shutdown WSL2.
wsl.exe --shutdown
See here for reference, if you want to know in detail why this is necessary.
After the command has finished successfully, you can start WSL2 again.
Back in WSL, remove the broken DNS configuration file that WSL leaves behind.
rm /etc/resolv.conf
Next, we’ll set up DNS inside Linux. There are multiple ways of varying complexity depending on your use case.
One remote DNS server
If you just need to use one DNS server like a public DNS or a server provided by your organization that can resolve everything you need, this is the most simple setup.
In WSL2, open the file /etc/resolv.conf
, paste the following content and save:
nameserver <your dns server>
If you wanted to use CloudFlare’s public DNS for example, it’d look like this:
nameserver 1.1.1.1
Multiple remote DNS servers
If you need to use multiple DNS servers, you’ll have to setup your own DNS server, which in turn uses the remote DNS servers you need. Don’t worry, it’s easy!
For example, in my WSL2 Ubuntu environment I need to use a specific DNS server for an internal domain and a public DNS for everything else.
Install dns server software dnsmasq
Firstly, install the dns server dnsmasq. You might need to use a different package manager depending on your Linux distro. This works on Ubuntu and other Debian-based distros:
sudo apt update && sudo apt install -y dnsmasq
Configure dnsmasq
After dnsmasq has been installed, open it’s config file /etc/dnsmasq.conf
, add the following and save.
dnsmasq comes with a big config file full of deactivated settings as reference. If you want to keep all that, that’s no problem - I did it as well and just appended the following:
server=/<your internal domain>/<your internal DNS server>
server=<your external DNS server>
no-dhcp-interface=
<your internal DNS server>
will only be used for domains under <your internal domain>
. You can add as many of these as you want, if you have multiple internal domains for example.
<your external DNS server>
is the public DNS server and will be used for everything else.
no-dhcp-interface=
deactives the DHCP and TFTP capabilities of dnsmasq, because we only want it to provide DNS.
So if I have an internal domain called mycompany.internal
, an internal DNS server 192.168.1.53
and the public CloudFlare DNS 1.1.1.1
, it’d look like this:
server=/mycompany.internal/192.168.1.53
server=1.1.1.1
no-dhcp-interface=
Finally, start dnsmasq…
sudo service dnsmasq start
…and check whether it started successfully.
sudo service dnsmasq status
Get dnsmasq ip address
Now that we have installed, configured and started dnsmasq, we need to configure our Linux to use it as for DNS. We need to find the IP address that dnsmasq is listening on first.
This can be accomplished with netstat
, which you can install with the package net-tools
.
sudo apt install -y net-tools
This command gives us the IPs that any running instances of dnsmasq are listening on:
sudo netstat -tulpen | grep dnsmasq
If there is not output, make sure dnsmasq is up and running. If its not running, check for errors in the config file.
Set dnsmasq as DNS server to be used
Open /etc/resolv.conf
and add the IP you’ve just found. In my case it was 127.0.0.53
but it can also be 0.0.0.0
.
If it is 0.0.0.0
just put 127.0.0.1
as IP here.
nameserver 127.0.0.53
Save the file to start using dnsmasq as DNS server.
Start dnsmasq automatically at WSL start (hacky)
Since WSL2 is not a real Linux, we can’t use systemd or similar good ways to automatically start our newly configured DNS server for now (systemd is supposed to be added to Ubuntu WSL in the future).
I didn’t dig for a perfect solution here tbh, because I’m using Windows and WSL2 involuntarily.
That’s why I just wrote a tiny Shell script which checks whether dnsmasq is running and, if it doesn’t, starts it. This runs every time I open a shell in WSL2.
It’s not pretty and in a real Linux environment I’d never do it this way but for this specific use-case it’s totally fine imho.
Open your ~/.bashrc
and append the following at the end of the file. If you’re using a different shell, such as ZSH, use the corresponding rc file like ~/.zshrc
instead of ~/.bashrc
.
service dnsmasq status > /dev/null
if [ $? -eq 3 ]; then echo "Dnsmasq not running, please provide sudo pw to start it..."; sudo service dnsmasq start; fi
Next time you start a shell, you’ll be prompted to enter your password to start dnsmasq, if it’s not yet running.