My home VPN server setup
In today’s digital age, many of us have smart devices or applications at home, but how can we access them from anywhere in the world without exposing them to potential threats? The answer is: with a VPN! A home VPN not only provides a secure and encrypted connection, but also allows us to access our home network, files, and devices remotely. In this blog post, I will share my home VPN setup and also explain how to use a DNS server to identify devices and applications using domain names instead of IP addresses.
For your knowledge
WireGuard is an extremely simple yet fast and modern VPN that utilizes state-of-the-art cryptography. It aims to be faster, simpler, leaner, and more useful than IPsec, while avoiding the massive headache. It intends to be considerably more performant than OpenVPN.
BIND 9 is the most commonly used DNS server software on the Internet. Performs both of the main DNS server roles, acting as an authoritative name server for DNS zones and as a recursive resolver in the network.
Project structure
Dockerfile
docker-compose.yml
wg-ui
├── wireguard
│ └── ...
└── dns-bind9
├── named.conf.options
├── named.conf.local
└── db.vpn.vpn
To replicate my setup you can adapt the following docker-compose.
Note: the WireGuard image is not official. It is a image with wireguard and a UI to manage the clients.
docker-compose
1 |
|
There are some images in docker hub for bind9 but I want to have a clean image to install more tools if needed. So to create this custom image you will need the following DockerFile:
Dockerfile
1 |
|
Manage WireGuard
As I said in the beginning, the image that I am using for WireGuard is not official. It is an image of a project that combines WireGuard and a UI to manage the clients.
Checkout the features:
- All-in-one: WireGuard + Web UI.
- Easy installation, simple to use.
- List, create, edit, delete, enable & disable clients.
- Show a client’s QR code.
- Download a client’s configuration file.
- Statistics for which clients are connected.
- Tx/Rx charts for each connected client.
- Gravatar support.
With this setup any container in the same vpn network will be accessible by any device connected to the VPN. The devices will get an IP in this 10.8.0.x range and you must set static IPs to other containers in this range 10.8.1.x.
variables | meaning |
---|---|
WG_HOST | Public hostname of your VPN server. |
PASSWORD | When set, requires a password when logging in to the Web UI. |
WG_DEFAULT_DNS | DNS server clients will use. |
WG_DEFAULT_ADDRESS | Clients IP address range. |
NET_ADMIN | Check https://man7.org/linux/man-pages/man7/capabilities.7.html |
SYS_MODULE | Check https://man7.org/linux/man-pages/man7/capabilities.7.html |
net.ipv4.ip_forward=1 | Sets up port forwarding on the docker network interface |
net.ipv4.conf.all.src_valid_mark=1 | Sets up a sysconfig entry to allow IP source addresses |
ipv4_address | Container static IP address |
Bind9 configuration
To configure the DNS server you will need to create the following files:
named.conf.options - Config for the cache directory, interface to listen and DNS forwarders (8.8.8.8 Google and 1.1.1.1 Cloudflare).
1
2
3
4
5
6
7
8
9
10
11
options {
directory "/var/cache/bind";
recursion yes;
listen-on { any; };
forwarders {
8.8.8.8;
1.1.1.1;
};
};
named.conf.local - Config file to organize multiple zones. In this example I am using only one zone for the domain vpn.vpn
1
2
3
4
zone "vpn.vpn" {
type master;
file "/etc/bind/zones/db.vpn.vpn";
};
db.vpn.vpn - Config of complete zone file for the domain vpn.vpn, which illustrates a number of common features. In this example I am only using A records (IP address of a domain).
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
$TTL 604800
@ IN SOA vpn.vpn. root.localhost. (
1 ; Serial
604800 ; Refresh
86400 ; Retry
2419200 ; Expire
604800 ) ; Negative Cache TTL
;
; name servers - NS records
IN NS localhost.
; name servers - A records
dashboard.vpn.vpn. IN A 10.8.1.6
device1.vpn.vpn. IN A 10.8.0.4
device2.vpn.vpn. IN A 10.8.0.5
With this config you are able to access your dashboard service via dashboard.vpn.vpn (docker container) or access one device via device1.vpn.vpn (vpn client). One drawback of this setup is that it is necessary to configure each DNS record manually.