Skip to content

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

Open
CompileNix wants to merge 1 commit intoprometheus:masterfrom
Plan-International-Deutschland-e-V:fix-http-host-header
Open

HTTP probe does not pass target dns name into "Host" request header#1303
CompileNix wants to merge 1 commit intoprometheus:masterfrom
Plan-International-Deutschland-e-V:fix-http-host-header

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 <Kevin.Weis@plan.de>
@CompileNix CompileNix force-pushed the fix-http-host-header branch from fea0e3d to 85ccdb0 Compare October 4, 2024 13:14
@paulbhart
Copy link

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

@c0depwn
Copy link

c0depwn commented Feb 27, 2025

I can't believe that blackbox_exporter has still not addressed this. Practically everything is served behind a reverse proxy or load balancer in any modern infrastructure. Without this PR it is a huge pain to simply probe sites which are not directly reachable by IP but are handled through the supplied Host header e.g. in a virtual hosting environment.

Please merge this. I cannot use blackbox exporter without this. Adding >100 modules manually to simply define a header is not a viable workaround and clearly makes things unmaintainable. I do not want to maintain another fork just because I need the http module to behave like any other normal HTTP client which is able to make a simple request.

Related issues include the following (there may be more but these are the main ones I found):

@VickyXie777
Copy link

Please merge this. Pre DNS resolving helps a lot when doing some CDN endpoint healthcheck.

@thomasvoneuw
Copy link

I was also forced to fork the repo because I need this feature. Very sad...

@charltonstanley
Copy link

I need this feature as well. Any chance it will be merged soon? thanks!

@github-actions github-actions bot removed the stale label Jan 15, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

6 participants