Skip to content

Instantly share code, notes, and snippets.

@tombowditch
Forked from itslukej/tunneling.md
Last active March 4, 2024 20:56
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save tombowditch/5845738245af344cdd01f7097d368d83 to your computer and use it in GitHub Desktop.
Save tombowditch/5845738245af344cdd01f7097d368d83 to your computer and use it in GitHub Desktop.
Tunneling a whole process through wireguard

Tunneling a whole process through wireguard

Certain company blocking a certain hosting provider? No problem, just tunnel the process through a small VPS with wireguard.

Consider server A your blocked server and server B your VPS.

Step 1: Generate a keypair on server A and server B

Server A:

wg genkey > endpoint-a.key
wg pubkey < endpoint-a.key > endpoint-a.pub

Server B:

wg genkey > endpoint-b.key
wg pubkey < endpoint-b.key > endpoint-b.pub

Step 2: Configure server B

Edit /etc/sysctl.conf and ensure the following line is uncommented:

net.ipv4.ip_forward=1

Create a wireguard config at /etc/wireguard/wg0.conf with the following content:

[Interface]
PrivateKey = <endpoint-b.key>
Address = 10.0.0.2/32
ListenPort = 51822

PreUp = iptables -t mangle -A PREROUTING -i wg0 -j MARK --set-mark 0x30
PreUp = iptables -t nat -A POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE
PostDown = iptables -t mangle -D PREROUTING -i wg0 -j MARK --set-mark 0x30
PostDown = iptables -t nat -D POSTROUTING ! -o wg0 -m mark --mark 0x30 -j MASQUERADE

[Peer]
PublicKey = <endpoint-a.pub>
AllowedIPs = 10.0.0.1/32
Endpoint = <server A ip address>:51822

If you wish to forward ports, add the following 2 lines under [Interface] per port you wish to forward:

PreUp = iptables -t nat -A PREROUTING -p tcp --dport 12345 -j DNAT --to-destination 10.0.0.1
PostDown = iptables -t nat -D PREROUTING -p tcp --dport 12345 -j DNAT --to-destination 10.0.0.1

Enable & start wg0 using wg-quick:

systemctl enable --now wg-quick@wg0

Step 3: Configure server A

Create a wireguard config at /etc/wireguard/wg0.conf with the following content:

[Interface]
PrivateKey = <endpoint-a.key>
ListenPort = 51821

[Peer]
PublicKey = <endpoint-b.pub>
Endpoint = <server B ip address>:51822
AllowedIPs = 0.0.0.0/0

Create a script to setup the namespace:

cat <<EOF | sudo tee /etc/wireguard/netns_setup.sh
ip netns add pvt-net1
ip -n pvt-net1 link set lo up
ip link add wg0 type wireguard
ip link set wg0 netns pvt-net1
ip netns exec pvt-net1 wg setconf wg0 /etc/wireguard/wg0.conf
ip -n pvt-net1 address add 10.0.0.1/32 dev wg0
ip -n pvt-net1 link set wg0 up
ip -n pvt-net1 route add default dev wg0
EOF

Make script executable:

chmod +x /etc/wireguard/netns_setup.sh

Make DNS work:

mkdir -p /etc/netns/pvt-net1
echo nameserver 1.1.1.1 | sudo tee /etc/netns/pvt-net1/resolv.conf >/dev/null
chmod -R o+rX /etc/netns

Create systemd service to execute this on boot:

cat <<EOF | sudo tee /etc/systemd/system/tunnel1.service
[Unit]
Description=Tunnel 1
After=network.target wg-quick@wg0.target

[Service]
ExecStart=/etc/wireguard/netns_setup.sh
Type=oneshot
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

Execute on boot & execute now:

systemctl enable --now tunnel1

Use a systemd override to bind to network namespace & ensure service is started after tunnel is up:

systemctl edit <service>

Add the following at the top, in the override section (you may have to change After=:

[Unit]
After=network.target network-online.target tunnel1.target

[Service]
NetworkNamespacePath=/run/netns/pvt-net1
BindReadOnlyPaths=/etc/netns/pvt-net1/resolv.conf:/etc/resolv.conf

Reload systemd & restart service:

systemctl daemon-reload
systemctl restart <your service>

Credit

This whole config was derived from https://www.procustodibus.com/blog/2023/04/wireguard-netns-for-specific-apps. All credit goes to them!

@VirtuBox
Copy link

Many thanks for this tutorial !

@george-emerald
Copy link

I'm getting this error:
/usr/bin/wg-quick: line 295: iptables: command not found

Do you know how to fix it? Maybe there's a different way to forward ports?

@tombowditch
Copy link
Author

@george-emerald should be a simple apt-get install iptables, or equlivant for your package manager

@george-emerald
Copy link

george-emerald commented Oct 19, 2023

Thanks for the help. I should have thought of that haha. Now I'm getting a different error code when I try to start the service on server A after following each step exactly:

failed to execute /etc/wireguard/netns_setup.sh: Exec format error
failed at step EXEC spawning /etc/wireguard/netns_setup.sh: Exec format error

I checked the file in question and it's the same as what's in the guide.

@VirtuBox
Copy link

Exec format error

Add the following line at the top of /etc/wireguard/netns_setup.sh

#!/bin/bash

@george-emerald
Copy link

@VirtuBox thanks, this worked! Now I'm getting this error in the last step when trying to restart the service after editing it:

Cannot create namespace file "/var/run/netns/pvt-net1": File exists

I've tried deleting the file in question and trying again but that doesn't seem to work.

@ulumios
Copy link

ulumios commented Oct 21, 2023

Shut down all services that use this namespace then:

$ ip netns pids pvt-net1 | sudo xargs -r kill
$ sudo ip netns del pvt-net1

Or reboot.

@george-emerald
Copy link

I'm just getting different errors again:

tunnel1.service: Failed to open network namespace path /run/netns/pvt-net1: No such file or directory
tunnel1.service: Failed at step NETWORK spawning /etc/wireguard/netns_setup.sh: No such file or directory

I tried re-creating netns_setup.sh and it didn't help.

@VirtuBox
Copy link

I'm just getting different errors again:

tunnel1.service: Failed to open network namespace path /run/netns/pvt-net1: No such file or directory
tunnel1.service: Failed at step NETWORK spawning /etc/wireguard/netns_setup.sh: No such file or directory

I tried re-creating netns_setup.sh and it didn't help.

You have to edit the service you want to route into your tunnel with systemctl edit <service-name> and to add the following lines before being able to start the tunnel service :

[Unit]
After=network.target network-online.target tunnel1.target

[Service]
NetworkNamespacePath=/run/netns/pvt-net1
BindReadOnlyPaths=/etc/netns/pvt-net1/resolv.conf:/etc/resolv.conf

This tutorial is not a standard wireguard guide where you can use the command wg to check your VPN status. You have to follow the guide until the end then the easiest is to reboot your server. After the reboot, you will be able to check if the trafic is properly routed through the VPN.

@george-emerald
Copy link

@VirtuBox thanks for the help, but I've already followed the guide to the letter including the step you mentioned. It's actually after doing this step that it stopped working. The service was starting before. I've checked that those lines are included.

@george-emerald
Copy link

george-emerald commented Oct 23, 2023

How in the world can it say that netns_setup.sh doesn't exist when it does? Should I change the permissions of the folder or something?
I even tried changing the permissions in the folder.

@ulumios
Copy link

ulumios commented Dec 18, 2023

Any tips to reconifg that for ipv4 + ipv6?
Edit: Did it.... not perfekt but works...
https://gist.github.com/ulumios/cb954027117ce7f875b03d936218e900

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment