Skip to content

Instantly share code, notes, and snippets.

@ThePlenkov
Last active November 13, 2024 23:49
Show Gist options
  • 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
@jamesmckibbenathrb
Copy link

jamesmckibbenathrb commented Nov 13, 2024

Sometimes an interface can have a DNS value on it, but not be "Up", this takes care of that (User used as username for reference to next step update):
file (Windows): C:\Users\User\bootDNS.ps1

$upAdapters = Get-NetAdapter | Where-Object { $_.Status -eq 'Up' }
$adapterDNS = Get-DnsClientServerAddress
$upAdapters | ForEach-Object {
    $adapterName = $_.Name
    $ipAddresses = Get-NetIPAddress -InterfaceAlias $adapterName | Where-Object { $_.IPAddress -ne $null }
    if ($ipAddresses) {
        $ipAddresses | ForEach-Object {
            $adapterDNS | Where-Object { $_.InterfaceAlias -eq $adapterName } | Select-Object -ExpandProperty ServerAddresses | ForEach-Object { "nameserver $_" }
        }
    }
}

then update as such (fix your "User" reference for the -File path, and update example.com to your environment):
file (WSL): /root/boot.sh

#!/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 -File C:\\Users\\User\\bootDNS.ps1 | sort | uniq | tr -d '\r'| tee -a /etc/resolv.conf > /dev/null

# Remove anything not having 'nameserver' in it
sed -i '/nameserver/!d' /etc/resolv.conf

# Add search domains
echo "search example.com" >> /etc/resolv.conf

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