VPN
AiFw ships with two VPN protocols: WireGuard and IPsec. Both compile their pass rules into the dedicated aifw-vpn anchor and are managed entirely through the API or CLI — no hand-edited wg-quick or ipsec.conf files. OpenVPN is intentionally not shipped; see the comparison page for the reasoning.
WireGuard
A WireGuard tunnel in AiFw is a server-side instance with its own keypair, listen port, and tunnel address. Peers (clients) are added one at a time and AiFw can auto-generate the client keypair so you can download a ready-to-import .conf file.
Quickstart
In the Web UI, go to VPN → WireGuard → Add tunnel. Pick an interface name (wg0, wg1, …), a listen port, and a tunnel address with prefix (e.g. 10.0.0.1/24). The keypair is generated automatically when the row is created. Then add peers and click Download config to get the client .conf file.
Create a tunnel:
curl -X POST https://aifw.local/api/v1/vpn/wg \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "office-vpn",
"interface": "wg0",
"listen_port": 51820,
"address": "10.0.0.1/24",
"dns": "10.0.0.1",
"mtu": 1420
}'
Add a peer with an auto-generated keypair (the server keeps the private key so it can build the client config):
curl -X POST "https://aifw.local/api/v1/vpn/wg/$TID/peers" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "laptop",
"allowed_ips": ["10.0.0.2/32"],
"persistent_keepalive": 25
}'
Download the peer’s ready-to-import config (server fills in [Interface] private key, [Peer] public key, Endpoint, AllowedIPs):
curl "https://aifw.local/api/v1/vpn/wg/$TID/peers/$PID/config?split_tunnel=false" \
-H "Authorization: Bearer $TOKEN" -o laptop.conf
Bring the tunnel up:
curl -X POST "https://aifw.local/api/v1/vpn/wg/$TID/start" \
-H "Authorization: Bearer $TOKEN"
Split-tunnel routes
Set split_routes on the tunnel to a comma-separated list of CIDRs (e.g. "172.29.0.0/16, 10.0.0.0/8") and request split_tunnel=true on the peer config download. Clients then only route those networks through the VPN. Without split_routes, AiFw masks the tunnel’s own address to its network boundary and uses that.
HA failover
WireGuard tunnels survive a CARP failover provided peers run with PersistentKeepalive. The wireguard-go process binds wildcard so the new master receives traffic on the CARP VIP automatically. See HA cluster for the full survival matrix.
IPsec
AiFw supports IPsec Security Associations with ESP, AH, or ESP+AH protocols, in either tunnel or transport mode. Each SA gets a random SPI and sensible algorithm defaults (AES-256-GCM + HMAC-SHA256). When the SA is in tunnel mode the engine also emits a pass quick on enc0 rule so encapsulated traffic flows.
Quickstart
In the Web UI, go to VPN → IPsec → Add SA. Provide endpoints, protocol, and mode.
curl -X POST https://aifw.local/api/v1/vpn/ipsec \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"name": "office-to-dc",
"src_addr": "203.0.113.1",
"dst_addr": "198.51.100.1",
"protocol": "esp",
"mode": "tunnel"
}'
The created SA emits these pass rules into the aifw-vpn anchor:
pass in/out quick proto esp from <peer> to <peer>(orah)pass in/out quick proto udp ... port { 500 4500 }for IKEpass quick on enc0 ...(tunnel mode only)
CLI
aifw vpn wg-add --name wg0 --interface wg0 --port 51820 --address 10.0.0.1/24
aifw vpn wg-peer-add --tunnel <id> --name laptop --pubkey <key> --endpoint 1.2.3.4:51820
aifw vpn ipsec-add --name office --src 203.0.113.1 --dst 198.51.100.1
aifw vpn list
aifw vpn remove <uuid>
API endpoints
| Method | Endpoint | Description |
|---|---|---|
GET |
/api/v1/vpn/wg |
List WireGuard tunnels |
POST |
/api/v1/vpn/wg |
Create a tunnel (auto-generates keypair) |
PUT |
/api/v1/vpn/wg/{id} |
Update a tunnel |
DELETE |
/api/v1/vpn/wg/{id} |
Delete a tunnel |
POST |
/api/v1/vpn/wg/{id}/start |
Bring tunnel up |
POST |
/api/v1/vpn/wg/{id}/stop |
Bring tunnel down |
GET |
/api/v1/vpn/wg/{id}/status |
Live tunnel status |
GET |
/api/v1/vpn/wg/{id}/peers |
List peers |
POST |
/api/v1/vpn/wg/{id}/peers |
Add a peer |
GET |
/api/v1/vpn/wg/{id}/peers/next-ip |
Suggest the next free peer IP |
DELETE |
/api/v1/vpn/wg/{tid}/peers/{pid} |
Delete a peer |
GET |
/api/v1/vpn/wg/{tid}/peers/{pid}/config |
Download peer .conf file |
GET |
/api/v1/vpn/ipsec |
List IPsec SAs |
POST |
/api/v1/vpn/ipsec |
Create an SA |
DELETE |
/api/v1/vpn/ipsec/{id} |
Delete an SA |
Configuration
| Field | Default | Notes |
|---|---|---|
| Anchor name | aifw-vpn |
All WG/IPsec pass rules live here |
enc_algo (IPsec) |
aes-256-gcm |
Set per SA |
auth_algo (IPsec) |
hmac-sha256 |
Set per SA |
persistent_keepalive (WG) |
unset | Set on the peer (typically 25) so the tunnel survives NAT timeouts and HA failovers |
split_routes (WG) |
unset | Comma-separated CIDRs; falls back to the masked tunnel network |