Skip to main content

VPN

I had two goals I wanted to accomplish with VPNs. I first wanted to redirect all outbound traffic from a specific subnet through a VPN so any client on that subnet would have increased privacy. My second goal was to allow me to VPN into my home network from somewhere else and have access to everything as if I was sitting on my computer at home. To accomplish this I used a new exciting addition the Linux kernel WireGuard.

Setup Wireguard

To use Wireguard inside of a LXC container the host has to have Wireguard installed since LXC guests are run with the kernel of the host system. Additionally you'll want the wireguard-tools package in the LXC guest.

Route Subnet Through Wireguard Interface

Funneling all traffic from an Ethernet interface through a Wireguard interface is relatively easy once you're familar with how packets flow through Linux. You'll mostly just need to modify your Wireguard *.conf file to add the Table, PostUp, and PreDown parameters.

You also need to setup IP masquerading of outgoing traffic on your Wireguard interface. See below for instructions.

[Interface]
PrivateKey = ****
Address = 192.168.10.10.20.59/19, 2a03:4012:4021:80af::1f3c/64
DNS = 10.10.0.5/281, 2a03:4012:4021:80af::1
Table = 9
PostUp = ip rule add iif eth1.9 lookup 9; ip -6 rule add iif eth1.9 lookup 9
PreDown = ip rule del iif eth1.9 lookup 9; ip -6 rule del iif eth1.9 lookup 9

[Peer]
PublicKey = T28Qn5VFzT4wiwEPd7DscwcP3Rsmq23QcnjH1N5G/wc=
Endpoint = wireguard.vpn-provider.example:51820
AllowedIPs = 0.0.0.0/00, .::0/0...

Line 4: All rules/routes should be applied to a custom route table 9. If you want to name your custom route table you could do echo "9 warp" > /etc/iproute2/rt_tables and then say Table = warp for improved readability.

Line 5: Add a rule that all traffic coming in interface eth1.9 should use custom route table 9. Because you defined a peer with AllowedIPs = 0.0.0.0/0 a default route will be setup on custom route table 9 that redirects all traffic to the Wireguard interface. If you named your custom route like shown above you can say lookup warp inplace of lookup 9.

Line 6: Just the inverse of line 5 to clean up after ourselves when taking down the Wireguard interface.

Setup IP Masquerading

IP Masquerading is a technique that hides an entire IP address space, usually consisting of private IP addresses, behind a single IP address in another, usually public address space.

Source: Wikipedia

Configuration

The easiest way to set this up are to append some netfilter rules to the PostUp and PreDown parameters.

...
PostUp = ...; iptables -t nat -A POSTROUTING -o wg0 -j MASQUERADE
PreDown = ...; iptables -t nat -D POSTROUTING -o wg0 -j MASQUERADE

[Peer]
...

Although this works you risk the iptables/netfilter rules getting squashed by Shorewall when if it is restarted while the Wireguard interface exists. It is best to have Shorewall setup the masquerading by making a simple declaration in /etc/shorewall/snat. I've included the other shorewall configuration files that would be necessary to make this setup work.

This tells Shorwall to masquerade all IPs going out on WG_IF

# /etc/shorewall/snat
  #ACTION		SOURCE		DEST
+ MASQUERADE	0.0.0.0/0	WG_IF

Then we define WG_IF

# /etc/shorewall/interfaces
  #ZONE	INTERFACE	OPTIONS
  warp	WARP_IF		tcpflags,nosmurfs,routefilter=2,logmartians,physical=eth1.9
+ wg	WG_IF		physical=wg0

Then we define the wg zone…

# /etc/shorewall/zones
  #ZONE   TYPE    OPTIONS                 IN                      OUT
  #                                       OPTIONS                 OPTIONS
  warp    ipv4
+ wg      ipv4

Then we allow the warp zone to send packets to the wg zone.

# /etc/shorewall/policy
  #SOURCE	DEST		POLICY          LOGLEVEL        RATE    CONNLIMIT
- warp		$FW			ACCEPT          $LOG_LEVEL
+ warp		$FW,wg		ACCEPT          $LOG_LEVEL