[Bug] Mender client 5.1.0 sends the proxy address in the CONNECT Host header; strict proxies reject with 403

Since commit 23e43e700d (MEN-9262, shipped in 5.0.x and 5.1.0, still on master), the Mender client sends the wrong Host header on the proxy CONNECT request. It names the proxy instead of the tunnel destination.

Request-target Host header
What the client sends today server.example.com:443 10.0.0.1:3128 (the proxy)
What it must send (RFC 9110 §9.3.6) server.example.com:443 server.example.com:443

Captured with tcpdump on the plaintext leg between the device and the proxy:

CONNECT server.example.com:443 HTTP/1.1
HOST: 10.0.0.1:3128
User-Agent: Mender/5.1.0

RFC 9110 §9.3.6 requires the Host header of a CONNECT request to be identical to the request-target. curl and Go’s net/http on the same device, through the same proxy, to the same destination send Host: server.example.com:443 and succeed.

Cause. In src/common/http/platform/beast/http.cpp, Client::HandleProxySetup() overwrites request_->address_.host with the proxy address and then, three lines later, builds the Host header from that same field via CreateHOSTAddress(request_). The request-target (address_.path) is computed correctly from the original request; only the header reads the wrong field. Client::AsyncCall() has the same ordering problem for plain http:// requests via HTTP_PROXY: it sets Host after HandleProxySetup() has rewritten the address.

Impact. Squid, nginx, Envoy and tinyproxy route CONNECT on the request-target and ignore Host, so this went unnoticed. One of our customers runs a corporate forward proxy that enforces destination policy on the Host header. It rejects every CONNECT with 403, so devices can neither authenticate nor update:

Proxy error: POST https://<server>/api/devices/v1/authentication/auth_requests: Proxy returned unexpected response: 403 Forbidden

Isolating the header with curl against that proxy:

curl -x http://10.0.0.1:3128 https://server.example.com/                                    -> 200 Connection established
curl -x http://10.0.0.1:3128 --proxy-header "Host: 10.0.0.1" https://server.example.com/    -> 403 Forbidden

There is no configuration workaround. The value is hard-coded.

Reproduce without a strict proxy:

nc -l -p 8888                                              # terminal 1: prints what it receives
HTTPS_PROXY=http://127.0.0.1:8888 mender-auth bootstrap    # terminal 2

Terminal 1 shows CONNECT <server>:443 HTTP/1.1 followed by HOST: 127.0.0.1:8888. Expected: HOST: <server>:443.

Fix. I have opened fix: send the tunnel destination in the Host header of proxy CONNECT requests by meghasuvarna-voxelai · Pull Request #2021 · mendersoftware/mender · GitHub. It sets the CONNECT Host header from the request-target before the address is rewritten, moves the regular Host header before proxy setup, and adds two regression tests using a recording proxy built on http::Server (the existing tinyproxy-based tests cannot detect this because tinyproxy ignores Host). Both new tests fail on master and pass with the change. Full http_proxy_test (28) and http_test (47) pass locally.

Could someone open a MEN ticket for this so I can reference it in the commit? Happy to adjust anything for review.