From a4ff443588ad83f668a5434257dfcbb2716d5ef8 Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Mon, 30 Sep 2019 14:49:13 +0300 Subject: Document [peer], implement in procd. --- README.md | 11 +++++++- dist/procd/wgconfd | 13 +++++++++ src/main.rs | 82 +++++++++++++++++++++++++++++++++++++----------------- 3 files changed, 79 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 4ce6c8b..8330823 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,15 @@ 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. -The preshared key is applied to all peers defined in a source. If a single peer is defined in multiple sources, only the endpoint and preshared key from a single nondeterministic source are considered, but all IP ranges are allowed (TODO: add some per-pubkey filtering). +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. + +It is possible to override the preshared key for a specific public key, and to restrict the source that can define that peer: + +```toml +[peer."yIOdSFrFQ1WPYS6IUWCsRjzw2Iqq0HMcyVVEXu5z+nM="] +source = "remote2" +psk = "QJmzt2PpKx8g98qrOtsNR4tB1bik+fMSabNNXCC5OUU=" +``` Alternative configuration --- @@ -52,6 +60,7 @@ The arguments are a sequence of global options and sources: - `max_keepalive TIME` - `refresh_sec TIME` - `source NAME URL [psk PSK] [ipv4 NET,NET,...] [ipv6 NET,NET,...] [required]` + - `peer PUBKEY [psk PSK] [source NAME] Source format --- diff --git a/dist/procd/wgconfd b/dist/procd/wgconfd index 41718c5..91e0e55 100755 --- a/dist/procd/wgconfd +++ b/dist/procd/wgconfd @@ -27,6 +27,8 @@ handle_interface() { config_list_foreach "$1" source handle_source + config_list_foreach "$1" peer handle_peer + procd_set_param respawn 30 5 5 procd_set_param stderr 1 procd_close_instance @@ -52,6 +54,17 @@ handle_source_arg() { procd_append_param command "$2" "$1" } +handle_peer() { + local val + procd_append_param command peer "$1" + + config_get val "$1" psk + [ -n "$val" ] && procd_append_param command psk "$val" + + config_get val "$1" source + [ -n "$val" ] && procd_append_param command source "$val" +} + start_service() { config_load wgconfd config_foreach handle_interface interface diff --git a/src/main.rs b/src/main.rs index 0a6e356..f084c40 100644 --- a/src/main.rs +++ b/src/main.rs @@ -37,43 +37,64 @@ fn file_config(path: OsString) -> io::Result { } fn cli_config(args: &mut impl Iterator) -> Option { + enum State<'a> { + Source(&'a mut config::Source), + Peer(&'a mut config::Peer), + None, + } + use std::str::FromStr; let mut cfg = config::Config::default(); - let mut cur_src: Option<&mut config::Source> = None; + let mut cur = State::None; while let Some(key) = args.next() { let arg; - if let Some(ref mut s) = cur_src { - if key == "psk" { - arg = args.next()?; - let arg = arg.to_str()?; - s.psk = Some(model::Key::from_str(arg).ok()?); - continue; - } - if key == "ipv4" { - arg = args.next()?; - let arg = arg.to_str()?; - for arg in arg.split(',') { - s.ipv4.insert(model::Ipv4Net::from_str(arg).ok()?); + match cur { + State::Source(ref mut s) => { + if key == "psk" { + arg = args.next()?; + let arg = arg.to_str()?; + s.psk = Some(model::Key::from_str(arg).ok()?); + continue; } - continue; - } - if key == "ipv6" { - arg = args.next()?; - let arg = arg.to_str()?; - for arg in arg.split(',') { - s.ipv6.insert(model::Ipv6Net::from_str(arg).ok()?); + if key == "ipv4" { + arg = args.next()?; + let arg = arg.to_str()?; + for arg in arg.split(',') { + s.ipv4.insert(model::Ipv4Net::from_str(arg).ok()?); + } + continue; + } + if key == "ipv6" { + arg = args.next()?; + let arg = arg.to_str()?; + for arg in arg.split(',') { + s.ipv6.insert(model::Ipv6Net::from_str(arg).ok()?); + } + continue; + } + if key == "required" { + s.required = true; + continue; } - continue; } - if key == "required" { - s.required = true; - continue; + State::Peer(ref mut p) => { + if key == "psk" { + arg = args.next()?; + let arg = arg.to_str()?; + p.psk = Some(model::Key::from_str(arg).ok()?); + continue; + } + if key == "source" { + p.source = Some(args.next()?.into_string().ok()?); + continue; + } } + State::None => {} } - cur_src = None; + cur = State::None; if key == "min_keepalive" { arg = args.next()?; @@ -96,7 +117,7 @@ fn cli_config(args: &mut impl Iterator) -> Option) -> Option