AlinsRan opened a new pull request, #13743: URL: https://github.com/apache/apisix/pull/13743
### Description An active health check runs independently of any request. There is no downstream client — **the gateway itself is the client** probing the upstream node, so the probe must address the node by the node's own identity: its configured **domain**. `compute_targets()` in `apisix/healthcheck_manager.lua` currently derives the probe Host header by reusing the request-path `pass_host` logic: ```lua local use_node_hdr = up_conf.pass_host == "node" or nil local host_hdr = up_hdr or (use_node_hdr and node.domain) or nil ``` But `pass_host` only decides how a **client** request's Host is forwarded to the upstream, which is meaningless for a probe (there is no client Host). For a **domain-based upstream with the default `pass_host` (`pass`)**, this yields a `nil` Host header, and the health-check library then falls back to `hostname`, which is the **resolved ip** for a domain node. The result, for every domain upstream: - the probe sends `Host: <resolved-ip>` → hits the wrong virtual host on the backend → **false unhealthy**; - over HTTPS it sends `SNI: <resolved-ip>` → **the TLS handshake fails** (the certificate does not match the ip) → the node is marked unhealthy and never recovers. Real traffic never has this problem: for `pass_host = node`/`rewrite` the request Host/SNI is `node.domain`/`upstream_host`, and for `pass` it forwards the real client's Host. Only the client-less health checker degrades to the ip. ### Fix ```lua local host_hdr = up_hdr or node.domain ``` Always carry `node.domain` as the probe Host header, except when `pass_host` is `rewrite` (which still pins `upstream_host` via `up_hdr`). `node.domain` is `nil` for ip-based nodes, so ip upstreams are unaffected. This makes the probe address the node by the node's identity and honors the documented default of `checks.active.host` being the node host. Per `pass_host` mode: | `pass_host` | before | after | |---|---|---| | `node` | `node.domain` | `node.domain` (unchanged) | | `rewrite` | `upstream_host` | `upstream_host` (unchanged) | | `pass` (default), domain node | `nil` → probe uses resolved **ip** | `node.domain` | | any, ip node | `nil` | `nil` (unchanged) | ### Tests `t/node/healthcheck-node-domain-host.t`: a domain node (`test.com:1988`, resolved locally to `127.0.0.1`) with the default `pass_host` and an active check; a probe-target server logs the received Host header. Asserts the probe sends `Host: test.com`, not `Host: 127.0.0.1`. ### Checklist - [x] I have explained the need for this PR and the problem it solves - [x] I have explained the changes or the new features added to this PR - [x] I have added tests corresponding to this change - [ ] I have updated the documentation to reflect this change (behavior now matches the documented default of `checks.active.host`; no user-facing config change) - [x] I have verified that the change follows the existing code style -- This is an automated message from the Apache Git Service. To respond to the message, please log on to GitHub and use the URL above to go to the specific comment. To unsubscribe, e-mail: [email protected] For queries about this service, please contact Infrastructure at: [email protected]
