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

Inconsistent support of IPv6 literals #1171

Open
candlerb opened this issue Dec 15, 2023 · 3 comments
Open

Inconsistent support of IPv6 literals #1171

candlerb opened this issue Dec 15, 2023 · 3 comments

Comments

@candlerb
Copy link
Contributor

candlerb commented Dec 15, 2023

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)

@candlerb
Copy link
Contributor Author

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'

@SuperQ
Copy link
Member

SuperQ commented Dec 15, 2023

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.

@candlerb
Copy link
Contributor Author

candlerb commented Dec 15, 2023

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants