Skip to content

Design a simple credential distribution mechanism for WireGuard experiments #2772

@ainghazal

Description

@ainghazal

Problem statement

We need a simple way of distributing credentials for probing target WireGuard nodes. We assume we're able to control abuse, for instance by adding firewall rules to the wireguard node restricting what are allowed IP addresses routed from the gateway.

In a recent conversation with @hellais we said that we'd like an implementation that keeps as little state as possible: this means that we can control what information is passed to the clients via the VPN endpoint API, and/or hardcoding tokens on the experiment itself. On the wireguard server, we need to generate the list of public keys (and IP allocations) for the set of allowed Peers -- but we'd rather avoid modifying the configuration file dynamically.

We agree that we can pre-compute a number of public keys (a 32-byte Curve25519 point) on the server; this number needs only to be big enough to practically minimize the likelihood of a "collision" (i.e., two probes attempting to use the same encryption key).

This constrain is given by WireGuard design:

Since a public key uniquely identifies a peer, the outer external 
source IP of an encrypted WireGuard packet is used to identify
the remote endpoint of a peer, enabling peers to roam freely between
different external IPs, between mobile networks for example

Design Discussion

  • On the server-side: given a (sufficiently big) number N of allowed Peers, 1) compute N 32-byte random numbers with a known seed, 2) derive their public keys, 3) assign a unique allowed IP to each of them, 4) serialize this info as a valid wireguard configuration file and start the wireguard server with this configuration.

Do note that Curve25519 clamping may need to be accounted for (i.e., different private keys can result in the same public key), although the likelihood of this happening is possibly negligible.

  • On the client-side: given a known seed, 1) initialize the PRNG with the known seed, 2) pick a random 32-byte number between 0 and N, 3) use the 32-byte number as the private key, 4) derive the public key, 5) derive the IP using the same deterministic rule as the server did, 5) use these credentials+config (plus the preshared key) to connect to the server.

Choice of PRNG

Minor detail (need to benchmark it for practical usage), but we could either iterate through the whole range every time, if using a LCG (as the default PRNG in Go), that will give us O(n) complexity, or perhaps use a generator that allows skip-ahead, and thus O(1).

Priority & Deadlines

This would be the main blocker for distributing wireguard experiments to clients. At this point I'd say we're not on time to make it to the July release, so I would tentatively assign it to the September probe-cli release cycle. For sure testing from VPs can start as soon as I have a prototype ready.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions