This is write up is on how to port forward over wireguard. I am going to be port forwarding a mail server running MailCow on my local server, but really any service can be port forwared with some modifications to the IPTables commands in the wireguard file.
I am using a cheap Vultr VPS as my proxy server, if your intrested heres a referral link https://www.vultr.com/?ref=9019507 where I get $10 or if you plan to spend more then $35 on your account you will get $100 and I will get $35 https://www.vultr.com/?ref=9019508-8H
- Debain 10 Buster
- Tunnel subnet: 10.1.1.0
- Proxy-VPS Tunnel IP: 10.1.1.1
- Peer [Mail Server] Tunnel IP: 10.1.1.2
I installed WireGuard using this script: https://github.com/angristan/wireguard-install
Had an error used to fix: https://stackoverflow.com/a/66745279
Allow wireguard on port 51820(make sure the port is correct, the script assign's a random port): E.g.
sudo ufw allow 51820/udp
Start the WireGuard service at boot time using the systemctl command, run:
sudo systemctl enable wg-quick@wg0
- Destination NAT(DNAT) only rewrites the destination IP address, this should be used for incoming trafic headed to a peer.
- Source NAT(SNAT) rewrites the source IP address to and should happen automatically for outbound traffic that passes through the Wg Tunnel.
Services Port Forwarded
- Http on port 80
- Https on port 443
- Postfix SMTP on port 25
- Postfix SMTPS on port 465
- Postfix Submission on port 587
- Dovecot IMAP on port 143
- Dovecot IMAPS on port 993
- Dovecot POP3 on port 110
- Dovecot POP3S on port 995
- Dovecot ManageSieve on port 4190
Also add ufw for each port on Proxy-VPS E.g. sudo ufw allow 25/tcp
Run and find the WAN interface name and replace enp1s0
blow to the correct interface name we want the portforward to listen on
ip addr
Place in /etc/wireguard/wg0.conf
on Proxy-VPS just above [Peer]
### Http on port 80
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 80 -j DNAT --to-destination 10.1.1.2:80
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 80 -j DNAT --to-destination 10.1.1.2:80
### Https on port 443
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 443 -j DNAT --to-destination 10.1.1.2:443
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 443 -j DNAT --to-destination 10.1.1.2:443
### Postfix SMTP on port 25
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 25 -j DNAT --to-destination 10.1.1.2:25
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 25 -j DNAT --to-destination 10.1.1.2:25
### Postfix SMTPS on port 465
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 465 -j DNAT --to-destination 10.1.1.2:465
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 465 -j DNAT --to-destination 10.1.1.2:465
### Postfix Submission on port 587
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 587 -j DNAT --to-destination 10.1.1.2:587
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 587 -j DNAT --to-destination 10.1.1.2:587
### Dovecot IMAP on port 143
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 143 -j DNAT --to-destination 10.1.1.2:143
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 143 -j DNAT --to-destination 10.1.1.2:143
### Dovecot IMAPS on port 993
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 993 -j DNAT --to-destination 10.1.1.2:993
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 993 -j DNAT --to-destination 10.1.1.2:993
### Dovecot POP3 on port 110
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 110 -j DNAT --to-destination 10.1.1.2:110
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 110 -j DNAT --to-destination 10.1.1.2:110
### Dovecot POP3S on port 995
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 995 -j DNAT --to-destination 10.1.1.2:995
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 995 -j DNAT --to-destination 10.1.1.2:995
### Dovecot ManageSieve on port 4190
PostUp = iptables -t nat -A PREROUTING -p tcp -i enp1s0 --dport 4190 -j DNAT --to-destination 10.1.1.2:4190
PostDown = iptables -t nat -D PREROUTING -p tcp -i enp1s0 --dport 4190 -j DNAT --to-destination 10.1.1.2:4190
sudo apt install wireguard
Transfer the file created by the script from the remote VPS to /etc/wireguard/wg0.conf
On the local machine we kept encountering an issue where the tunnel would die after several minutes, once the handshake connection expired. To fix this I added
PersistentKeepAlive = 25
to the bottom of the wg0.conf file
I left
AllowedIPs = 0.0.0.0/0
to forward all traffic of all my mail server through the remote VPS IP address, due to it needing to send outgoing SMTP email through the NAT masquerade as the remote IP instead of my home networks IP
Start the WireGuard service at boot time using the systemctl command, run:
sudo systemctl enable wg-quick@wg0
Start WireGuard the tunnel:
sudo wg-quick up wg0
Your question is quite good. The reason we chose this setup instead of running everything directly on a VPS—despite the fact that we actually own one—is actually quite simple.
We value privacy. For example, we want everything to be handled on a machine we fully control, not on a rented VPS processing data that might become difficult to manage at scale and increase our dependency on that VPS provider.
Yes, it’s true that we have to run a machine 24/7 because it needs to act as a server, but this is still a cheaper and simpler solution for us compared to storing everything directly on a VPS with equivalent specs.
Did you know that VPS performance is never truly equivalent to real physical hardware? A physical machine with 2 cores/2 threads and 8GB RAM will easily outperform a VPS with 16 vCPUs and 16GB RAM—even from major providers—because almost all cloud providers oversell their VPS with often poor QoS.
Our main problem is not having a static IP, or even lacking access to public IP with port forwarding capabilities. Using this method, we only need to rent the cheapest VPS (1 core / 1GB RAM is enough) to handle proxy-level connections, even at speeds up to 1Gbps. We then rely on our local physical server to do the heavy lifting. So we’re getting a powerful server at a much cheaper cost than renting a high-spec VPS.
Also, this setup makes our services, like our email server, very portable and independent of any particular VPS provider. We can switch VPS providers at any time without having to migrate large volumes of data, since everything is on our physical machine. Having a local server is beneficial in many operational scenarios, especially for latency and accessibility.
So yes, there are many reasons behind our approach.