1

I have configured OpenVPN as a server to host my own VPN and I want use DNSMasq to resolve hostnames on the VPN.

Say I have the OpenVPN server, two computers on the internal network, and one outside, all clients for the VPN (192.168.254.0/24):

  • Internal Network: 192.168.1.0/24
    • server: IP: 192.168.1.1
    • A: IP: 192.168.1.2, VPN: 192.168.254.2
    • B: IP: 192.168.1.3, VPN: 192.168.254.3
  • External Network: 192.168.2.0/24
    • C: IP: 192.168.2.1, VPN: 192.168.254.4

With my current setup, both A and B can resolve their hostnames via DNSMasq on the internal network. And, all of A, B, and C can access each other by direct IP. But, I want to allow C to access A and B by hostname (DNS resolution, not NetBIOS) without directing all network traffic through the VPN.

OpenVPN configuration:

proto tcp
dev tap
server 192.168.254.0 255.255.255.0
client-to-client
persist-key
persist-tun

Do I need to also configure the VPN server as a client? Do I need to push the domain from the Internal Network across the VPN? What do I need to do?

1

With great complexity, I have something approximating DNS over the VPN.

First, I had to run a script upon the addition of an address to OpenVPN. In the server configuration:

ifconfig-pool-persist ip-pool # Store mappings of CN,IP, 1 per line
script-security 2             # Allow OpenVPN to run user scripts
learn-address /path/to/learn-address.sh

I started with the learn-address.sh script from an old OpenVPN thread, but since I was running a TAP interface, I had to add script to parse the ip-pool file as well:

#!/bin/sh
# openvpn learn-address script to manage a hosts-like file
# - intended to allow dnsmasq to resolve openvpn clients
#   addn-hosts=/etc/hosts.openvpn-clients
#
# Changelog
# 2006-10-13 BDL original
# 2018-12-10 Palswim change to query OpenVPN Persistent pool for TAP interfaces

# replace with a sub-domain of your domain, use a sub-domain to
# prevent VPN clients from stealing existing names
DOMAIN=example

HOSTS=/etc/openvpn/hosts

h="hosts-openvpn-$DOMAIN"
LOCKFILE="/var/run/$h.lock"

IP="$2"
CN="$3"

if [ -z "$IP" ]; then
    echo "$0: IP not provided" >&2
    exit 1
else
    # In TAP mode, OpenVPN passes MAC instead of IP, since with TAP, clients can use protocols other than IP
    MAC="$IP"
    IP=$(grep "^$CN[[:space:]]*," ip-pool | head -n 1 | cut -d, -f 2)
    if [ -z "$IP" ]; then
        echo "$0: Failed to find IP in ipconfig-pool" >&2
        exit 0
    else
        echo "$0: Translated MAC ($MAC) to IP ($IP)"
    fi
fi

case "$1" in
    add|update)
        if [ -z "$CN" ]; then
            echo "$0: Common Name not provided" >&2
            exit 0
        fi
    ;;
    delete)
    ;;
    *)
        echo "$0: unknown operation [$1]" >&2
        exit 1
    ;;
esac

# serialise concurrent accesses
[ -x /bin/lock ] && /bin/lock "$LOCKFILE"

# clean up IP if we can
[ -x /bin/ipcalc ] && eval $(ipcalc "$IP")

FQDN="$CN"

# busybox mktemp must have exactly six X's
t=$(/bin/mktemp "/run/shm/$h.XXXXXX")
if [ $? -ne 0 ]; then
    echo "$0: mktemp failed" >&2
    exit 1
fi


case "$1" in
    add|update)
        /usr/bin/awk '
            # update/uncomment address|FQDN with new record, drop any duplicates:
            $1 == "'"$IP"'" || $1 == "#'"$IP"'" || $2 == "'"$FQDN"'" \
            { if (!m) print "'"$IP"'\t'"$FQDN"'"; m=1; next }
            { print }
            END { if (!m) print "'"$IP"'\t'"$FQDN"'" }           # add new address to end
        ' "$HOSTS" > "$t" && cat "$t" > "$HOSTS"
    ;;

    delete)
            /usr/bin/awk '
            # no FQDN, comment out all matching addresses (should only be one)
            $1 == "'"$IP"'" { print "#" $0; next }
            { print }
        ' "$HOSTS" > "$t" && cat "$t" > "$HOSTS"
    ;;

esac

# signal dnsmasq to reread hosts file
kill -HUP $(cat /var/run/dnsmasq/dnsmasq.pid)

rm "$t"

[ -x /bin/lock ] && /bin/lock -u "$LOCKFILE"
exit 0

I ended up running DNSMasq on one server for my own LAN, and a different server for the VPN. I had to update my configuration (/etc/dnsmasq.conf) on the VPN DNS server:

no-resolv                     # Didn't want to serve anything but VPN requests
interface=tap0
no-hosts                      # Don't use /etc/hosts
addn-hosts=/etc/openvpn/hosts # Target the output of the learn-address.sh script
expand-hosts
domain=example

Once I had this, I then had to push a few options via OpenVPN's DHCP server. Again, in the OpenVPN server configuration:

server 192.168.254.0 255.255.255.0 # Assuming this VPN network
push "dhcp-option DNS 192.168.254.1"
push "dhcp-option DOMAIN example"  # Push domain to clients

Unfortunately, only the Windows version of OpenVPN supports setting these options automatically. Linux clients will need to configure scripts to run on connection up/down. If you Linux system uses /etc/resolv.conf, ultimately, you need your VPN domain to appear in your search list, and your server IP to appear as a nameserver:

search example # you may have other strings here too, separated by a space
# ... other nameservers, then:
nameserver 192.168.254.1

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.