Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
Ma27 opened this issue Jul 21, 2019 · 3 comments
Open

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

Ma27 opened this issue Jul 21, 2019 · 3 comments
Labels
bug Something isn't working dependency

Comments

@Ma27
Copy link
Contributor

Ma27 commented Jul 21, 2019

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.

Ma27 added a commit to Ma27/prometheus_wireguard_exporter that referenced this issue Nov 2, 2019
This is a fairly ugly hack to temporarily work around the issue MindFlavor#10.
Until now Rust doesn't support so-called zone-ids[1] in link-local IPv6
socket-addresses and has a pending RFC on this topic. As I'm
encountering this issue on one of my machines I decided to work around
this issue (for now) by removing the zone-id from the IPv6 address.

This won't harm any other cases as `regex.replace_all` simply returns
the input if the regex doesn't match:

```
>> extern crate regex;
>> let re = regex::Regex::new(r"^\[(?P<ip>[A-Fa-f0-9:]+)%(.*)\]:(?P<port>[0-9]+)$");
>> let rs = re.replace_all("fairly unrelated stuff", "[$ip]:$port");
>> rs
"fairly unrelated stuff"
```

Please note that (1) this regex isn't RFC-compliant[2] and is just a
heuristic to remove zone-ids that currently break this exporter and
(2) this is something that probably shouldn't be merged as-is. I mainly
pushed this since I needed a workaround for this issue (and others
probably too), but it may be better to wait for proper support from the
language.

[1] https://tools.ietf.org/html/rfc4007#section-11
@MindFlavor
Copy link
Owner

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
Copy link
Contributor Author

Ma27 commented Nov 8, 2019

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 MindFlavor reopened this Nov 11, 2019
@MindFlavor
Copy link
Owner

Good point! Reopened.

@MindFlavor MindFlavor added bug Something isn't working dependency labels Jul 20, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working dependency
Projects
None yet
Development

No branches or pull requests

2 participants