From fa31b1a5177805b06058d414ed5a8b30408f4d6e Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Wed, 5 Feb 2020 00:24:56 +0100 Subject: Release v0.3.0. --- CHANGELOG.md | 13 ++++++++ Cargo.toml | 2 +- README.md | 107 ++++++++++++++++++++++++++++++++++++++++++++--------------- 3 files changed, 95 insertions(+), 27 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fbb7e29..426e8a4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,16 @@ +v0.3.0 +--- + +- Preshared keys are now always referred to by filename. The file must contain +the base64 encoding of the key itself, followed by newline. + +- Sources are now given in `[[source]]` sections and the name is in a `name` +attribute. Endpoints are taken from the first source that defines the peer. + +- Peer overrides can also set the endpoint and the keepalive timeout. + +- The OpenWRT procd init script has been replaced by a netifd protocol. + v0.2.0 --- diff --git a/Cargo.toml b/Cargo.toml index 84aca12..4d76d31 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,7 +4,7 @@ [package] name = "wgconfd" -version = "0.2.1" +version = "0.3.0" edition = "2018" authors = [ "Hristo Venev " ] license = "LGPL-3.0-or-later" diff --git a/README.md b/README.md index 7e6f367..6a5877d 100644 --- a/README.md +++ b/README.md @@ -1,66 +1,76 @@ wgconfd === -wgconfd is a configuration manager for [WireGuard](https://wireguard.com). +wgconfd is a configuration manager for [WireGuard](https://wireguard.com/). -General behavior +Overview --- `wgconfd INTERFACE CONFIG` starts a process that manages some peers of a WireGuard interface. It adds/overwrites peers it knows about and removes peers once they disappear from its view. It leaves any peers it has never seen intact. +Peers are defined in sources. A source is a JSON file served over a protocol that `curl` understands. + +A "server" peer has a known IP address and talks to other servers directly. A "road warrior" peer communicates with everyone through its base server. + Configuration --- -The configuration consists of a set of sources. A source consists of a URL (required), a set of allowed IP address ranges (optional, defaults to nothing), and a preshared key (optional): +The main configuration file is written in [toml](https://github.com/toml-lang/toml). ```toml refresh_sec = 1200 # default min_keepalive = 10 # default max_keepalive = 0 # default, means "never" -[source.remote1] +[[source]] +name = "remote1" url = "https://wg.example.org/peers.json" ipv4 = [ "172.16.0.0/12", "192.168.5.0/24" ] ipv6 = [ "2001:db8::/32" ] -[source.remote2] +[[source]] +name = "remote2" url = "https://wg.example.com/peers.json" ipv4 = [ "172.16.0.0/12", "192.168.6.0/24" ] ipv6 = [ "2001:db8:1234:/48" ] -psk = "GBRwvlGYEcHqe+ft+px5I9dMAGWAqsghftSDz2PhoM8=" +psk = "/path/to/psk/file" +allow_road_warriors = false -[source.local-user1] -url = "file:///home/user1/.config/wg-dev.json" +[[source]] +name = "local-user1" +url = "file:///etc/wireguard/example/user1.json" ipv4 = [ "172.16.5.54/32" ] -[source.local-user2] -url = "file:///home/user2/.config/wg-dev.json" +[[source]] +name = "local-user2" +url = "file:///etc/wireguard/example/user2.json" ipv6 = [ "2001:db8::5/128" ] ``` -All IP address ranges from the source URL not entirely contained within the config are discarded - if a source claims `0.0.0.0/0` but the config only allows `10.0.0.0/8`, nothing is allowed. +All IP address ranges from the source URL not entirely contained within the ones configured are discarded - if a source claims `0.0.0.0/0` but the config only allows `10.0.0.0/8`, nothing is allowed. -The preshared key is applied to all peers defined in a source. If a single peer is defined in multiple sources, both the endpoint and preshared key are taken from a single source chosen nondeterministically, but all IP ranges are allowed. +The preshared key is applied to all peers defined in a source. If a single peer is defined in multiple sources, both the endpoint and preshared key are taken from the first source that defines it. -It is possible to override the preshared key for a specific public key, and to restrict the source that can define that peer: +It is possible to override some options for a specific public key, and/or to restrict the source that can define that peer: ```toml [peer."yIOdSFrFQ1WPYS6IUWCsRjzw2Iqq0HMcyVVEXu5z+nM="] source = "remote2" +endpoint = "[2001:db8::6]:10656" psk = "QJmzt2PpKx8g98qrOtsNR4tB1bik+fMSabNNXCC5OUU=" +keepalive = 20 ``` -Alternative configuration ---- +### Alternative configuration There is an alternative configuration mechanism intended for integration with other software: `wgconfd --cmdline INTERFACE ARGS...` The arguments are a sequence of global options and sources: - - `min_keepalive TIME` - - `max_keepalive TIME` - - `refresh_sec TIME` - - `source NAME URL [psk PSK] [ipv4 NET,NET,...] [ipv6 NET,NET,...] [required]` - - `peer PUBKEY [psk PSK] [source NAME]` + - `min_keepalive SEC` + - `max_keepalive SEC` + - `refresh_sec SEC` + - `source NAME URL [psk PATH] [ipv4 NET,NET,...] [ipv6 NET,NET,...] [required] [allow_road_warriors | deny_road_warriors]` + - `peer PUBKEY [endpoint IP:PORT] [psk PATH] [keepalive SEC] [source NAME]` Source format --- @@ -89,18 +99,20 @@ wgconfd also supports roaming peers called "road warriors": ... "road_warriors": [{ "public_key": "YJ0Ye/Z/f+kzMu5au8JL/OP+cMs0eRsJPSQ9FZIa7Sk=", - "base": "ymTvQHxgEDacZq90T/1dYR4ARvtbBTH4rIHab83WFBY=", + "base": "hw0U7vI2rhjG9mQ34CUKO6M4dIF9e8ofKj5N6cAPtwY=", "ipv4": [ "10.2.5.44/32" ] }, ...] } ``` -A road warrior does not have an endpoint and does not run wgconfd - it is instead expected to only talk to its base server peer. +A road warrior does not typically run wgconfd. It is instead expected to only talk to its base server peer. -On the base peer, a WireGuard peer is created for the road warrior. On all other peers an additional allowed IP address is added for the base. +On the base peer, a WireGuard peer is created for the road warrior. On all other peers the allowed IP address ranges of the road warrior are added to its base instead. A road warrior from one source can use a server from another source, but allowed IPs are always checked against the source that contains the road warrior definition. +The `allow_road_warriors` option in `[[source]]` sections can be used to deny being the base of road warriors from certain sources. + ### Configuration updates The root object can contain a field `"next"` with an `"update_at"` timestamp and another configuration: @@ -117,7 +129,7 @@ The root object can contain a field `"next"` with an `"update_at"` timestamp and }], "road_warriors": [{ "public_key": "YJ0Ye/Z/f+kzMu5au8JL/OP+cMs0eRsJPSQ9FZIa7Sk=", - "base": "ymTvQHxgEDacZq90T/1dYR4ARvtbBTH4rIHab83WFBY=", + "base": "hw0U7vI2rhjG9mQ34CUKO6M4dIF9e8ofKj5N6cAPtwY=", "ipv4": [ "10.2.5.44/32" ] }], "next": { @@ -131,7 +143,7 @@ The root object can contain a field `"next"` with an `"update_at"` timestamp and "endpoint": "[2002:cb00:71af::4]:656", "ipv4": [ "10.1.3.0/25" ] }, { - "public_key": "nlFVtJrOwR2sVJji6NQjXnv//GVUK5W9T7ftkSnYPA8=", + "public_key": "JjSETJ9ACv0sTTEtBE2qp9q4vbeq1i5suwWaJCuncFo=", "endpoint": "[2001:db8:ddcc:bbaa::5]:565", "ipv4": [ "10.1.3.128/25" ] }], @@ -144,4 +156,47 @@ The root object can contain a field `"next"` with an `"update_at"` timestamp and } ``` -All instances of `wgconfd` using that source will switch to the new configuration at the same time according to their system clocks. Note that the regular mechanism for updates still applies - to cancel an update, remove the `"next"` field early enough so that all machines refresh the source before `"update_at"`. +All instances of `wgconfd` using that source will switch to the new configuration at the specified time according to their system clocks. Note that the regular mechanism for updates still applies - to cancel an update, remove the `"next"` field early enough so that all machines refresh the source before `"update_at"`. + +Operating system support +--- + +wgconfd should work on all operating systems that provide the `wg` and `curl` commands. + +### systemd-based Linux distributions + +Sample unit files are provided in the `dist/systemd` directory: + + - `wgconfd@IFNAME.service` runs wgconfd on the network interface `IFNAME` using configuration in `/etc/wireguard/IFNAME.toml`. The service expects that the interface has already been created and the prviate key has been set. + - `wgconfd-state@IFNAME.service` should be restarted every time the network interface loses its configuration, for example when wg-quick is restarted. + +A Fedora source package is available at [https://git.venev.name/hristo/fedora/rust-wgconfd/]. + +### OpenWRT + +There is an OpenWRT netifd protocol script in `dist/netifd`. The global options are set in the interface section in `/etc/config/network`. Sources and peers are defined in `wgconfd_source_IFNAME`/`wgconfd_peer_IFNAME` sections in the same file: + +```sh +config interface 'wg0' + option proto 'wgconfd' + option listen_port '656' + option private_key 'uAoL9qoAFbAPg46NxIQJ36Zc5gJaYDBleL2iGEa8SEA=' + list ip6addr '2002:db8:1:1/48' + list ipaddr '10.4.0.1/10' + +config wgconfd_source_wg0 + option name 'source1' + option url 'https://wg.example.org/peers.json' + list ipv4 '10.5.0.0/16' + list ip6addr '2002:db8:2:3/48' + +config wgconfd_source_wg0 + option name 'source2' + option url 'https://wg.example.com/peers.json' + list ipv4 '10.6.0.0/16' + +config wgconfd_peer_wg0 + option public_key 'dJyitquxsM3gf8a8yVDko6Se0sKrXi+glUTQN4mPZCo=' + option source 'source2' + option psk '/etc/wgconfd-psk/example.com-machine1' +``` -- cgit