Skip to content

Commit

Permalink
v1.0.0 - initial release of wg-nat-tunnel
Browse files Browse the repository at this point in the history
  • Loading branch information
Someguy123 committed Feb 10, 2024
0 parents commit 7cb584e
Show file tree
Hide file tree
Showing 6 changed files with 416 additions and 0 deletions.
226 changes: 226 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,226 @@
# NAT Tunnel between two servers FRONT and BACK

This set of configs/scripts was created by Someguy123 @ Privex Inc.

```
├── back
│   └── wg0.conf
├── front
   ├── config.env
   ├── down.sh
   ├── up.sh
   └── wg0.conf
```

In this repo, are configs and scripts for setting up a Wireguard tunnel between two servers,
with NAT in both directions to forward traffic to/from the `FRONT` server.

The wireguard configs come with private + public keys preloaded, you may want to re-generate
them using `wg genkey | tee wg0-privkey | wg pubkey > wg0-pubkey` for FRONT and BACK, then
paste the keys into wg0.conf on each server (remember to copy the public key into `[peer]` on
the opposite server - i.e. FRONT's pubkey in BACK's peer config and vice versa)

This script also allows you to exclude ports on `FRONT`, so that they go directly to `FRONT` instead
of being proxied to `BACK`. By default, 22 and 2222 are excluded so that you can still access
SSH on FRONT, you can adjust this in `config.env` under `EXCL_PORTS`.

WARNING: We strongly recommend making sure you have IPv6 setup on the `BACK` server, as the VPN
will make `BACK`'s real IPv4 inaccessible, but IPv6 should still work, so you can use IPv6 in order
to get into SSH on `BACK`.


## Setting up the BACK server

The `BACK` server is the server which you want to protect/hide, all of it's traffic will be
tunneled to/from the IP of the `FRONT` server.

WARNING: We strongly recommend making sure you have IPv6 setup on the `BACK` server, as the VPN
will make `BACK`'s real IPv4 inaccessible, but IPv6 should still work, so you can use IPv6 in order
to get into SSH on `BACK`.

This is the easiest to setup, as it simply uses plain Wireguard.

Install wireguard:

```
apt update
apt install -y wireguard
```

Copy the contents of `back/wg0.conf` from this repo, into `/etc/wireguard/wg0.conf` on the BACK server, then open it up and replace `1.1.1.1` with the external IPv4 address of your `FRONT` server:

```
nano /etc/wireguard/wg0.conf
```

Fix the permissions, otherwise wireguard will complain:

```
chmod 700 /etc/wireguard/wg0.conf
```

