Manage a community vpn/dns network
 
 
 
 
Go to file
Keith Irwin d26b744bf6
fix: 🚑 Fixed mixup between client_allowedips and server_allowedips
2024-02-12 10:05:13 -07:00
back fix: 🚑 Fixed mixup between client_allowedips and server_allowedips 2024-02-12 10:05:13 -07:00
etc.sample fix: 🐛 Moved PostUp and PostDown lines to config file 2024-02-12 09:59:41 -07:00
front fix: 🚑 Fix broken cert/key requests 2023-12-30 19:02:35 -07:00
img Added logo 2023-04-08 15:30:51 -06:00
.gitignore fix: 🐛 Fixed .gitignore ignoring wrong file 2023-12-02 11:47:36 -07:00
INSTALL.md feat: Custom AllowedIPs and PostUp/PostDown lines 2024-01-11 15:44:54 -07:00
LICENSE.md #9 Renamed to wagon and added README info 2023-04-08 15:30:25 -06:00
README.md fix: 📝 Updated Roadmap 2024-01-11 11:24:17 -07:00
USAGE.md fix: 🚑 Fix broken cert/key requests 2023-12-30 19:02:35 -07:00
docker-compose.override.yml.sample refactor: 🏗️ Move network_mode to docker-compose override files 2023-12-02 12:01:13 -07:00
docker-compose.yml fix: 🐛 Remove volumes from docker-compose, set in override 2023-12-02 14:23:22 -07:00

README.md

wagon

2022-2023 Keith Irwin (ki9.gf4.pw)
MIT License

wagon is a an api, user dashboard, and admin ui for managing devices and services on a dns-enabled wireguard network. It was built with small web communities in mind.

IP address allocation

wagon manages devices on a wireguard network, 10.X.Y.Z/16 where X is a number associated with the community, configured at the first setup. Servers are hosted on 10.X.0.Z/24, where each Z is a different server. Finally, each user gets a number Y (between 1 and 254) and a /24 subnet for each of their their devices, Z.

For example: Your home pc could be 10.11.1.1 and your phone 10.11.1.2. After configuring wireguard, you can use either device to ping your friend, whose pc is at 10.11.2.1.

IPv6 is also preconfigured for a /96 subnet, with users getting their own /112 network for each /128 device.

Nameserver

wagon manages a bind9 nameserver through the nsupdate command. Device domain names have a similar structure as IP addresses, A.B.C, where:

  • C is the community's top-level-domain (TLD)
  • B is the username
  • A is hostname of the device

The TLD could be anything that isn't already a global TLD like .com. The recursive nameserver takes these private domains as questions and provides private wireguard IPs as answers. It only responds to .mynet queries from its own network on 10.X.0.0/16. This nameserver is then preconfigured in clients' wireguard configs' DNS = setting. Optionally the community's TLD can be set as a search domain for the wireguard interface.

For example: Your home pc could be pc.myuser.mynet and your phone phone.myuser.mynet. Either can ping up phone.myfriend.mynet. These would point to 10.11.1.1, 10.11.1.2, and 10.11.2.1 respectively

Servers (IPs with Y=0) have domains of the form A.C, as above. Wildcard subdomains are CNAMEd to their base address, that is, *.phone.myuser.mynet CNAMEs to phone.myuser.mynet and *.myerver.mynet CNAMEs to myserver.mynet. Of course, this means no username can match a server hostname.

The nameserver is also preconfigured for rDNS so you can perform lookups on IP addresses:

$ nslookup 10.11.1.1
1.1.11.10.in-addr.arpa   name = pc.myuser.mynet.

Using this setup, the community's entire wireguard network and DNS can be accessed from any device by importing a single wireguard config. One purpose of wagon is to easily generate these device configs.

Certificate authority

wagon also automatically signs SSL certs for its own invented TLD (.mynet) so network-hosted services can be encrypted. The certificates are signed for the IPs and wildcard domains listed above, so, with the right web proxy configuration, a user can use the same certificate to self-host a service on any of these domains:

  • https://10.11.1.2/
  • https://[fd69:1337:0:420:f4:11:1:2]/
  • https://mypc.myuser.mynet/
  • https://myservice.mypc.myuser.mynet/
  • https://myotherservice.mypc.myuser.mynet/
  • https://anyotherservice.mypc.myuser.mynet/

