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

HTTP probe does not pass target dns name into "Host" request header #1303

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

compilenix
Copy link

The HTTP probe module overrides the HTTP request header Host to the resolved IP address, which causes servers / hosts that require or expect the proper host name to be set, to behave differently then a typical browser or cURL would have. This affects both TLS (SNI) as well as vhost server name matching, on servers that either have multiple vhosts configured.

This and similar issues have been created, with different outcomes here (i.e.: #936 and #558).

A mentioned workaround is to statically configure the desired DNS name via the blackbox.yml module config, just like in this partial example:

modules:
  http_2xx_strict_ssl:
    prober: http
    http:
      headers:
        Host: www.google.com

The downside of this workaround is that you would need to create a separate module config for each target that requires it, which might be a lot or even all targets.

My proposed solution is to override only the HTTP request header Host to the original target host, after resolving it's IP and creating the HTTP request context.

I hope I've made correct assumptions with this PR, if not feel free to comment, discuss or change :)

Kind regards,
Kevin | CompileNix

Host operating system: via Docker on:

  • Linux 6fe1959b57a1 6.10.9-100.fc39.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Sep 9 02:28:01 UTC 2024 x86_64 GNU/Linux
  • Linux 12b86e19e018 6.8.0-45-generic #45-Ubuntu SMP PREEMPT_DYNAMIC Fri Aug 30 12:02:04 UTC 2024 x86_64 x86_64 x86_64 GNU/Linux

blackbox_exporter version: 0.25.0

What is the blackbox.yml module config:

modules:
  http_2xx_strict_ssl:
    prober: http
    timeout: 5s
    http:
      tls_config:
        insecure_skip_verify: false
      preferred_ip_protocol: "ip4"
      ip_protocol_fallback: false
      valid_http_versions: ["HTTP/1.1", "HTTP/2.0"]
      valid_status_codes: []
      method: GET
      follow_redirects: false
      fail_if_ssl: false
      fail_if_not_ssl: true

How do you perform the probe?

Start the container

docker run -it --rm -p 36692:9115 -v $(pwd)/blackbox.yml:/config/blackbox.yml:z blackbox_exporter --config.file=/config/blackbox.yml

Perform Probe via Browser or cURL

http://127.0.0.1:36692/probe?module=http_2xx_strict_ssl&debug=true&target=https%3A%2F%2Fwww.google.com%3A443%2F

What logging output did you get from adding &debug=true to the probe URL?

Logs for the probe:
ts=2024-10-04T12:29:39.47268359Z caller=main.go:190 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Beginning probe" probe=http timeout_seconds=5
ts=2024-10-04T12:29:39.472930237Z caller=http.go:328 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Resolving target address" target=www.google.com ip_protocol=ip4
ts=2024-10-04T12:29:39.483251771Z caller=http.go:328 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Resolved target address" target=www.google.com ip=172.217.19.68
ts=2024-10-04T12:29:39.483537823Z caller=client.go:259 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Making HTTP request" url=https://172.217.19.68:443/ host=172.217.19.68:443
ts=2024-10-04T12:29:39.531547618Z caller=client.go:505 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Received redirect" location=http://www.google.com/
ts=2024-10-04T12:29:39.531644482Z caller=client.go:505 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Not following redirect"
ts=2024-10-04T12:29:39.532436315Z caller=handler.go:119 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Received HTTP response" status_code=301
ts=2024-10-04T12:29:39.532501634Z caller=handler.go:119 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Invalid HTTP response status code, wanted 2xx" status_code=301
ts=2024-10-04T12:29:39.532530534Z caller=handler.go:119 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Response timings for roundtrip" roundtrip=0 start=2024-10-04T12:29:39.483836356Z dnsDone=2024-10-04T12:29:39.483836356Z connectDone=2024-10-04T12:29:39.485972823Z gotConn=2024-10-04T12:29:39.520369586Z responseStart=2024-10-04T12:29:39.531355498Z tlsStart=2024-10-04T12:29:39.486060343Z tlsDone=2024-10-04T12:29:39.52025469Z end=2024-10-04T12:29:39.53251754Z
ts=2024-10-04T12:29:39.532671446Z caller=main.go:190 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=error msg="Probe failed" duration_seconds=0.059878633



Metrics that would have been returned:
# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds
# TYPE probe_dns_lookup_time_seconds gauge
probe_dns_lookup_time_seconds 0.010341419
# HELP probe_duration_seconds Returns how long the probe took to complete in seconds
# TYPE probe_duration_seconds gauge
probe_duration_seconds 0.059878633
# HELP probe_failed_due_to_regex Indicates if probe failed due to regex
# TYPE probe_failed_due_to_regex gauge
probe_failed_due_to_regex 0
# HELP probe_http_content_length Length of http content response
# TYPE probe_http_content_length gauge
probe_http_content_length 219
# HELP probe_http_duration_seconds Duration of http request by phase, summed over all redirects
# TYPE probe_http_duration_seconds gauge
probe_http_duration_seconds{phase="connect"} 0.002136469
probe_http_duration_seconds{phase="processing"} 0.010985945
probe_http_duration_seconds{phase="resolve"} 0.010341419
probe_http_duration_seconds{phase="tls"} 0.034194328
probe_http_duration_seconds{phase="transfer"} 0.001162041
# HELP probe_http_redirects The number of redirects
# TYPE probe_http_redirects gauge
probe_http_redirects 1
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
probe_http_ssl 1
# HELP probe_http_status_code Response HTTP status code
# TYPE probe_http_status_code gauge
probe_http_status_code 301
# HELP probe_http_uncompressed_body_length Length of uncompressed response body
# TYPE probe_http_uncompressed_body_length gauge
probe_http_uncompressed_body_length 0
# HELP probe_http_version Returns the version of HTTP of the probe response
# TYPE probe_http_version gauge
probe_http_version 2
# HELP probe_ip_addr_hash Specifies the hash of IP address. It's useful to detect if the IP address changes.
# TYPE probe_ip_addr_hash gauge
probe_ip_addr_hash 2.743157313e+09
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
probe_ip_protocol 4
# HELP probe_ssl_earliest_cert_expiry Returns last SSL chain expiry in unixtime
# TYPE probe_ssl_earliest_cert_expiry gauge
probe_ssl_earliest_cert_expiry 1.733736964e+09
# HELP probe_ssl_last_chain_expiry_timestamp_seconds Returns last SSL chain expiry in timestamp
# TYPE probe_ssl_last_chain_expiry_timestamp_seconds gauge
probe_ssl_last_chain_expiry_timestamp_seconds 1.733736964e+09
# HELP probe_ssl_last_chain_info Contains SSL leaf certificate information
# TYPE probe_ssl_last_chain_info gauge
probe_ssl_last_chain_info{fingerprint_sha256="4ec8173ae2e73b96e6c4dacf565a87addf5dd70108595a3b0681cd8e365c29ee",issuer="CN=WR2,O=Google Trust Services,C=US",subject="CN=www.google.com",subjectalternative="www.google.com"} 1
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
probe_success 0
# HELP probe_tls_version_info Returns the TLS version used or NaN when unknown
# TYPE probe_tls_version_info gauge
probe_tls_version_info{version="TLS 1.3"} 1



Module configuration:
prober: http
timeout: 5s
http:
  valid_http_versions:
  - HTTP/1.1
  - HTTP/2.0
  preferred_ip_protocol: ip4
  fail_if_not_ssl: true
  method: GET
  follow_redirects: false
  enable_http2: true
tcp:
  ip_protocol_fallback: true
icmp:
  ip_protocol_fallback: true
  ttl: 64
dns:
  ip_protocol_fallback: true
  recursion_desired: true

What did you do that produced an error?

curl 'http://127.0.0.1:36692/probe?module=http_2xx_strict_ssl&debug=true&target=https%3A%2F%2Fwww.google.com%3A443%2F'

What did you expect to see?

target=https://www.google.com:443/ level=info msg="Making HTTP request" url=https://142.250.181.196:443/ host=www.google.com
[...]
target=https://www.google.com:443/ level=info msg="Probe succeeded"

What did you see instead?

target=https://www.google.com:443/ level=info msg="Making HTTP request" url=https://172.217.19.68:443/ host=172.217.19.68:443
[...]
target=https://www.google.com:443/ level=error msg="Probe failed"

What logging output did you get with this PR?

Logs for the probe:
ts=2024-10-04T12:32:48.952092821Z caller=main.go:190 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Beginning probe" probe=http timeout_seconds=5
ts=2024-10-04T12:32:48.952341626Z caller=http.go:328 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Resolving target address" target=www.google.com ip_protocol=ip4
ts=2024-10-04T12:32:48.963387214Z caller=http.go:328 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Resolved target address" target=www.google.com ip=142.250.181.196
ts=2024-10-04T12:32:48.963504315Z caller=client.go:259 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Making HTTP request" url=https://142.250.181.196:443/ host=www.google.com
ts=2024-10-04T12:32:49.022374701Z caller=handler.go:119 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Received HTTP response" status_code=200
ts=2024-10-04T12:32:49.025218851Z caller=handler.go:119 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Response timings for roundtrip" roundtrip=0 start=2024-10-04T12:32:48.963631137Z dnsDone=2024-10-04T12:32:48.963631137Z connectDone=2024-10-04T12:32:48.965958085Z gotConn=2024-10-04T12:32:48.979420187Z responseStart=2024-10-04T12:32:49.02208641Z tlsStart=2024-10-04T12:32:48.966086457Z tlsDone=2024-10-04T12:32:48.97923827Z end=2024-10-04T12:32:49.025207463Z
ts=2024-10-04T12:32:49.025320994Z caller=main.go:190 module=http_2xx_strict_ssl target=https://www.google.com:443/ level=info msg="Probe succeeded" duration_seconds=0.073163062



Metrics that would have been returned:
# HELP probe_dns_lookup_time_seconds Returns the time taken for probe dns lookup in seconds
# TYPE probe_dns_lookup_time_seconds gauge
probe_dns_lookup_time_seconds 0.011044931
# HELP probe_duration_seconds Returns how long the probe took to complete in seconds
# TYPE probe_duration_seconds gauge
probe_duration_seconds 0.073163062
# HELP probe_failed_due_to_regex Indicates if probe failed due to regex
# TYPE probe_failed_due_to_regex gauge
probe_failed_due_to_regex 0
# HELP probe_http_content_length Length of http content response
# TYPE probe_http_content_length gauge
probe_http_content_length -1
# HELP probe_http_duration_seconds Duration of http request by phase, summed over all redirects
# TYPE probe_http_duration_seconds gauge
probe_http_duration_seconds{phase="connect"} 0.00232699
probe_http_duration_seconds{phase="processing"} 0.042666263
probe_http_duration_seconds{phase="resolve"} 0.011044931
probe_http_duration_seconds{phase="tls"} 0.013151826
probe_http_duration_seconds{phase="transfer"} 0.003120944
# HELP probe_http_redirects The number of redirects
# TYPE probe_http_redirects gauge
probe_http_redirects 0
# HELP probe_http_ssl Indicates if SSL was used for the final redirect
# TYPE probe_http_ssl gauge
probe_http_ssl 1
# HELP probe_http_status_code Response HTTP status code
# TYPE probe_http_status_code gauge
probe_http_status_code 200
# HELP probe_http_uncompressed_body_length Length of uncompressed response body
# TYPE probe_http_uncompressed_body_length gauge
probe_http_uncompressed_body_length 21189
# HELP probe_http_version Returns the version of HTTP of the probe response
# TYPE probe_http_version gauge
probe_http_version 2
# HELP probe_ip_addr_hash Specifies the hash of IP address. It's useful to detect if the IP address changes.
# TYPE probe_ip_addr_hash gauge
probe_ip_addr_hash 3.007906776e+09
# HELP probe_ip_protocol Specifies whether probe ip protocol is IP4 or IP6
# TYPE probe_ip_protocol gauge
probe_ip_protocol 4
# HELP probe_ssl_earliest_cert_expiry Returns last SSL chain expiry in unixtime
# TYPE probe_ssl_earliest_cert_expiry gauge
probe_ssl_earliest_cert_expiry 1.733736964e+09
# HELP probe_ssl_last_chain_expiry_timestamp_seconds Returns last SSL chain expiry in timestamp
# TYPE probe_ssl_last_chain_expiry_timestamp_seconds gauge
probe_ssl_last_chain_expiry_timestamp_seconds 1.733736964e+09
# HELP probe_ssl_last_chain_info Contains SSL leaf certificate information
# TYPE probe_ssl_last_chain_info gauge
probe_ssl_last_chain_info{fingerprint_sha256="4ec8173ae2e73b96e6c4dacf565a87addf5dd70108595a3b0681cd8e365c29ee",issuer="CN=WR2,O=Google Trust Services,C=US",subject="CN=www.google.com",subjectalternative="www.google.com"} 1
# HELP probe_success Displays whether or not the probe was a success
# TYPE probe_success gauge
probe_success 1
# HELP probe_tls_version_info Returns the TLS version used or NaN when unknown
# TYPE probe_tls_version_info gauge
probe_tls_version_info{version="TLS 1.3"} 1



Module configuration:
prober: http
timeout: 5s
http:
  valid_http_versions:
  - HTTP/1.1
  - HTTP/2.0
  preferred_ip_protocol: ip4
  fail_if_not_ssl: true
  method: GET
  follow_redirects: false
  enable_http2: true
tcp:
  ip_protocol_fallback: true
icmp:
  ip_protocol_fallback: true
  ttl: 64
dns:
  ip_protocol_fallback: true
  recursion_desired: true

Override the HTTP request header `Host` to the original target host, after resolving it's IP and creating the HTTP request context.

Signed-off-by: Kevin Weis <[email protected]>
@paulbhart
Copy link

would love to see this go live, it is block us

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

Successfully merging this pull request may close these issues.

2 participants