When implementing HAProxy as an SSL terminator, many administrators face the dilemma of maintaining security between HAProxy and backend servers while avoiding the overhead of managed certificates. The optimal solution balances encryption strength with operational simplicity.
Self-signed certificates offer these advantages for backend communication:
- No certificate authority costs
- Long expiration periods (10+ years)
- Simple regeneration process
- No DNS validation requirements
The key to security lies in properly configuring certificate verification. Instead of using verify none
, we should create a CA bundle:
# Generate CA certificate for self-signed certs
openssl genrsa -out ca.key 2048
openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
# On each backend server:
openssl genrsa -out backend.key 2048
openssl req -new -key backend.key -out backend.csr
openssl x509 -req -days 3650 -in backend.csr -CA ca.crt -CAkey ca.key -set_serial 01 -out backend.crt
Here's the proper backend configuration with certificate pinning:
backend secure-backend
balance leastconn
server web1 1.1.1.1:443 check ssl ca-file /etc/ssl/ca.crt verify required
server web2 2.2.2.2:443 check ssl ca-file /etc/ssl/ca.crt verify required
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https if { ssl_fc }
This approach provides equivalent security to commercial certificates for backend communication because:
- The private CA key never leaves your infrastructure
- Only servers with certificates signed by your CA are trusted
- Certificate verification prevents MITM attacks
- You maintain control over certificate lifetimes
For additional security, implement mutual TLS where both sides authenticate:
backend mTLS-backend
server web1 1.1.1.1:443 check ssl ca-file /etc/ssl/ca.crt verify required crt /etc/ssl/haproxy.pem
This requires each backend server to be configured with the HAProxy client certificate in its trust store.
When using SSL to backends, consider these optimizations:
backend optimized-backend
server web1 1.1.1.1:443 check ssl ca-file /etc/ssl/ca.crt verify required alpn h2,http/1.1 no-tls-tickets
When implementing HAProxy as a reverse proxy, many administrators face the dilemma of securing backend connections without the overhead of managing multiple CA-signed certificates. The typical setup involves:
frontend public
bind *:443 ssl crt /etc/ssl/cert.pem
default_backend secured_servers
While using verify none
with self-signed certs works, it's not ideal for security. Here's a better way to configure trusted self-signed certificates:
backend secured_servers
balance roundrobin
server web1 192.168.1.10:443 ssl ca-file /etc/ssl/backend-ca.pem verify required
server web2 192.168.1.11:443 ssl ca-file /etc/ssl/backend-ca.pem verify required
1. Generate self-signed certificates for your backend servers:
openssl req -x509 -newkey rsa:4096 -sha256 -nodes \
-keyout backend.key -out backend.crt -subj "/CN=backend.example.com" \
-days 3650
2. Create a CA bundle containing all your backend certificates:
cat backend1.crt backend2.crt > /etc/ssl/backend-ca.pem
For additional security, consider these HAProxy settings:
backend secured_servers
server web1 192.168.1.10:443 ssl \
ca-file /etc/ssl/backend-ca.pem \
crt /etc/ssl/backend.pem \
verify required \
ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384 \
no-sslv3 no-tlsv10 no-tlsv11
Check your setup with OpenSSL:
openssl s_client -connect backend:443 -showcerts -CAfile /etc/ssl/backend-ca.pem
Look for the "Verify return code: 0 (ok)" message to confirm proper validation.
For larger deployments, consider setting up an internal CA:
# Create CA
openssl genrsa -aes256 -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 -out ca.crt
# Sign backend certificates
openssl x509 -req -in backend.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out backend.crt -days 365 -sha256
Then configure HAProxy to trust your internal CA:
global
ssl-server-verify none
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
backend secure_backend
server node1 10.0.0.1:443 ssl ca-file internal-ca.crt verify required