DEV Community

Mayur Bhatti
Mayur Bhatti

Posted on

Setting up WireGuard VPN with WAG for Enhanced Security and MFA

In today’s security-conscious environment, having a VPN setup that integrates multi-factor authentication (MFA) is essential. WAG, a tool that adds 2FA and device enrollment capabilities to WireGuard, enables secure VPN access with MFA for specific routes. This guide walks you through setting up a WireGuard VPN with WAG on an Ubuntu server.

Introduction to WAG with WireGuard

WAG enhances WireGuard by providing 2FA on selected routes while allowing other routes to remain accessible as long as the client has a valid public key. With WAG, you can ensure only authenticated users can access sensitive network resources, securing your VPN further.

Reference: WAG GitHub Repository

Prerequisites

  • System Requirements: This guide assumes you are working on Ubuntu 20.04.
  • Necessary Tools: Make sure iptables is installed and IP forwarding is enabled. Wag must be run as root, to manage iptables and the wireguard device.
sysctl -w net.ipv4.ip_forward=1
Enter fullscreen mode Exit fullscreen mode

Step 1: Install WAG

  • Create Directory: Install WAG in the /opt directory.
mkdir /opt/wag && cd /opt/wag
Enter fullscreen mode Exit fullscreen mode
  • Download WAG:
curl -L $(curl -s https://api.github.com/repos/NHAS/wag/releases/latest | jq -M -r '.assets[0].browser_download_url') -o wag
Enter fullscreen mode Exit fullscreen mode
  • Set Permissions:
chmod 700 wag
Enter fullscreen mode Exit fullscreen mode

Step 2: Generate WAG Configurations

  • Generate the initial configuration file:
sudo ./wag gen-config
Enter fullscreen mode Exit fullscreen mode
  • Rename the generated config file:

After providing valid information in the above command, it will generate one config file with the tag "config.json.*". Rename it to "config.json"

mv config.json.* config.json
Enter fullscreen mode Exit fullscreen mode

Step 3: Modify WireGuard Port and Add ACLs in the Config File

  • Set Port and Add Private Key: Configure WireGuard to listen on a chosen port (e.g., 51820).
"Wireguard": {
    "DevName": "wg0",
    "ListenPort": 51820,
    "PrivateKey": "your_private_key_here",
    "Address": "10.1.2.1/24",
    "MTU": 1420,
    "PersistentKeepAlive": 25,
    "DNS": ["8.8.8.8"]
}
Enter fullscreen mode Exit fullscreen mode
  • Define ACLs: Use ACL policies to enforce 2FA for specific networks while allowing general access to others. Here, a username "mayur" is allowed only for network "0.0.0.0/0, ::/0" but it must enter MFA for network "172.69.0.0/16 and following", mfa defines the network which will be accessible only if it is authorized.

Example ACL Configuration:

"Acls": {
    "Groups": {
        "group:admin": ["mayur"]
    },
    "Policies": {
        "group:admin": {
            "Mfa": [
               "172.69.0.0/16", "172.63.0.0/16"
            ],
            "Allow": [
               "0.0.0.0/0", "::/0"
            ]
        }
    }
}
Enter fullscreen mode Exit fullscreen mode

After adding this, the config will look like this:

{
  "Proxied": false,
  "ExposePorts": null,
  "HelpMail": "<email address>",
  "Lockout": 5,
  "ExternalAddress": "<public ip>",
  "MaxSessionLifetimeMinutes": 1440,
  "SessionInactivityTimeoutMinutes ": 60,
  "ManagementUI": {
    "ListenAddress": "",
    "Enabled": false
  },
  "Webserver": {
    "Public": {
      "ListenAddress": ":8080"
    },
    "Tunnel": {
      "Port": "80"
    }
  },
  "Authenticators": {
    "Issuer": "Wireguard",
    "Methods": ["totp"],
    "DomainURL": "",
    "OIDC": {
      "IssuerURL": "",
      "ClientSecret": "",
      "ClientID": ""
    }
  },
  "Wireguard": {
    "DevName": "wg0",
    "ListenPort": 51820,
    "PrivateKey": "<private key>",
    "Address": "10.1.2.1/24",
    "MTU": 1420,
    "PersistentKeepAlive": 25,
    "DNS": ["8.8.8.8"]
  },
  "DatabaseLocation": "devices.db",
  "Acls": {
    "Groups": {
      "group:admin": ["mayur"]
    },
    "Policies": {
      "group:admin": {
        "Mfa": ["172.69.0.0/16", "172.63.0.0/16"],
        "Allow": ["0.0.0.0/0", "::/0"]
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Step 4: Start the WAG Service

  • Run WAG with the following command:
./wag start -config config.json
Enter fullscreen mode Exit fullscreen mode

wag will create a database "devices.db" where it will store all users and their respective keys.

Step 5: Set Up WAG as a Service

  • Create a wag.service file for managing WAG via systemd:
sudo nano /etc/systemd/system/wag.service
Enter fullscreen mode Exit fullscreen mode
  • Add the following service configuration:
[Unit]
Description=WireguardManager

[Service]
User=root

WorkingDirectory=/opt/wag
ExecStart=/opt/wag/wag start

# If any of the ExecStarttasks fail, then ExecStopPostwill run
ExecStopPost=/opt/wag/wag cleanup

Restart=on-failure
RestartSec=10
RestartPreventExitStatus=3

KillSignal=SIGINT

[Install]
WantedBy=multi-user.target
Enter fullscreen mode Exit fullscreen mode
  • Enable and start the service:
sudo systemctl enable wag
sudo systemctl start wag
Enter fullscreen mode Exit fullscreen mode

Step 6: Register New Users with WAG

  • Register a user:
./wag registration -add -username your_username
Enter fullscreen mode Exit fullscreen mode

token

This command generates a token for device enrollment.

  • Restart the WAG service:

Now copy the token that was generated from the adding username, Now restart the wag service

sudo systemctl restart wag
Enter fullscreen mode Exit fullscreen mode

Step 7: Download User Configuration File

  • Users can retrieve their VPN configuration file using their generated token:
curl http://{public.server.address}:8080/register_device?key={token}
Enter fullscreen mode Exit fullscreen mode

This will download the config that will later need to be used in the WireGuard Client.


Additional Feature:

Registration - Deals with creating, deleting and listing the registration tokens

Usage of registration:

  • "-add" : Create a new enrolment token
  • "-del" : Delete existing enrolment token
  • "-group value" : Manually set user group (can supply multiple -group, or use -groups for delimited group list, useful for OIDC)
  • "-groups string" : Set user groups manually, ',' delimited list of groups, useful for OIDC
  • "-list" : List tokens
  • "-overwrite string" : Add registration token for an existing user device, will overwrite wireguard public key (but not 2FA)
  • "-socket string" : Wag socket to act on (default "/tmp/wag.sock")
  • "-token string" : Manually set registration token (Optional)
  • "-username string" : User to add device

(Optional) Configure WAG Management UI

  • To enable the WAG UI, make the following changes in config.json:
"ManagementUI": {
    "ListenAddress": ":9000",
    "Enabled": true
}
Enter fullscreen mode Exit fullscreen mode
  • Restart WAG to apply changes:
sudo systemctl restart wag
Enter fullscreen mode Exit fullscreen mode
  • Set up an admin account for the web console:
sudo ./wag webadmin -add -username admin -password admin_password
Enter fullscreen mode Exit fullscreen mode

Now, Just use http://{public_ip}:9000 and we will be able to access the WAG UI console where we will be able to manage the user and config.

wag ui

Top comments (0)