Ā
Ā
What the heck is a VPN?
A virtual private network, or VPN, is an encrypted connection over the Internet from a device to a network. The encrypted connection helps ensure that sensitive data is safely transmitted. It prevents unauthorized people from eavesdropping on the traffic and allows the user to conduct work remotely. VPN technology is widely used in corporate environments.
Ā
What are the available VPN providers in the market?
- Express VPN
- Nord VPN
- Surfshark
- OpenVPN
- Tailscale
Ā
Why to use a third party VPN provider and why not?
Why NOT?
- When you use a VPN service, your activity is only encrypted until it reaches the endpoint for that service. All of your activities can be monitored and logged by that VPN provider.
- No support for ad-blocking and trackers online.
- Probable breach/sell of data.
- Data transfer speed caps.
Why you should?
- You can switch to multiple countries, you can still do it with self hosted, but the infrastructure would cost you more than a regular VPN service provider.
Ā
Ā
What is OpenVPN?
OpenVPNĀ is a self-hostedĀ virtual private networkĀ (VPN) system that implements techniques to create secure point-to-point or site-to-site connections in routed or bridged configurations and remote access facilities. It implements bothĀ client and serverĀ applications.
OpenVPN allowsĀ peersĀ toĀ authenticateĀ each other usingĀ pre-shared secret keys,Ā certificatesĀ orĀ username/password. When used in a multiclient-server configuration, it allows the server to release an authentication certificate for every client, usingĀ signaturesĀ andĀ certificate authority.
It uses theĀ OpenSSLĀ encryptionĀ libraryĀ extensively, as well as theĀ TLSĀ protocol, and contains many security and control features. It uses a custom security protocol[11]Ā that utilizesĀ SSL/TLSĀ for key exchange.
Ā
Enough talk š¬, is it free?
Ā
Yes, OpenVPN is open-source and free to use software, which means you pay only for the infrastructure you setup
Ā
GitHub:
openvpn
OpenVPN ā¢ Updated Jan 26, 2024
Ā
What is and Why Docker š, why not install bare-metal?
> The future is container(ising) your software, easy replication of your infra, auto recovery on failureā¦ā¦ā¦
Talk is cheap, guide me through the setup.
To use a VPN you need an always on computing power, we will harness the power of the cloud for this case.
To technically state, I would be using Microsoft Azureās Virtual Machines
Ā
Technical Setup š»
- After you have signed up for Azure, and have a billing method/credit setup in your account, visit: https://portal.azure.com/#home
- You should be greeted with a dashboard similar to this.
- Create a resource, in Azure any VM/Database you setup, is called a resource.
- Please specify:
- A name for the virtual machine
- A region where you want the vpn connection to be made. (this is a very crucial step, keep it in mind)
- A machine size, there are a plethora of options to select, please check the pricing page of Azure, anyway the vm should have >1GB RAM
- Now we are pretty much done setting up the VM, click the Review + create button to Azure do the magic creating the vm for you. We wonāt fiddle with next options, as this is just a demo, if you want you can fiddle around with other options.
- Visit the template repository, and either fork/clone/use the template in your github account.
Ā
After the instance details are specified, come down to setup login creds to the vm.
I have selected SSH pub-key based auth to the vm, since it would provide more security than password based security, as I need to carry the private key with me to login to the vm.
Ā
Give a moment for the VM to be created. Also, I would be providing the azure automation template JSON āØ if you do not want to go through the above steps.
JSON template
{ "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#", "contentVersion": "1.0.0.0", "parameters": { "location": { "type": "string" }, "networkInterfaceName": { "type": "string" }, "networkSecurityGroupName": { "type": "string" }, "networkSecurityGroupRules": { "type": "array" }, "subnetName": { "type": "string" }, "virtualNetworkName": { "type": "string" }, "addressPrefixes": { "type": "array" }, "subnets": { "type": "array" }, "publicIpAddressName": { "type": "string" }, "publicIpAddressType": { "type": "string" }, "publicIpAddressSku": { "type": "string" }, "pipDeleteOption": { "type": "string" }, "virtualMachineName": { "type": "string" }, "virtualMachineComputerName": { "type": "string" }, "virtualMachineRG": { "type": "string" }, "osDiskType": { "type": "string" }, "osDiskDeleteOption": { "type": "string" }, "virtualMachineSize": { "type": "string" }, "nicDeleteOption": { "type": "string" }, "adminUsername": { "type": "string" }, "adminPublicKey": { "type": "secureString" } }, "variables": { "nsgId": "[resourceId(resourceGroup().name, 'Microsoft.Network/networkSecurityGroups', parameters('networkSecurityGroupName'))]", "vnetName": "[parameters('virtualNetworkName')]", "vnetId": "[resourceId(resourceGroup().name,'Microsoft.Network/virtualNetworks', parameters('virtualNetworkName'))]", "subnetRef": "[concat(variables('vnetId'), '/subnets/', parameters('subnetName'))]" }, "resources": [ { "name": "[parameters('networkInterfaceName')]", "type": "Microsoft.Network/networkInterfaces", "apiVersion": "2021-03-01", "location": "[parameters('location')]", "dependsOn": [ "[concat('Microsoft.Network/networkSecurityGroups/', parameters('networkSecurityGroupName'))]", "[concat('Microsoft.Network/virtualNetworks/', parameters('virtualNetworkName'))]", "[concat('Microsoft.Network/publicIpAddresses/', parameters('publicIpAddressName'))]" ], "properties": { "ipConfigurations": [ { "name": "ipconfig1", "properties": { "subnet": { "id": "[variables('subnetRef')]" }, "privateIPAllocationMethod": "Dynamic", "publicIpAddress": { "id": "[resourceId(resourceGroup().name, 'Microsoft.Network/publicIpAddresses', parameters('publicIpAddressName'))]", "properties": { "deleteOption": "[parameters('pipDeleteOption')]" } } } } ], "networkSecurityGroup": { "id": "[variables('nsgId')]" } } }, { "name": "[parameters('networkSecurityGroupName')]", "type": "Microsoft.Network/networkSecurityGroups", "apiVersion": "2019-02-01", "location": "[parameters('location')]", "properties": { "securityRules": "[parameters('networkSecurityGroupRules')]" } }, { "name": "[parameters('virtualNetworkName')]", "type": "Microsoft.Network/virtualNetworks", "apiVersion": "2021-01-01", "location": "[parameters('location')]", "properties": { "addressSpace": { "addressPrefixes": "[parameters('addressPrefixes')]" }, "subnets": "[parameters('subnets')]" } }, { "name": "[parameters('publicIpAddressName')]", "type": "Microsoft.Network/publicIpAddresses", "apiVersion": "2020-08-01", "location": "[parameters('location')]", "properties": { "publicIpAllocationMethod": "[parameters('publicIpAddressType')]" }, "sku": { "name": "[parameters('publicIpAddressSku')]" } }, { "name": "[parameters('virtualMachineName')]", "type": "Microsoft.Compute/virtualMachines", "apiVersion": "2022-03-01", "location": "[parameters('location')]", "dependsOn": [ "[concat('Microsoft.Network/networkInterfaces/', parameters('networkInterfaceName'))]" ], "properties": { "hardwareProfile": { "vmSize": "[parameters('virtualMachineSize')]" }, "storageProfile": { "osDisk": { "createOption": "fromImage", "managedDisk": { "storageAccountType": "[parameters('osDiskType')]" }, "deleteOption": "[parameters('osDiskDeleteOption')]" }, "imageReference": { "publisher": "canonical", "offer": "0001-com-ubuntu-server-focal", "sku": "20_04-lts-gen2", "version": "latest" } }, "networkProfile": { "networkInterfaces": [ { "id": "[resourceId('Microsoft.Network/networkInterfaces', parameters('networkInterfaceName'))]", "properties": { "deleteOption": "[parameters('nicDeleteOption')]" } } ] }, "osProfile": { "computerName": "[parameters('virtualMachineComputerName')]", "adminUsername": "[parameters('adminUsername')]", "linuxConfiguration": { "disablePasswordAuthentication": true, "ssh": { "publicKeys": [ { "path": "[concat('/home/', parameters('adminUsername'), '/.ssh/authorized_keys')]", "keyData": "[parameters('adminPublicKey')]" } ] } } }, "diagnosticsProfile": { "bootDiagnostics": { "enabled": true } } } } ], "outputs": { "adminUsername": { "type": "string", "value": "[parameters('adminUsername')]" } } }
Ā
Log in to your created VM instance using SSH and install docker and docker-compose on it (Compose isĀ a tool for defining and running multi-container Docker applications With Compose, you use a YAML file to configure your application's services.)
Here are the setup, I am leaving Docker setup on you, or just Ctrl + C, Ctrl + V
the below code using aptitude to install docker and docker-compose.
sudo apt-get update -y sudo apt-get upgrade -y # Install Docker from repository sudo apt install docker.io -y # Enable the docker daemon. systemctl start docker systemctl enable docker # Check whether docker is installed. docker --version ####################################### # Install docker-compose ####################################### D_COMP_URL="https://github.com/docker/compose/releases/download/v2.12.0/docker-compose-$(uname -s)-$(uname -m)" # Print the evironment variable set | grep D_COMP_URL sudo curl -SL $D_COMP_URL -o /usr/local/bin/docker-compose sudo chmod +x /usr/local/bin/docker-compose docker-compose --version
If you share your VPN with others it's highly recommended changing the admin password for the PiHole dashboard in theĀ docker-compose.ymlĀ file now.
After you've installed all the pre-requisites you can run the below in bash shell.
sudo docker-compose up -d
You can use my version or the repo version of the docker-compose script as a reference.
nooobcoderās docker-compose.yaml
version: "3.5" services: openvpn: container_name: openvpn build: ./openvpn-docker ports: - 1194:1194/udp networks: vpn-net: ipv4_address: 172.20.0.3 environment: REQ_COUNTRY: US REQ_PROVINCE: California REQ_CITY: San Francisco REQ_ORG: Copyleft Certificate Co REQ_OU: My Organizational Unit REQ_CN: MyOpenVPN volumes: - ./openvpn/pki:/etc/openvpn/pki - ./openvpn/clients:/etc/openvpn/clients - ./openvpn/config:/etc/openvpn/config cap_add: - NET_ADMIN restart: unless-stopped pihole: container_name: pihole image: pihole/pihole:latest depends_on: - "openvpn" ports: - 80:80/tcp networks: vpn-net: ipv4_address: 172.20.0.2 environment: TZ: "Asia/Kolkata" WEBPASSWORD: "sUpEr.l0nG.p@$$w0rd" DNS1: 208.67.222.222 # OpenDNS DNS2: 208.67.220.220 ServerIP: 172.20.0.2 volumes: - ./pihole/pihole:/etc/pihole - ./pihole/dnsmasq.d:/etc/dnsmasq.d cap_add: - NET_ADMIN restart: unless-stopped networks: vpn-net: driver: bridge ipam: driver: default config: - subnet: 172.20.0.0/16
Ā
After this is done you'll find two new folders inside of this repository - theĀ
/openvpn
Ā folder will contain all of your certificates as well as an easy-rsa configuration file.Ā /pihole
Ā will contain the content ofĀ /etc/pihole
Ā andĀ /etc/dnsmasq.d
If you want to migrate settings, or your query-database you can now copy it into the corresponding folder inĀ
/pihole
Ā š The PiHole admin dashboard can only be reached through the vpn.GeneratingĀ .ovpn
Ā files
Before you generate any client certificate you must update the host inĀ client configuration. This file will be used as base-configuration for eachĀ .ovpnĀ file! You probably at least want to change the IP address to your public one.
Ā
sudo docker exec \ openvpn bash \ /opt/app/bin/genclient.sh <name> <password?>
Ā
You can find youĀ
.ovpn
Ā file underĀ /openvpn/clients/<name>.ovpn
, make sure to change the remote ip-address / port / protocol.RevokingĀ .ovpn
Ā files
sudo docker exec openvpn bash /opt/app/bin/rmclient.sh <name>
Revoked certificates won't kill active connections, you'll have to restart the service if you want the user to immediately disconnect:
sudo docker-compose restart openvpn
FAQ & Recipes
Launching multiple openvpn instances with different protocol/port config
First copy theĀ openvpnĀ directory includingĀ openvpn/configĀ (copy just theĀ
config
Ā folder!), then add another service toĀ docker-compose.yml.Example assuming we want to name our second openvpn instanceĀ
openvpn-tcp-443
:mkdir openvpn-tcp-443
cp -r openvpn/config openvpn-tcp-443
You can now make changes to our new config files inĀ
openvpn-tcp-443/config
. ChangeĀ proto
Ā toĀ tcp
Ā andĀ port
Ā toĀ 443
, you'll also need to comment outĀ explicit-exit-notify 1
Ā as this is only compatible withĀ proto udp
Ā (update bothĀ server.conf
Ā andĀ client.conf
!).Now add our new service:
# ... other services openvpn-tcp-443: container_name: openvpn-tcp-443 build: ./openvpn-docker ports: - 443:443/tcp volumes: - ./openvpn/pki:/etc/openvpn/pki # Keep the PKI - ./openvpn-tcp-443/clients:/etc/openvpn/clients - ./openvpn-tcp-443/config:/etc/openvpn/config # !! We're using our second configuraion cap_add: - NET_ADMIN restart: unless-stopped # ... other services
Keep in mind that if you want to generate a client-config for that service we've just made you'll have to use the openvpn-tcp-443 container e.g.Ā sudo docker exec openvpn-tcp-443 bash /opt/app/bin/genclient.sh <name>.
Troubleshooting
Port 53 is already in use
ERROR: for pihole Cannot start service pihole: driver failed programming external connectivity on endpoint pihole (...): Error starting userland proxy: listen tcp 0.0.0.0:53: bind: address already in use
You'll need to disable the local dns-server, seeĀ thisĀ andĀ thisĀ askubuntu thread. You can stop, disable and mask theĀ
systemd-resolved
Ā service using the following commands:sudo systemctl stop systemd-resolved sudo systemctl disable systemd-resolved sudo systemctl mask systemd-resolved
Pi-hole Dashboard
Ā
Ā
Ā
Ā
Ā
VPN and Ad-blocking in action š¤š
1. VPN Dashboard | 1. VPN Dashboard |
2. Ad Blocking in action | 2. Ad Blocking in action |
3. PiHole Dashboard killing the ads | 3. PiHole killing ads |
4. Proving VPN is in action using geolocation of ip-address | 4. Proving VPN is in action using geolocation of ip-address |
Ā