Merge pull request #25 from pi-hole/fix/vpnguide

Update VPN docs from last wiki revision
This commit is contained in:
Adam Warner
2018-05-22 20:44:42 +01:00
committed by GitHub
4 changed files with 232 additions and 113 deletions
+37 -5
View File
@@ -1,7 +1,39 @@
1. Install the official OpenVPN App
See [App Store](https://play.google.com/store/apps/details?id=net.openvpn.openvpn)
Full article: https://github.com/pi-hole/pi-hole/wiki/Pi-hole---OpenVPN-server
2. Create a new certificate as described [here](clients.md#create-certificate)
1. Install the official OpenVPN App from the [App Store](https://play.google.com/store/apps/details?id=net.openvpn.openvpn)
2. Log into your OpenVPN server and use the road warrior installer to create a new certificate for your device:
```
root@ubuntu-512mb-fra1-01:~# bash openvpn-install.sh
Looks like OpenVPN is already installed
What do you want to do?
1) Add a cert for a new user
2) Revoke existing user cert
3) Remove OpenVPN
4) Exit
Select an option [1-4]: 1
Tell me a name for the client cert
Please, use one word only, no special characters
Client name: android
Generating a 2048 bit RSA private key
.....+++
..................................+++
writing new private key to '...'
-----
Using configuration from /etc/openvpn/easy-rsa/openssl-1.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'android'
Certificate is to be certified until Jan 25 15:07:37 2027 GMT (3650 days)
Write out database with 1 new entries
Data Base Updated
Client android added, configuration is available at /root/android.ovpn
```
3. Copy the mentioned file (`/root/android.ovpn`) to your Android device (e.g. SD card) and import it in the app:
@@ -15,8 +47,8 @@
4. Connect to your OpenVPN server
![](Android-Connected.png)
![](Android-Connected.png)
5. You are ready to go!
![](Android-Pi-hole.png)
![](Android-Pi-hole.png)
+41 -29
View File
@@ -1,49 +1,62 @@
### Connect from a client
There are various tutorials available for all operating systems for how to connect to an OpenVPN server.
## Create a client config file (`.ovpn`)
Now that the server is configured, you'll want to connect some clients so you can make use of your Pi-hole wherever you are. Doing so requires the use of a certificate. You generate these and the resulting `.ovpn` file by running the installer and choosing `1) Add a new user` for each client that will connect to the VPN.
You can repeat this process for as many clients as you need. In this example, we'll "Add a new user" by naming the `.ovpn` file the same as the client's hostname but you may want to adopt your own naming strategy.
Run the OpenVPN installer again
### Create certificate
Log into your OpenVPN server and use the road warrior installer to create a new certificate for your client:
```
bash openvpn-install.sh
./openvpn-install.sh
```
Choose `1) Add a new user` and enter a client name
```
Looks like OpenVPN is already installed
What do you want to do?
1) Add a cert for a new user
2) Revoke existing user cert
1) Add a new user
2) Revoke an existing user
3) Remove OpenVPN
4) Exit
Select an option [1-4]: 1
Tell me a name for the client cert
Tell me a name for the client certificate
Please, use one word only, no special characters
Client name: android
Generating a 2048 bit RSA private key
.....+++
..................................+++
writing new private key to '...'
-----
Using configuration from /etc/openvpn/easy-rsa/openssl-1.0.cnf
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'android'
Certificate is to be certified until Jan 25 15:07:37 2027 GMT (3650 days)
Write out database with 1 new entries
Data Base Updated
Client android added, configuration is available at /root/android.ovpn
Client name: iphone7
```
**WARNING** Anyone who gets his hands on this configuration/certificate file can obtain full access to your VPN. Make sure that you use only trusted paths for transferring the file (e.g. *never* send it via an un-encrypted channel, e.g. email or FTP). Best strategy is to use a USB thumb drive to avoid any network transport at all. Make sure to delete the certificate on the USB drive afterwards.
This will generate a `.ovpn` file, which needs to be copied to your client machine (often times using the OpenVPN app). This process also generates a few other files found in `/etc/openvpn/easy-rsa/pki/`, which make public key authentication possible; you only need to worry about the `.ovpn` file, though.
**NOTICE** If one of your certificates has been compromised, remove it using option `2` (see above) and generate a new certificate. This will effectively lock out anyone who might have gotten access to the certificate.
## Connect a client using the `.ovpn` file
The OpenVPN documentation has some decent [guides on connecting desktop clients for Mac, Windows, and Linux](https://openvpn.net/index.php/access-server/docs/admin-guides-sp-859543150/howto-connect-client-configuration.html), so we'll instead explain how to connect a mobile device, since that provides the most usefulness in today's world--**connecting to your ad-blocking VPN via a mobile device**. We'll go through two examples:
1. connect an iPhone using the OpenVPN Connect mobile app (see [here](https://github.com/pi-hole/pi-hole/wiki/OpenVPN-server:-Connect-from-a-client-(Android)) for Android)
2. connect a Linux machine
### iOS
First make sure the OpenVPN connect app is installed on your phone or mobile device.
Import the `.ovpn` file into iOS. There are several ways to do this, but be careful about transferring it over an insecure medium.
1. Airdrop the file from another device
2. Store the file in a cloud app and open it ion your device
3. Message the file to yourself (not recommended)
4. Email the file to yourself (not recommended)
>**WARNING** Anyone who gets his hands on this configuration/certificate file can obtain full access to your VPN. Make sure that you use only trusted paths for transferring the file (e.g. never send it via an un-encrypted channel, e.g. email or FTP). Best strategy is to use an USB thumb drive to avoid any network transport at all (when possible). Make sure to delete the certificate on the USB drive afterwards.
>**NOTICE** If one of your certificates has been compromised, remove it using option 2 when you run the installer and generate a new certificate. This will effectively lock out anyone who might have gotten access to the certificate.
Once you get it on your device, you can open the file in the OpenVPN app.
Click the green plus to add the profile to your phone.
You can connect from within the app or you can connect from the Settings app once you grant it access to do so.
### Linux
I'll demonstrate the procedure here for Ubuntu Linux (which trivially extends to Linux Mint, etc.)
We'll demonstrate the procedure here for Ubuntu Linux (which trivially extends to Linux Mint, etc.)
1. Install the necessary network-manager plugins
```
@@ -67,7 +80,6 @@ Further details can be found in the screenshots provided below:
![](NetworkManager5.png)
![](NetworkManager6.png)
![](NetworkManager7.png)
Your whole network traffic will now securely be transferred to your Pi-hole.
![](VPNclients.png)
+151 -77
View File
@@ -1,93 +1,167 @@
### Optional: Firewall configuration (using iptables)
If your server is visible to the world, you will want prevent port 53/80 from being accessible from the global Internet. You will want be only able to connect to your Pi-hole from within the VPN.
### (optional) Secure the server with firewall rules (`iptables`)
**This step is recommended if you are running your server in the cloud, such as a droplet made on [Digital Ocean](http://www.digitalocean.com/?refcode=344d234950e1)**. If this is the case, you need to secure the server for your safety as well as others to prevent aiding in DDoS attacks.
In addition to the risk of being an open resolver, your Web interface is also open to the world increasing the risk. So you will want to prevent ports 53 and 80, respectively, from being accessible from the public Internet.
It's recommended that you [clear out your entire firewall](https://serverfault.com/questions/200635/best-way-to-clear-all-iptables-rules) so you have full control over it's setup. You have two options for setting up your firewall with your VPN.
#### Option 1: Allow everything from within your VPN
Enter this command, which will allow all traffic through the VPN `tun0` interface.
Using `iptables`: First, verify that there is no rule that explicitly accepts `http` requests
```
sudo iptables -L --line-numbers
iptables -I INPUT -i tun0 -j ACCEPT
```
If you get something like
```
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- anywhere anywhere tcp dpt:http
2 ACCEPT tcp -- anywhere anywhere tcp dpt:domain
3 ACCEPT udp -- anywhere anywhere udp dpt:domain
#### Option 2: Explicitly allow what can be accessed within the VPN
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
These commands will allow DNS and HTTP needed for name resolution (using Pi-hole as a resolver) and accessing the Web interface, respectively.
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
```
you have to first explicitly delete the first INPUT rule using:
```
sudo iptables -D INPUT 1
iptables -A INPUT -i tun0 -p tcp --destination-port 53 -j ACCEPT
iptables -A INPUT -i tun0 -p udp --destination-port 53 -j ACCEPT
iptables -A INPUT -i tun0 -p tcp --destination-port 80 -j ACCEPT
```
We recommend that you empty out the firewall so you have full control over its setup.
You will also want to enable SSH and VPN access from anywhere.
For setting up your firewall in conjunction with your VPN you have **TWO** options:
Option 1: Allow everything within your VPN:
```
sudo iptables -I INPUT -i tun0 -j ACCEPT
```
or
Option 2: Explicitly allow what can be accessed from within the VPN:
```
sudo iptables -A INPUT -i tun0 -p tcp --destination-port 53 -j ACCEPT
sudo iptables -A INPUT -i tun0 -p udp --destination-port 53 -j ACCEPT
sudo iptables -A INPUT -i tun0 -p tcp --destination-port 80 -j ACCEPT
sudo iptables -A INPUT -i tun0 -p udp --destination-port 80 -j ACCEPT
```
Obviously, it is important to enable SSH and VPN access from anywhere
```
sudo iptables -A INPUT -p tcp --destination-port 22 -j ACCEPT
sudo iptables -A INPUT -p tcp --destination-port 1194 -j ACCEPT
sudo iptables -A INPUT -p udp --destination-port 1194 -j ACCEPT
iptables -A INPUT -p tcp --destination-port 22 -j ACCEPT
iptables -A INPUT -p tcp --destination-port 1194 -j ACCEPT
iptables -A INPUT -p udp --destination-port 1194 -j ACCEPT
```
The next crucial setting is to explicitly allow TCP/IP to do "three way handshakes":
```
sudo iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
```
Also, we want to allow any loopback traffic, i.e. the Pi is allowed to talk to itself without any limitations using `127.0.0.0/8`:
```
sudo iptables -I INPUT -i lo -j ACCEPT
```
Finally, prevent access from anywhere else (i.e. if no rule has matched up to this point):
```
sudo iptables -P INPUT DROP
```
Optional: If you want to allow access to the Pi-hole from within the VPN *and* from the local network, you will have to explicitly allow your local network as well (assuming the local network is within the address space 192.168.**178**.1 - 192.168.**178**.254):
```
sudo iptables -A INPUT -s 192.168.178.0/24 -p tcp --destination-port 53 -j ACCEPT
sudo iptables -A INPUT -s 192.168.178.0/24 -p udp --destination-port 53 -j ACCEPT
sudo iptables -A INPUT -s 192.168.178.0/24 -p tcp --destination-port 80 -j ACCEPT
sudo iptables -A INPUT -s 192.168.178.0/24 -p udp --destination-port 80 -j ACCEPT
```
See also [this](https://discourse.pi-hole.net/t/pihole-vpn-with-iptables/2384) thread on Discourse.
---
### Optional: IPv6
Note that you will have to repeat the firewall setup using `ip6tables` if your server is also reachable via IPv6:
```
sudo ip6tables -A INPUT -i tun0 -p tcp --destination-port 53 -j ACCEPT
sudo ip6tables -A INPUT -i tun0 -p tcp --destination-port 80 -j ACCEPT
sudo ip6tables -A INPUT -i tun0 -p udp --destination-port 53 -j ACCEPT
sudo ip6tables -A INPUT -i tun0 -p udp --destination-port 80 -j ACCEPT
sudo ip6tables -A INPUT -p tcp --destination-port 22 -j ACCEPT
sudo ip6tables -A INPUT -p tcp --destination-port 1194 -j ACCEPT
sudo ip6tables -A INPUT -p udp --destination-port 1194 -j ACCEPT
sudo ip6tables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo ip6tables -I INPUT -i lo -j ACCEPT
sudo ip6tables -P INPUT DROP
```
iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
```
Also, we want to allow any loopback traffic, i.e. the server is allowed to talk to itself without any limitations using 127.0.0.0/8:
```
iptables -I INPUT -i lo -j ACCEPT
```
Finally, reject access from anywhere else (i.e. if no rule has matched up to this point):
```
iptables -P INPUT DROP
```
###### Blocking HTTPS advertisement assets
Since you're `:head-desk:`ing with `iptables`, you can also use this opportunity to block HTTPS advertisements to [improve blocking ads that are loaded via HTTPS](https://discourse.pi-hole.net/t/why-do-some-sites-take-forever-to-load-when-using-pi-hole/3654/4) and also deal with QUIC.
> Why doesn't Pi-hole just use a certificate to prevent this? The answer is [here](https://discourse.pi-hole.net/t/slow-loading-websites/3408/12).
```
iptables -A INPUT -p udp --dport 80 -j REJECT --reject-with icmp-port-unreachable
iptables -A INPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset
iptables -A INPUT -p udp --dport 443 -j REJECT --reject-with icmp-port-unreachable
```
Depending on the systems you have connecting, you may benefit from appending `--reject-with tcp-reset` to the command above. If you still get slow load times of HTTPS assets, the above may help.
If you want to test how your Pi-hole behaves with blocking HTTP vs. HTTPS assets, use [this page](https://pi-hole.net/pages-to-test-ad-blocking-performance/#https-test).
##### IPv6 `iptables`
If your server is reachable via IPv6, you'll need to run the same commands but using `ip6tables`:
```
ip6tables -A INPUT -i tun0 -p tcp --destination-port 53 -j ACCEPT
ip6tables -A INPUT -i tun0 -p udp --destination-port 53 -j ACCEPT
ip6tables -A INPUT -i tun0 -p tcp --destination-port 80 -j ACCEPT
ip6tables -A INPUT -p tcp --destination-port 22 -j ACCEPT
ip6tables -A INPUT -p tcp --destination-port 1194 -j ACCEPT
ip6tables -A INPUT -p udp --destination-port 1194 -j ACCEPT
ip6tables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -I INPUT -i lo -j ACCEPT
ip6tables -A INPUT -p udp --dport 80 -j REJECT --reject-with icmp6-port-unreachable
ip6tables -A INPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset
ip6tables -A INPUT -p udp --dport 443 -j REJECT --reject-with icmp6-port-unreachable
ip6tables -P INPUT DROP
```
View the rules you just created
```
iptables -L --line-numbers
```
and they should look something like this:
```
Chain INPUT (policy DROP)
num target prot opt source destination
1 ACCEPT all -- anywhere anywhere
2 ACCEPT all -- anywhere anywhere state RELATED,ESTABLISHED
3 ACCEPT all -- anywhere anywhere
4 ACCEPT tcp -- anywhere anywhere tcp dpt:domain
5 ACCEPT udp -- anywhere anywhere udp dpt:domain
6 ACCEPT tcp -- anywhere anywhere tcp dpt:http
7 ACCEPT udp -- anywhere anywhere udp dpt:80
8 ACCEPT tcp -- anywhere anywhere tcp dpt:ssh
9 ACCEPT tcp -- anywhere anywhere tcp dpt:openvpn
10 ACCEPT udp -- anywhere anywhere udp dpt:openvpn
11 ACCEPT tcp -- 10.8.0.0/24 anywhere tcp dpt:domain
12 ACCEPT udp -- 10.8.0.0/24 anywhere udp dpt:domain
13 ACCEPT tcp -- 10.8.0.0/24 anywhere tcp dpt:http
14 ACCEPT udp -- 10.8.0.0/24 anywhere udp dpt:80
15 ACCEPT tcp -- 10.8.0.0/24 anywhere tcp dpt:domain
16 ACCEPT tcp -- 10.8.0.0/24 anywhere tcp dpt:http
17 ACCEPT udp -- 10.8.0.0/24 anywhere udp dpt:domain
18 ACCEPT udp -- 10.8.0.0/24 anywhere udp dpt:80
19 REJECT tcp -- anywhere anywhere tcp dpt:https reject-with icmp-port-unreachable
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
```
Similarly, `ip6tables -L --line-numbers` should look like this:
```
Chain INPUT (policy DROP)
num target prot opt source destination
1 ACCEPT all anywhere anywhere
2 ACCEPT all anywhere anywhere state RELATED,ESTABLISHED
3 ACCEPT tcp anywhere anywhere tcp dpt:domain
4 ACCEPT udp anywhere anywhere udp dpt:domain
5 ACCEPT tcp anywhere anywhere tcp dpt:http
6 ACCEPT udp anywhere anywhere udp dpt:80
7 ACCEPT tcp anywhere anywhere tcp dpt:ssh
8 ACCEPT tcp anywhere anywhere tcp dpt:openvpn
9 ACCEPT udp anywhere anywhere udp dpt:openvpn
10 REJECT tcp anywhere anywhere tcp dpt:https reject-with icmp6-port-unreachable
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination
```
##### Verify the rules are working
Connect to the VPN as a client and verify you can resolve DNS names as well as access the Pi-hole Web interface. These settings are stored in memory until you save them. If it's not working, you can restart your server to start from scratch. Alternatively, you could also go through and delete lines with `iptables -D INPUT <SOME LINE NUMBER>`
#### Save your `iptables`
If things look good, you may want to save your rules so you can revert to them if you ever make changes to the firewall. Save them with these commands:
```
iptables-save > /etc/pihole/rules.v4
ip6tables-save > /etc/pihole/rules.v6
```
Similarly, you can restore these rules:
```
iptables-restore < /etc/pihole/rules.v4
ip6tables-restore < /etc/pihole/rules.v6
```
---
+3 -2
View File
@@ -1,8 +1,9 @@
### Optional: Only route DNS via VPN
With this setup you will force connected clients to use only the DNS provided by the VPN connection, i.e. the Pi-hole. Do this only if you **don't** want to tunnel all traffic from the client thru the VPN, but only its DNS queries.
With this setup, you will force connected clients to use **only the DNS provided by the VPN connection, i.e. the Pi-hole.** Do this only if you **don't** want to tunnel all traffic from the client through the VPN, but only its DNS queries.
Edit your `/etc/openvpn/server.conf` and remove (comment out) the following line:
Edit your `/etc/openvpn/server.conf` and remove (comment) the following line:
```
# push "redirect-gateway def1 bypass-dhcp"
```