Skip to content

Instantly share code, notes, and snippets.

@ThePlenkov
Last active May 7, 2024 16:39
Show Gist options
  • Star 39 You must be signed in to star a gist
  • Fork 6 You must be signed in to fork a gist
  • Save ThePlenkov/6ecf2a43e2b3898e8cd4986d277b5ecf to your computer and use it in GitHub Desktop.
Save ThePlenkov/6ecf2a43e2b3898e8cd4986d277b5ecf to your computer and use it in GitHub Desktop.
Resolve WSL DNS automatically
#!/bin/bash
# Remove existing "nameserver" lines from /etc/resolv.conf
sed -i '/nameserver/d' /etc/resolv.conf
# Run the PowerShell command to generate "nameserver" lines and append to /etc/resolv.conf
# we use full path here to support boot command with root user
/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe -Command '(Get-DnsClientServerAddress -AddressFamily IPv4).ServerAddresses | ForEach-Object { "nameserver $_" }' | tr -d '\r'| tee -a /etc/resolv.conf > /dev/null

How to resolve DNS issue in WSL once and forever

There are tons of gists available for this problem:

However even solution is there - I was not satisfied that this problem always persists and I had to do same steps again from time to time. Also using a static DNS like 8.8.8.8 was not the option for me because we use pool of enterprise DNS servers and those are controlled by our IT on our Windows machines. So I wanted to find the way to get those DNS servers dynamically from Windows.

This guide describes the permanent solution using brand-new WSL boot command.

This gist removes nameservers every time your WSL starts and adds newly from powershell results. If it doesn't work for you - please feel free to adjust the script according to your needs.

Prepare boot config

  • login to your wsl and run sudo bash. It's important that you do this with a root user because it's a user which executes this command during boot
  • change to ~ folder ( or use any folder you like )
  • create a new file for example boot.sh and update it with a content from boot.sh gist
  • make it executable with chmod +x boot.sh
  • create a symbolic link in one of PATH folders ( keep in mind, that for root user number of path folders is very limited by default )
/usr/local/sbin
/usr/local/bin
/usr/sbin
/usr/bin
/sbin
/bin
  • i have used ln -s ~/boot.sh /usr/local/bin/boot.sh
  • having such a limited list of folders makes root not aware of powershell.exe and rest of window utilities. I have preferred to use an absolute path like /mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe in my script - but you may think of creating a symlink for powershell too.
  • now let's add boot command to /etc/wsl.conf file. In my case it looks like this:
[network]
generateResolvConf=false
[boot]
systemd=true
command=boot.sh
  • now just exit from bash, from wsl as well. Terminate your wsl with a command like wsl -t Ubuntu and start again
  • if everything went well cat /etc/resolv.conf should have nameservers from your Windows
@ThePlenkov
Copy link
Author

@7wells thanks for the feedback. Well indeed what you describe - I face myself too when changing the network locations. Please let me know if your experiment works

@ddlandim
Copy link

ddlandim commented May 7, 2024

in boot.sh, change

sed -i '/nameserver/d' /etc/resolv.conf

to

:> /etc/resolv.conf

In some cases the file does not exist and the script will give an error on tee.

about output redirection:
The :> operator redirects an empty string to the any file.
Creation/cleanup:
If the file does not exist, it will be created as an empty file.
If the file exists, its contents will be overwritten with an empty string, clearing it.

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