Gabriel Tello

How to Expose a Local Server Behind CGNAT Using WireGuard and a VPS

Published on: | 1100 words | 5 mins

If you’re like many who face the frustrating limitations of Carrier-Grade NAT (CGNAT), you might struggle to expose services hosted on your home server to the internet. CGNAT makes it challenging to access your server remotely because you don’t have a public IP address. In this guide, I’ll walk you through a method to route traffic through a Virtual Private Server (VPS) using WireGuard. This solution ensures reliable and secure connectivity, even behind CGNAT.

Overview

The goal is to use a VPS with a public IP address as a relay point for your traffic. We’ll use WireGuard, a fast and lightweight VPN, to create a secure tunnel between the VPS and your home server. Once the tunnel is established, we’ll configure iptables on the VPS to forward traffic to your home server. This guide is based on this excellent tutorial but adapted for clarity and specific use cases.

Note

The steps in this guide assume both the VPS and the home server are running Ubuntu (version 20.04 or later).

To better understand the flow of traffic in this setup, here’s a visual representation of how the connection between the user, VPS, and home server is established and maintained. The VPS acts as a bridge, routing traffic between the internet and your home server via a WireGuard tunnel:

Diagram

What You’ll Need

  1. A VPS with a public IP: Make sure your VPS provider supports Kernel-based Virtual Machines (KVM). I recommend these providers:
  2. A home server behind CGNAT: This can be any device on your local network. I like to use HP’s Elite Desk Mini PCs such as this one.
  3. WireGuard installed on both VPS and home server.
  4. Basic understanding of Linux commands and networking.

Check VPS Networking Configuration

Before proceeding, ensure your VPS provider does not have firewall rules or networking restrictions that could block traffic. Some providers enforce default firewall settings that might prevent incoming connections to your VPS’s public IP or interfere with forwarding traffic through the WireGuard tunnel. Check your VPS control panel or contact your provider to confirm:

  • Inbound rules: Ensure the necessary ports (e.g., 55107 for WireGuard and ports for HTTP/SSH) are open.
  • Outbound rules: Ensure your VPS can establish outbound connections to your home server through the WireGuard tunnel.

Without the proper configuration, your setup may fail to work as expected. Adjust these settings as needed before proceeding.

Enable IP Forwarding on the VPS

IP forwarding allows the VPS to route traffic between its interfaces.

  • Check if IP forwarding is enabled:

    1cat /proc/sys/net/ipv4/ip_forward

    If it outputs 0, it’s disabled.

  • Enable IP forwarding temporarily:

    1sudo sysctl -w net.ipv4.ip_forward=1
  • Make IP forwarding persistent across reboots:

    1echo "net.ipv4.ip_forward = 1" | sudo tee -a /etc/sysctl.conf
    2sudo sysctl -p

Install WireGuard

Install WireGuard on both the VPS and the Home Server:

1sudo apt install wireguard

Configure WireGuard

On both the VPS and the Home Server, generate WireGuard keys:

  • Create the initial configuration file:

    1umask 077 && printf "[Interface]\nPrivateKey = " | sudo tee /etc/wireguard/wg0.conf > /dev/null
  • Generate private and public keys:

    1wg genkey | sudo tee -a /etc/wireguard/wg0.conf | wg pubkey | sudo tee /etc/wireguard/publickey
    • wg0.conf: Stores the private key for WireGuard.
    • publickey: Contains the public key for sharing.
  • Note down both public keys. These will be used to configure the tunnel between the VPS and the Home Server.

On the VPS:

Edit /etc/wireguard/wg0.conf:

1[Interface]
2PrivateKey = YOUR_VPS_PRIVATE_KEY
3ListenPort = 55107
4Address = 192.168.4.1/24
5
6[Peer]
7PublicKey = YOUR_HOME_SERVER_PUBLIC_KEY
8AllowedIPs = 192.168.4.2/32

On the Home Server:

Edit /etc/wireguard/wg0.conf:

1[Interface]
2PrivateKey = YOUR_HOME_SERVER_PRIVATE_KEY
3Address = 192.168.4.2/24
4
5[Peer]
6PublicKey = YOUR_VPS_PUBLIC_KEY
7AllowedIPs = 192.168.4.1/32
8Endpoint = VPS_PUBLIC_IP:55107
9PersistentKeepalive = 25

Start WireGuard

Run these commands on both the VPS and the Home Server to start WireGuard:

  • Start WireGuard:

    1sudo systemctl start wg-quick@wg0
  • Enable it to start on boot:

    1sudo systemctl enable wg-quick@wg0
  • Verify the connection:

    1sudo wg show

    If the setup is correct, you should see a handshake between the VPS and the Home Server.

Forward Traffic Using iptables

This step should be performed on the VPS to forward incoming traffic to your Home Server.

Forwarding HTTP Traffic (Port 80)

  • Add the following iptables rules:

    1sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 192.168.4.2:80
    2sudo iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport 80 -d 192.168.4.2 -j SNAT --to-source 192.168.4.1
    3sudo iptables -A FORWARD -i eth0 -o wg0 -p tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
    4sudo iptables -A FORWARD -i wg0 -o eth0 -p tcp --sport 80 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
  • Save the rules with netfilter-persistent to make them persistent:

    1sudo apt install iptables-persistent
    2sudo netfilter-persistent save
    3sudo netfilter-persistent reload

Forwarding SSH Traffic

This step should be performed on the VPS to allow SSH access to your Home Server. SSH forwarding allows you to connect to your Home Server by first connecting to your VPS and having the VPS route the SSH traffic through the WireGuard tunnel.

Configure SSH Forwarding

  • Add these iptables rules:

    1sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 2222 -j DNAT --to-destination 192.168.4.2:22
    2sudo iptables -t nat -A POSTROUTING -o wg0 -p tcp --dport 22 -d 192.168.4.2 -j SNAT --to-source 192.168.4.1
    3sudo iptables -A FORWARD -i eth0 -o wg0 -p tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT
    4sudo iptables -A FORWARD -i wg0 -o eth0 -p tcp --sport 22 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
  • Test SSH to your Home Server via the VPS:

    1ssh -p 2222 <username>@<VPS_PUBLIC_IP>

Remember to save the rules with netfilter-persistent to make them persistent.

Retain Direct Access to the VPS

The SSH forwarding rules won’t affect your ability to SSH directly to the VPS via its default port (22). If needed, explicitly allow direct SSH access:

1sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT

Testing the Setup

Verify HTTP traffic by navigating to your VPS’s public IP in a browser:

1http://<VPS_PUBLIC_IP>

Test SSH by connecting to the VPS:

1ssh <username>@<VPS_PUBLIC_IP>

SSH into your Home Server via the VPS:

1ssh -p 2222 <username>@<VPS_PUBLIC_IP>

By following this guide, you’ve successfully exposed a Home Server behind CGNAT using WireGuard and a VPS. This setup allows you to securely forward traffic to your Home Server, including HTTP and SSH, while retaining direct access to your VPS.

#Linux   #Self-Hosting   #VPN   #VPS   #Server   #Post  

Reply to this post by email ↪