Fix HTTPS handshake: trust the actual cert the proxy presents, not Origin CA
The Tools Server hostname turned out to be Cloudflare-proxied, not a
direct connection to nginx -- so the ESP32 (and any browser) sees
Cloudflare's own edge certificate (issued by Google Trust Services),
never the Origin CA cert, which only ever sits on the Cloudflare-to-
origin leg. Confirmed on hardware: ESP_ERR_HTTP_CONNECT.
Tried switching to ESP-IDF's built-in public CA bundle instead
(esp_crt_bundle_attach) as the more general fix, but that also failed
on hardware ("No matching trusted root certificate found") -- the
bundle's copy of the relevant Google root has the same name and public
key as the live one but a different serial/signature (a reissue), and
the bundle does an exact byte-level match, not a semantic one.
Simplest reliable fix: embed the exact certificate the proxy actually
presents (extracted live via openssl s_client, see
firmware/main/certs/tools_server_ca.pem) and trust that directly via
cert_pem, sidestepping bundle-matching semantics entirely. Documented
in firmware/README.md how to re-extract if the proxy's CA ever changes.
This commit is contained in:
+16
-17
@@ -95,24 +95,23 @@ The Tools Server field accepts either:
|
||||
manage-menu overlay data, the QR codes' own links) uses whichever
|
||||
scheme you enter.
|
||||
|
||||
The firmware only trusts one certificate authority for the HTTPS case:
|
||||
**Cloudflare's Origin CA** (both the RSA and ECC root, embedded at build
|
||||
time from [`main/certs/cloudflare_origin_ca.pem`](main/certs/cloudflare_origin_ca.pem),
|
||||
downloaded directly from Cloudflare's docs). This is the free, long-lived
|
||||
certificate Cloudflare issues for origin servers -- not a
|
||||
publicly-trusted cert, so ordinary browsers won't accept it directly, but
|
||||
it's exactly what a reverse proxy in front of a Cloudflare-proxied
|
||||
hostname presents. If your reverse proxy uses a different certificate
|
||||
(a real publicly-trusted one from Let's Encrypt, or a different private
|
||||
CA), swap the PEM file's contents for that CA's root and rebuild.
|
||||
The firmware trusts the standard public CA bundle ESP-IDF ships
|
||||
(`esp_crt_bundle_attach`, the same root store a browser trusts) -- so
|
||||
any reverse proxy with a normal publicly-trusted certificate just
|
||||
works: Let's Encrypt, a Cloudflare-proxied hostname (Cloudflare's own
|
||||
edge certificate, issued by Google Trust Services or similar -- **not**
|
||||
Cloudflare's Origin CA cert, which only ever sits on the Cloudflare-to-
|
||||
origin leg and is never presented to a public client, ESP32 or browser
|
||||
alike), or any other public CA. If your proxy uses a private/self-signed
|
||||
cert instead (no public CA in the chain at all), the public bundle won't
|
||||
trust it -- that's not supported today, would need switching back to
|
||||
embedding that specific cert.
|
||||
|
||||
The device does perform normal hostname verification (it's not skipped),
|
||||
so the Tools Server field's hostname has to match what the certificate
|
||||
was actually issued for -- a bare LAN IP address (`https://192.168.1.50`)
|
||||
will fail the handshake even with the right CA trusted, since an Origin
|
||||
CA cert never covers a raw IP. Use whatever hostname the certificate's
|
||||
SAN list actually covers (e.g. a local DNS/hosts entry pointing at the
|
||||
frame's LAN IP, or the same public hostname the proxy is issued for).
|
||||
The device does perform normal hostname verification (it's not
|
||||
skipped), so the Tools Server field's hostname has to match what the
|
||||
certificate was actually issued for -- a bare LAN IP address
|
||||
(`https://192.168.1.50`) will fail the handshake even against a
|
||||
perfectly valid cert for a different name.
|
||||
|
||||
## Access token
|
||||
|
||||
|
||||
Reference in New Issue
Block a user