aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--README.md11
-rwxr-xr-xdist/procd/wgconfd13
-rw-r--r--src/main.rs82
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<config::Config> {
}
fn cli_config(args: &mut impl Iterator<Item = OsString>) -> Option<config::Config> {
+ 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<Item = OsString>) -> Option<config::Confi
if key == "source" {
let name = args.next()?.into_string().ok()?;
let url = args.next()?.into_string().ok()?;
- cur_src = Some(cfg.sources.entry(name).or_insert(config::Source {
+ cur = State::Source(cfg.sources.entry(name).or_insert(config::Source {
url,
psk: None,
ipv4: model::Ipv4Set::new(),
@@ -105,6 +126,15 @@ fn cli_config(args: &mut impl Iterator<Item = OsString>) -> Option<config::Confi
}));
continue;
}
+ if key == "peer" {
+ arg = args.next()?;
+ let key = model::Key::from_str(arg.to_str()?).ok()?;
+ cur = State::Peer(cfg.global.peers.entry(key).or_insert(config::Peer {
+ source: None,
+ psk: None,
+ }));
+ continue;
+ }
return None;
}