diff --git a/docs/guides/wireguard/client.md b/docs/guides/wireguard/client.md new file mode 100644 index 0000000..359cb2f --- /dev/null +++ b/docs/guides/wireguard/client.md @@ -0,0 +1,111 @@ +# Adding a WireGuard client + +Adding clients is really simple and easy. The process for setting up a client is similar to setting up the server. This is expected as WireGuard's concept is more of the type Peer-to-Peer than server-client as mentioned at the very beginning of the [Server configuration](server.md). + +For each new client, the following steps must be taken. For the sake of simplicity, we will create the config file on the server itself. This, however, means that you need to transfer the config file *securely* to your server as it contains the private key of your client. An alternative way of doing this is to generate the configuration locally on your client and add the necessary lines to your server's configuration. + +## Key generation + +We generate a key-pair for the client `NAME` (replace accordingly everywhere below): + +``` bash +sudo -i +cd /etc/wireguard +umask 077 +wg genkey | tee NAME.key | wg pubkey > NAME.pub +``` + +## PSK Key generation + +We furthermore recommend generating a pre-shared key (PSK) in addition to the keys above. This adds an additional layer of symmetric-key cryptography to be mixed into the already existing public-key cryptography and is mainly for post-quantum resistance. A pre-shared key should be generated for each peer pair and *should not be reused*. + +``` bash +wg genpsk > NAME.psk +``` + +## Add client to server configuration + +Add the following to your `/etc/wireguard/wg0.conf`: + +``` toml +[Peer] +Address = 10.100.0.2/24 # Replace this IP address for subsequent clients +AllowedIPs = 10.100.0.1/32 # This client is only allowed to talk to the server +``` + +Then run + +``` bash +echo "PublicKey = $(cat NAME.pub)" >> /etc/wireguard/wg0.conf +echo "PresharedKey = $(cat NAME.psk)" >> /etc/wireguard/wg0.conf +``` + +to copy the clients's public and pre-shared keys into the server's config file. + +## Create client configuration + +Create a dedicated config file for your new client: + +``` bash +nano NAME.conf +``` + +with the content + +``` toml +[Interface] +Address = 10.100.0.2/24 # Replace this IP address for subsequent clients +DNS = 10.100.0.1 # IP address of your Pi-hole +Domains = ~. # Enforce all DNS over the WireGuard connection +``` + +``` bash +echo "PrivateKey = $(cat NAME.key)" >> NAME.conf +``` + +Then add your server as the only peer for this client: + +``` toml +[Peer] +AllowedIPs = 10.0.0.1/24 +Endpoint = [your public IP or domain]:44711 +PersistentKeepalive = 25 +``` + +Make sure that each IP is used only once. + + +??? info "About the `PersistentKeepalive` setting" + By default WireGuard peers remain silent while they do not need to communicate, so peers located behind a NAT and/or firewall may be unreachable from other peers until they reach out to other peers themselves (or the connection may time out). + + When a peer is behind NAT or a firewall, it typically wants to be able to receive incoming packets even when it is not sending any packets itself. Because NAT and stateful firewalls keep track of "connections", if a peer behind NAT or a firewall wishes to receive incoming packets, he must keep the NAT/firewall mapping valid, by periodically sending keepalive packets. This is called *persistent keepalives*. + + When this option is enabled, a keepalive packet is sent to the server endpoint once every interval seconds. A sensible interval that works with a wide variety of firewalls is `25` seconds. Setting it to 0 turns the feature off, which is the default. + + **TL;DR** If you're behind NAT or a firewall and you want to receive incoming connections long after network traffic has gone silent, this option will keep the "connection" open in the eyes of NAT. + + +Then add the public key of the server as well as the PSK for this connection: + +``` bash +echo "PublicKey = $(cat server.pub)" >> NAME.conf +echo "PresharedKey = $(cat NAME.psk)" >> NAME.conf +``` + +That's it. + +## Copy config file to client + +You can now copy the configuration file to your client (if you created the config on the server). If the client is a mobile device such as a phone, `qrencode` can be used to generate a scanable QR code: + +``` bash +qrencode -t ansiutf8 -r NAME.conf +``` + +(you may need to install `qrencode` using `sudo apt-get install qrencode`) + +## Connect to your WireGuard VPN + +After creating/copying the connection information over to your client, you may use the client you prefer to connect to your system. Mind that setting up auto-start of the WireGuard connection may lead to issues if you are doing this too early (when the system cannot resolve DNS). See our [FAQ](faq.md) for further hints. + +{!abbreviations.md!} diff --git a/docs/guides/wireguard/concept.md b/docs/guides/wireguard/concept.md new file mode 100644 index 0000000..9edcdf6 --- /dev/null +++ b/docs/guides/wireguard/concept.md @@ -0,0 +1,32 @@ +# Conceptual overview + +Before we get started with installing a `wireguard` server, we'll quickly give a general conceptual overview of what WireGuard is about. You can skip this section if you already know what is going on under the hood or don't care (and just want to have it running). + +WireGuard securely encapsulates IP packets over UDP. You add a WireGuard interface, configure it with your private key and your peers' public keys, and then you send packets across it. + +WireGuard works by adding a network interface, like `eth0` or `wlan0`, called `wg0` (or `wg1`, +`wg2`, `wg3`, etc). This interface acts as a tunnel interface. Routes for this network interface will be added automatically based on the configuration file you will learn about below. All aspects of this virtual interface will be configured automatically by the `wg-tools`. + +WireGuard associates tunnel IP addresses with public keys and remote endpoints. When the interface +**sends a packet to a peer**, it does the following: + +1. This packet is meant for `192.168.30.8`. Is this peer configured? + 1. Yes: peer `adams-laptop`. Continue with step 2. + 2. No: Not for any configured peer, drop the packet and end here. + +2. Encrypt the IP packet using peer `adams-laptop`'s public key. +3. What is the remote endpoint of peer `adams-laptop`? Let me look... Okay, the endpoint is host `216.58.211.110:53133` (UDP). +4. Send encrypted data over the Internet to this host. + +When the interface **receives a packet from a peer**, this happens: + +1. Received a packet from host `98.139.183.24:7361`. Let's decrypt it! +2. It decrypted and authenticated properly for peer `evas-android`. Okay, let's remember that peer +`evas-android`'s most recent Internet endpoint is `98.139.183.24:7361` (UDP). +3. Once decrypted, the plain-text packet is from `192.168.43.89`. Is peer `evas-android` allowed to be sending us packets as 192.168.43.89? + 1. Yes: accept the packet on the interface and process it (forwarding to further local client, into the Internet, etc.) + 2. No: drop it. + +Behind the scenes there is much happening to provide proper privacy, authenticity, and perfect forward secrecy, using state-of-the-art cryptography. + +If you're interested in the internal inner workings, you might be interested in reading through the various articles on their official website [www.wireguard.com](https://www.wireguard.com) which is also where we took the vast majority of content in this guide from. diff --git a/docs/guides/wireguard/faq.md b/docs/guides/wireguard/faq.md new file mode 100644 index 0000000..e92e3ec --- /dev/null +++ b/docs/guides/wireguard/faq.md @@ -0,0 +1,85 @@ +# Frequently asked questions + +## Issues with dynamic server IP + +Host names cannot be resolved during startup. This may lead to a five minutes delay during boot. A solution to this is to disable the automatic start of the `wg` interface during start and connect only later (manually) when you are sure that you can resolve host names. + +1. Disable `auto wg0` in `/etc/network/interfaces` (put `#` in front, like `#auto wg0`) +2. Start `wireguard` manually using `sudo ifup wg0` + +If the IP changes while the connection is running, resolving the new IP address fails otten. Reconnect using + +``` bash +sudo ifdown wg0 && sudo ifup wg0 +``` + +To achieve a permanent solution, one can install a `cron` job which restarts the connection automatically whenever a change is detected. This avoids excessive restarts of the interface. Example script (taken from [Ubuntuusers Wiki](https://wiki.ubuntuusers.de/WireGuard)): + +``` bash +#!/bin/bash +# Check state of wg0 interface +wgstatus=$(wg) +if [ "$wgstatus" == "interface: wg0" ]; then + ip link delete wg0 && ifup wg0 +elif [ "$wgstatus" == "interface: wg0" ]; then + ifup wg0 +else + file="/tmp/digIP.txt" + digIP=$(dig +short beispiel2.domain.de) # Change this to your domain ! + if [ -e "$file" ]; then + fileTXT=$(cat "$file") + if [ "$digIP" != "$fileTXT" ]; then + #echo "Daten sind gleich" + /sbin/ifdown wg0 + /sbin/ifup wg0 + echo "$digIP" > "$file" + fi + else + echo "$digIP" > "$file" + fi +fi +``` + +Store this file as `/home/[user name]/wg-restart.sh` and add it to your `crontab`: + +``` bash +sudo crontab -e +``` + +``` plain +*/10 * * * * bash /home/[user name]/wg-restart.sh # Runs the script every 10 minutes +``` + +## Routes are periodically reset + +Users of NetworkManager should make sure that it is not managing the WireGuard interface(s). For example, create the configuration file `/etc/NetworkManager/conf.d/unmanaged.conf` with content + +``` toml +[keyfile] +unmanaged-devices=interface-name:wg* +``` + +[source](https://wiki.archlinux.org/index.php/WireGuard) + +## Broken DNS resolution + +When tunneling all traffic through a WireGuard interface, the connection can become seemingly lost after a while or upon new connection. This could be caused by a network manager or DHCP client overwriting `/etc/resolv.conf`. +By default, `wg-quick` uses `resolvconf` to register new DNS entries (from the DNS keyword in the configuration file). This will cause issues with network managers and DHCP clients that do not use `resolvconf`, as they will overwrite `/etc/resolv.conf` thus removing the DNS servers added by `wg-quick`. + +The solution is to use networking software that supports `resolvconf`. + +!!! info "Hint for Ubuntu users" + Users of `systemd-resolved` should make sure that `systemd-resolvconf` is installed. + +[source](https://wiki.archlinux.org/index.php/WireGuard) + +## Low MTU + +Due to too low MTU (lower than 1280), `wg-quick` may fail to create the WireGuard interface. This can be solved by setting the MTU value in WireGuard configuration in Interface section on client: + +``` toml +[Interface] +MTU = 1500 +``` + +[source](https://wiki.archlinux.org/index.php/WireGuard) diff --git a/docs/guides/wireguard/internal.md b/docs/guides/wireguard/internal.md new file mode 100644 index 0000000..2405b65 --- /dev/null +++ b/docs/guides/wireguard/internal.md @@ -0,0 +1,71 @@ +# Access devices in the internal network through the WireGuard tunnel + +## Enable IP forwarding on the server + +Enable IP forwarding on your server by removing the comments in front of + +``` toml +net.ipv4.ip_forward = 1 +net.ipv6.conf.all.forwarding = 1 +``` + +in the file `/etc/sysctl.d/99-sysctl.conf` + +Then apply the new option with the command below. + +``` bash +sudo sysctl -p +``` + +If you see the options repeated like + +``` plain +net.ipv4.ip_forward=1 +``` + +they were enabled successfully. + +A properly configured firewall is ***highly*** recommended for any Internet-facing device. Configuring a firewall (`iptables`, `ufw`, etc.) is not part of this guide. + +## Enable NAT on the server + +!!! info "Optional for NAT" + If the server is behind a router and receives traffic via NAT, these iptables rules are not needed. + +On your server, add the following to the `[INTERFACE]` section: + +``` toml +PostUp = iptables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -A POSTROUTING -o eth0 -j MASQUERADE +PostDown = iptables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -w -t nat -D POSTROUTING -o eth0 -j MASQUERADE +``` + +!!! warning "Substitute interface" + Substitute `eth0` in the preceding lines to match the Internet-facing interface. + +??? info "The `PostUp` and `PostDown` options" + `PostUp` and `PostDown` defines steps to be run after the interface is turned on or off, respectively. In this case, iptables is used to set Linux IP masquerade rules to allow all the clients to share the server’s IPv4 and IPv6 address. + The rules will then be cleared once the tunnel is down. + +## Allow clients to access other devices + +In our standard configuration, we have configured the clients in such a way that they can only speak to the server. This has to be changed on both the server and the clients. + +### Server side + +``` toml +[Peer] +AllowedIPs = 10.100.0.1/32 +``` + +Change this to + +``` toml +[Peer] +AllowedIPs = 10.100.0.1/32, 192.168.2.1/24 +``` + +if your internal network is in the IP range `192.168.2.1` - `192.168.2.254`. + +### Client side + +Do the same in the `[Interface]` section. diff --git a/docs/guides/wireguard/overview.md b/docs/guides/wireguard/overview.md new file mode 100644 index 0000000..babbd8d --- /dev/null +++ b/docs/guides/wireguard/overview.md @@ -0,0 +1,30 @@ +### Remote accessing Pi-hole using WireGuard + +WireGuard is an ***extremely simple yet fast and modern VPN*** that utilizes state-of-the-art cryptography. Comparing to other solutions, such as OpenVPN or IPsec, it aims to be **faster, simpler and leaner** while avoiding the massive overhead involved with other VPN solutions. +A combination of extremely high-speed cryptographic primitives and the fact that WireGuard lives +inside the Linux kernel means that secure networking can be very high-speed. +It intends to be considerably more performant than OpenVPN. + +WireGuard is designed as a general purpose VPN for running on embedded interfaces and super computers alike, fit for many circumstances. + +There is no need to manage connections, be concerned about state, manage daemons, or worry about what's under the hood. WireGuard presents an extremely basic yet powerful interface. + +Using WireGuard is a modern and safe way to access your Pi-hole's capabilities remotely. Setting up a DNS server has become a simple task with Pi-hole's automated installer, which has resulted in many people knowingly--or unknowingly--creating an open resolver, which aids in DNS Amplification Attacks. + +WireGuard has been designed with ease-of-implementation and simplicity in mind. It is meant to be +easily implemented in very few lines of code, and easily auditable for security vulnerabilities. + +This article aims to provide a step-by-step walk-through on setting up a server running Pi-hole and WireGuard so you can securely connect to your Pi-hole's DNS (and *optionally* your entire internal network) from anywhere. + +**This tutorial walks you through the installation of a WireGuard server on your Pi-hole**. + +Via this VPN, you can: + +- use the full filtering capabilities of your Pi-hole +- access your Pi-hole dashboard remotely +- access all your internal devices (*optional*) +- reroute your entire Internet traffic through your Pi-hole (*optional*) + +from everywhere around the globe. + +{!abbreviations.md!} diff --git a/docs/guides/wireguard/route-everything.md b/docs/guides/wireguard/route-everything.md new file mode 100644 index 0000000..1363222 --- /dev/null +++ b/docs/guides/wireguard/route-everything.md @@ -0,0 +1,13 @@ +Routing your entire Internet traffic is **optional**, however, it can be advantageous in cases where you are expecting eavesdropping on the network. This may not only happen in unsecure open Wi-Fi networks (airports, hotels, trains, etc.) but also in encrypted Wi-Fi networks where the creator of the network can monitor client activity. + +Rerouting the Internet traffic through your Pi-hole will furthermore cause all of your Internet traffic to reach the Internet from the place where your WireGuard server is located. This can be used to obfuscate your real location as well as to be allowed to access geo-blocked content, e.g., when your Pi-hole is located in Germany but you are traveling in the United States. If you want to access a page only accessible from within Germany (like the live-broadcast of Tagesschau, etc.), this will typically not work. However, if you route your entire Internet through your Pi-hole, your network traffic will originate from Germany, allowing you to watch the content. + +To route all traffic through the tunnel to a specific peer, add the default route (`0.0.0.0/0` for IPv4 and `::/0`for IPv6) to `AllowedIPs` in your WireGuard config files: + +```toml +AllowedIPs = 0.0.0.0/0, ::/0 +``` + +Do **not** set this on the server in the `[Interface]` section. WireGuard will automatically take care of setting up [correct routing](https://www.wireguard.com/netns/#routing-all-your-traffic) so that networking still functions on all your clients. + +That's all you need to do. diff --git a/docs/guides/wireguard/server.md b/docs/guides/wireguard/server.md new file mode 100644 index 0000000..da18b83 --- /dev/null +++ b/docs/guides/wireguard/server.md @@ -0,0 +1,110 @@ +# Installing the WireGuard server + + +!!! info "The terms "server" and "client"" + Usage of the terms `server` and `client` were purposefully chosen in this guide specifically to help both new users and existing OpenVPN users become familiar with the construction of WireGuard's configuration files. + + WireGuard documentation simply refers to both of these concepts as `peers`. + + +## Installing the server components + +Installing everything we will need for a `wireguard` connections is as simple as running: + +``` bash +sudo apt-get install wireguard wireguard-tools wireguard-dkms +``` + +For Ubuntu 18.04 and lower, you need to do some extra steps: + +``` bash +sudo add-apt-repository ppa:wireguard/wireguard +sudo apt update +sudo apt install wireguard wireguard-tools wireguard-dkms +``` + +## Initial configuration + +Each network interface has a private key and a list of peers. Each peer has a public key. Public keys are short and simple, and are used by peers to authenticate each other. They can be passed around for use in configuration files by any out-of-band method, similar to how one might send their SSH public key to a friend for access to a shell server. + +First, we create the folder containing our `wireguard` configuration: + +``` bash +sudo -i +cd /etc/wireguard +umask 077 +``` + +### Key generation + +Inhere, we generate a key-pair for the server: + +``` bash +wg genkey | tee server.key | wg pubkey > server.pub +``` + +### Creating the WireGuard configuration + +Create a config file + +``` bash +sudo nano /etc/wireguard/wg0.conf +``` + +and put the following into it: + +``` toml +[Interface] +Address = 10.100.0.1/24 +ListenPort = 44711 +SaveConfig = true +``` + +Then run + +``` bash +echo "PrivateKey = $(cat server.key)" >> /etc/wireguard/wg0.conf +``` + +to copy the server's private key into your config file. + +## Forward port + +If the server is behind NAT, be sure to forward the specified port on which WireGuard will be running (for this example, `44711/UDP`) from the router to the WireGuard server. + +## Start the server + +Register your server `wg0` as: + +``` bash +systemctl enable wg-quick@wg0.service +systemctl daemon-reload +systemctl start wg-quick@wg0 +``` + +If successful, you should not see any output. In case you get an error like + +``` plain +RTNETLINK answers: Operation not supported +Unable to access interface: Protocol not supported +``` + +you should check that the WireGuard kernel module is loaded with the command below: + +```bash +sudo modprobe wireguard +``` + +If you get an error saying the module is missing, try reinstalling WireGuard or restart your server and try again. This may happen when the WireGuard server is installed for a more recent kernel than you are currently running. This typically happens when you have neither updated nor restarted your system for a long time. + +## Check everything is running + +With the following command, you can check if your `wireguard` server is running: + +``` bash +wg +``` + +You can now continue to add clients. + +{!abbreviations.md!} diff --git a/mkdocs.yml b/mkdocs.yml index 5efd672..505ae0e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -99,6 +99,15 @@ nav: - 'Configuring Caddy for Pi-hole': guides/caddy-configuration.md - 'Configuring Traefik for Pi-hole (not in Docker)': guides/traefik-configuration-nodocker.md - 'Benchmarking': guides/benchmark.md + - 'Remote accessing Pi-hole using WireGuard': + - 'Overview': guides/wireguard/overview.md + - 'Concept': guides/wireguard/concept.md + - 'Install server': guides/wireguard/server.md + - 'Add client(s)': guides/wireguard/client.md + - 'Optional extra features': + - 'Make all local devices accessible': guides/wireguard/internal.md + - 'Reroute all Internet traffic': guides/wireguard/route-everything.md + - 'Troubleshooting': guides/wireguard/faq.md - 'Pi-hole and OpenVPN Server': - 'Overview': guides/vpn/overview.md - 'Installation': guides/vpn/installation.md