5

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
6
  • Are you using a tun or a tap interface? How are your clients IPs assigned? Mar 26, 2018 at 19:47
  • @RobinThoni I'm using a tun interface and the IPs are assigned "automagically". I've added the server config to the question.
    – emorris
    Mar 26, 2018 at 20:57
  • You can use a tap interface with a DDNS enabled DHCP server on the VPN server. You can also use a client-connect script (openvpn.net/index.php/open-source/documentation/manuals/…) Mar 26, 2018 at 21:08
  • Ah, so my question has been asked before! Did you ever solve this?
    – Thomas
    Nov 15, 2019 at 8:57
  • @Thomas yes, I have added my solution as the accepted answer.
    – emorris
    Nov 18, 2019 at 16:22

1 Answer 1

4

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.

1
  • Thanks for this, works great. With status file version 3, the script can be replaced by a shell oneliner, with far fewer dependencies: awk '$1 == "CLIENT_LIST" { print $4"\t"$2"\t"$2".myvpn.example.com" }' /etc/openvpn/openvpn-status.log > /etc/hosts.openvpn && systemctl reload dnsmasq
    – Thomas
    Feb 18, 2021 at 12:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .