How the network works¶
A Kiwi Network is a WireGuard mesh with one hub. Every machine is built by kiwi-server and gets a role. The modules section has the details of each service.
Internet
▲
│ exit: a commercial VPN (Mullvad, ProtonVPN, AirVPN, …)
│ through gluetun — the "double hop"
┌────────────┴─────────────────────────────┐
│ kiwi-master (a VPS, or any reachable box) │
│ wg-easy WireGuard server, 10.8.0.1 │ ◀── UDP 51820, the one
│ gluetun VPN client: the master's exit │ published port
│ Pi-hole DNS for the mesh │
│ Tor SOCKS5 for mesh clients │
└────────────▲─────────────────────────────┘
│ WireGuard mesh 10.8.0.0/16 — everyone dials out to the master
┌───────────────────┼────────────────────┬──────────────────────┐
│ │ │ │
kiwi-node (cloud) kiwi-node (gateway) laptops, phones a router (OpenWrt,
Nextcloud AIO, routes its LAN through (wg-easy clients) FritzBox, …) joins
Vaultwarden, nginx the VPN; Pi-hole, DHCP a whole LAN
relay, downloads, SFTP
The master¶
The master (role master) runs four modules:
- vpn-server (wg-easy) is the entry point for every client and node. It
issues the WireGuard client configs. Its web UI listens on
127.0.0.1:51821on the master and, by default (admin_from_mesh), at the server's mesh address for regular clients. - vpn-client (gluetun) connects to a commercial VPN provider (Mullvad in the preset; any gluetun provider works). The WireGuard server's default route points at it, so traffic from the mesh to the Internet leaves through the provider, not the master's own address. That is the double hop: client → master → VPN provider → Internet.
- dns (Pi-hole) runs inside the WireGuard server's network stack and
answers at the master's mesh address (
10.8.0.1). See DNS, names & certificates. - tor offers a Tor SOCKS5 proxy at the master's mesh address, for mesh
clients only (
10.8.0.0/16), with entry and exit nodes pinned to a set of countries (defaultde,ch,at,nl,fr,StrictNodes).
What is reachable from the Internet¶
The master's stack publishes one port: WireGuard on UDP 51820 (set
public_ip to bind it to a single address). wg-easy's and Pi-hole's admin pages
are bound to localhost or the mesh. kiwi-server opens the stack's ports in
firewalld or ufw when one of them is active; it does not otherwise change the
target's firewall. In particular, SSH stays as the OS has it (keys only, by
default). If you want WireGuard to be the only thing reachable, restrict SSH at
your provider's firewall or to the mesh.
Isolated clients¶
wg-easy hands out addresses from the mesh subnet (10.8.0.0/24). Clients given
an address in the isolated subnet (10.8.1.0/24 by default) get the
Internet (through the double hop) and the fleet's nodes, but they cannot see
other clients, and they never get the admin pages. Use it for devices or people
you give access to services but not to your network.
Nodes¶
A node's vpn-client (gluetun) does not talk to a commercial VPN. It uses the
WireGuard client config that the master's wg-easy issued for it
(vpn_provider: custom). A node therefore needs no open port of its own: it
dials out to the master, and it keeps working behind a home router's NAT.
Services on a node are reachable on its LAN and at its mesh address (e.g.
10.8.0.25). Mesh traffic to the node's mesh address on 80/443 is forwarded
(DNAT) to the reverse proxy.
- node-cloud: Nextcloud All-in-One and Vaultwarden behind nginx, plus Portainer.
- node-gw: a LAN gateway. LAN clients that use this machine as their default gateway leave through the VPN client: they can reach the mesh, but not the node's docker network. Pi-hole serves the LAN (optionally as its DHCP server, through the DHCP relay). Transmission and JDownloader run inside the VPN client's network namespace, so if the tunnel is down they have no route at all. Also nginx, Portainer and SFTP.
Addressing¶
| What | Default |
|---|---|
| Mesh (routed on every host) | 10.8.0.0/16 (mesh_subnet) |
| wg-easy client range | 10.8.0.0/24, server 10.8.0.1 |
| Isolated clients | 10.8.1.0/24 |
| Stack docker network | 172.64.0.0/24 on a master, 172.128.0.0/24 on a node |
| WireGuard MTU inside the stack | 1412 |
Every stack host routes the mesh subnet through its VPN client (through the WireGuard server on the master), so the host and its containers, Pi-hole included, reach every other node. The master masquerades that traffic as its mesh address.
Keeping the tunnel fresh¶
Each stack host gets two timers from the stack settings: a daily VPN restart
(07:00 by default; the old cron did this for a fresh exit address) and a
weekly kiwi-stack update (Sunday 00:00: pull, restart, prune). Either can be
turned off by setting it empty. kiwi-stack vpn-restart also restarts the
containers that share the VPN client's network namespace.
Reaching the mesh from a whole LAN¶
A router can join the mesh as a WireGuard client, or send the mesh subnet to a gateway node with a static route. Then every device on that LAN reaches every node without running WireGuard itself. See Routers.