Openvpn – Setting up an automatic DNS server on OpenVPN server

binddomain-name-systemopenvpnvpn

I have a number of networks in remote locations, which I want to be able to access over a VPN. The topology of each network is simply a NAT router, and a machine running an SSH server. The router has the SSH port forwarded, so all that's needed is to be able to access the router's IP. I've configured an OpenVPN server, and set up the routers on each remote network to access it. The client PC is also configured to access the VPN, and the server has been configured so it can access the various routers by using their VPN IP addresses.

Topology:

This all works great, except the VPN IP addresses of the routers are unknown to the client. Currently, I must look at the OpenVPN status log, then use that IP. I'd rather not use static IPs, as the number of remote networks will grow.

So, my question is, is it possible to run a local DNS server on the VPN server, and have it automatically be updated for the clients that connect?

I have seen several articles surrounding updating resolv.conf on the VPN server, as well as pushing DNS details to clients, but am unsure of the missing piece of actually running and updating a DNS server.

Server config:

port 1194
proto udp
dev tun
ca ca.crt
cert cert.crt
key key.key  # This file should be kept secret
dh dh2048.pem
server 10.8.0.0 255.255.255.0
ifconfig-pool-persist ipp.txt
client-to-client
keepalive 10 120
cipher AES-256-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status openvpn-status.log
verb 3

Best Answer

For the purposes of others searching for a solution to a similar problem, this is how I solved it.

I added/uncommented the following OpenVPN server settings (/etc/openvpn/server.conf) to the example config, to tell clients to use its DNS server, and allow clients to communicate with one another:

topology subnet
push "dhcp-option DOMAIN myvpn.example.com"
push "dhcp-option DNS 10.8.0.1"
client-to-client

Then I configured dnsmasq (/etc/dnsmasq.conf) with the following, which listens on the VPN connection, and uses an additional hosts file, which we'll keep updated:

domain-needed
bogus-priv
local-service

listen-address=127.0.0.1
listen-address=10.8.0.1

local=/myvpn.example.com/
addn-hosts=/etc/hosts.openvpn

Finally, the following Python script (placed in /usr/local/sbin/update-openvpn-hosts) uses the openvpn-status library to update the additional hosts file and reload dnsmasq config. This is called every minute from a cron job in /etc/crontab (* * * * * root /usr/local/sbin/update-openvpn-hosts).

#!/usr/bin/env python3

"""Create hosts file from OpenVPN client list."""

import subprocess

import openvpn_status

with open('/etc/openvpn/openvpn-status.log') as logfile:
    status = openvpn_status.parse_status(logfile.read())

with open('/etc/hosts.openvpn', 'w') as hostsfile:
    for routing in status.routing_table.values():
        line = '{0} {1} {1}.myvpn.example.com\n'.format(routing.virtual_address, routing.common_name)
        hostsfile.write(line)

subprocess.run(['systemctl', 'reload', 'dnsmasq'])

One thing to be aware of, is that when connected to the VPN, all DNS requests will be routed through the VPN server machine, not just those destined for VPN clients. This is a fundamental limitation of DNS.