VPN Configuration as a Service Operator
Setting up the VPN as a Service Operator.
This guide explains how a service operator should set up VPN access for users who have been assigned to a tenant.
For help with setting up and configuring WireGuard, refer to the WireGuard Quick Start guide.
Overview
When a user is added to a tenant, the operator can generate a VPN configuration script for that user. The user then combines this script with their private key to create a complete VPN configuration. This page explains the service operator steps, the user steps of this process are outlined here.
Setup Process
Once the user has generated a WireGuard key pair and has shared the public key with the service operator, the VPN setup follows these steps:
- Operator adds user to tenant with the public key
- Operator fetches and provides VPN configuration script to the user
Add User to Tenant
After receiving the user's public key, add the user to a tenant. The user's WireGuard public key must be provided in the pubkey field for VPN access configuration.
For complete API details and examples, see the Add User to Tenant section in the Operator API Guide.
Fetch and provide VPN Configuration Script
Retrieve the VPN configuration script for the user:
curl -H "Authorization: Bearer $JWT_TOKEN" \
-H "Content-Type: application/json" \
"${API_BASE_URL}/users/${USER_ID}/vpn" > vpn-config-script.sh
Provide this script to the user.
VPN Configuration Reference
The configuration script retrieved above produces a WireGuard configuration file in the following format. Values that are user-specific are populated automatically by the script; placeholders are shown here for illustration.
[Interface]
# The user's private key — generated by the user, never shared with the operator
PrivateKey = <user private key>
# The user's VPN IP address, assigned per-user by the API
Address = 172.31.42.42/32
# VPN DNS server, shared across all users on this tenant;
# optionally followed by a search domain (not supported on the macOS App Store client — see Troubleshooting)
DNS = 172.31.0.254, tld
# Optional: set if the user's network MTU is below 1500 bytes (e.g. IPv4 over IPv6)
MTU = 1312
[Peer]
# The VPN server's public key — the same for all users on this tenant
PublicKey = ExampleServerPublicKey+/+/+/+/+/+/+/+/+/+/+=
# Traffic destined for these IP ranges is routed through the VPN
AllowedIPs = 10.8.42.0/24, 172.31.42.0/24
# Address and port of the VPN server
Endpoint = vpn.example.com:4242
# Optional: sends a keepalive packet at this interval (seconds) to maintain the connection through NAT
PersistentKeepAlive = 25
Troubleshooting
If users report VPN connectivity issues, use the following flowchart to identify the likely cause, then follow the linked sections for detailed steps.
Verifying Connectivity
A key feature of WireGuard is that invalid packets are ignored. This means that neither side of the connection will warn the other about invalid keys. The absence of an error does not mean that the connection is successful: it is necessary to troubleshoot issues step-by-step.
Step 1: Verify that the server is reachable
Ping the WireGuard endpoint to confirm network connectivity:
# First, check that you can connect to the Internet.
ping midokura.com
# Then, try pinging the VPN server.
ping vpn.example.com
The VPN server may not be responding to ping by design.
Step 2: Verify VPN Connection
After enabling the WireGuard connection:
Check wg stats
- Linux
- macOS
Check the status of the WireGuard client locally:
$ sudo wg
Sample output when successfully connected:
interface: wg-tenant
public key: ExampleUserPublicKey+/+/+/+/+/+/+/+/+/+/+/+=
private key: (hidden)
listening port: 49913
peer: ExampleServerPublicKey+/+/+/+/+/+/+/+/+/+=
endpoint: 203.0.113.42:4242
allowed ips: 10.8.42.0/24, 172.31.42.0/24
latest handshake: 1 minute, 30 seconds ago
transfer: 24.92 KiB received, 24.55 KiB sent
persistent keepalive: every 25 seconds
Sample output when either the client key or the server key is incorrect:
interface: wg-tenant
public key: ThisIsAnExampleOfIncorrectClientPublicKey+/=
private key: (hidden)
listening port: 45986
peer: ExampleServerPublicKey+/+/+/+/+/+/+/+/+/+=
endpoint: 203.0.113.42:4242
allowed ips: 10.8.42.0/24, 172.31.42.0/24
transfer: 0 B received, 444 B sent
persistent keepalive: every 25 seconds
In this case:
- some data is sent (but there is no indication of whether that data is correctly received by the server)
- zero bytes are received: either the server can not be validated and its data gets ignored, or the server can not validate the client, and does not reply
- there is no "latest handshake" timestamp
The WireGuard app from the Mac App Store does not bundle the wg command-line tool, so sudo wg is not available.
To check the status of a tunnel, open Manage Tunnels from the macOS Menu Bar. This shows the connection state including last handshake timestamp, as well as transfer statistics for each configured tunnel.
A working connection shows bytes being received. If received bytes remain at zero and there is no handshake, the keys are likely misconfigured. In this case, verify that the user's public key was registered correctly with the operator.
Ping the DNS endpoint
Verify that traffic can go through the VPN to the server by pinging the DNS endpoint's IP address:
ping 172.31.0.254
A successful ping indicates the WireGuard connection is working correctly.
Testing DNS
DNS resolution is critical for accessing resources through the VPN. You can troubleshoot like this, step-by-step:
# Test resolution of a public domain through the VPN server that is listed in the configuration
nslookup midokura.com 172.31.0.254
# Check that you can resolve the "tld" subdomain from the configuration if present in your Wireguard DNS config
nslookup myvm.tenant.example.tld 172.31.0.254
# Check that ".tld" DNS queries are sent to the VPN by default
nslookup myvm.tenant.example.tld
# Check that you can resolve the IA Factory Console URL
nslookup console.aifactory.example.tld 172.31.0.254
# Check that the DNS resolver is set correctly when connected
nslookup console.aifactory.example.com
Both commands should return valid IP addresses. If DNS resolution fails, verify that the DNS servers specified in the WireGuard configuration are correct and reachable.
The App Store client does not support the search domain suffix in the DNS field (e.g. DNS = 172.31.0.254, tld). Use the DNS server address without a search domain instead:
DNS = 172.31.0.254
This routes all DNS queries through the VPN, rather than only queries matching the search domain.
Alternatively, one can set up search domains via the resolver(5) system resolver like so:
# /etc/resolver/ai-factory.tld
domain tld
search tld
nameserver 172.31.0.254
For more information, please refer to the mac OS manual pages for resolver(5).
Advanced VPN troubleshooting
Some troubleshooting steps are very specific (to your OS, browser, or Internet connection), and / or not usually required.
Checking Allowed Routes
Resources accessed through the VPN must be covered by the AllowedIPs ranges in the WireGuard configuration.
For example, if a user needs to access a service on 10.0.0.5, AllowedIPs must include 10.0.0.0/8 or a more specific range containing that IP.
Review the AllowedIPs configuration to ensure all required networks are included.
AllowedIPs = 10.8.42.0/24, 172.31.0.0/24
Typically, this will contain at least two networks:
- the address range of the tenant VPN. In the example config, the client address is
172.31.42.42/32, the range is172.31.42.0/24 - the address range of the tenant network resources. In the example config, this network is
10.8.42.0/24
When having connectivity issues to a resource, consider the address of the resource:
- Is it available on the VPN networks?
- Is the network covered by the VPN configuration?
- Is there a conflict between a local (non-VPN) network resource and a VPN address range?
MTU troubleshooting
MTU (Maximum Transmission Unit) issues can cause packets to be silently dropped. IPv4 over IPv6 connections, for example, may have an MTU lower than the standard 1500 bytes. This configuration is not always necessary, depending on whether the local network gateway is aware of the MTU.
Test your connection's MTU:
- Linux
- macOS
ping -4 -M do -s 1472 example.com
The IPv4 header adds 20 bytes, and the ICMP header adds 8 bytes to the packet size. Therefore, we need to use a payload size of 1472 to test sending exactly 1500 byte packets.
If this fails, try smaller packet sizes, for example, 1400 or 1300, to find the maximum working size. Ensure the MTU value in the VPN configuration is set appropriately for your network.
Sample output:
ping -4 -M do -s 1352 midokura.com
PING midokura.com (198.51.100.42) 1472(1500) bytes of data.
From _gateway (192.168.1.1) icmp_seq=1 Frag needed and DF set (mtu = 1380)
ping: sendmsg: Message too long
^C
ping -M do -s 1352 midokura.com
PING midokura.com (198.51.100.42) 1352(1380) bytes of data.
1360 bytes from 42-100.midokura.com (198.51.100.42): icmp_seq=1 ttl=47 time=12 ms
^C
In this example, the router is aware of the MTU and can deal with the packet size for us. It replies with a message telling us "the MTU is 1380, I can't send your packet without fragmenting it".
When this happens, the MTU setting in the client configuration is not necessary. Ping probes that fail with size 1472 and that work with size 1352, though, would indicate that 1380 ≥ MTU < 1500.
To test MTU on macOS, use:
ping -D -s 1472 midokura.com
If this fails, try smaller packet sizes, for example, 1400 or 1300, to find the maximum working size. Ensure the MTU value in the VPN configuration is set appropriately for your network.
Ubuntu and NetworkManager
Ubuntu uses NetworkManager to manage network connections, including WireGuard VPN.
NetworkManager provides a helper on top of wg, so the troubleshooting steps in this guide still apply.
However, if you experience connection issues after configuration changes, restarting the VPN connection or flushing the DNS cache can help.
Restart the VPN connection:
sudo nmcli connection down <vpn-connection-name>
sudo nmcli connection up <vpn-connection-name>
Flush the DNS cache:
sudo resolvectl flush-caches
Browser DNS-over-HTTPS (DoH)
"DNS over HTTPS" (DoH) features may bypass the VPN's DNS configuration, causing resolution failures for resources only accessible through the VPN.
Firefox
To allow using the system DNS resolver in Firefox:
- Open [about:preferences#privacy](Firefox's privacy preferences page)
- Scroll to DNS over HTTPS
- Select Default Protection or Increased Protection to allow using the system DNS, or Off to disable DoH altogether
Chrome
To disable DoH in Chrome:
- Open [chrome://settings/security](Chrome's settings page)
- Scroll to Use secure DNS
- Turn off the toggle, or select With your current service provider