# WireGuard VPN on VyOS - Setup and Examples

> Configure WireGuard VPN on VyOS - Site-to-Site, Road Warrior, and Hub-and-Spoke topologies with examples for Yandex Cloud and VK Cloud.

Source: https://opennix.org/en/docs/vyos/vpn/vyos-wireguard/


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:
```bash
wg genkey | tee privatekey | wg pubkey > publickey
```

On Windows (PowerShell):
```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`:

```ini
[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:
```bash
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

| 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

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](/docs/vyos/vpn/vyos-ipsec/) - if you need interoperability with other vendors
- [OpenVPN](/docs/vyos/vpn/vyos-openvpn/) - for legacy remote access
- [Firewall](/docs/vyos/firewall/) - configuring VPN protection
- [NAT](/docs/vyos/nat/) - NAT for VPN traffic

