In this post I will explain you how to update your DNS server when a client connects to your OpenVPN server, in the example I will be using PowerDNS as my authoritative name server, which runs on the same machine. However you can easily customize the script to your configured environment. This has been tested on Ubuntu 22.04.
1. Create the Client Connect Hook script
We will create a script that gets called by the OpenVPN server when a client connects. We will use the Common Name of the client as the name for the A record.
sudo nano /etc/openvpn/client-connect.sh
#!/bin/bash # https://MrWaggel.be # For debugging in logs echo "Client-Connect called for $common_name" # Use the common name as the record name. record=$(echo "$common_name" | tr '_' '-' | tr ' ' '-') # Remove old records with the same name pdnsutil delete-rrset example.com $record A # Update the record in PowerDNS using pdnsutil pdnsutil add-record example.com $record A 60 $ifconfig_pool_remote_ip
The script is quite short as you can see, when the OpenVPN server runs a script it passes environment variables related to the client1 in question. The script works as following;
- Echo something in case we need to debug, so you can search for this line.
- First we sanitize the Common Name by replacing spaces and underscores with '-'. This example it is quite basic and does not take in account special characters or different alphabets, refer to the list of valid characters in DNS names2, and adjust to your own needs.
- Removing any previous A records for the record name to prevent having multiple A records with different IP addresses, it results in a no-op when the record is not found, so the return code is 0.
- Create a new A record for the client, where the value is the Virtual IP address it gets assigned
$ifconfig_pool_remote_ip, with a TTL of 60 seconds.
Good to know, if your script does not exit with code 0, the client will not be allowed to connect.
Make sure the script is executable, and only by root, else other users on the machine would be able to change DNS records.
sudo chmod 700 /etc/openvpn/client-connect.sh
2. Edit the server.conf
Now it is time to edit your OpenVPN server configuration. The default location for this config file is:
sudo nano /etc/openvpn/server.conf
Change or add the following values in your config file.
user root script-security 2 client-connect /etc/openvpn/client-connect.sh
- user: for simplicity we use root here, however if you want more security you can change it your environment, but make sure the ownership of the script is adjusted as well, and that the user can execute changes towards your DNS servers.
- script-security: required if you want OpenVPN to execute scripts. You can set it to 3 if you need to read out the password that the client provides when it connects to do some custom authentication handling.
- client-connect: the absolute path to the script that gets called when the client connects.
3. Restart the server
Time to restart the server and test the script, for systemd users;
sudo systemctl restart openvpn-server # Follow logs for testing and debugging purposes journalctl -u firstname.lastname@example.org -f
Connect a client to your server and check the logs for any errors or messages.