Haproxy基于SNI的TLS透传与终止配置问题求助
a.mydomain.com Let's break down what's causing your handshake error and fix it step by step:
Root Cause
The error SSL peer handshake failed, the server most likely requires a client certificate to connect is directly tied to this line in your frontend a configuration:
verify required
This option forces HAProxy to demand a valid client certificate from the connecting client during TLS handshake. Since your regular clients (browsers, API callers) don't send client certificates by default, the handshake fails immediately.
Additionally, your SNI capture showing - is likely due to missing SNI capture configuration in the main TCP frontend, though your routing rules work because the ACLs are correctly inspecting the SNI during the TLS hello.
Fix Steps
1. Remove Client Certificate Requirement (Critical Fix)
Update your frontend a to remove the client certificate verification rules—you only need to terminate TLS for the subdomain, not enforce client auth:
frontend a bind *:9666 ssl crt server.pem accept-proxy mode http default_backend proxy_a
We removed ca-file ca.pem and verify required because these are only needed for mutual TLS (mTLS) authentication, which isn't part of your stated requirement.
2. Fix SNI Logging (Optional but Useful)
To properly capture SNI in your logs (so you don't see - for capture0), add SNI capture logic to your main frontend and update the log format:
First, modify the frontend main to capture SNI:
frontend main bind *:443 mode tcp option tcplog log global # Capture SNI from TLS hello for logging tcp-request content capture req_ssl_sni len 64 tcp-request inspect-delay 5s acl is_main req_ssl_sni -i "${pDomainName}" acl is_a req_ssl_sni -m beg "a" tcp-request content accept if { req_ssl_hello_type 1 } use_backend main if is_main use_backend a if is_a
Then update your global section to include the captured SNI in logs:
global log /dev/log local0 # Add sni=%{+Q}[capture.req.hdr(0)] to your log format log-format %ci:%cp [%tr] %ft %b/%s %Tw/%Tc/%Tt %B %ts %ac/%fc/%bc/%sc/%rc %sq/%bq sni=%{+Q}[capture.req.hdr(0)]
3. Validate the Flow
With these changes, your traffic path for a.mydomain.com will work as intended:
- Client sends TLS hello to NLB:443 with SNI
a.mydomain.com - HAProxy main frontend matches the SNI ACL and forwards the TCP stream to
127.0.0.1:9666with proxy protocol headers frontend aterminates the TLS connection usingserver.pem, then forwards the HTTP request to yourproxy_abackend
Why Your Test with a Different HTTP Port Worked
When you switched frontend a to a different port using HTTP mode, there was no TLS handshake involved—so the client certificate requirement (which only applies to SSL/TLS connections) wasn't triggered, hence no error.
内容的提问来源于stack exchange,提问作者CrusaderX

