HAProxy SSL终止:客户端证书Extended Key Usage与Basic Constraints验证问询
Let's break down your questions step by step based on HAProxy 1.6.9's behavior and its integration with OpenSSL:
1. Do Basic Constraints and Extended Key Usage (EKU) get validated?
Basic Constraints
Yes, Basic Constraints are automatically validated as part of the standard X.509 certificate chain verification process. HAProxy 1.6.9 relies on OpenSSL's X509_verify_cert function for certificate checks, which enforces Basic Constraints rules by default. This includes:
- Verifying if a certificate is marked as a CA (
cA:TRUE) when it's part of the trust chain - Ensuring compliance with path length constraints (if specified)
- Blocking end-entity certificates that incorrectly have
cA:TRUEset
You don't need extra configuration for this—it's baked into the core SSL verification flow when you enable client certificate checks (e.g., using verify required in your bind directive).
Extended Key Usage (EKU)
No, HAProxy 1.6.9 does NOT validate EKU by default. OpenSSL's default verification doesn't enforce EKU matching for client authentication unless explicitly configured, and HAProxy 1.6.x doesn't include native settings to require specific EKU values (like clientAuth).
Even if a client certificate lacks the clientAuth EKU, HAProxy will still accept it as long as the certificate chain is trusted and basic validation checks pass.
2. Can we forward these extension values in request headers?
Absolutely. While HAProxy 1.6.9 doesn't expose pre-built variables for EKU or Basic Constraints, you can use Lua scripting (supported in HAProxy 1.6+) to parse the client certificate's DER data, extract these extensions, and inject them into request headers for your backend services.
Example Lua Script & HAProxy Configuration
First, create a Lua script (e.g., cert_extensions.lua) to parse certificate extensions:
local openssl = require("openssl") local x509 = require("openssl.x509") function extract_cert_extensions(txn) -- Fetch client certificate in DER format local cert_der = txn.sf:ssl_c_der() if not cert_der then return end local cert = x509.new(cert_der, "DER") -- Extract Basic Constraints local bc = cert:getExtension("basicConstraints") if bc then txn:set_var("txn.basic_constraints", tostring(bc)) end -- Extract Extended Key Usage local eku = cert:getExtension("extendedKeyUsage") if eku then txn:set_var("txn.extended_key_usage", tostring(eku)) end end
Then, update your HAProxy config to load the script and set the headers:
global lua-load /path/to/cert_extensions.lua frontend ssl_frontend bind *:443 ssl crt /path/to/server.crt ca-file /path/to/ca.crt verify required http-request lua-extract_cert_extensions http-request set-header X-Client-Basic-Constraints %{txn.basic_constraints} if { var(txn.basic_constraints) -m found } http-request set-header X-Client-EKU %{txn.extended_key_usage} if { var(txn.extended_key_usage) -m found } default_backend backend_servers backend backend_servers server server1 192.168.1.10:80
Optional: Enforce EKU Validation via Lua
If you want to reject certificates missing the clientAuth EKU, extend the Lua script with a validation check:
function validate_eku(txn) local cert_der = txn.sf:ssl_c_der() if not cert_der then return end local cert = x509.new(cert_der, "DER") local eku = cert:getExtension("extendedKeyUsage") if eku then local eku_str = tostring(eku) if not string.find(eku_str, "clientAuth") then txn:respond(403, "Forbidden: Client certificate lacks clientAuth EKU") return end else -- Optional: Reject certificates with no EKU extension txn:respond(403, "Forbidden: Client certificate missing EKU extension") end end
Add this validation to your frontend config:
http-request lua-validate_eku
Key Notes
- Verify your HAProxy build has Lua support enabled (run
haproxy -vv | grep Luato check). - Ensure the OpenSSL Lua bindings are installed on your system.
- For more granular parsing of Basic Constraints (e.g., extracting CA flag or path length), modify the Lua script to parse the extension's ASN.1 data instead of converting it directly to a string.
内容的提问来源于stack exchange,提问作者user2492286

