WireGuard VPN on VyOS - Setup and Examples
WireGuard is a modern, fast, and secure VPN protocol built on state-of-the-art cryptography.
Overview
WireGuard offers:
- High performance - significantly faster than IPsec and OpenVPN
- Simple configuration - a minimalist setup
- Modern cryptography - ChaCha20, Poly1305, Curve25519
- Small codebase - easier to audit and secure
- Fast reconnection - ideal for mobile devices
- Kernel-space operation - high performance
Protocol: UDP (port 51820 by default)
Architecture
WireGuard is built around the concept of cryptokey routing:
- Each peer has a key pair (private + public)
- A peer defines allowed-ips - which traffic is routed through the tunnel
- Automatic roaming - the IP/port can change without reconnecting
Key Generation
Private and Public Keys
Generate a key pair on VyOS:
generate pki wireguard key-pairOutput:
Private key: qKIj212...
Public key: yAnz456...Important:
- Keep the private key secret
- Share the public key with peers
- One key per interface
Pre-shared Key (optional)
An additional security layer (post-quantum):
generate pki wireguard preshared-keyThe pre-shared key is added to each peer connection.
Generating Keys Outside VyOS
On Linux/macOS:
wg genkey | tee privatekey | wg pubkey > publickeyOn Windows (PowerShell):
wg genkey | Tee-Object -FilePath privatekey | wg pubkey | Out-File publickeyBasic Configuration
Creating the Interface
set interfaces wireguard wg0 address '10.10.0.1/24'
set interfaces wireguard wg0 port '51820'
set interfaces wireguard wg0 private-key '<private-key>'
commitParameters:
- wg0 - the interface name (can be anything: wg0, wg1, wg-site1, etc.)
- address - the IP address of the VPN tunnel
- port - the UDP port to listen on (51820 by default)
- private-key - the interface’s private key
Adding a Peer
set interfaces wireguard wg0 peer <peer-name> public-key '<peer-public-key>'
set interfaces wireguard wg0 peer <peer-name> allowed-ips '10.10.0.2/32'
set interfaces wireguard wg0 peer <peer-name> allowed-ips '192.168.2.0/24'
set interfaces wireguard wg0 peer <peer-name> address '<peer-external-IP>'
set interfaces wireguard wg0 peer <peer-name> port '51820'
commitPeer parameters:
- public-key - the remote peer’s public key
- allowed-ips - which traffic is allowed to and from this peer
- address - the peer’s external IP address (endpoint)
- port - the peer’s UDP port
Configuration Parameters
Interface
Address
The tunnel IP address:
set interfaces wireguard wg0 address '10.10.0.1/24'
set interfaces wireguard wg0 address 'fd00::1/64'You can assign multiple addresses (IPv4 and IPv6).
Port
The UDP port for incoming connections:
set interfaces wireguard wg0 port '51820'If not specified, a random port is chosen (suitable for clients).
Private Key
The interface’s private key:
set interfaces wireguard wg0 private-key '<your-private-key>'Description
The interface description:
set interfaces wireguard wg0 description 'VPN to Branch Office'MTU
The maximum packet size:
set interfaces wireguard wg0 mtu '1420'Default: 1420 (1500 minus 80 bytes of WireGuard/IP/UDP overhead).
Peer Parameters
Public Key
The peer’s public key (required):
set interfaces wireguard wg0 peer branch1 public-key 'yAnz456...'Allowed IPs
The list of networks/addresses allowed for the peer:
set interfaces wireguard wg0 peer branch1 allowed-ips '10.10.0.2/32'
set interfaces wireguard wg0 peer branch1 allowed-ips '192.168.2.0/24'Critically important: allowed-ips defines:
- Which traffic to send through the tunnel to this peer
- From which source to accept traffic from the peer
For a full tunnel (all traffic):
set interfaces wireguard wg0 peer client1 allowed-ips '0.0.0.0/0'Endpoint (Address + Port)
The peer’s external address used to initiate the connection:
set interfaces wireguard wg0 peer branch1 address '203.0.113.10'
set interfaces wireguard wg0 peer branch1 port '51820'If the peer is behind NAT or has a dynamic IP, you can omit the endpoint on the server.
Persistent Keepalive
Periodic keepalive packets that maintain the NAT mapping:
set interfaces wireguard wg0 peer client1 persistent-keepalive '25'The value is in seconds. 25 seconds is recommended for clients behind NAT.
When to use:
- The peer is behind NAT
- Mobile clients
- Dynamic IP addresses
When not to use:
- Static public IPs on both sides
- Traffic savings are critical
Pre-shared Key
An additional symmetric key:
set interfaces wireguard wg0 peer branch1 preshared-key '<psk-key>'Adds post-quantum security.
Site-to-Site VPN
Scenario
Connect two offices over the internet:
Site A (HQ):
- Public IP: 198.51.100.1
- Local network: 192.168.1.0/24
- WireGuard IP: 10.10.0.1/30
Site B (Branch):
- Public IP: 203.0.113.10
- Local network: 192.168.2.0/24
- WireGuard IP: 10.10.0.2/30
Site A (HQ) Configuration
# Generate keys
generate pki wireguard key-pair
# WireGuard interface
set interfaces wireguard wg0 address '10.10.0.1/30'
set interfaces wireguard wg0 description 'VPN to Branch Office'
set interfaces wireguard wg0 port '51820'
set interfaces wireguard wg0 private-key '<private-key-site-a>'
# Peer configuration for Site B
set interfaces wireguard wg0 peer branch public-key '<public-key-site-b>'
set interfaces wireguard wg0 peer branch allowed-ips '10.10.0.2/32'
set interfaces wireguard wg0 peer branch allowed-ips '192.168.2.0/24'
set interfaces wireguard wg0 peer branch address '203.0.113.10'
set interfaces wireguard wg0 peer branch port '51820'
# Firewall - allow WireGuard
set firewall ipv4 input filter rule 100 action 'accept'
set firewall ipv4 input filter rule 100 destination port '51820'
set firewall ipv4 input filter rule 100 protocol 'udp'
set firewall ipv4 input filter rule 100 description 'Allow WireGuard'
commit
saveSite B (Branch) Configuration
# Generate keys
generate pki wireguard key-pair
# WireGuard interface
set interfaces wireguard wg0 address '10.10.0.2/30'
set interfaces wireguard wg0 description 'VPN to HQ'
set interfaces wireguard wg0 port '51820'
set interfaces wireguard wg0 private-key '<private-key-site-b>'
# Peer configuration for Site A
set interfaces wireguard wg0 peer hq public-key '<public-key-site-a>'
set interfaces wireguard wg0 peer hq allowed-ips '10.10.0.1/32'
set interfaces wireguard wg0 peer hq allowed-ips '192.168.1.0/24'
set interfaces wireguard wg0 peer hq address '198.51.100.1'
set interfaces wireguard wg0 peer hq port '51820'
# Firewall
set firewall ipv4 input filter rule 100 action 'accept'
set firewall ipv4 input filter rule 100 destination port '51820'
set firewall ipv4 input filter rule 100 protocol 'udp'
commit
saveTesting
From Site A:
ping 10.10.0.2
ping 192.168.2.1From Site B:
ping 10.10.0.1
ping 192.168.1.1Road Warrior (Remote Access)
Scenario
The VyOS server provides VPN access for remote clients.
Server:
- Public IP: 198.51.100.1
- WireGuard IP: 10.20.0.1/24
- Local network: 192.168.1.0/24
Clients:
- Each client is assigned an IP from 10.20.0.0/24
- Access to the local network 192.168.1.0/24
Server Configuration
# WireGuard interface
set interfaces wireguard wg0 address '10.20.0.1/24'
set interfaces wireguard wg0 description 'Road Warrior VPN'
set interfaces wireguard wg0 port '51820'
set interfaces wireguard wg0 private-key '<server-private-key>'
# Client 1
set interfaces wireguard wg0 peer client1 public-key '<client1-public-key>'
set interfaces wireguard wg0 peer client1 allowed-ips '10.20.0.10/32'
# Client 2
set interfaces wireguard wg0 peer client2 public-key '<client2-public-key>'
set interfaces wireguard wg0 peer client2 allowed-ips '10.20.0.11/32'
# Client 3
set interfaces wireguard wg0 peer client3 public-key '<client3-public-key>'
set interfaces wireguard wg0 peer client3 allowed-ips '10.20.0.12/32'
# Firewall
set firewall ipv4 input filter rule 100 action 'accept'
set firewall ipv4 input filter rule 100 destination port '51820'
set firewall ipv4 input filter rule 100 protocol 'udp'
# Allow forwarding for VPN clients
set firewall ipv4 forward filter rule 110 action 'accept'
set firewall ipv4 forward filter rule 110 source address '10.20.0.0/24'
commit
saveClient Configuration (Linux example)
Create the file /etc/wireguard/wg0.conf:
[Interface]
PrivateKey = <client-private-key>
Address = 10.20.0.10/32
DNS = 192.168.1.1
[Peer]
PublicKey = <server-public-key>
Endpoint = 198.51.100.1:51820
AllowedIPs = 10.20.0.0/24, 192.168.1.0/24
PersistentKeepalive = 25Start:
sudo wg-quick up wg0Client Configuration (Windows/macOS/iOS/Android)
Use the official WireGuard clients and import the configuration above, either directly or via a QR code.
Split-tunnel vs Full-tunnel
Split-tunnel (only corporate traffic through the VPN):
AllowedIPs = 10.20.0.0/24, 192.168.1.0/24Full-tunnel (all traffic through the VPN):
AllowedIPs = 0.0.0.0/0For a full tunnel, add NAT on the server:
set nat source rule 100 outbound-interface name 'eth0'
set nat source rule 100 source address '10.20.0.0/24'
set nat source rule 100 translation address 'masquerade'Hub-and-Spoke (Star Topology)
A central hub connects multiple spoke sites.
Hub Configuration
set interfaces wireguard wg0 address '10.30.0.1/24'
set interfaces wireguard wg0 port '51820'
set interfaces wireguard wg0 private-key '<hub-private-key>'
# Spoke 1
set interfaces wireguard wg0 peer spoke1 public-key '<spoke1-public-key>'
set interfaces wireguard wg0 peer spoke1 allowed-ips '10.30.0.10/32'
set interfaces wireguard wg0 peer spoke1 allowed-ips '192.168.10.0/24'
# Spoke 2
set interfaces wireguard wg0 peer spoke2 public-key '<spoke2-public-key>'
set interfaces wireguard wg0 peer spoke2 allowed-ips '10.30.0.11/32'
set interfaces wireguard wg0 peer spoke2 allowed-ips '192.168.20.0/24'
# Spoke 3
set interfaces wireguard wg0 peer spoke3 public-key '<spoke3-public-key>'
set interfaces wireguard wg0 peer spoke3 allowed-ips '10.30.0.12/32'
set interfaces wireguard wg0 peer spoke3 allowed-ips '192.168.30.0/24'
# Allow forwarding between spokes
set firewall ipv4 forward filter rule 120 action 'accept'
set firewall ipv4 forward filter rule 120 source address '10.30.0.0/24'
set firewall ipv4 forward filter rule 120 destination address '10.30.0.0/24'
commitSpoke Configuration
set interfaces wireguard wg0 address '10.30.0.10/32'
set interfaces wireguard wg0 private-key '<spoke1-private-key>'
set interfaces wireguard wg0 peer hub public-key '<hub-public-key>'
set interfaces wireguard wg0 peer hub allowed-ips '10.30.0.0/24'
set interfaces wireguard wg0 peer hub allowed-ips '192.168.10.0/24'
set interfaces wireguard wg0 peer hub allowed-ips '192.168.20.0/24'
set interfaces wireguard wg0 peer hub allowed-ips '192.168.30.0/24'
set interfaces wireguard wg0 peer hub address '198.51.100.1'
set interfaces wireguard wg0 peer hub port '51820'
set interfaces wireguard wg0 peer hub persistent-keepalive '25'
commitRouting
WireGuard does not create routes automatically. Use static routes or dynamic routing.
Static Routes
set protocols static route 192.168.2.0/24 interface wg0Or via a next-hop:
set protocols static route 192.168.2.0/24 next-hop 10.10.0.2Dynamic Routing (BGP)
WireGuard works well with BGP for automatic route exchange:
set protocols bgp system-as 65001
set protocols bgp neighbor 10.10.0.2 remote-as 65002
set protocols bgp neighbor 10.10.0.2 address-family ipv4-unicastOperational Commands
Viewing Interfaces
List the interfaces:
show interfaces wireguardInterface details:
show interfaces wireguard wg0Summary information:
show interfaces wireguard wg0 summaryExample output:
interface: wg0
public key: yAnz456...
private key: (hidden)
listening port: 51820
peer: branch
endpoint: 203.0.113.10:51820
allowed ips: 10.10.0.2/32, 192.168.2.0/24
latest handshake: 45 seconds ago
transfer: 1.2 MiB received, 856 KiB sentViewing Keys
Show the interface’s public key:
show interfaces wireguard wg0 public-keyRestarting the Interface
restart wireguard wg0Troubleshooting
The Tunnel Does Not Come Up
Check the status:
show interfaces wireguard wg0 summaryIf latest handshake: never, there are connectivity problems.
Checklist:
- Check the firewall on both sides
- Check the public keys (they must match)
- Check the endpoint address and port
- Check NAT traversal
Check the firewall:
show firewall ipv4 input filterCheck whether WireGuard is listening:
sudo netstat -ulnp | grep 51820Handshake Succeeds but There Is No Traffic
Check allowed-ips:
show interfaces wireguard wg0Make sure allowed-ips include the required networks.
Check the routing:
show ip routeCheck the firewall forward rules:
show firewall ipv4 forward filterPoor Performance
Check the MTU:
show interfaces wireguard wg0Try lowering the MTU:
set interfaces wireguard wg0 mtu 1400
commitCheck CPU usage:
show system cpuA Peer Behind NAT Cannot Connect
Add persistent-keepalive on the peer behind NAT:
set interfaces wireguard wg0 peer client1 persistent-keepalive '25'
commitMake sure the endpoint is not specified on the server (the peer initiates the connection).
Security
Key Management
- Generate keys on each device - never transfer private keys
- Store private keys securely - use disk encryption
- Key rotation - rotate keys periodically
- One key = one interface - do not reuse keys
Firewall
Restrict access to the WireGuard port:
set firewall ipv4 input filter rule 100 action 'accept'
set firewall ipv4 input filter rule 100 destination port '51820'
set firewall ipv4 input filter rule 100 protocol 'udp'
set firewall ipv4 input filter rule 100 source address '0.0.0.0/0'For production, restrict the sources:
set firewall ipv4 input filter rule 100 source address '203.0.113.0/24'Allowed IPs
Be careful with allowed-ips:
- Do not overlap allowed-ips between peers
- Use the smallest networks necessary
- For a full tunnel, use 0.0.0.0/0 deliberately
Pre-shared Keys
Add a PSK for post-quantum security:
generate pki wireguard preshared-key
set interfaces wireguard wg0 peer branch preshared-key '<psk>'Performance
Optimization
WireGuard is already very fast, but you can still optimize it:
- MTU: Correct tuning avoids fragmentation
- CPU: WireGuard makes efficient use of multiple cores
- Offloading: Enable it on physical interfaces
Benchmark
Typical performance on modern hardware:
- 1 Gbps: ~70% CPU on a single core
- 10 Gbps: Achievable on high-end hardware
- Latency: +0.5-1ms overhead
Comparison with Other VPNs
| Characteristic | WireGuard | IPsec | OpenVPN |
|---|---|---|---|
| Performance | Excellent | Good | Fair |
| Simplicity | Excellent | Complex | Moderate |
| Security | Excellent | Excellent | Good |
| Compatibility | Good | Excellent | Excellent |
| Roaming | Excellent | Poor | Good |
| NAT traversal | Excellent | Complex | Excellent |
Best Practices
- Use descriptive peer names -
branch-office-nycinstead ofpeer1 - Document allowed-ips - what is allowed and why
- Monitor handshakes - track the latest handshake
- Back up the configuration - store keys separately
- Test failover - verify backup tunnels
- Persistent keepalive - use it for NAT traversal
- Correct MTU - avoid fragmentation
- Firewall - protect the WireGuard port
- Key rotation - rotate keys regularly
- Traffic monitoring - watch for anomalies
Migration from OpenVPN/IPsec
Benefits of Migrating to WireGuard
- Significantly higher performance
- Simpler configuration and maintenance
- Better for mobile clients (fast reconnection)
- Less overhead
Migration Strategy
- Run WireGuard in parallel with the existing VPN
- Migrate clients gradually
- Test each stage
- Decommission the old VPN after the migration is complete