I recently wanted to setup an Ubuntu virtual machine on my Proxmox server so that my friends and I could share a server for hosting things on. The issue was that I am currently using the default ports for the services we wanted to run on my existing internet connection. So the obvious options were as follows:

  1. Run the new services on non-default ports.
  2. Pay for a second internet connection/second IP address.

This either costs money, or causes unneccesary hassel. This is where the VPS comes in, im using an Amazon Web Services t2.micro instance based in London, (as close as possible to home to avoid performance issues), but you can use any server with a dedicated IP or DMZ which you aren’t using for any other services, ideally with a dedicated IP so not to cause double NAT issues.

So, to start, I’m assuming you have both your client (my local VM) and your server (my remote VPS) setup with Ubuntu and connected to the internet. On both machines, begin by installing wireguard, we are going to use wireguard to create a VPN tunnel between the VPS (server) and the VM (client).

$ sudo apt update
$ sudo apt install wireguard

Now we need to generate a public and private key. This command uses generates a private key, with the ‘wg genkey’ command, creates a file called privatekey, then pipes the output of ‘wg genkey’ into ‘wg pubkey’, which takes the private key and outputs a matching public key, again, run the following command on both the client and the server.

$ wg genkey | sudo tee /etc/wireguard/privatekey | wg pubkey | sudo tee /etc/wireguard/publickey

You should now have 2 files in ‘/etc/wireguard’, ‘publickey’, and ‘privatekey’. You can view them using the ‘cat’ command. You will need them later.

We now need to begin creating our config files for the wireguard VPN interface. We can start on the server, begin by running:

$ sudo vim /etc/wireguard/wg0.conf

This creates the file wg0.conf in /etc/wireguard, in the command above im using vim, but you can use your preferred text editor. In the file you should insert the following, making sure to replace the PublicKey with the public key from the client, and PrivateKey with the private key from the server.

Address =
ListenPort = 51820
PrivateKey = <Server PrivateKey here>
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE; ip6tables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PostDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE; ip6tables -t nat -D POSTROUTING -o eth0 -j MASQUERADE

PublicKey = <Client PublicKey here>
AllowedIPs =

The ‘PostUp’ and ‘PostDown’ sections enable NAT on the VPN to allow the client to connect to the internet via the server.

Now open the same file on the client but instead insert this:

PrivateKey = <Client PrivateKey here>
Address =

PublicKey = <Server Privatekey here>
Endpoint = <Server IP Address Here>:51820
AllowedIPs =

Same thing as before, but we need to set the endpoint to the server, and the PrivateKey and PublicKey are swapped.

Now run on both the client and the server:

$ sudo wg-quick up wg0

This will set the interface ‘wg0’ up and start wireguard, creating a tunnel between both machines.

You can check the connection is successful by seeing if you can ping the client from the server, run this on the client:

$ ping

If you did everything correctly, you should see the following output!:

PING ( 56(84) bytes of data.
64 bytes from icmp_seq=1 ttl=64 time=14.6 ms
64 bytes from icmp_seq=2 ttl=64 time=15.3 ms
64 bytes from icmp_seq=3 ttl=64 time=15.5 ms
64 bytes from icmp_seq=4 ttl=64 time=15.5 ms
--- ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 14.612/15.224/15.500/0.358 ms

You can also use ‘wg show’ to check the connection.

$ wg show
interface: wg0
  public key: (hidden)
  private key: (hidden)
  listening port: 54832
  fwmark: 0xca6c

  endpoint: (hidden)
  allowed ips:, ::/0
  latest handshake: 1 minute, 20 seconds ago
  transfer: 663.55 MiB received, 87.98 MiB sent

On both the client and the server, run this command to start up the VPN on boot.

$ sudo systemctl enable wg-quick@wg0

Almost there! We are done on the client now, we just need to enable some iptable rules on the server, to forward all ports from the server to the client via the VPN tunnel.

Run this script on the server:

sudo iptables -A FORWARD -i eth0 -o wg0 -p tcp --syn --dport 1:21 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wg0 -p tcp --syn --dport 23:51819 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wg0 -p tcp --syn --dport 51821:65535 -m conntrack --ctstate NEW -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A FORWARD -i wg0 -o eth0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 1:21 -j DNAT --to-destination
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 23:51819 -j DNAT --to-destination
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 51821:65535 -j DNAT --to-destination

And thats it! Thanks for reading, the only things you need to know now are:

The only ports you won’t be able to use now are 51820, and 22, because they are in use by the server.

  • You should now be able to access the clients ports and services on the IP address that was assigned to the server!
  • I would highly reccommend installing UFW firewall on the client.
  • DO NOT use these rules in a production environment! I am using a disposable VPS
  • If you want to be extra safe you should manually forward the ports you need from the server.

Recommended Posts

No comment yet, add your voice below!

Add a Comment

Your email address will not be published. Required fields are marked *