Configuración Avanzada de HAProxy: Terminación SSL
HAProxy es un potente balanceador de carga y proxy inverso de código abierto, renombrado por su rendimiento y flexibilidad. La terminación SSL/TLS en HAProxy descarga la sobrecarga de encriptación de los servidores backend, permitiendo manejo eficiente de tráfico HTTPS. Esta guía cubre configuraciones avanzadas de terminación SSL, gestión de certificados múltiples, listas de control de acceso (ACLs), persistencia de sesión y registro exhaustivo.
Tabla de Contenidos
- Conceptos Básicos de Terminación SSL/TLS
- Instalación y Configuración
- Configuración de Certificado Único
- Configuración de Múltiples Certificados
- ACLs y Enrutamiento
- Mapas para Enrutamiento Dinámico
- Stick Tables y Persistencia de Sesión
- Límites de Conexión
- Registro Avanzado
- Verificaciones de Salud
- Sintonización de Rendimiento
- Solución de Problemas
Conceptos Básicos de Terminación SSL/TLS
La terminación SSL/TLS en HAProxy proporciona varios beneficios:
- Reduce la carga de CPU del servidor backend (sin sobrecarga de encriptación)
- Centraliza la gestión de certificados
- Habilita enrutamiento avanzado basado en propiedades SSL/TLS
- Simplifica la configuración del servidor backend
- Facilita la rotación y actualización de certificados
HAProxy descifra conexiones HTTPS entrantes y se comunica con backends sobre HTTP o HTTPS.
Instalación y Configuración
Instala HAProxy en Debian/Ubuntu:
sudo apt update
sudo apt install haproxy
Instala en RHEL/CentOS:
sudo yum install haproxy
Verifica instalación:
haproxy -v
Comprueba la configuración por defecto:
cat /etc/haproxy/haproxy.cfg
Inicia el servicio:
sudo systemctl enable haproxy
sudo systemctl start haproxy
Configuración de Certificado Único
Crea una configuración básica de HAProxy con terminación SSL:
sudo tee /etc/haproxy/haproxy.cfg > /dev/null <<'EOF'
global
log stdout local0
log stdout local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon
tune.ssl.default-dh-param 2048
tune.ssl.ciphers HIGH:!aNULL:!MD5
tune.ssl.options ssl-default-bind-ciphers ssl-default-server-ciphers ssl-min-ver TLSv1.2
defaults
log global
mode http
option httplog
option denylogging
timeout connect 5000
timeout client 50000
timeout server 50000
listen stats
bind *:8404
mode http
stats enable
stats uri /stats
stats refresh 30s
stats show-legends
stats admin if TRUE
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
bind *:80
mode http
option httpclose
option forwardfor except 127.0.0.1
http-request redirect scheme https code 301 if !{ ssl_fc }
default_backend web_servers
backend web_servers
balance roundrobin
mode http
option httpchk GET /health HTTP/1.1\r\nHost:\ example.com
server web1 192.168.1.100:80 check inter 2000 fall 3 rise 2
server web2 192.168.1.101:80 check inter 2000 fall 3 rise 2
server web3 192.168.1.102:80 check inter 2000 fall 3 rise 2 backup
EOF
Crea el archivo de certificado combinando el certificado y clave privada:
sudo mkdir -p /etc/haproxy/certs
sudo cat /path/to/certificate.crt /path/to/private.key > /etc/haproxy/certs/example.com.pem
sudo chmod 600 /etc/haproxy/certs/example.com.pem
Valida configuración:
sudo haproxy -f /etc/haproxy/haproxy.cfg -c
Recarga configuración:
sudo systemctl reload haproxy
Configuración de Múltiples Certificados
Maneja múltiples dominios con SNI (Server Name Indication):
sudo tee /etc/haproxy/haproxy.cfg > /dev/null <<'EOF'
global
log stdout local0
stats socket /run/haproxy/admin.sock mode 660 level admin
defaults
log global
mode http
timeout connect 5000
timeout client 50000
timeout server 50000
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem crt /etc/haproxy/certs/api.example.com.pem crt /etc/haproxy/certs/blog.example.com.pem
bind *:80
mode http
option httpclose
option forwardfor
http-request redirect scheme https code 301 if !{ ssl_fc }
acl is_example_com hdr(host) -i example.com www.example.com
acl is_api hdr(host) -i api.example.com
acl is_blog hdr(host) -i blog.example.com
use_backend backend_web if is_example_com
use_backend backend_api if is_api
use_backend backend_blog if is_blog
default_backend backend_web
backend backend_web
balance roundrobin
server web1 192.168.1.100:8000 check
server web2 192.168.1.101:8000 check
backend backend_api
balance roundrobin
server api1 192.168.1.110:8080 check
server api2 192.168.1.111:8080 check
backend backend_blog
balance roundrobin
server blog1 192.168.1.120:3000 check
EOF
Crea archivos de certificado:
sudo mkdir -p /etc/haproxy/certs
# Combina certificado y clave para cada dominio
sudo cat /etc/ssl/certs/example.com.crt /etc/ssl/private/example.com.key > /etc/haproxy/certs/example.com.pem
sudo cat /etc/ssl/certs/api.example.com.crt /etc/ssl/private/api.example.com.key > /etc/haproxy/certs/api.example.com.pem
sudo cat /etc/ssl/certs/blog.example.com.crt /etc/ssl/private/blog.example.com.key > /etc/haproxy/certs/blog.example.com.pem
sudo chown -R haproxy:haproxy /etc/haproxy/certs
sudo chmod 600 /etc/haproxy/certs/*.pem
ACLs y Enrutamiento
Usa ACLs (Listas de Control de Acceso) para decisiones de enrutamiento avanzadas:
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
bind *:80
mode http
option httpclose
option forwardfor
# Define ACLs
acl is_api hdr(host) -i api.example.com
acl is_admin path_beg /admin
acl is_static path_beg /static /images /css /js
acl is_mobile hdr(user-agent) -i smartphone mobile
acl high_traffic src_conn_rate gt 100
# Deniega fuentes de tráfico alto
http-request deny if high_traffic
# Enruta tráfico
use_backend backend_api if is_api
use_backend backend_static if is_static
use_backend backend_admin if is_admin is_admin
use_backend backend_mobile if is_mobile
default_backend backend_web
backend backend_api
balance roundrobin
server api1 192.168.1.110:8080 check
backend backend_static
balance roundrobin
server cdn1 192.168.1.130:80 check
backend backend_admin
balance roundrobin
server admin1 192.168.1.140:8000 check
backend backend_mobile
balance roundrobin
server mobile1 192.168.1.150:3000 check
backend backend_web
balance roundrobin
server web1 192.168.1.100:8000 check
server web2 192.168.1.101:8000 check
Mapas para Enrutamiento Dinámico
Usa mapas para gestionar reglas de enrutamiento a través de archivos externos:
Crea un archivo de mapa de enrutamiento /etc/haproxy/maps/backends.map:
example.com backend_web
api.example.com backend_api
blog.example.com backend_blog
cdn.example.com backend_static
admin.example.com backend_admin
Referencia el mapa en la configuración de HAProxy:
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
bind *:80
mode http
option httpclose
option forwardfor
http-request redirect scheme https code 301 if !{ ssl_fc }
use_backend %[req.hdr(host),lower,map(/etc/haproxy/maps/backends.map,backend_web)]
backend backend_web
balance roundrobin
server web1 192.168.1.100:8000 check
backend backend_api
balance roundrobin
server api1 192.168.1.110:8080 check
backend backend_blog
balance roundrobin
server blog1 192.168.1.120:3000 check
backend backend_static
balance roundrobin
server cdn1 192.168.1.130:80 check
backend backend_admin
balance roundrobin
server admin1 192.168.1.140:8000 check
Actualiza mapas sin reiniciar HAProxy vía socket de administración:
echo "example.com backend_api" | socat - /run/haproxy/admin.sock
Stick Tables y Persistencia de Sesión
Implementa sesiones sticky usando stick tables:
global
stats socket /run/haproxy/admin.sock mode 660 level admin
defaults
mode http
timeout connect 5000
timeout client 50000
timeout server 50000
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
bind *:80
mode http
option httpclose
option forwardfor
http-request redirect scheme https code 301 if !{ ssl_fc }
stick-table type string len 32 size 100k expire 30m
stick on cookie(JSESSIONID)
default_backend backend_web
backend backend_web
balance roundrobin
stick-table type string len 32 size 100k expire 30m
stick on cookie(JSESSIONID)
server web1 192.168.1.100:8000 check
server web2 192.168.1.101:8000 check
server web3 192.168.1.102:8000 check
Usa stickiness basada en IP:
frontend https_in
bind *:443 ssl
stick-table type ip size 100k expire 30m
stick on src
default_backend backend_web
backend backend_web
balance roundrobin
server web1 192.168.1.100:8000 check
server web2 192.168.1.101:8000 check
Límites de Conexión
Implementa límites de conexión por cliente:
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem
stick-table type ip size 100k expire 1m store http_req_rate(10s)
http-request track-sc0 src
http-request deny if { sc_http_req_rate(0) gt 100 }
default_backend backend_web
backend backend_web
balance roundrobin
server web1 192.168.1.100:8000 check maxconn 1000
server web2 192.168.1.101:8000 check maxconn 1000
Limita conexiones concurrentes:
frontend https_in
bind *:443 ssl crt /etc/haproxy/certs/example.com.pem maxconn 10000
default_backend backend_web
backend backend_web
balance roundrobin
server web1 192.168.1.100:8000 check maxconn 500
server web2 192.168.1.101:8000 check maxconn 500
Registro Avanzado
Configura registro detallado de solicitudes:
global
log 127.0.0.1 local0 debug
log 127.0.0.1 local1 notice
defaults
log global
mode http
option httplog
option http-server-close
option denylogging
log-format "%ci:%cp [%tr] %ft %b/%s %TR/%Tw/%Tc/%Tr/%Ta %ST %B %CC %CS %tsc %ac/%fc/%bc/%sc/%rc %sq/%bq %hr %hs %{+Q}r"
El formato de registro se desglosa como:
%ci:%cp- IP:puerto del cliente%tr- Marca de tiempo de solicitud%ft- Nombre del frontend%b/%s- Nombre de backend/servidor%TR/%Tw/%Tc/%Tr/%Ta- Tiempos (solicitud, cola, conexión, respuesta, total)%ST- Código de estado HTTP%B- Tamaño de respuesta%CC/%CS- Conteos de cookies%tsc- Estado de terminación%{+Q}r- Línea de solicitud
Ver logs:
tail -f /var/log/haproxy.log
Envía logs a syslog:
sudo tee /etc/rsyslog.d/49-haproxy.conf > /dev/null <<'EOF'
:programname, isequal, "haproxy" /var/log/haproxy.log
& stop
EOF
sudo systemctl restart rsyslog
Verificaciones de Salud
Configura verificaciones de salud avanzadas:
backend backend_web
balance roundrobin
option httpchk GET /health HTTP/1.1\r\nHost:\ example.com
http-check expect status 200
server web1 192.168.1.100:8000 check inter 2000 fall 3 rise 2 weight 1
server web2 192.168.1.101:8000 check inter 2000 fall 3 rise 2 weight 2
server web3 192.168.1.102:8000 check inter 2000 fall 3 rise 2 backup
backend backend_api
balance roundrobin
option tcp-check
tcp-check connect port 8080
server api1 192.168.1.110:8080 check inter 5000 fall 2 rise 1
Sintonización de Rendimiento
Optimiza HAProxy para escenarios de tráfico alto:
global
tune.maxconn 200000
tune.maxconnrate 4000
tune.maxsslconn 100000
tune.ssl.cachesize 1000000
tune.ssl.lifetime 600
tune.http.maxhdr 101
tune.http.uri-max 8192
tune.bufsize 32768
defaults
mode http
timeout connect 5s
timeout client 50s
timeout server 50s
timeout tunnel 1h
timeout http-keep-alive 1s
option http-server-close
option dup-cookie-names
Solución de Problemas
Comprueba estado de HAProxy:
sudo systemctl status haproxy
sudo tail -f /var/log/haproxy.log
Valida configuración:
sudo haproxy -f /etc/haproxy/haproxy.cfg -c
Monitorea estadísticas en tiempo real:
watch -n 1 'echo "show stat" | socat - /run/haproxy/admin.sock'
Prueba certificado SSL:
openssl s_client -connect localhost:443 -servername example.com
Comprueba expiración de certificado:
openssl x509 -in /etc/haproxy/certs/example.com.pem -noout -dates
Conclusión
HAProxy entrega terminación SSL/TLS de grado empresarial con características avanzadas para escenarios complejos de balanceo de carga. Sus poderosos ACLs, enrutamiento dinámico a través de mapas, persistencia de sesión con stick tables y capacidades exhaustivas de registro la hacen ideal para entornos de producción de alto tráfico. Combinado con verificaciones de salud sofisticadas y opciones de sintonización de rendimiento, HAProxy proporciona la base para infraestructura confiable y escalable.


