Inconsistent support of IPv6 literals
candlerb opened this issue · 4 comments
Host operating system: output of uname -a
Linux prometheus 5.4.0-162-generic #179-Ubuntu SMP Mon Aug 14 08:51:31 UTC 2023 x86_64 x86_64 x86_64 GNU/Linux
blackbox_exporter version: output of blackbox_exporter --version
blackbox_exporter, version 0.24.0 (branch: HEAD, revision: 0b0467473916fd9e8526e2635c2a0b1c56011dff)
build user: root@e5bbfcc8184e
build date: 20230516-11:07:25
go version: go1.20.4
platform: linux/amd64
tags: netgo
What is the blackbox.yml module config.
modules:
icmp:
prober: icmp
timeout: 3s
dns_version:
prober: dns
timeout: 5s
dns:
query_name: version.bind
query_type: TXT
query_class: CH
validate_answer_rrs:
fail_if_none_matches_regexp:
- '.*'
certificate_invalid:
prober: tcp
timeout: 5s
tcp:
tls: true
tls_config:
insecure_skip_verify: true
http_example:
prober: http
timeout: 5s
http:
method: GET
follow_redirects: true
fail_if_ssl: false
fail_if_not_ssl: false
tls_config:
insecure_skip_verify: true
What did you do that produced an error?
Supplying an IPv6 literal with square brackets but without a port.
icmp prober (where port makes no sense)
- Works:
curl -gsSv 'localhost:9115/probe?target=2001:db8::1&module=icmp'
- FAILS:
curl -gsSv 'localhost:9115/probe?target=[2001:db8::1]&module=icmp'
- Response code 200
- probe_success=0, probe_ip_addr_hash=0, probe_ip_protocol=0
- With
debug=true
:caller=icmp.go:91 module=icmp target=[2001:db8::1] level=error msg="Resolution with IP protocol failed" target=[2001:db8::1] err="lookup [2001:db8::1]: no such host"
dns prober (port is optional, default is 53)
- Works:
curl -gsSv 'localhost:9115/probe?target=2606:4700:58::adf5:3b60&module=dns_version'
- Works:
curl -gsSv 'localhost:9115/probe?target=[2606:4700:58::adf5:3b60]:53&module=dns_version'
- FAILS:
curl -gsSv 'localhost:9115/probe?target=[2606:4700:58::adf5:3b60]&module=dns_version'
- Response code 200
- probe_success=0
- With
debug=true
:caller=dns.go:200 module=dns_version target=[2606:4700:58::adf5:3b60] level=error msg="Resolution with IP protocol failed" target=[2606:4700:58::adf5:3b60] err="lookup [2606:4700:58::adf5:3b60]: no such host"
(This is similar to prometheus/snmp_exporter#1076)
tcp prober (port is required)
- Works:
curl -gsSv 'localhost:9115/probe?target=[2001:db8::1]:443&module=certificate_invalid
There is no problem here because a port is always required. (A bare IPv4 address says that it can't split address/port, and a bare IPv6 address says there are too many colons)
Aside: this could change if the tcp prober gained an option to set a default port. For example, given this config:
ssh_banner:
prober: tcp
tcp:
query_response:
- expect: "^SSH-2.0-"
- send: "SSH-2.0-blackbox-ssh-check"
It would be nice if a default port 22 could be set in blackbox.yml.
http prober (default port 80 or 443)
- Works:
curl -gsSv 'localhost:9115/probe?target=http://[2001:db8::1]&module=http_example'
- Works:
curl -gsSv 'localhost:9115/probe?target=http://[2001:db8::1]:8080&module=http_example'
- Works:
curl -gsSv 'localhost:9115/probe?target=https://[2001:db8::1]&module=http_example'
- Works:
curl -gsSv 'localhost:9115/probe?target=https://[2001:db8::1]:8443&module=http_example'
- Works (defaults to http on port 80):
curl -gsSv 'localhost:9115/probe?target=[2001:db8::1]&module=http_example'
There is no problem here, because the URL syntax requires IPv6 addresses to be enclosed in square brackets anyway.
Proposal
Fix dns_prober to accept IPv6 literals with square brackets but without a port.
Make icmp_prober accept IPv6 literals with or without square brackets, for consistency with dns_prober (and snmp_exporter when fixed)
Oddly, Go's own net.SplitHostPort allows domain names and IPv4 literals inside square brackets.
- Works:
curl -gsSv 'localhost:9115/probe?target=[damon.ns.cloudflare.com]:53&module=dns_version'
- Works:
curl -gsSv 'localhost:9115/probe?target=[108.162.193.96]:53&module=dns_version'
Reading RFC 3986 3.2.2, which defines the square bracket syntax, I don't think IPv4 or DNS names with square brackets are allowed.
The host subcomponent of authority is identified by an IP literal
encapsulated within square brackets, an IPv4 address in dotted-
decimal form, or a registered name.
My understanding of that means you can have [IPv6]
, IPv4
, example.com
. Not square brackets with the other options.
Indeed, that's why it'd odd and I think the behaviour is too lax here - the last two examples should have been rejected. Changing it is backwards-incompatible though.
EDIT: thinking about it, [name-or-ip]:port
is quite convenient when building targets from a database, as you don't need to special-case IPv6 addresses.
It would appear that this also doesn't support scoped v6 link-local addresses:
ts=2024-08-07T20:20:37.520908651Z caller=main.go:190 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8] level=info msg="Beginning probe" probe=icmp timeout_seconds=9.5
ts=2024-08-07T20:20:37.521554009Z caller=icmp.go:91 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8] level=info msg="Resolving target address" target=[fe80::9ee0:41ff:fe5e:ebe8] ip_protocol=ip6
ts=2024-08-07T20:20:37.52281406Z caller=icmp.go:91 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8] level=error msg="Resolution with IP protocol failed" target=[fe80::9ee0:41ff:fe5e:ebe8] err="lookup [fe80::9ee0:41ff:fe5e:ebe8]: no such host"
ts=2024-08-07T20:20:37.52290189Z caller=handler.go:119 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8] level=error msg="Error resolving address" err="lookup [fe80::9ee0:41ff:fe5e:ebe8]: no such host"
ts=2024-08-07T20:20:37.523090385Z caller=main.go:190 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8] level=error msg="Probe failed" duration_seconds=0.001953452
ts=2024-08-07T20:24:33.623290618Z caller=main.go:190 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8]%enp1s0 level=info msg="Beginning probe" probe=icmp timeout_seconds=9.5
ts=2024-08-07T20:24:33.623762539Z caller=icmp.go:91 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8]%enp1s0 level=info msg="Resolving target address" target=[fe80::9ee0:41ff:fe5e:ebe8]%enp1s0 ip_protocol=ip6
ts=2024-08-07T20:24:33.62477881Z caller=icmp.go:91 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8]%enp1s0 level=error msg="Resolution with IP protocol failed" target=[fe80::9ee0:41ff:fe5e:ebe8]%enp1s0 err="lookup [fe80::9ee0:41ff:fe5e:ebe8]%enp1s0: no such host"
ts=2024-08-07T20:24:33.624865349Z caller=handler.go:119 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8]%enp1s0 level=error msg="Error resolving address" err="lookup [fe80::9ee0:41ff:fe5e:ebe8]%enp1s0: no such host"
ts=2024-08-07T20:24:33.624949371Z caller=main.go:190 module=icmp target=[fe80::9ee0:41ff:fe5e:ebe8]%enp1s0 level=error msg="Probe failed" duration_seconds=0.001487811