Skip to content

WireGuard VPN

atreoAGENT uses WireGuard to create encrypted peer-to-peer tunnels between mobile clients and your server. WireGuard is a modern, high-performance VPN that’s been part of the Linux kernel since 5.6.

The agent creates a WireGuard interface called wg-atreo with the following defaults:

SettingDefaultOverride
Interface namewg-atreo(not configurable)
Server IP (IPv4)100.64.0.1/24(not configurable)
Server IP (IPv6)fd00:64::1/64(not configurable)
Listen port51820 (UDP)wireguard.listen_port / WG_PORT
Subnet (IPv4)100.64.0.0/24(not configurable)
Subnet (IPv6)fd00:64::/64(not configurable)
Max clients253(determined by subnet size)

The overlay is dual-stack: every connected device gets both a 100.64.0.x IPv4 address and the matching fd00:64::x IPv6 address on the tunnel. The 100.64.0.0/10 range is reserved for Carrier-Grade NAT and fd00:64::/64 is a private ULA range, so neither is likely to conflict with your home network’s typical 192.168.x.x or 10.x.x.x ranges.

The IPv6 overlay keeps your apps reachable from IPv6-only and DNS64+NAT64 client networks — some mobile carriers and IPv6-only corporate or Wi-Fi networks — where an IPv4-only tunnel would otherwise fail to connect.

The expected client is the atreoLINK app, which has WireGuard built in. Members don’t install a separate WireGuard app. The tunnel is part of the atreoLINK app itself.

Power users can still use the official WireGuard apps or any compatible third-party client by exporting a manual WireGuard config from the web dashboard, but it’s not the default path.

When a member’s device first connects, the agent provisions it via a challenge-response flow over the atreoLINK control channel:

  1. Challenge. The mobile sends wg:challenge as a member-signed envelope (intent + ts, signed under the member’s identity key).
  2. Nonce. The agent verifies the envelope against the member’s pinned identity, then generates a 32-byte random nonce and returns it (5-minute validity).
  3. Provision. The mobile sends wg:provision as a member-signed envelope binding (memberId, clientId, nonce, ts) plus its WireGuard public key.
  4. Verification. The agent verifies the envelope against the member’s pinned identityKey from the ACL, not against any pubkey in the request body. (See Authentication for why this distinction matters.) It also confirms the nonce matches the one it issued.
  5. Allocation. The agent allocates a tunnel IP from the 100.64.0.0/24 pool — plus the matching fd00:64::x IPv6 address — and persists the assignment.
  6. Peer add. The client’s WireGuard public key is validated (32-byte base64) and added as a peer via wg set.
  7. Response. The agent signs a transcript covering nonce | client_pubkey | device_id | server_pubkey | tunnel_ip | endpoint | allowed_ips | persistent_keepalive with its long-term identity key and returns it. The mobile verifies this against the agent’s identity pubkey it pinned at pair time.

After step 7 the WireGuard tunnel comes up and the mobile starts routing app traffic directly to the agent.

Tunnel IPs are allocated sequentially from the subnet and persisted at /var/lib/atreoagent/ip_allocations.json. The server always uses .1 (100.64.0.1 and fd00:64::1); clients get .2 through .254, each with the matching IPv6 address (fd00:64::2, fd00:64::3, …).

On every startup and on every owner-signed ACL update from atreoLINK, the agent reconciles WireGuard peers with the ACL:

  • Peers in the ACL but not in WireGuard are added.
  • Peers in WireGuard but not in the ACL are removed.
  • Existing peers that match are left alone. Handshake state is preserved.

This is what makes “remove member” feel instant from a server owner’s perspective: as soon as atreoLINK pushes the ACL change, the agent rips out the WireGuard peer entries belonging to that member’s devices, and existing tunnels go silent.

WireGuard uses its own keypair, separate from the agent’s identity key:

KeyLocationPurpose
Privatekeys/wg_private.keyServer’s WireGuard private key.
Publickeys/wg_public.keyShared with clients during provisioning.

Keys are generated on first startup and persisted to disk. They survive across restarts, so existing tunnels don’t break unless you delete the data volume.

  • Endpoint discovery for how atreoLINK derives the public IP from the agent’s connection and advertises it to mobile clients.
  • NAT-PMP & UPnP for optional automatic mapping of the WG listen port.
  • Manual port forwarding for routers without UPnP/NAT-PMP (a fully supported path).
  • CGNAT relay for how off-network access works when no inbound port can be opened.
  • Manual WireGuard configs for exporting a config to a plain WireGuard client.
  • Tunnel protocol for what travels over the control WS to atreoLINK (separate from WG traffic).

WireGuard is a registered trademark of Jason A. Donenfeld.