Home VPN with DNS server
you have some servers at home (e.g. a kubernetes cluster) but you want to work with them at Starbucks or out in the green? Here is how to setup a VPN server in your home network with a DNS server that would resolve anything you want.
The DNS Server
Even if you don't need the VPN, you can set up a DNS server, that would resolve any host you want. Of course you can just put the hosts in the /etc/hosts file on every device, but that could be tricky if you have a lot of devices/VMs and change/add hosts frequently, or if you need them on a tablet/smart phone.
The following shows how to install and configure the DNS server bind9 on a Ubuntu Server. It could be a standalone server or a VM or even a Raspberry Pi.
Install bind9
bind9 is the DNS server that I am going to use. Here is how to install it:
$ sudo apt update $ sudo apt install bind9 $ sudo apt install dnsutils
Add Forwarders
Edit the file /etc/bind/named.conf.options and add:
forwarders { 8.8.8.8; };
You can use also your favourite DNS server, instead of Google. It will be used to resolve anything that your local DNS "does not know".
Test
You can now do a quick test to make sure it works.
$ sudo systemctl restart bind9 $ dig google.com
The expected output should looks like this:
; <<>> DiG 9.18.1-1ubuntu1.1-Ubuntu <<>> google.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 49030 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 65494 ;; QUESTION SECTION: ;google.com. IN A ;; ANSWER SECTION: google.com. 193 IN A 142.250.186.46 ;; Query time: 15 msec ;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP) ;; WHEN: Fri Oct 14 19:20:42 UTC 2022 ;; MSG SIZE rcvd: 55
If you execute the dig command again, it should be much faster:
; <<>> DiG 9.18.1-1ubuntu1.1-Ubuntu <<>> google.com ;; global options: +cmd ;; Got answer: ;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 59904 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1 ;; OPT PSEUDOSECTION: ; EDNS: version: 0, flags:; udp: 65494 ;; QUESTION SECTION: ;google.com. IN A ;; ANSWER SECTION: google.com. 168 IN A 142.250.186.46 ;; Query time: 0 msec ;; SERVER: 127.0.0.53#53(127.0.0.53) (UDP) ;; WHEN: Fri Oct 14 19:21:07 UTC 2022 ;; MSG SIZE rcvd: 55
(0msec vs 15msec)
Configure named.conf
open /etc/bind/named.conf and make sure these lines are not commented out:
include “/etc/bind/named.conf.options”; include “/etc/bind/named.conf.local”; include “/etc/bind/named.conf.default-zones”;
Add a zone (and a reverse zone)
Now, we have to define our zones. Edit the file /etc/bind/named.conf.local and add:
zone "mydomain.com" { type master; file "/etc/bind/db.mydomain.com"; }; zone "192.168.0.in-addr.arpa" { type master; file "/etc/bind/db.192"; };
I am assuming here, that the home network has the standard subnet 192.168.0.0/24.
Configure the zone db file
Next, we must add the zones' DB files, defined above. Starting with the zone db file, you can copy the local db file and edit it:
$ sudo cp /etc/bind/db.local /etc/bind/db.mydomain.com
Example configuration:
$TTL 604800 @ IN SOA mydomain. root.mydomain.com. ( 2 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire 604800 ) ; Negative Cache TTL ; @ IN NS ns.mydomain.com. @ IN A 192.168.0.100 ; the IP of the Ubuntu Server, that's hosting the DNS server @ IN AAAA ::1 ns IN A 192.168.0.100 ; ns.mydomain.com test IN A 192.168.0.111 ; test.mydomain.com test2 IN A 192.168.0.122 ; test2.mydomain.com real IN NS 8.8.8.8 ; real.mydomain.com
Above we configure the subdomains test.mydomain.com and test2.mydomain.com to local IPs and we let the real.mydomain.com be resolved by the Google's DNS server, so that the real IP of that domain is used. This is required, because when you define a zone in your DNS server, you take exclusive control over it. Anything that is not defined or forwarded would not be resolved, even if it is a real host, known by other DNS servers.
You can do much more in this configuration. If you need something specific, check the list of record types: https://en.wikipedia.org/wiki/List_of_DNS_record_types.
Configure the reverse db file
Similar to the zone db file, you can also copy the local reverse zone db file and edit it:
$ sudo cp /etc/bind/db.127 /etc/bind/db.192
Just set the NS to the local server:
$TTL 604800 @ IN SOA ns.mydomain.com. root.mydomain.com. ( 1 ; Serial 604800 ; Refresh 86400 ; Retry 2419200 ; Expire 604800 ) ; Negative Cache TTL ; @ IN NS ns. 1.0.0 IN PTR ns.mydomain.com.
Verify
You can execute the following commands to verify your configuration files. No errors should be reported.
$ named-checkzone mydomain.com /etc/bind/db.mydomain.com $ named-checkzone 192.168.0.0/32 /etc/bind/db.192 $ named-checkconf /etc/bind/named.conf.local $ named-checkconf /etc/bind/named.conf
Final Test
At this point your DNS server is configured and ready to use. Let's do some tests.
Edit /etc/resolve.conf and set (temporary) the DNS server to your local DNS server:
nameserver 192.168.0.131
Then you can start "digging" the hosts defined above:
$ dig test.mydomain.com ... $ dig test2.mydomain.com ... $ dig real.mydomain.com ...
The VPN Server
There is a script that makes configuring OpenVPN very easy.
However, make sure the OS is up to date:
$ sudo apt update $ sudo apt upgrade
Download the script and run it
$ wget https://git.io/vpn -O openvpn-install.sh $ chmod +x openvpn-install.sh $ sudo ./openvpn-install.sh
Here is an example how to configure it:
Welcome to this OpenVPN road warrior installer! This server is behind NAT. What is the public IPv4 address or hostname? Public IPv4 address / hostname [xxx.xxx.xxx.xxx]: vpn.myhost.com Which protocol should OpenVPN use? 1) UDP (recommended) 2) TCP Protocol [1]: 1 What port should OpenVPN listen to? Port [1194]: Select a DNS server for the clients: 1) Current system resolvers 2) Google 3) 1.1.1.1 4) OpenDNS 5) Quad9 6) AdGuard DNS server [1]: 2 Enter a name for the first client: Name [client]: MyLaptop OpenVPN installation is ready to begin. Press any key to continue... ... Using configuration from /etc/openvpn/server/easy-rsa/pki/52d1ba80/temp.e290b259 ....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+............+..+.+..............+.+...+..+....+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+......+.....+...+.+............+..+...+............+.+.....+.+.....+.+..+.......+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...+.......+....................+...+.+......+...+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+.+.....+.+........+.......+.....+....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.......+..+....+.....+....+..+.......+...............+.....+................+..+.........+...............................+.....+.......+....................+..........+......+......+......+..+.+..+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ----- .+....+..+.......+...........+...................+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+..+............+...................+..+....+...+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+..+...+....+.....+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ..........+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..+...+.....+.......+.....+...+.+......+......+..+...+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*..............+...+...+.........+.......................+....+......+............+..+.+.................+......+.+......+.........+......+........+....+...+..+...+.........+....+.........+........+....+.....+...+............+....+...........+..........+.........+.........+..+...+.+..+..................+.......+.....+..................+.+........+...+.......+..+.+.....+...+....+........+.........+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ----- Using configuration from /etc/openvpn/server/easy-rsa/pki/06983a57/temp.da1b8443 4057FD16457F0000:error:0700006C:configuration file routines:NCONF_get_string:no value:../crypto/conf/conf_lib.c:315:group=<NULL> name=unique_subject Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :ASN.1 12:'server' Certificate is to be certified until Nov 6 20:25:53 2032 GMT (3650 days) Write out database with 1 new entries Data Base Updated .........+......+.+.........+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+....+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+..........+..+...+......+.......+..+.......+......+........+.+.........+.....+......+.+............+...+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ...............+.........+.+..+............+.............+..+.+..+.+...........+....+..+..........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+..........+.....+.......+..+...+...+.+...+..+.........+....+...+...+.................+...+....+.................+.+..+.............+.........+...........+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+......+.........+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ----- Using configuration from /etc/openvpn/server/easy-rsa/pki/35d70dcf/temp.95880599 Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :ASN.1 12:'MyLaptop' Certificate is to be certified until Nov 6 20:25:53 2032 GMT (3650 days) Write out database with 1 new entries Data Base Updated Using configuration from /etc/openvpn/server/easy-rsa/pki/dbda15cb/temp.c5eccaad 2022-11-09 20:25:53 WARNING: Using --genkey --secret filename is DEPRECATED. Use --genkey secret filename instead. Created symlink /etc/systemd/system/multi-user.target.wants/openvpn-iptables.service → /etc/systemd/system/openvpn-iptables.service. Created symlink /etc/systemd/system/multi-user.target.wants/openvpn-server@server.service → /lib/systemd/system/openvpn-server@.service. Finished! The client configuration is available in: /root/MyLaptop.ovpn New clients can be added by running this script again.
Notes:
- "IPv4 address / hostname" should be the IP or hostname of your home network (here: vpn.myhostname.com). In case you don't have a static IP address you can use a DDNS like https://www.noip.com/ to get a hostname. Additionally, if you have a domain name of your own, you can configure it to resolve the subdomain, using the DDNS by CNAME.
- You can use any DNS from the list. In the next step we will configure it to use the local one.
- The client name should be something meaningful, e.g. "MyLaptop", "MyTablet", etc. In case you have many clients and you want to remove the access of one of them, it's easier to find out which one that is.
- The file listed above, /root/MyLaptop.ovpn, must be copied to your device in order to connect.
Add the Local DNS Server
Edit the file /etc/openvpn/server/server.conf and add this line "before all other DNSes":
push "dhcp-option DNS 192.168.0.100"
where the IP is that of the local DNS server, configured above.
Run Again the Script to Create more Clients
$ sudo ./openvpn-install.sh
Example:
OpenVPN is already installed. Select an option: 1) Add a new client 2) Revoke an existing client 3) Remove OpenVPN 4) Exit Option: 1 Provide a name for the client: Name: MyTablet ...........+.+.....+...+.+..+....+.....+..........+...+..+.+...+.....+.......+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*....+...+...........+.+.....+.+..+.......+......+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+...+......+.....+.+..............+......+.+.....+...+.+...........+.........+....+.................+.........+......+............+.+.....+.+...+...........+......+......+.......+...+.....+...+.......+..............+...+.+.........+..+.............+...+...+..+..........+.......................+............+.........+...............+....+..+....+...+..+...+..........+.....+.............+.........+......+..+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ....+.....+.+......+...+............+.........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+.+........+..........+.....+....+..+...+...+.........+...................+..+.......+..+...+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.....+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ----- Using configuration from /etc/openvpn/server/easy-rsa/pki/fc167864/temp.78d7fada Check that the request matches the signature Signature ok The Subject's Distinguished Name is as follows commonName :ASN.1 12:'MyTablet' Certificate is to be certified until Nov 6 20:35:20 2032 GMT (3650 days) Write out database with 1 new entries Data Base Updated MyTablet added. Configuration available in: /root/MyTablet.ovpn
As you might have noticed, you can also run the script to revoke clients.
Configure your Home Router
In order to be able to connect to the VPN server from the internet, you must configure your router to forward UDP requests on port 1194 to the Ubuntu Server, where you installed it.
Finally, restart the OpenVPN server:
$ sudo systemctl stop openvpn-server@server.service $ sudo systemctl start openvpn-server@server.service
Connect to the VPN
You can either use the apps, provided by OpenVPN or use the built-in VPN functionality of the device's OS, in case OpenVPN is supported.
You can download the OpenVPN client apps for Windows, MacOS, Android and iOS from here: https://openvpn.net/vpn-client/
You just have to import the ovpn file, created above and connect.