如何通过HAProxy实现反向SSL终止?后端HTTPS服务代理问题排查
Alright, let's tackle this problem head-on. The error you're seeing—"Unable to communicate securely with peer: requested domain name does not match the server's certificate"—happens because your current configuration is just transmitting raw TCP traffic (via mode tcp) instead of handling SSL termination at the HAProxy level. Here's why that breaks things:
When you use mode tcp, HAProxy acts like a dumb pipe: your client tries to establish an SSL connection directly with foo.bar.com, but the client is connecting to 127.0.0.1 (your HAProxy frontend). The backend server presents a certificate for foo.bar.com, which doesn't match the IP the client is actually connecting to—hence the domain mismatch error.
Step-by-Step Fix: Enable Reverse SSL Termination
To fix this, we need to configure HAProxy to handle the SSL handshake with the client (terminate the SSL connection), then forward the decrypted traffic to your backend (either over HTTP or HTTPS, your choice).
1. Update the Frontend Configuration
First, modify your frontend to terminate SSL. You'll need a valid SSL certificate (PEM format, containing both the certificate and private key) for the domain your clients will use to access HAProxy (e.g., if clients use foo.bar.com, your cert should be for that domain).
frontend foofront bind 127.0.0.1:443 ssl crt /path/to/your/foo.bar.com.pem # Path to your SSL cert + key mode http default_backend fooback option forwardfor # Optional: Pass client's real IP to the backend
2. Configure the Backend
You have two options here, depending on whether your backend accepts HTTP or requires HTTPS:
Option A: Forward to Backend Over HTTP (Most Efficient)
If your backend can accept unencrypted HTTP traffic (and it's safe within your network):
backend fooback mode http balance leastconn server foo foo.bar.com:80 check
Option B: Forward to Backend Over HTTPS (More Secure)
If your backend only accepts HTTPS, you need to tell HAProxy to establish an SSL connection with the backend and send the correct SNI (Server Name Indication) to match the backend's certificate:
backend fooback mode http balance leastconn server foo foo.bar.com:443 check ssl verify required ca-file /path/to/system-ca-bundle.crt sni str(foo.bar.com)
ssl verify required: Ensures HAProxy validates the backend's SSL certificate (remove or change toverify noneif using a self-signed backend cert).sni str(foo.bar.com): Sends the correct domain name to the backend so its certificate matches the requested SNI.
Key Notes to Avoid Future Issues
- Make sure your HAProxy user has read permissions for the SSL certificate file.
- If clients access HAProxy via a domain (e.g.,
foo.bar.com), your HAProxy SSL certificate must include that domain (or be a wildcard cert). - If you're testing locally, add an entry in your
/etc/hostsfile pointingfoo.bar.comto127.0.0.1so the client uses the correct domain when connecting.
内容的提问来源于stack exchange,提问作者Georg Heiler