Enable wireguard on boot and start wireguard (WARNING: If you're connected to SSH via IPv4 you will be kicked out!):

```
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
```

Wireguard should now be started, so now we can move on to the `FRONT` server.

## Setting up the FRONT server

The `FRONT` server is the server which will be "in front" of the `BACK` server, all traffic to and from `BACK` will go through the `FRONT` server and use it's external IP

Install wireguard:

```
apt update
apt install -y wireguard
```

Copy the contents of `front/wg0.conf` from this repo, into `/etc/wireguard/wg0.conf` on the FRONT server, then open it up and replace `2.2.2.2` with the external IPv4 address of your `BACK` server:

```
nano /etc/wireguard/wg0.conf
```

Fix the permissions, otherwise wireguard will complain:

```
chmod 700 /etc/wireguard/wg0.conf
```

Copy `config.env`, `up.sh`, and `down.sh` from the `/front/` folder inside this repo and put them inside of `/etc/wireguard/` on this FRONT server with the same name

```
nano /etc/wireguard/up.sh
nano /etc/wireguard/down.sh
nano /etc/wireguard/config.env
```

Make `up.sh` and `down.sh` executable:

```
chmod +x /etc/wireguard/{up,down}.sh
```

Open up `config.env` on the FRONT server and update `MY_IP` - replace it's value with `FRONT`'s external IPv4 (the main IP on eth0 or whatever it's primary interface is)

You can also adjust `EXCL_PORTS` if desired, these are ports which won't be forwarded to `BACK`, and instead will just go directly to `FRONT`. By default, port 22 and 2222 are excluded to allow you to use SSH on the FRONT server.

```
nano /etc/wireguard/config.env
```

Enable wireguard on boot and start wireguard (WARNING: If you're connected to SSH via IPv4 you may be kicked out!):

```
systemctl enable wg-quick@wg0
systemctl start wg-quick@wg0
```

Now it should all be setup! :)

Time to do some tests!

## Verifying that it's working

Connect to your `BACK` server's SSH - you'll likely need to connect via IPv6 or via your server host's console.

### Test outgoing connection

Run this command to test outgoing IPv4 connectivity:

```
curl -4 https://myip.vc/index.txt
```

If outgoing connectivity is working okay, you'll see `FRONT`'s external IP listed in the output, instead of `BACK`'s IP

Be aware: some outgoing traffic may still go out via IPv6 unprotected, if you don't want this to happen, you'll need to either restrict your IPv6 routing so that it only routes IPv6 to the IP you're using to manage the server, or disable IPv6 (but if you disable IPv6 you'll only be able to manage the server via your host's console)

### Test incoming connection

First you'll need to install netcat before you can do either test:

```
apt install -y netcat
```

#### Option 1 - Test with a browser

If you're managing your server from a Windows computer, the easiest option is to test it using a browser.

First, run this command on `BACK`'s console:

```
nc -l 80
```

It'll show nothing at first, and may look like it's hanged, but it's perfectly normal, don't worry.

Now, while that's running in your console, open up your web browser on your home computer, and browse to `http://FRONT_IP` - where `FRONT_IP` is the external IPv4 address of `FRONT`

It won't load in your browser, however, after trying to load the URL, if you check back on your console, you should hopefully see a bunch of HTTP headers in your console:

```
root@ak-back:~# nc -l 80
GET / HTTP/1.1
Host: 138.68.152.xxx
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.14; rv:109.0) Gecko/20100101 Firefox/115.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Connection: keep-alive
Upgrade-Insecure-Requests: 1
Sec-GPC: 1
```

If you see something that looks like the above - then your incoming connectivity is working, and FRONT is properly forwarding traffic to BACK! :)

You can now hit CTRL-C in the console to exit netcat.

#### Option 2 - Test from a terminal

If you prefer, you can test it from a terminal instead!

First, run netcat on `BACK` - this command will listen on port 23 (telnet) for any incoming data:

```
nc -l 23
```

Now, from your home computer, open up a terminal (command prompt) and run this:

```
telnet FRONT_IP
```

Replace `FRONT_IP` with `FRONT`'s external IP address

Wait 2-3 seconds to ensure it's connected, then start typing something and hit enter, e.g.

```
hello
world
```

You should now see what you typed appear on `BACK`'s console!

If you did, then incoming connectivity is working!

## Finished!

You should be all setup now.

Be aware, at the time of writing, this does NOT tunnel IPv6 - which is intentional, so that you have
another method to connect to FRONT/BACK while the IPv4 is being tunneled. However, this means outgoing traffic on BACK may go via IPv6 directly, not through FRONT. If you want to avoid IPv6 leaks, you can either adjust the IPv6 routes so that it only knows to route to your home/work IPv6, or disable IPv6 and manage it through your host's console. Alternatively if you're more technically inclined, you could adjust the wireguard and iptables rules in the up/down.sh files to handle IPv6.

This set of configs/scripts was created by Someguy123 @ Privex Inc.

## [Buy a server from PRIVEX.IO starting from just 99 cents per month!](https://www.privex.io)


30 changes: 30 additions & 0 deletions back/wg0.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#############################
# Wireguard Configs for Privex <-> OVH
# Replace 1.1.1.1 with FRONT server's external IPv4
# Replace 2.2.2.2 with BACK server's external IPv4
#############################


##################################################
#
# --- BACK SERVER ---
#
# This config is to be put on the BACK server
# Place in /etc/wireguard/wg0.conf
##################################################


[Interface]
Address = 10.22.0.2/32
# Public: 9Nw243x6RRfGbhb44Axl9atBum1EdhkMbO7bsX8YSWE=
PrivateKey = gCdrlIm69O+ZcNywTEdj5wVfA9uro+PMqBUbb6Om7no=
ListenPort = 4433

# FRONT VPN server
[Peer]
PublicKey = qlWXGrh4fdboJSWyiIcaxSCdnX56/vWOW4oUailI6Wo=
Endpoint = 1.1.1.1:4433
AllowedIPs = 0.0.0.0/0

PersistentKeepalive = 120

26 changes: 26 additions & 0 deletions front/config.env
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
#!/usr/bin/env bash
##################################################
#
# --- FRONT SERVER ---
#
# This config is to be put on the FRONT server
# Place in /etc/wireguard/config.env
#
# Please replace MY_IP's value with the actual
# primary IP for FRONT's main interface
# (e.g. eth0's IP)
##################################################

# Primary interface of FRONT server to send traffic out through
OUTFACE="eth0"
# Public IP of FRONT server
MY_IP="1.1.1.1"
# Destination IP (BACK) to forward incoming FRONT traffic to
DST_IP="10.22.0.2"
# Forward traffic from FRONT server to BACK server
NAT_IN=1
# Forward traffic from BACK server through FRONT server's IP
NAT_OUT=1
# Do not forward these ports from FRONT to BACK:
EXCL_PORTS=(22 2222)

55 changes: 55 additions & 0 deletions front/down.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
##################################################
#
# --- FRONT SERVER ---
#
# This config is to be put on the FRONT server
# Place in /etc/wireguard/down.sh
# then run: chmod +x /etc/wireguard/down.sh
##################################################

set -o xtrace

(( $# > 1 )) && IFACE="$1" || IFACE="wg0"
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

: ${CONF_FILE="${DIR}/config.env"}

if [[ ! -f "$CONF_FILE" ]]; then
>&2 echo " [!!!] ERROR: Config file $CONF_FILE is missing! Please create it!"
exit 4
fi
source "$CONF_FILE"

sysctl -w net.ipv4.ip_forward=0

iptables -D FORWARD -i "$IFACE" -j ACCEPT
iptables -D FORWARD -o "$IFACE" -j ACCEPT
ip6tables -D FORWARD -i "$IFACE" -j ACCEPT
ip6tables -D FORWARD -o "$IFACE" -j ACCEPT

iptables -D INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -D INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -D FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -t mangle -D POSTROUTING -o "$IFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -D POSTROUTING -o "$OUTFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -D POSTROUTING -o "$IFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -D POSTROUTING -o "$OUTFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

if (( NAT_OUT )); then
iptables -t nat -D POSTROUTING -o "$OUTFACE" -j MASQUERADE
fi
if (( NAT_IN )); then
iptables -t nat -D PREROUTING -i "$OUTFACE" -d "$MY_IP" -j DNAT --to-destination "$DST_IP"
for p in "${EXCL_PORTS[@]}"; do
iptables -t nat -D PREROUTING -i "$OUTFACE" -p tcp --dport "$p" -j RETURN
iptables -t nat -D PREROUTING -i "$OUTFACE" -p udp --dport "$p" -j RETURN
done
fi
iptables -D FORWARD -j DROP

echo " [+++] Removed iptables rules!"
exit 0

55 changes: 55 additions & 0 deletions front/up.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
#!/usr/bin/env bash
##################################################
#
# --- FRONT SERVER ---
#
# This config is to be put on the FRONT server
# Place in /etc/wireguard/up.sh
# then run: chmod +x /etc/wireguard/up.sh
##################################################

set -o xtrace

(( $# > 1 )) && IFACE="$1" || IFACE="wg0"
DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

: ${CONF_FILE="${DIR}/config.env"}

if [[ ! -f "$CONF_FILE" ]]; then
>&2 echo " [!!!] ERROR: Config file $CONF_FILE is missing! Please create it!"
exit 4
fi
source "$CONF_FILE"

sysctl -w net.ipv4.ip_forward=1

iptables -I FORWARD -i "$IFACE" -j ACCEPT
iptables -I FORWARD -o "$IFACE" -j ACCEPT
ip6tables -I FORWARD -i "$IFACE" -j ACCEPT
ip6tables -I FORWARD -o "$IFACE" -j ACCEPT

iptables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -I INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
ip6tables -I FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -t mangle -A POSTROUTING -o "$IFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
iptables -t mangle -A POSTROUTING -o "$OUTFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -A POSTROUTING -o "$IFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
ip6tables -t mangle -A POSTROUTING -o "$OUTFACE" -p tcp -m tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

if (( NAT_OUT )); then
iptables -t nat -I POSTROUTING -o "$OUTFACE" -j MASQUERADE
fi
if (( NAT_IN )); then
for p in "${EXCL_PORTS[@]}"; do
iptables -t nat -A PREROUTING -i "$OUTFACE" -p tcp --dport "$p" -j RETURN
iptables -t nat -A PREROUTING -i "$OUTFACE" -p udp --dport "$p" -j RETURN
done
iptables -t nat -A PREROUTING -i "$OUTFACE" -d "$MY_IP" -j DNAT --to-destination "$DST_IP"
fi
iptables -A FORWARD -j DROP

echo " [+++] Added iptables rules!"
exit 0

Loading

0 comments on commit 7cb584e

Please sign in to comment.