Using Wireguard and a VPS to Bypass ISP Port Blocking and Hide Your Public IP

Nov 5, 2020
(C) The article was initially published at https://selfhosted.pro/hl/wireguard_vps/; the original owner retains ownership and rights. (R)SelfHostedPro

11/30/2022

This article is now a collab between SelfHostedPro and WIckedYoda. I also assume you have some minor networking knowledge and know how to create a VM in DigitalOcean, AWS, or your preferred service.

Here is also a youtube video as I walked through the commands and verified below works. https://youtu.be/ge1bRTLFZXU

Intro

In the past, I’ve had to deal with ISPs blocking ports and, in some cases, the most usable incoming ports. I want to show you how to bypass this using Wireguard and a VPS. That way, you can start self-hosting services even if your ISP doesn’t want you to.

For this tutorial, I will use a DigitalOcean VPS (their smallest one), but you can use any provider you want. I’m going to provide referral links for some hosting services below. I don’t make money from them, but I can get free server time.

In my attached video (WickedYoda), I used AWS lightsail to spin up a small VM on the cloud and removed it after making the video. I ran through all the setups on one end of the setup; the cloud. The home end is almost duplicated of the cloud side minus a few specified changes.

Also, the start (as I am not done) of scripting this is at https://github.com/wickedyoda/VPS_tunnel_Commands on GitHub. You are welcome to contribute and work on the project as well.

Wireguard setup

Once you’ve got your VPS setup, you’ll want to ssh in and start setting up Wireguard. Keep a terminal open on your internal server that you want to forward to, as we’ll be running many of the same commands on both.

Updates

The first thing we’ll do on both servers is up to date all of our software and reboot to ensure we’ve got the latest kernel.

#both
sudo apt update -y && sudo apt upgrade -y && sudo reboot

I ran the following commands to get the client and server’s OS up to date. I create a minor update.sh file, which can be run at any time.

#create the file
sudo nano update.sh

#paste this in the file
sudo apt-get update
sudo apt-get full-upgrade -y
sudo apt-get dist-upgrade -y
sudo apt-get autoremove -y
sudo apt-get clean -y
sudo apt-get purge -y

#use ctl+o to save and ctl+x to exit nano

#then use the chmod to enable excute perms to the file you created.
sudo chmod +x ./update.sh

#run the updates by
sudo ./update.sh

This update file is always there and will remain on your system; you can run it manually or schedule it through crontabs.

Wireguard install

We’ll go ahead and add the wireguard repository and install it now. First, you will want to add the required packages to their repository and then add their repository.

sudo apt install software-properties-common
#Depleted and not necessary as of on Ubuntu only Debian
sudo add-apt-repository ppa:wireguard/wireguard

Then we’re going to install wireguard.

#both
sudo apt update 
# to make sure we've indexed the packages on their repo
sudo apt install wireguard -y

Wireguard Configuration

We’ll first use the wg utility to generate some keys so the servers can authenticate with each other.

#both
(umask 077 && printf "[Interface]\nPrivateKey= " | sudo tee /etc/wireguard/wg0.conf > /dev/null)
wg genkey | sudo tee -a /etc/wireguard/wg0.conf | wg pubkey | sudo tee /etc/wireguard/publickey

Save both of the public keys that show for later. We’ll use them later. Go ahead and open /etc/wireguard/wg0.conf them with your preferred editor, and we’ll finish configuring these.

The following is an example of the wg0.conf on the VPS.

[Interface]
PrivateKey = <private key should be here>
ListenPort = 55107
Address = 192.168.4.1
[Peer]
PublicKey = <paste the public key from your home server here>
AllowedIPs = 192.168.4.2/32

The following is an example of the wg0.conf on your home server.

[Interface]
PrivateKey = <private key should be here>
Address = 192.168.4.2
[Peer]
PublicKey = <paste the public key from your VPS here>
AllowedIPs = 192.168.4.1/32
Endpoint = <paste the public ipv4 address of your VPS here>:55107
PersistentKeepalive = 25

Sysctl Setup

Now we’ll need to make some changes to our sysctl.conf to allow our VPS to forward using IPtables. Open /etc/sysctl.conf in your favorite editor.

Please find the following line and remove the # one commenting it out. They should look like the below once done.

#VPS
net.ipv4.ip_forward=1

#if you wish to IP forward via IPv6 then remove the # from:
net.ipv6.conf.all.forwarding=1

Then we’ll apply that change with the following commands.

#VPS
sudo sysctl -p
sudo sysctl --system

Testing

Now that everything is configured, we’ll go ahead and start up our tunnel between the servers using the following command.

#both
sudo systemctl start wg-quick@wg0
sudo systemctl enable wg-quick@wg0

Then we’re going to ping the servers from each other. On your VPS, try to ping your home server. On your home server, try to ping your VPS. (using the IPs in your wireguard configuration)

#VPS
ping 192.168.4.2
#Home server
ping 192.168.4.1

If successful, then the tunnel is working.

IPTables Setup

On our VPS, we’re going to set up some IPtables rules to forward to a reverse proxy running on our home server.

Replace eth0 with the public interface of your VPS (found using ip a)

# VPS

# By default drop traffic
sudo iptables -P FORWARD DROP

# Allow traffic on specified ports
sudo iptables -A FORWARD -i eth0 -o wg0 -p tcp --syn --dport 80 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wg0 -p tcp --syn --dport 443 -m conntrack --ctstate NEW -j ACCEPT

# Allow traffic between wg0 and eth0
sudo iptables -A FORWARD -i wg0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -i wg0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT

# Forward traffic from eth0 to wg0 on specified ports
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.4.2
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 192.168.4.2

# Forward traffic back to eth0 from wg0 on specified ports
sudo iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport 80 -d 192.168.4.2 -j SNAT --to-source 192.168.4.1
sudo iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport 443 -d 192.168.4.2 -j SNAT --to-source 192.168.4.1

Persisting IPTables

To have these rules persist through reboots, we’ll need to install netfilter-persistent, use it to save the current configuration, and then enable it.

# VPS
sudo apt install netfilter-persistent
sudo netfilter-persistent save
sudo systemctl enable netfilter-persistent

Then we’ll need to use iptables persistent and configure that.

# VPS
sudo apt install iptables-persistent
# hit yes to save the current rules.

Summary

Now everything should be set up, and ports 80 and 443 should be forwarded to your home server.

# Forward traffic from eth0 to wg0 on specified ports 

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.4.2 
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to-destination 192.168.4.2 

# Forward traffic back to eth0 from wg0 on specified ports 
sudo iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport 80 -d 192.168.4.2 -j SNAT --to-source 192.168.4.1 
sudo iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport 443 -d 192.168.4.2 -j SNAT --to-source 192.168.4.1

#You can also edit the above code to open additional ports into your network by replaceing the port 80/443 and exchanging tcp/udp depending on the protocol.