Skip to content

Instantly share code, notes, and snippets.

@simonbru
Last active January 2, 2020 06:35
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save simonbru/6a3d7bf127389913cbb8b2ba0de801a7 to your computer and use it in GitHub Desktop.
Redirect TCP traffic to a box behind NAT with Wireguard

Redirect TCP traffic to a box behind NAT with Wireguard

We have a web server on a box without direct access from the internet (e.g. behind a CGNAT). We want to use a box with a public IP address (such as a cheap VPS) as a gateway that will redirect HTTP traffic to the web server. We will setup a Wireguard VPN to enable bidirectional traffic between both boxes, as well as a few routing/NAT rules to redirect HTTP traffic.

Setup

Install Wireguard and wg-quick on both boxes: https://www.wireguard.com/install/

Note: in later steps, a public/private key pair can be generated with:

wg genkey | tee private.key | wg pubkey > public.key

For security, these *.key files should be deleted once the VPN is configured.

Gateway

Enable IP forwarding:

sudo tee <<<"net.ipv4.ip_forward = 1" /etc/sysctl.d/99-enable-ip-forward.conf
sysctl --system

Copy wgweb_gateway.conf to /etc/wireguard/wgweb.conf and replace placeholders with actual values. You may need to replace eth0 with the network interface that relays internet traffic. Run ip a to get a list of network interfaces.

Make sure that the gateway can receive UDP traffic on port 51820.

Start VPN (create and configure network interface):

systemctl start wg-quick@wgweb

Server

Copy wgweb_server.conf to /etc/wireguard/wgweb.conf and replace placeholders with actual values.

Start VPN (create and configure network interface):

systemctl start wg-quick@wgweb

Enable VPN on system startup

Once everything works correctly, run systemctl enable wg-quick@wgweb on both boxes to enable the VPN when the system starts.

[Interface]
Address = 10.0.90.1/24
PrivateKey = {{ gateway private key, such as: eD+7gE8XLKPS9S2gUhrzf6Ual8l8eaMbxX8kdm39SF8= }}
ListenPort = 51820
# On VPN startup, create NAT rules
# that replace the destination IP of HTTP requests with the server IP, and vice-versa for responses.
PostUp = iptables -t nat -A PREROUTING -p tcp -i eth0 -m multiport --dports 80,443 -j DNAT --to-destination 10.0.90.2
PostUp = iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
PreDown = iptables -t nat -D PREROUTING -p tcp -i eth0 -m multiport --dports 80,443 -j DNAT --to-destination 10.0.90.2
PreDown = iptables -t nat -D POSTROUTING -o eth0 -j MASQUERADE
[Peer]
PublicKey = {{ server public key, such as: JZixYKvRsxqJ8nd22YecATBuruO9lT+9d+u+56ZN1Qk= }}
AllowedIPs = 10.0.90.2/32
[Interface]
PrivateKey = {{ server private key, such as: uJS25dXFt1QgmB1PsgFJaFGMqvz0f1byqeibgWDRQlk= }}
Address = 10.0.90.2/24
# On VPN startup, manually create a separate routing table
# that routes through the VPN all traffic with the VPN IP as source address.
# This ensures that requests incoming from the VPN will also be answered through the VPN
Table = off
PostUp = ip rule add from 10.0.90.2/32 table 4242
PostUp = ip route add default dev %i table 4242
PreDown = ip rule del from 10.0.90.2/32 table 4242
[Peer]
PublicKey = {{ gateway public key, such as: emooV/PcVMiPmWA8AXEYg76qdSliAYMuBMvS+5ADy2k= }}
Endpoint = {{ gateway public IP address }}:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment