diff options
authorDaniel Kahn Gillmor <dkg@fifthhorseman.net>2019-02-11 18:30:42 -0500
committerThomas Gschwantner <tharre3@gmail.com>2019-02-13 16:59:07 +0100
commit683bad6556607a0b23930f6c258e4144ff35d310 (patch)
parentImplement key=value parsing (diff)
Move the google doc into the git repository
2 files changed, 103 insertions, 1 deletions
diff --git a/README.md b/README.md
index 03a9c9c..379d241 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
# Wireguard Dynamic IP Configuration Tool
-This is an implementation of [the wg-dynamic description](https://docs.google.com/document/d/11RJDDrdIsnGivz8xP5NsOteHdviuV4jfNG1CSl0q8cY/edit).
+This is an implementation of [the wg-dynamic description](./docs/idea.md).
Work-in-progress; nothing to see here yet.
diff --git a/docs/idea.md b/docs/idea.md
new file mode 100644
index 0000000..3dea318
--- /dev/null
+++ b/docs/idea.md
@@ -0,0 +1,102 @@
+If this looks like an interesting project to you, get in touch with
+the WireGuard development team.
+WireGuard currently uses static addresses everywhere. This is because
+that is mostly a better way to design your network. But in some cases,
+insane people want dynamic IP addresses or other dynamic
+This paper explores a couple approaches to WireGuard in-band
+configuration. Ultimately, however, custom in-band communication
+brings with it many difficulties, such as introducing new non-standard
+APIs and having to reinvent the wheel with reliable transport
+Traditionally, configuration of IP addresses has been done at a layer
+in between 2 and 3 using DHCP. DHCP, however, has numerous drawbacks
+that make it unsuitable for use with WireGuard:
+ * Relies on broadcast.
+ * Unicast DHCP is not well supported nor mature.
+ * Two different protocols for v6 and v4, and v4-in-v6 dhcp is a bit insane.
+ * Cumbersome and old.
+Fortunately IPv6 link-local addresses give us exactly the semantics we
+need for an in-band configuration protocol, without needing to
+introduce new layer 3 types. Since a server must know each of its
+clients public keys beforehand, it is not ridiculous to, at the same
+time, assign a unique link-local IP address to that client. In this
+setup, the server knows a priori the client’s public key and the
+client’s link local IPv6 address. The client needs only to know the
+server’s public key.
+When wg-dynamic is run on a certain WireGuard interface, say wg0, it
+determines whether that interface has a link-local IP address that is
+actually a /128 and also has a peer whose allowedips include
+`fe80::/128`. If not, it exits. If so, it initiates the protocol with
+`fe80::%wg0` -- notice the use of the link-local scope identifier.
+In the protocol, the server -- communicated with via `fe80::%wg0` --
+assigns the client dynamically determined global IPv4 and IPv6
+addresses and masks from an address pool, with a lease, and usual
+dhcp-like renewal semantics commence. All leased IP addresses are
+added to that peer’s set of allowed IPs, so that the client can
+actually use them. The protocol could also push routes to be added to
+allowedips and the routing table. The protocol would likely use TCP
+rather than UDP, since we have the luxury of unicast and being inside
+of a secure tunnel.
+In the future, the protocol could also push information about other
+peers, transitioning wg-dynamic from a basic boring dhcp-substitute
+into a full fledged WireGuard mesh networking utility.
+Thus, the above consists of implementing a lightweight client daemon
+and server daemon in C with no dependencies, to become part of the
+standard set of WireGuard tools. The UI of the client daemon is
+simplest in its usage:
+ $ wg-dynamic-client wg0
+After this, it validates wg0 has the necessary configuration for it to
+function, and then it forks into the background, listens to up/down
+events, and lives until wg0 is removed, at which time it exits.
+This will then hook nicely into wg-quick(8) configurations. The
+following configuration will initiate a wg-dynamic IP address
+assignment on the client side:
+ [Interface]
+ PrivateKey = …
+ Address = fe80::abcd:abcd:abcd:abcd/128, auto
+ [Peer]
+ PublicKey = …
+ AllowedIPs =, ::/0
+The “auto” in the list of addresses means “spawn wg-dynamic.” And
+notice that `fe80::/128` is a subset of the included `::/0`. However,
+this would be equally as valid:
+ [Interface]
+ PrivateKey = …
+ Address = fe80::abcd:abcd:abcd:abcd/128, auto
+ [Peer]
+ PublicKey = …
+ AllowedIPs = fe80::/128
+Though part of the standard set of WireGuard utilities, which is
+GPLv2, the code from wg-dynamic would likely be recycled in various
+client apps; thus MIT license is preferred for this.
+The app will require various APIs and competencies:
+ * Standard linux socket programming.
+ * Rtnetlink for configuring device, listening to events, and so forth, preferably using libmnl.
+ * Genetlink for talking to wireguard, preferably using the mini wireguard library.
+ * Design of a new protocol wire format that is sane and appropriate for 2019.
+ * Implementation of code that parses untrusted packets, makes
+ decisions with this data, and does not get your box owned in the
+ process. This is harder than it may seem.