diff --git a/Cargo.lock b/Cargo.lock index 58459f6..a3100d2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -514,7 +514,7 @@ dependencies = [ [[package]] name = "prometheus_wireguard_exporter" -version = "3.0.0" +version = "3.0.1" dependencies = [ "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)", diff --git a/Cargo.toml b/Cargo.toml index 297d607..78fd3bf 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "prometheus_wireguard_exporter" -version = "3.0.0" +version = "3.0.1" authors = ["Francesco Cogno "] description = "Prometheus WireGuard Exporter" edition = "2018" diff --git a/README.md b/README.md index f488ffa..ea4d1fe 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,8 @@ Start the binary with `-h` to get the complete syntax. The parameters are: | `-v` | no | | | Enable verbose mode. | `-p` | no | any valid port number | 9586 | Specify the service port. This is the port your Prometheus instance should point to. | `-n` | no | path to the wireguard configuration file | | This flag adds the *friendly_name* attribute to the exported entries. See [Friendly names](#friendly-names) for more details. -| `-s` | no | | off | Enabled the allowed ip + subnet split mode for the labels. +| `-s` | no | | off | Enable the allowed ip + subnet split mode for the labels. +| `-r` | no | | off | Exports peer's remote ip and port as labels (if available). Once started, the tool will listen on the specified port (or the default one, 9586, if not specified) and return a Prometheus valid response at the url `/metrics`. So to check if the tool is working properly simply browse the `http://localhost:9586/metrics` (or whichever port you choose). diff --git a/src/main.rs b/src/main.rs index 4e230cb..7b3eac4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,6 +35,7 @@ fn wg_with_text( Ok(Response::new(Body::from(wg.render_with_names( Some(&pehm), options.separate_allowed_ips, + options.export_remote_ip_and_port, )))) } @@ -71,9 +72,11 @@ fn perform_request( done(WireGuard::try_from(&output_str as &str)) .from_err() .and_then(move |wg| { - ok(Response::new(Body::from( - wg.render_with_names(None, options.separate_allowed_ips), - ))) + ok(Response::new(Body::from(wg.render_with_names( + None, + options.separate_allowed_ips, + options.export_remote_ip_and_port, + )))) }) }, )) @@ -105,7 +108,13 @@ fn main() { .help("separate allowed ips and ports") .takes_value(false), ) - .arg( + .arg( + Arg::with_name("export_remote_ip_and_port") + .short("r") + .help("exports peer's remote ip and port as labels (if available)") + .takes_value(false), + ) + .arg( Arg::with_name("extract_names_config_file") .short("n") .help("If set, the exporter will look in the specified WireGuard config file for peer names (must be in [Peer] definition and be a comment)") diff --git a/src/options.rs b/src/options.rs index 0744f4a..91fcd00 100644 --- a/src/options.rs +++ b/src/options.rs @@ -3,6 +3,7 @@ pub(crate) struct Options { pub verbose: bool, pub separate_allowed_ips: bool, pub extract_names_config_file: Option, + pub export_remote_ip_and_port: bool, } impl Options { @@ -12,12 +13,14 @@ impl Options { verbose: matches.is_present("verbose"), separate_allowed_ips: matches.is_present("separate_allowed_ips"), extract_names_config_file: Some(e.to_owned()), + export_remote_ip_and_port: matches.is_present("export_remote_ip_and_port"), } } else { Options { verbose: matches.is_present("verbose"), separate_allowed_ips: matches.is_present("separate_allowed_ips"), extract_names_config_file: None, + export_remote_ip_and_port: matches.is_present("export_remote_ip_and_port"), } } } diff --git a/src/wireguard.rs b/src/wireguard.rs index 63258a1..99aae65 100644 --- a/src/wireguard.rs +++ b/src/wireguard.rs @@ -119,6 +119,7 @@ impl WireGuard { &self, pehm: Option<&PeerEntryHashMap>, split_allowed_ips: bool, + export_remote_ip_and_port: bool, ) -> String { // these are the exported counters let pc_sent_bytes_total = PrometheusCounter::new( @@ -200,11 +201,13 @@ impl WireGuard { } } - if let Some(r_ip) = &ep.remote_ip { - attributes.push(("remote_ip", &r_ip)); - } - if let Some(r_port) = &ep.remote_port { - attributes_owned.push(("remote_port".to_string(), r_port.to_string())); + if export_remote_ip_and_port { + if let Some(r_ip) = &ep.remote_ip { + attributes.push(("remote_ip", &r_ip)); + } + if let Some(r_port) = &ep.remote_port { + attributes_owned.push(("remote_port".to_string(), r_port.to_string())); + } } for (label, val) in &attributes_owned { @@ -278,7 +281,7 @@ wg0\t928vO9Lf4+Mo84cWu4k1oRyzf0AR7FTGoPKHGoTMSHk=\t(none)\t5.90.62.106:21741\t10 #[test] fn test_parse_and_serialize() { let a = WireGuard::try_from(TEXT).unwrap(); - let s = a.render_with_names(None, false); + let s = a.render_with_names(None, false, true); println!("{}", s); } @@ -304,7 +307,7 @@ wg0\t928vO9Lf4+Mo84cWu4k1oRyzf0AR7FTGoPKHGoTMSHk=\t(none)\t5.90.62.106:21741\t10 v.push(re); wg.interfaces.insert("Pippo".to_owned(), v); - let prometheus = wg.render_with_names(None, false); + let prometheus = wg.render_with_names(None, false, true); assert_eq!(prometheus, REF); } @@ -317,6 +320,8 @@ wg0\t928vO9Lf4+Mo84cWu4k1oRyzf0AR7FTGoPKHGoTMSHk=\t(none)\t5.90.62.106:21741\t10 const REF_SPLIT :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 14\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 1000000000\n# HELP wireguard_latest_handshake_seconds Seconds from the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",remote_port=\"100\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",remote_ip=\"remote_ip\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\",remote_port=\"100\"} 50\n"; + const REF_SPLIT_NO_REMOTE :&'static str = "# HELP wireguard_sent_bytes_total Bytes sent to the peer\n# TYPE wireguard_sent_bytes_total counter\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 1000\nwireguard_sent_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 14\n# HELP wireguard_received_bytes_total Bytes received from the peer\n# TYPE wireguard_received_bytes_total counter\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 5000\nwireguard_received_bytes_total{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 1000000000\n# HELP wireguard_latest_handshake_seconds Seconds from the last handshake\n# TYPE wireguard_latest_handshake_seconds gauge\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"test\",allowed_ip_0=\"10.0.0.2\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\"} 500\nwireguard_latest_handshake_seconds{interface=\"Pippo\",public_key=\"second_test\",friendly_name=\"this is my friendly name\",allowed_ip_0=\"10.0.0.4\",allowed_subnet_0=\"32\",allowed_ip_1=\"fd86:ea04:::4\",allowed_subnet_1=\"128\",allowed_ip_2=\"192.168.0.0\",allowed_subnet_2=\"16\"} 50\n"; + let re1 = Endpoint::Remote(RemoteEndpoint { public_key: "test".to_owned(), remote_ip: Some("remote_ip".to_owned()), @@ -355,11 +360,13 @@ wg0\t928vO9Lf4+Mo84cWu4k1oRyzf0AR7FTGoPKHGoTMSHk=\t(none)\t5.90.62.106:21741\t10 }; pehm.insert(pe.public_key, pe); - let prometheus = wg.render_with_names(Some(&pehm), false); + let prometheus = wg.render_with_names(Some(&pehm), false, true); assert_eq!(prometheus, REF); - let prometheus = wg.render_with_names(Some(&pehm), true); + let prometheus = wg.render_with_names(Some(&pehm), true, true); assert_eq!(prometheus, REF_SPLIT); - } + let prometheus = wg.render_with_names(Some(&pehm), true, false); + assert_eq!(prometheus, REF_SPLIT_NO_REMOTE); + } }