WireGuard VPN on VyOS - Setup and Examples

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-pair

Output:

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-key

The pre-shared key is added to each peer connection.

Generating Keys Outside VyOS

On Linux/macOS:

wg genkey | tee privatekey | wg pubkey > publickey

On Windows (PowerShell):

wg genkey | Tee-Object -FilePath privatekey | wg pubkey | Out-File publickey

Basic 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>'
commit

Parameters:

  • 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'
commit

Peer 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:

  1. Which traffic to send through the tunnel to this peer
  2. 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
save

Site 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
save

Testing

From Site A:

ping 10.10.0.2
ping 192.168.2.1

From Site B:

ping 10.10.0.1
ping 192.168.1.1

Road 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
save

Client 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 = 25

Start:

sudo wg-quick up wg0

Client 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/24

Full-tunnel (all traffic through the VPN):

AllowedIPs = 0.0.0.0/0

For 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'

commit

Spoke 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'

commit

Routing

WireGuard does not create routes automatically. Use static routes or dynamic routing.

Static Routes

set protocols static route 192.168.2.0/24 interface wg0

Or via a next-hop:

set protocols static route 192.168.2.0/24 next-hop 10.10.0.2

Dynamic 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-unicast

Operational Commands

Viewing Interfaces

List the interfaces:

show interfaces wireguard

Interface details:

show interfaces wireguard wg0

Summary information:

show interfaces wireguard wg0 summary

Example 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 sent

Viewing Keys

Show the interface’s public key:

show interfaces wireguard wg0 public-key

Restarting the Interface

restart wireguard wg0

Troubleshooting

The Tunnel Does Not Come Up

Check the status:

show interfaces wireguard wg0 summary

If latest handshake: never, there are connectivity problems.

Checklist:

  1. Check the firewall on both sides
  2. Check the public keys (they must match)
  3. Check the endpoint address and port
  4. Check NAT traversal

Check the firewall:

show firewall ipv4 input filter

Check whether WireGuard is listening:

sudo netstat -ulnp | grep 51820

Handshake Succeeds but There Is No Traffic

Check allowed-ips:

show interfaces wireguard wg0

Make sure allowed-ips include the required networks.

Check the routing:

show ip route

Check the firewall forward rules:

show firewall ipv4 forward filter

Poor Performance

Check the MTU:

show interfaces wireguard wg0

Try lowering the MTU:

set interfaces wireguard wg0 mtu 1400
commit

Check CPU usage:

show system cpu

A Peer Behind NAT Cannot Connect

Add persistent-keepalive on the peer behind NAT:

set interfaces wireguard wg0 peer client1 persistent-keepalive '25'
commit

Make sure the endpoint is not specified on the server (the peer initiates the connection).

Security

Key Management

  1. Generate keys on each device - never transfer private keys
  2. Store private keys securely - use disk encryption
  3. Key rotation - rotate keys periodically
  4. 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:

  1. MTU: Correct tuning avoids fragmentation
  2. CPU: WireGuard makes efficient use of multiple cores
  3. 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

CharacteristicWireGuardIPsecOpenVPN
PerformanceExcellentGoodFair
SimplicityExcellentComplexModerate
SecurityExcellentExcellentGood
CompatibilityGoodExcellentExcellent
RoamingExcellentPoorGood
NAT traversalExcellentComplexExcellent

Best Practices

  1. Use descriptive peer names - branch-office-nyc instead of peer1
  2. Document allowed-ips - what is allowed and why
  3. Monitor handshakes - track the latest handshake
  4. Back up the configuration - store keys separately
  5. Test failover - verify backup tunnels
  6. Persistent keepalive - use it for NAT traversal
  7. Correct MTU - avoid fragmentation
  8. Firewall - protect the WireGuard port
  9. Key rotation - rotate keys regularly
  10. 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

  1. Run WireGuard in parallel with the existing VPN
  2. Migrate clients gradually
  3. Test each stage
  4. Decommission the old VPN after the migration is complete

Next Steps

  • IPsec - if you need interoperability with other vendors
  • OpenVPN - for legacy remote access
  • Firewall - configuring VPN protection
  • NAT - NAT for VPN traffic
Reviewed by OpenNix LLC · Last updated on