I recently encountered a situation where I needed to route traffic from three subdomains (sub1.mydomain.com, sub2.mydomain.com, and sub3.mydomain.com) to the same HAProxy instance, with different backend ports and SSL handling requirements. Here's how I approached the solution.
The setup consists of:
- HAProxy server with IP 10.10.10.100 (haproxy01.mydomain.com)
- Three CNAME records pointing to the HAProxy
- Two backend servers (10.10.10.101 and 10.10.10.102)
- Different ports for each subdomain (8081, 8082, 8083)
The key challenge was handling SSL differently for each subdomain:
- sub1.mydomain.com: Requires SSL passthrough (TCP mode)
- sub2.mydomain.com and sub3.mydomain.com: Can terminate SSL at HAProxy
Initially, I tried using TCP mode for all traffic, which led to connection issues. The logs showed:
localhost haproxy[6097]: x.x.x.x:51241 [20/Mar/2015:12:19:38.720] mytraffic mytraffic/ -1/-1/0 0 SC 0/0/0/0/0 0/0
Here's the corrected configuration that handles both SSL passthrough and termination:
frontend https-in
# SSL termination for sub2 and sub3
bind *:443 ssl crt /etc/haproxy/certs/mydomain.com.pem
# ACLs for subdomain routing
acl is_sub1 hdr(host) -i sub1.mydomain.com
acl is_sub2 hdr(host) -i sub2.mydomain.com
acl is_sub3 hdr(host) -i sub3.mydomain.com
# Route to appropriate backends
use_backend sub1_backend if is_sub1
use_backend sub2_backend if is_sub2
use_backend sub3_backend if is_sub3
# TCP mode for SSL passthrough (sub1)
frontend sub1_tcp
bind *:8081
mode tcp
default_backend sub1_backend
backend sub1_backend
mode tcp
balance roundrobin
server node1 10.10.10.101:8081 check
server node2 10.10.10.102:8081 check
backend sub2_backend
mode http
balance roundrobin
server node1 10.10.10.101:8082 check ssl verify none
server node2 10.10.10.102:8082 check ssl verify none
backend sub3_backend
mode http
balance roundrobin
server node1 10.10.10.101:8083 check ssl verify none
server node2 10.10.10.102:8083 check ssl verify none
- Separate frontends for HTTP and TCP traffic
- SSL certificate bundled for the main domain and subdomains
- TCP mode for SSL passthrough (sub1)
- HTTP mode with SSL termination for other subdomains
- SSL verification disabled for backend connections (verify none)
If you encounter issues:
- Check HAProxy logs:
tail -f /var/log/haproxy.log
- Verify DNS resolution for all subdomains
- Test backend connectivity:
curl -vk https://sub2.mydomain.com
- Check certificate chain:
openssl s_client -connect sub2.mydomain.com:443
For production environments:
- Enable SSL session caching
- Consider using SSL offloading hardware if traffic is heavy
- Implement proper health checks for backends
- Monitor connection queues and adjust timeouts as needed
When implementing HAProxy with multiple subdomains pointing to different backend ports, we need to carefully handle both the routing logic and SSL requirements. Your current setup has three key requirements:
- Subdomain-based routing (sub1/sub2/sub3.mydomain.com)
- Mixed SSL handling (pass-through vs termination)
- Port-based backend distribution (8081/8082/8083)
The SC (Session Closed) error in your logs suggests HAProxy isn't properly establishing the TCP connection to your backends. Let's analyze the critical issues in your current setup:
# Main problem areas in original config:
1. Incorrect backend section indentation (sub1_nodes is misaligned)
2. Missing proper SSL certificate configuration
3. Potential SNI requirement for host header inspection
Here's the corrected version that handles both SSL passthrough and termination scenarios:
# Global SSL certificates (for termination)
global
ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256
ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11
# Frontend for SSL traffic
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/mydomain.com.pem alpn h2,http/1.1
mode tcp
option tcplog
# TLS inspection for host-based routing
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
# ACLs for subdomain routing
acl sub1 req_ssl_sni -i sub1.mydomain.com
acl sub2 req_ssl_sni -i sub2.mydomain.com
acl sub3 req_ssl_sni -i sub3.mydomain.com
# Routing logic
use_backend sub1_servers if sub1
use_backend sub2_servers if sub2
use_backend sub3_servers if sub3
# Backend for SSL passthrough (sub1)
backend sub1_servers
mode tcp
balance roundrobin
option ssl-hello-chk
server node1 10.10.10.101:8081 check send-proxy
server node2 10.10.10.102:8081 check send-proxy
# Backend for SSL termination (sub2)
backend sub2_servers
mode http
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https
server node1 10.10.10.101:8082 check ssl verify none
server node2 10.10.10.102:8082 check ssl verify none
# Backend for SSL termination (sub3)
backend sub3_servers
mode http
balance roundrobin
option forwardfor
http-request set-header X-Forwarded-Port %[dst_port]
http-request add-header X-Forwarded-Proto https
server node1 10.10.10.101:8083 check ssl verify none
server node2 10.10.10.102:8083 check ssl verify none
1. SSL Certificates: Combine all certificates into a single PEM file for HAProxy:
cat sub1.mydomain.com.crt sub1.mydomain.com.key \
sub2.mydomain.com.crt sub2.mydomain.com.key \
sub3.mydomain.com.crt sub3.mydomain.com.key \
> /etc/haproxy/certs/mydomain.com.pem
2. Debugging Tips: Enable detailed logging by adding to your global section:
global
log /dev/log local0 debug
log-tag HAProxy
For high-traffic environments, consider these optimizations:
- Enable SSL session caching
- Implement connection rate limiting
- Use separate frontends for HTTP/HTTPS if needed
# SSL performance tuning example
global
tune.ssl.default-dh-param 2048
ssl-default-bind-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384
ssl-default-server-ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384