Part 1: Instructional Guide

This guide will walk you through setting up a WireGuard VPN on an Ubuntu / Linux Mint system with split tunneling, allowing local services to remain accessible while routing all internet traffic through the VPN.

Prerequisites

  • Ubuntu system with wg-quick and WireGuard installed.
  • Basic understanding of networking and VPNs.
  • Access to your VPN provider’s configuration details (PrivateKey, PublicKey, Endpoint, etc.).

Step 1: Creating the WireGuard Configuration File

1. Navigate to the WireGuard directory:

cd /etc/wireguard

2. Create and edit the configuration file:

Create a file named ‘wg0.conf’:

sudo nano wg0.conf

Paste the following configuration, adjusting the values based on your VPN provider’s details:

[Interface]
# Adjust these settings based on your VPN provider's instructions
PrivateKey = MIIBOgIBAAJBAJh->PRIVATE KEY<-BrPrs/wtl5Dg2IbMvi=
Address = 10.2.0.2/32
# Uncomment the DNS line if needed and replace with your DNS server
#DNS = 127.0.0.1

# Split Tunneling: Remove VPN routes for local subnets
PostUp = ip route del 192.168.0.0/24 dev wg0; ip route del 10.0.0.0/8 dev wg0; ip route del 172.16.0.0/12 dev wg0

[Peer]
PublicKey = MFwwDQYJKoZIhvc->PUBLIC KEY<-vbmzvlebR6wecaiptLEUra=
Endpoint = <peer-endpoint>:51820
AllowedIPs =  0.0.0.0/0, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/24
PersistentKeepalive = 25

Save and close the file by pressing Ctrl + X, then Y, and Enter.

Step 2: Enabling WireGuard as a Systemd Service

1. Create a systemd service link:

The [email protected] template is already provided by WireGuard. To create a specific service for your wg0 configuration:

sudo ln -s /lib/systemd/system/[email protected] /etc/systemd/system/[email protected]

2. Start the WireGuard service:

Enable and start the service using the following commands:

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

This will start the WireGuard VPN immediately and ensure it starts on boot.

3. Check the status of the service:

You can verify that the service is running correctly with:

sudo systemctl status wg-quick@wg0

Step 3: Testing Your Configuration

1. Verify the VPN connection:

Use the following command to check your IP address and ensure it reflects the VPN’s IP:

curl ifconfig.me

Your output should show the IP address of the VPN, not your local IP.

2. Test access to local services:

Ensure you can still access local resources like your NAS, typically on 192.168.x.x subnet, as these routes are excluded from the VPN tunnel.

Troubleshooting Tips

  • If you cannot access local resources, verify the routes excluded in the PostUp command match your local network.
  • If the VPN does not connect, check the AllowedIPs setting and ensure the endpoint is reachable.

Part 2: Deep Dive, Understanding WireGuard and Linux Routing

In the first part of this tutorial, we set up WireGuard with split tunneling, allowing local services to remain accessible while routing all internet traffic through the VPN. In this section, we’ll take a deeper dive into how WireGuard, in combination with Linux routing, knows which packets to route through the VPN and which to leave for local access.

1. Basics of Routing in Linux

Before diving into WireGuard specifics, it’s important to understand some basics of how routing works in Linux. When a packet leaves your machine, the Linux kernel looks at the destination IP address and consults the system’s routing table to determine where to send it.

  • Routing Table: The routing table contains rules that determine the next hop for packets based on their destination IP address.
  • Default Gateway: If no specific route exists for a destination, the packet is sent to the default gateway, which is often your router.

2. WireGuard Configuration and Routing

WireGuard interacts with the Linux routing table through its configuration, specifically through the AllowedIPs setting.

2.1 Understanding Allowed IPs

In your wg0.conf, you have the following AllowedIPs setting under the [Peer] section:

[Peer]
AllowedIPs = 0.0.0.0/0, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/24
  • 0.0.0.0/0: This represents the entire IPv4 address space. Any packet destined for any public internet address will match this.
  • 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/24: These are private IP ranges typically used in local networks. By including these ranges in AllowedIPs, you specify that traffic destined for these networks should go through the VPN.

2.2 How WireGuard Uses Allowed IPs

  • Internet Traffic: The 0.0.0.0/0 route tells WireGuard to route all internet-bound traffic through the VPN tunnel. When WireGuard is active, the kernel routes packets that match this rule through the WireGuard interface (wg0), sending them to the VPN endpoint specified in the Endpoint configuration.
  • Local Network Traffic: Conversely, when packets are destined for addresses in the 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/24 ranges, WireGuard also directs this traffic to the VPN tunnel. However, in our configuration, we specifically removed these routes using the PostUp directive:
PostUp = ip route del 192.168.0.0/24 dev wg0; ip route del 10.0.0.0/8 dev wg0; ip route del 172.16.0.0/12 dev wg0

This means that while the VPN is responsible for routing all internet-bound traffic, local traffic destined for the subnets above will be handled by the default network interface, allowing you to access local services like your NAS.

3. Detailed Packet Flow Example

Let’s walk through a packet’s journey based on the configuration:

3.1 Packet Destined for the Internet

  1. Destination: 8.8.8.8 (Google DNS)
  2. Routing Table Lookup: The Linux kernel checks the routing table and finds that 0.0.0.0/0 is routed through the wg0 interface.
  3. WireGuard Handling: The packet is encrypted and sent to the VPN endpoint specified in the wg0.conf file.
  4. VPN Endpoint: The VPN provider routes the packet to its destination on the internet.

3.2 Packet Destined for a Local Network

  1. Destination: 192.168.1.100 (NAS)
  2. Routing Table Lookup: The Linux kernel checks the routing table and finds that 192.168.1.0/24 is a local network.
  3. WireGuard Handling: Due to the PostUp rule that deleted the route, this packet bypasses the wg0 interface.
  4. Default Network Interface: The packet is sent directly to the NAS over the local network, without going through the VPN.

4. Advanced Considerations

  • Traffic Splitting with Multiple Interfaces: If you have multiple network interfaces (e.g., wired and wireless), you can further refine your routing to handle traffic based on the source interface.
  • Policy-Based Routing: In more advanced setups, you might use policy-based routing to handle complex scenarios where you want different rules for different types of traffic.

5. Testing and Verification

To verify that your setup is working as expected, you can use tools like traceroute and ip route to inspect where traffic is going. For example:

  • Check the Default Route:
ip route show
  • Trace Internet Traffic:
traceroute 8.8.8.8

This should show the first hop as your VPN server.

  • Check Local Traffic:
traceroute 192.168.1.100

This should show the first hop as your local router.

Conclusion

By understanding how WireGuard interacts with Linux’s routing system, you can fine-tune your VPN setup to achieve the perfect balance between privacy and access to local resources. This deeper dive should give you the confidence to customize your WireGuard configuration to meet your specific needs, whether that’s simple split tunneling or more advanced network setups.

One thought on “Setting Up WireGuard VPN with Split Tunneling”

Leave a Reply