# wgmesh Automatically build private wireguard mesh networks. [![Go Report Card](https://goreportcard.com/badge/github.com/aschmidt75/wgmesh)](https://goreportcard.com/report/github.com/aschmidt75/wgmesh) [![Go](https://github.com/aschmidt75/wgmesh/actions/workflows/go.yml/badge.svg)](https://github.com/aschmidt75/wgmesh/actions/workflows/go.yml) ![wgmesh Dashboard](docs/wgmesh-ui-sample.png) ## How it works * A mesh consist of interconnected nodes. Each node has a [wireguard](https://www.wireguard.com/) interface with all other nodes registered as peers. The mesh is fully-connected through the wireguard-based overlay network. Each node can IP-reach all other nodes via direct host routes. * At least one of the mesh nodes is a bootstrap node. Besides the wireguard peerings it runs a gRPC-based mesh endpoint, where other nodes can issue join requests. * New nodes can enter the mesh by joining via a bootstrap node. The bootstrap node learns about the joining node and its wireguard endpoint and public key. It distributes this information to the other mesh nodes. It also fowards a list of mesh peers to the new joining node so it is able to configure its own wireguard interface. * Existing mesh nodes learn about the new joining node from the bootstrap node and update their wireguard peer configuration accordingly. * Mesh nodes integrate [serf.io](https://serf.io) to maintain state about the network topology, learn about new nodes joining and failing nodes or nodes leaving the mesh. This is done using serf's encrypted gossip-based cluster membership protocol. * The bootstrap node's gRPC endpoint runs TLS with requesting and validating client certificates. This way new nodes are required to authenticate themselves by x.509 certificates. ## Build The default targets of `Makefile` generate protobuf and grpc parts and build the binary in `dist/`. It also builds the web ui (and needs node/npm for this), and appends the web artifacts using [go.rice](https://github.com/GeertJohan/go.rice). ```bash $ make all ``` The binary can be built without web ui support: ```bash $ make clean gen build ``` Additionally, goreleaser can be used to create a snapshot release for different platforms (also in `dist/`) ```bash $ make release ``` So for a full, releaseable build one needs * go (tested w/ version go1.15.5 darwin/amd64) * [rice](https://github.com/GeertJohan/go.rice) * node (tested w/ v14.16.0) * npm (tested w/ 6.14.11) * [goreleaser](https://github.com/goreleaser/goreleaser) (tested w/ version 0.155.0) ## Prerequisites * Linux * Wireguard module installed/enabled in kernel * Works best with a non-NATed setup. It can partially work with NAT, but there's no guarantee. ## Usage The fastest way to start a mesh is using the development mode, either with a bunch of local virtual machine or with available cloud instances. [This walkthrough](docs/multipass-demo-setup.md) shows how to use it with local multipass-based ubuntu lts instances. The mesh is initiated with a first bootstrap node. It creates a wireguard interface and starts listening for join requests on a gRPC endpoint. Make sure that the bootstrap node is not behind a NAT. In development mode, no security/TLS/mesh encryption is enforced, so all other nodes can join with authentication. This simplifies testing but is not suitable for non-development purposes. ```bash # wgmesh bootstrap -dev ** Mesh name: xoJbYw07PM ** Mesh CIDR range: 10.232.0.0/16 ** gRPC Service listener endpoint: 0.0.0.0:5000 ** This node's name: xoJbYw07PMAE80101 ** This node's mesh IP: 10.232.1.1 ** ** This mesh is running in DEVELOPMENT MODE without encryption. ** Do not use this in a production setup. ** ** To have another node join this mesh, use this command: ** wgmesh join -v -dev -n xoJbYw07PM -bootstrap-addr <PUBLIC_IP_OF_THIS_NODE>:5000 ** ** To inspect the wireguard interface and its peer data use: ** wg show wgxoJbYw07PM ** ** To inspect the current mesh status use: wgmesh info ** ``` For other nodes to join, the (public or private) IP address of the bootstrap node is needed, so joining nodes are able to connect. Switch to a second instance and run the join command as stated above: ```bash # wgmesh join -v -dev -n xoJbYw07PM -bootstrap-addr 10.0.0.0:5000 INFO[2021/02/27 10:46:31] Fetching external IP from STUN server INFO[2021/02/27 10:46:31] Using external IP when connecting with mesh ip= INFO[2021/02/27 10:46:31] Created and configured wireguard interface wgxoJbYw07PM as no-up WARN[2021/02/27 10:46:31] Using insecure connection to gRPC mesh service INFO[2021/02/27 10:46:32] Starting gRPC Agent Service at /var/run/wgmesh.sock ** ** Mesh 'xoJbYw07PM' has been joined. ** ** Mesh name: xoJbYw07PM ** Mesh CIDR range: 10.232.0.0/16 ** This node's name: xoJbYw07PMAE8B8DB ** This node's mesh IP: 10.232.184.219 ** ** This mesh is running in DEVELOPMENT MODE without encryption. ** Do not use this in a production setup. ** ** To inspect the wireguard interface and its peer data use: ** wg show wgxoJbYw07PM ** ** To inspect the current mesh status use: wgmesh info ** INFO[2021/02/27 10:46:33] Mesh has 2 nodes ``` Additional nodes can join using the same `join` command. On any node, the `info` command prints out connected nodes: ```bash # wgmesh info Mesh 'xoJbYw07PM' has 2 nodes, started 2021-02-27 10:45:31 +0100 CET This node 'xoJbYw07PMAE8B8DB' joined 2021-02-27 10:46:31 +0100 CET Name |Address |Status |RTT |Tags | xoJbYw07PMAE8B8DB |10.232.184.219 |alive |7 | _addr=, _port=54540, | xoJbYw07PMAE80101 |10.232.1.1 |alive |38 | _addr=, _port=54540, | ``` The `ui` command start an HTTP server, serving a simple, vue-based dashboard. By default it binds to port 9095 on the localhost interface only. It does not authenticate clients and does not (yet) support TLS. ```bash # wgmesh ui Serving files on 127.0.0.1:9095, press ctrl-C to exit ``` ## License (C) 2020,2021 @aschmidt75 Apache License, Version 2.0 Wireguard ist a registered trademark of Jason A. Donenfeld / [wireguard.com](https://wireguard.com)