Skip to content

Instantly share code, notes, and snippets.

@matthiassb
Last active March 20, 2024 12:12
Show Gist options
  • Save matthiassb/9c8162d2564777a70e3ae3cbee7d2e95 to your computer and use it in GitHub Desktop.
Save matthiassb/9c8162d2564777a70e3ae3cbee7d2e95 to your computer and use it in GitHub Desktop.
Init.d script for keeping WSL resolv.conf in-sync with Windows
#! /bin/bash
### BEGIN INIT INFO
# Provides: dns-sync
# Required-Start:
# Required-Stop:
# Default-Start: S
# Default-Stop:
# Short-Description: Synchronizes /etc/resolv.conf in WLS with Windows DNS - Matthias Brooks
### END INIT INFO
PATH=/sbin:/bin
PS=/mnt/c/Windows/System32/WindowsPowerShell/v1.0/powershell.exe
. /lib/init/vars.sh
. /lib/lsb/init-functions
do_start () {
while true
do
#Retrieve nameservers from via Powershell
TEMPFILE=$(mktemp)
$PS -Command "Get-DnsClientServerAddress -AddressFamily IPv4 | Select-Object -ExpandProperty ServerAddresses" > $TEMPFILE
/usr/bin/awk '!x[$0]++' $TEMPFILE > $TEMPFILE.2
IFS=$'\r\n' GLOBIGNORE='*' command eval 'UNIQUE_NAMESERVERS=($(cat $TEMPFILE.2))'
rm -f $TEMPFILE $TEMPFILE.2
#Retrive search domains via powershell
IFS=$'\r\n' GLOBIGNORE='*' command eval 'SEARCH_DOMAIN=($($PS -Command "Get-DnsClientGlobalSetting | Select-Object -ExpandProperty SuffixSearchList"))'
UNIQUE_SEARCH_DOMAIN=($(/usr/bin/tr ' ' '\n' <<< "${SEARCH_DOMAIN[@]}" | /usr/bin/sort -u | /usr/bin/tr '\n' ' '))
#Modify /etc/resolv.conf
touch /etc/resolv.conf
sed -i '/nameserver/d' /etc/resolv.conf > /dev/null 2>&1 || true
sed -i '/search/d' /etc/resolv.conf > /dev/null 2>&1 || true
for i in "${UNIQUE_NAMESERVERS[@]}"
do
echo "nameserver ${i}" >> /etc/resolv.conf
done
if [ ${#UNIQUE_SEARCH_DOMAIN[@]} -ne 0 ]; then
echo "search ${UNIQUE_SEARCH_DOMAIN[@]}" >> /etc/resolv.conf
fi
sleep 15
done
}
do_status () {
PID=$(cat /var/run/dns-sync.pid 2>/dev/null)
if [ "$PID" == "" ]; then
echo "dns-sync is not running"
return
fi
if ps -p $PID > /dev/null
then
echo "dns-sync is running"
else
echo "dns-sync is not running"
fi
}
case "$1" in
start|"")
kill $(cat /var/run/dns-sync.pid >/dev/null 2>&1) > /dev/null 2>&1 || true
do_start &
DO_SYNC_PID=$!
echo "${DO_SYNC_PID}" > /var/run/dns-sync.pid
;;
restart|reload|force-reload)
echo "Error: argument '$1' not supported" >&2
exit 3
;;
stop)
PID=$(cat /var/run/dns-sync.pid)
if ps -p $PID > /dev/null
then
kill -9 $(cat /var/run/dns-sync.pid)
echo "dns-sync stopped"
else
echo "dns-sync is not running"
fi
;;
status)
do_status
exit $?
;;
*)
echo "Usage: dns-sync.sh [start|stop]" >&2
exit 3
;;
esac
@jan-glx
Copy link

jan-glx commented Nov 12, 2021

I needed to change line 22 to $PS -Command 'Get-DnsClientServerAddress -AddressFamily IPv4 -InterfaceIndex $(Get-NetIPInterface -AddressFamily IPv4 | Where-Object ConnectionState -EQ "Connected" | Sort-Object InterfaceMetric | Select-Object -ExpandProperty ifIndex) | Select-Object -ExpandProperty ServerAddresses' > $TEMPFILE to avoid DNS servers from disconnected interfaces showing up first

@jarrodhroberson
Copy link

jarrodhroberson commented Feb 27, 2023

Does anyone have any updates to this.

I started at the top and tried every thing listed as I went down the list of comments and nothing works.

I still get this, I applied every mod/patch that everyone mentioned all the way down to jan-glx one at a time and nothing changed.

I did wsl --shutdown after every change to make sure it was getting a fresh start and data.

I still get:

❯ go mod tidy
go: downloading github.com/spf13/cobra v1.6.1
adotools/cmd imports
        github.com/spf13/cobra: github.com/spf13/cobra@v1.6.1: Get "https://proxy.golang.org/github.com/spf13/cobra/@v/v1.6.1.zip": proxyconnect tcp: dial tcp: lookup my.corp.proxy.com: i/o timeout

when I try to do sudo apt update all I get is:

Temporary failure resolving 'my.corp.proxy.com'

my.corp.proxy.com is anonymized obviously :-)

Anything else anyone can think out would help.

@cantti
Copy link

cantti commented Aug 29, 2023

Now WSL2 supports systemd, so we can run script as a service.

Download script to home directory

wget https://gist.github.com/matthiassb/9c8162d2564777a70e3ae3cbee7d2e95/raw/b204a9faa2b4c8d58df283ddc356086333e43408/dns-sync.sh -O ~/dns-sync.sh
chmod +x ~/dns-sync.sh

Add these lines to the /etc/wsl.conf if not exists (sudo nano /etc/wsl.conf)

[boot]
systemd=true

[network]
generateResolvConf=false

Reboot.

Create a unit file

sudo touch /etc/systemd/system/dns-sync.service

Edit (sudo nano /etc/systemd/system/dns-sync.service) and fix path to script inside

[Unit]
Description=dns sync

[Service]
ExecStart=PUT_PATH_HERE
Type=forking

[Install]
WantedBy=multi-user.target

Reboot

Run service

sudo systemctl enable dns-sync.service
sudo systemctl start dns-sync.service
sudo systemctl status dns-sync.service

@rroblik
Copy link

rroblik commented Aug 31, 2023

@cantti : enabling systemd prevent any .execommand to work, including the powershell command required by the script. That resulted in... an empty /etc/resolv.conf ! ❌

Related interesting thread : https://www.reddit.com/r/bashonubuntuonwindows/comments/11vx61n/wsl2_error_cannot_execute_binary_file_exec_format/

I'm looking for a workaround but for now I have to (re)disable systemd 😭

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