MindFlavor / prometheus_wireguard_exporter

A Prometheus exporter for WireGuard, written in Rust.
https://mindflavor.github.io/prometheus_wireguard_exporter
MIT License
483 stars 51 forks source link

Exporter fails to parse IPv6 link-local addresses with zone IDs #10

Open Ma27 opened 5 years ago

Ma27 commented 5 years ago

I recently discovered that link-local IPv6 addresses can't be parsed by the exporter and cause errors like this in the log:

Jul 16 20:00:08 wgvm s74b03w8rpp818cdprkmd9qcki34jqvr-unit-script-prometheus-wireguard-exporter-start[807]: thread 'tokio-runtime-worker-0' panicked at 'called `Result::unwrap()` on an `Err` value: AddrParseError(())', src/libcore/result.rs:997:5
Jul 16 20:00:08 wgvm s74b03w8rpp818cdprkmd9qcki34jqvr-unit-script-prometheus-wireguard-exporter-start[807]: note: Run with `RUST_BACKTRACE=1` environment variable to display a backtrace.
Jul 16 20:01:08 wgvm s74b03w8rpp818cdprkmd9qcki34jqvr-unit-script-prometheus-wireguard-exporter-start[807]: [2019-07-16T20:01:08Z TRACE prometheus_wireguard_exporter] Request { method: GET, uri: /metrics, version: HTTP/1.1, headers: {"host": "<http-ip>:9586", "user-agent": "Prometheus/1.8.2", "accept": "application/vnd.google.protobuf;proto=io.prometheus.client.MetricFamily;encoding=delimited;q=0.7,text/plain;version=0.0.4;q=0.3,*/*;q=0.1", "x-prometheus-scrape-timeout-seconds": "10.000000", "accept-encoding": "gzip", "connection": "close"}, body: Body(Empty) }

The reason for this error is that link-local IPv6 addresses can have a so-called zone-id as described in RFC 4007, Section 11 to disambiguate local addresses. In my case one peer had the IPv6 socket address [fe80::d457:12ff:fe48:176b%ens3]:34216 with ens3 being a predictably named network interface.

The problem here is that the socket and IP parsers of Rust in std::net appear to be unable to parse zone IDs:

>> use std::net::SocketAddr;
>> let addr = "[fe80::1%ens3]:23542".parse::<SocketAddr>().unwrap();
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: AddrParseError(())', src/libcore/result.rs:1009:5
stack backtrace:
   0: std::sys::unix::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: std::panicking::rust_panic_with_hook
   5: std::panicking::continue_panic_fmt
   6: rust_begin_unwind
   7: core::panicking::panic_fmt
   8: core::result::unwrap_failed
             at /build/rustc-1.32.0-src/src/libcore/macros.rs:26
   9: <std::panic::AssertUnwindSafe<F> as core::ops::function::FnOnce<()>>::call_once
             at /build/rustc-1.32.0-src/src/libcore/result.rs:808
             at /tmp/.tmpVAsFH6/user_code_1/src/lib.rs:15
             at /build/rustc-1.32.0-src/src/libcore/ops/function.rs:238
             at /build/rustc-1.32.0-src/src/libstd/panic.rs:319
  10: std::panicking::try::do_call
             at /build/rustc-1.32.0-src/src/libstd/panicking.rs:310
  11: __rust_maybe_catch_panic
  12: run_user_code_1
             at /build/rustc-1.32.0-src/src/libstd/panicking.rs:289
             at /build/rustc-1.32.0-src/src/libstd/panic.rs:398
             at /tmp/.tmpVAsFH6/user_code_1/src/lib.rs:12
  13: evcxr::runtime::Runtime::run_loop
  14: evcxr::runtime::runtime_hook
  15: evcxr::main
  16: std::rt::lang_start::{{closure}}
  17: std::panicking::try::do_call
  18: __rust_maybe_catch_panic
  19: std::rt::lang_start_internal
  20: main
  21: __libc_start_main
  22: _start
Panic occurred, the following variables have been lost: addr

The reason for this failure is that the parser doesn't appear to support those addresses. There's currently a pending discussion in rust-lang/rfcs about the issue.

MindFlavor commented 4 years ago

I will close it for now since @Ma27 solution addresses it. We'll probably need to revise the code some time in the future to see if the upstream crate solved the issue.

Ma27 commented 4 years ago

Tbh I'd prefer to leave this open until we have a proper solution. The problem is still there, we just worked around it (which is valid in our case since zone-ids broke the exporter before).

MindFlavor commented 4 years ago

Good point! Reopened.