I would like to share the way I finally got Ubuntu 20.04 to work with OpenVPN.
I first tried to get it to work with systemd sh...t but really this resolver can't work. You have to symbolically link /etc/resolv.conf to a file and then sometimes the system decides that the tunnel dns come first, sometimes not... My problem was therefore that, as my ISP DNS server can resolve some host, they send me a public IP, while actually, I use the VPN to be on the same LAN as the server, which will then present an admin interface...
Once I had the issue, there was really no way to push the right DNS to be first, so I went back to something I know well, dnsmasq.
This being said, let's get to business.
In Ubuntu 20.04, dnsmasq relies on a default config that can be overridden by files that you place in "/etc/dnsmasq.d/"
This offers an option to do some really nice things even with several tun{x} interfaces.
The excerpts below are just a first draft, but you'll understand the idea.
Based on the files "update-resolv-conf", I made my own "update-dnsmasq-conf" script as follows:
Code: Select all
#!/bin/bash
#
# Parses DHCP options from openvpn to update dnsmasq.d configuration
# To use set as 'up' and 'down' script in your openvpn *.conf:
# up /etc/openvpn/scripts/update-dnsmasq-conf
# down /etc/openvpn/scripts/update-dnsmasq-conf
#
# Used snippets of resolvconf script by Thomas Hood and Chris Hanson.
# Licensed under the GNU GPL. See /usr/share/common-licenses/GPL.
#
# Example envs set from openvpn:
#
# foreign_option_1='dhcp-option DNS 193.43.27.132'
# foreign_option_2='dhcp-option DNS 193.43.27.133'
# foreign_option_3='dhcp-option DOMAIN be.bnc.ch'
#
[ "$script_type" ] || exit 0
[ "$dev" ] || exit 0
CONFIG_FILE="/etc/dnsmasq.d/test2.test"
split_into_parts()
{
part1="$1"
part2="$2"
part3="$3"
}
case "$script_type" in
up)
NMSRVRS=""
SRCHS=""
foreign_options=$(printf '%s\n' ${!foreign_option_*} | sort -t _ -k 3 -g)
for optionvarname in ${foreign_options} ; do
option="${!optionvarname}"
echo "$option"
split_into_parts $option
if [ "$part1" = "dhcp-option" ] ; then
if [ "$part2" = "DNS" ] ; then
NMSRVRS="${NMSRVRS:+$NMSRVRS }$part3"
elif [ "$part2" = "DOMAIN" ] ; then
SRCHS="${SRCHS:+$SRCHS }$part3"
fi
fi
done
# for some reason the $NMSRVRS struct is badly made. I
# cannot access one server at a time as all are in ${NMSRVRS[0]}
split_into_parts $NMSRVRS
S=""
[ "$SRCHS" ] && S="server=/$SRCHS/$part1 #test
"
echo -n "$S" > $CONFIG_FILE
for NS in $NMSRVRS ; do
R="${R}server=$NS
"
done
echo -n "$R" >> $CONFIG_FILE
;;
down)
rm -f $CONFIG_FILE
;;
esac
I have now a doubt whether or not this works properly, as I saw this:
Code: Select all
bernard@bernard-Latitude-D630:/etc/openvpn/scripts$ service dnsmasq status
● dnsmasq.service - dnsmasq - A lightweight DHCP and caching DNS server
Loaded: loaded (/lib/systemd/system/dnsmasq.service; enabled; vendor preset: enabled)
Active: active (running) since Tue 2020-05-12 17:08:53 CEST; 3h 3min ago
Process: 24826 ExecReload=/bin/kill -HUP $MAINPID (code=exited, status=0/SUCCESS)
Main PID: 684 (dnsmasq)
Tasks: 1 (limit: 4645)
Memory: 1.8M
CGroup: /system.slice/dnsmasq.service
└─684 /usr/sbin/dnsmasq -x /run/dnsmasq/dnsmasq.pid -u dnsmasq -7 /etc/dnsmasq.d,.dpkg-dist,.dpkg-old,.dpkg-new --local-servic>
Mai 12 17:08:53 bernard-Latitude-D630 dnsmasq[684]: using nameserver 192.168.0.1#53
Mai 12 17:08:53 bernard-Latitude-D630 dnsmasq[684]: using nameserver 172.16.0.204#53
Where the first entry is actually hard coded... in a different file of the same folder, so I don't know why it is first...
Basically, if you choose to prefix your file with a numerical ID (e.g. a calling argument), you can select the order in which the files will be read, and hence, the order of the DNS servers to be used when one or more tunnels are up (If I understood correctly, last comes first -> We could surely improve the solution above, as it will predominantly use the secondary server).