How to setup Double VPN with Wireguard?

Viewed 1370

I am trying to route a home VPN via NordVPN, but I can't make it work.

Basically, I want my Internet requests to go: Phone -> Home -> NordVPN. The reason is that I want to have a split VPN which can access my home devices while also accessing the Internet without giving my IP.

Hardware

Raspberry Pi 4

Debian 10

$ uname -srvmpio
Linux 5.10.0-0.bpo.4-arm64 #1 SMP Debian 5.10.19-1~bpo10+1 (2021-03-13) aarch64 unknown unknown GNU/Linux

Software

Rootless Docker

linuxserver/wireguard

bubuntux/nordvpn

docker-compose.yml

version: "3.8"
services:
  vpn:
    image: bubuntux/nordvpn
    cap_add:
      - NET_ADMIN               # Required
      - SYS_MODULE              # Required for NordLynx
    sysctls:
      - net.ipv4.conf.all.rp_filter=2 # Required for Nordlynx
    devices:
      - /dev/net/tun            # Required
    environment:
      - USER=${NORDVPN_USERNAME}
      - PASS=${NORDVPN_PASSWORD}
      - CONNECT=${NORDVPN_CONNECT}
      - TECHNOLOGY=NordLynx
      - TZ=${TZ}
      - PORTS=64444;51820
      - CYBER_SEC=Enable
    ports:
      - 64444:51820
  
  wireguard:
    image: ghcr.io/linuxserver/wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      TZ: ${TZ}
      SERVERURL: ${URL}
      PEERS: peer1,peer2
      # INTERNAL_SUBNET: 10.13.13.0 #optional
    depends_on:
      - vpn
    volumes:
      - ${DOCKERCONFIG}/wireguard:/config
      - /lib/modules:/lib/modules:ro
    network_mode: service:vpn

It works without the vpn, thanks to port forwarding.

Does anyone have any clue how to make this work ?

Many thanks :)

1 Answers

https://unix.stackexchange.com/a/365296 - was the answer for me. By adding the routing allowances for Wireguard to go through the NordVPN container's bridge network when replying back to the connection as opposed to trying to route via NordVPN's server I was able to connect a client which then routed traffic through Wireguard and then onto NordVPN.

Firstly, I gave a defined private IP subnet of 172.18.0.0/24:

networks:
  private:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.18.0.0/24

Then attached it to the NordVPN container:

networks:
    private:
      ipv4_address: 172.18.0.2

This allowed me to define the route on the Wireguard container:

ip rule add from 172.18.0.2 table 128 # interface IP for container eth0 on the NordVPN network stack we specified in networks -> private -> ipv4_address
ip route add table 128 to 172.18.0.0/24 dev eth0 # the subnet range for NordVPN container eth0 interface
ip route add table 128 default via 172.18.0.1 # the default gateway

To have this configuration persist you can then add another PostUp & PostDown argument in the Wireguard interface setup file config/wg0.conf under the [Interface] tag and applying for the first time with docker-compose restart. Note: Wireguard accepts multiple PostUp & PostDown args, keep the PostUp & PostDown that already exist that were generated by Wireguard.

PostUp = ip rule add from 172.18.0.2 table 128; ip route add table 128 to 172.18.0.0/24 dev eth0; ip route add table 128 default via 172.18.0.1
PostDown = ip rule del from 172.18.0.2 table 128; ip route del table 128 to 172.18.0.0/24 dev eth0; ip route del table 128 default via 172.18.0.1

Sharing Compose file for posterity:

---
version: "3.3"
services:
  vpn:
    image: ghcr.io/bubuntux/nordvpn
    container_name: nordvpn
    cap_add:
      - NET_ADMIN               # Required
      - SYS_MODULE
    ports:
      - $EXTERNAL_WG_PORT:51820/udp
    environment:                # Review https://github.com/bubuntux/nordvpn#environment-variables
      - USER=$NORDUSR          # Required
      - PASS=$NORDPW            # Required
      - CONNECT=$COUNTRY
      - TECHNOLOGY=NordLynx
      - NETWORK=172.18.0.0/24  # So it can be accessed within the local network
      - PORTS=$EXTERNAL_WG_PORT;51820
      - FIREWALL=Enable
      - KILLSWITCH=Enable
      - CYBER_SEC=Enable
      - DNS=$NV_DNS
    sysctls:
      - net.ipv4.conf.eth0.rp_filter=2
    devices:
      - /dev/net/tun
    restart: unless-stopped
    networks:
        private:
          ipv4_address: 172.18.0.2

  wireguard:
    image: ghcr.io/linuxserver/wireguard
    container_name: wireguard
    cap_add:
      - NET_ADMIN
      - SYS_MODULE
    environment:
      - PUID=$PUID
      - PGID=$PGID
      - TZ=$TZ
      - SERVERURL=$FQDN #optional
      - SERVERPORT=$EXTERNAL_WG_PORT #optional
      - PEERS=3 #optional
      - PEERDNS=$WG_DNS #optional
      - INTERNAL_SUBNET=172.21.88.0/24 #optional
      - ALLOWEDIPS=$ALLOWEDIPS
    volumes:
      - ./config:/config
      - ./modules:/lib/modules
    sysctls:
      - net.ipv4.conf.all.src_valid_mark=1
      - net.ipv4.ip_forward=1
    network_mode: service:nordvpn
    restart: unless-stopped
    depends_on:
      - nordvpn

networks:
  private:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: 172.18.0.0/24
Related