The wagon user dashboard provides a server certificate and key that the user can download. Any wireguard-connected device with the community's ca certificate imported in their browser or OS will be able to see a green lock on their browser when visiting these private sites.

These certs can be used for other internet protocols like irc or imap.

Self-hosting and firewalls

Since firewalls and web proxies understand CIDR notation, controlling access to services is easy:

  • Allow 10.11.1.1/32 to allow access to pc.myuser.mynet only
  • Allow 10.11.1.0/24 to allow access to any of myuser's devices
  • Allow 10.11.2.1/32 to allow access to a friend's pc
  • Allow 10.11.2.0/24 to allow access to any of a friend's devices
  • Allow 10.11.0.0/16 to allow access to anyone in the community
  • Allow 10.0.0.0/8 to allow access to any other community (someday, maybe)

Allowing access to virtual webservers is just as simple. For example, I can let my friend access my development server with these allow/deny lines in an nginx vhost config (only showing IPv4, but works with IPv6 too).

server {
	server_name dev.mypc.myuser.mynet;
	listen 10.11.1.1:443 ssl http2;

	ssl_certificate     /path/to/downloaded/mypc.myuser.mynet/cert.pem;
	ssl_certificate_key /path/to/downloaded/mypc.myuser.mynet/key.pem;
	ssl_stapling        off;

	allow 10.11.1.0/24;  # My devices
	allow 10.11.2.0/24;  # My friend's devices
	deny  all;           # Everyone else

	# Proxy to local dev server
	location / {
		proxy_pass http://localhost:8080;
	}
}

Dashboard

Users can access a dashboard with a list of devices and links to download cert.pem and key.pem. Users can add and delete these devices, and admins can add/delete devices and users from a seperate admin interface. When adding a new user or device, the dashboard displays a wireguard configuration which must be copied or saved before the page is refreshed.

In this way, there is no central server storing all the private keys, like with most wireguard dashboards. In fact, wagon does not have a database and does not store any data at all; everything is stored in the server's nameserver and wireguard config.

This also means there is no login to the dashboard. Users simply connect to the dashboard over wireguard from any connected device, and wagon will recognize your IP and serve up a list of other devices on that same /24 subnet.

Structure

wagon is written in bash and run as a cgi script. It can be run in- or outside of docker. Why bash? Because it has great "SDKs" for wireguard (wg), nameserver updates (nsupdate), and SSL certs (openssl). The libraries used in the scripts are themselves scripts. Each script follows the unix philosophy of handling text through standard means (arguments and stdin to stdout), so individual libraries could be replaced with faster alternatives (c, rust, go) in the future.

Project status

The wireguard dashboard and admin are in a working alpha state. I have it implemented on my own network, gf4, and it seems to be working there. Work is still needed on all these unchecked boxes.

| Feature   | Multiuser daemon | Dashboard CRUD | Documented | Tests |
+-----------+------------------+----------------+------------+-------+
| wireguard |       [X]        |     [X]        |    [X]     |  [ ]  |
| bind9     |       [X]        |     [X]        |    [X]     |  [ ]  |
| TLS certs |       [X]        |     [X]        |    [X]     |  [ ]  |
| nginx     |       [X]        |     [ ]        |    [ ]     |  [ ]  |
| postfix   |       [X]        |     [ ]        |    [ ]     |  [ ]  |
| asterisk  |       [ ]        |     [ ]        |    [ ]     |  [ ]  |

 [ ] Replace bash scripts with binaries*
 [ ] API documentation
 [ ] A good CLI/TUI
 [ ] Hooks

*binaries compiled from languages like c/rust/go/haskell, as long as SDKs are available.

Installation

You want to use this half-built product on your server at your own risk? Fine, go right ahead! Take a look at INSTALL.md. If you have trouble, ask for help in the matrix room below.

Contributing

If you think you can help with any of these checkboxes, come by #wagon:gf4.pw on matrix.