Instalamos HaProxy en su versión 2 que se encuentra en los repositorios
aptinstallhaproxy
Ahora vamos a preparar las diferentes partes de la configuración de HAProxy para lo siguiente:
Todas las peticiones que tienen certificado se re direcciones automáticamente al puerto 443
Se añadirá HSTS a todas las peticiones con certificado
Se reenviara la petición a nuestra granja de WAF
Si a petición es correcta se devolverá al HaProxy para que lo envié a los nodos
La configuración de HAProxy se encuentra en
vim/etc/haproxy/haproxy.cfg
Ahora vamos a ir viendo las diferentes secciones
Las dos primeras son la global donde configuramos el usuarios, la jaula... y la de por defecto para configurar el modo, los tiempos de conexión y los errores.
La siguiente sección se encarga de escuchar las peticiones que vienen del exterior y configurar el SLL, redireccionar a SSL y mandar al WAF o a los nodos directamente
frontendclusterVaClusterVienebind*:80 bind *:443 ssl crt-list /etc/haproxy/certs.txt no-tls-tickets ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-GCM-SHA384:AES128-SHA256:AES128-SHA:AES256-SHA256:AES256-SHA:!MD5:!aNULL:!DH:!RC4:@STRENGTH no-tlsv10 no-tlsv11 alpn h2,http/1.1
#Comprobamos si el dominio esta en la lista de sslaclhttps_domainhdr(host) -f/etc/haproxy/domains.txtredirectschemehttpscode301if!{ssl_fc}https_domain# Distinguimos si la conexión es segura o noaclsecuredst_porteq443# Marcamos todas las cookies como seguras si se usa sslhttp-responsereplace-headerSet-Cookie"^((?:(?!; [Ss]ecure\b).)*)\$""\1; secure"ifsecure# Agregamos HSTS con un año de duracciónhttp-responsereplace-headerStrict-Transport-Security:\ max-age=31536000ifsecuremodehttp# Comprobamos la carga del WAF por si esta saturadoaclno_wafnbsrv(bk_waf) eq0aclwaf_max_capacityqueue(bk_waf) ge1# bypass WAF si no esta disponibleuse_backendbk_nodesifno_waf# bypass WAF si esta saturadouse_backendbk_nodesifwaf_max_capacity#Mandamos la petición al WAFdefault_backendbk_waf
Con la configuración actual de SSL conseguimos un A en SSLLabs.
Configuramos las peticiones a la granja de WAF, se manda una petición a waf_health_check a los diferentes nodos para ver si esta disponible esperando un 403 que luego configuraremos en el WAF y a continuación se envia al WAF.
El balance especifica la estrategia de equilibrio de carga. En este caso usamos Round-robin dado que vamos a provechar los pesos, dado que un WAF se encuentra en el mismo CPD que el HAProxy y el otro esta en otro CPD de esta manera reducimos los tiempos de latencia y priorizamos el que tenemos cerca.
backendbk_wafbalanceroundrobinmodehttplogglobaloptionforwardforheaderX-Client-IPoptionhttpchkhttp-checkconnecthttp-checksendmethGETuri/waf_health_checkverHTTP/1.1hdrhosthaproxy.local# Specific WAF checking: a DENY means everything is OKhttp-checkexpectstatus403timeoutserver25sdefault-serverinter3srise2fall3serverwaf1XXX.XXX.XXX.XXX:81maxconn100weight15checkserverwaf2XXX.XXX.XXX.XXX:81maxconn100weight10check
En esta sección lo que hacemos es recibir la petición de vuelta del WAF para mandarlos para los nodos, si solo usáramos una HAProxy podríamos decirle la ip interna que tiene que escuchar en el bind pero si usamos 2 y tenemos una ip flotante interna para que la granja de WAF siempre vuelva a la misma ip tenemos que dejarle el *, esto supone un fallo de seguridad porque podrían entrar por el puerto 82 saltando el WAF, pero lo solucionaremos mediante Iptables mas adelante.
La ultima sección lo que nos servirá es para enviar ya a los nodos volveremos a usar el tipo de conexión Round-robin con los pesos por el mismo motivo que antes dado que tenemos algunos en el mismo CPD y otros en otro.
Con esto tendríamos una configuración minima para poder usar nuestro tipo de infraestructura, podríamos añadir mas cosas al HAProxy como mitigación de DDoS, evitar que los ficheros estaticos como las imagenes tengan que pasar por el waf para liberarlos de carga...
Keepalived
Instalamos keepalived y psmisc
aptinstallkeepalivedpsmisc
Las configraciones entre los dos nodos son muy parecidas solo teniendo que cambiar la prioridad y el estado.
Nodo MASTER
Creamos la configuración en el siguiente fichero
vim/etc/keepalived/keepalived.conf
global_defs { enable_script_security script_user root}vrrp_script chk_haproxy { script "killall -0 haproxy"# Comprobamos que el Haproxy esta vivo interval 2#Cada 2 segundo weight 2# Agregamos 2 puntos de peso si esta OK}#Ip flotante dentro del VRackvrrp_instance VI_2 { interface ens4 # Interfaz que monitorizamos state MASTER # MASTER en haproxy1, BACKUP en haproxy2 virtual_router_id 24 priority 101#101 en haproxy1, 100 en haproxy2 authentication { auth_type PASS auth_pass PASSWORD } virtual_ipaddress { IP_FLOTANTE dev ens4 # Dirrección virtual } track_script { chk_haproxy }}#Ip flotante extermavrrp_instance VI_1 { interface ens3 # Interfaz que monitorizamos state MASTER # MASTER en haproxy1, BACKUP en haproxy2 virtual_router_id 23 priority 101#101 en haproxy1, 100 en haproxy2 authentication { auth_type PASS auth_pass PASSWORD } virtual_ipaddress { IP_FLOTANTE dev ens3 # Dirrección virtual } track_script { chk_haproxy }}
Nodo Backup
Creamos la configuración en el siguiente fichero
vim/etc/keepalived/keepalived.conf
global_defs { enable_script_security script_user root}vrrp_script chk_haproxy { script "killall -0 haproxy"# Comprobamos que el Haproxy esta vivo interval 2#Cada 2 segundo weight 2# Agregamos 2 puntos de peso si esta OK}#Ip flotante dentro del VRackvrrp_instance VI_2 { interface ens4 # Interfaz que monitorizamos state BACKUP # MASTER en haproxy1, BACKUP en haproxy2 virtual_router_id 24 priority 100#101 en haproxy1, 100 en haproxy2 authentication { auth_type PASS auth_pass PASSWORD } virtual_ipaddress { IP_FLOTANTE dev ens4 # Dirrección virtual } track_script { chk_haproxy }}#Ip flotante extermavrrp_instance VI_1 { interface ens3 # Interfaz que monitorizamos state BACKUP # MASTER en haproxy1, BACKUP en haproxy2 virtual_router_id 23 priority 101#101 en haproxy1, 100 en haproxy2 authentication { auth_type PASS auth_pass PASSWORD } virtual_ipaddress { IP_FLOTANTE dev ens3 # Dirrección virtual } track_script { chk_haproxy }}
certbot
Vamos a utilizar certbot para que todos los dominios de nuestros cluster tengan por lo menos un certificado ssl gratuito, en este caso tenemos los dominios en OVH (Si el dominio esta en otro proveedor tendriamos que mirar como sacar el certificado para dicho proveedor) por lo primero que tenemos que hacer es generar una api token y los permisos necesarios, para no tener que reconfigurar el HAProxy para que funcione dado que este camino es mas fácil y cómodo.
pero seria bastante inseguro por lo que podemos dar solo los permisos necesarios
GET /domain/zone/
GET /domain/zone/{domain.ext}/status
GET /domain/zone/{domain.ext}/record
GET /domain/zone/{domain.ext}/record/*
POST /domain/zone/{domain.ext}/record
POST /domain/zone/{domain.ext}/refresh
DELETE /domain/zone/{domain.ext}/record/*
Reemplace {domain.ext} con su nombre de dominio. Tenga en cuenta que este es siempre el nombre de dominio raíz sin un subdominio.
Después de la validación, deberá crearse un archivo de configuración para que Certbot pueda acceder a los identificadores de API. Puedes guardar este archivo donde quieras y nombrarlo como quieras. Por mi parte /root/certs/.ovhapi con el siguiente contenido.
Obviamente, los reemplaza xxx con la información obtenida durante la creación del token. Finalmente, asegúrese de configurar permisos para este archivo con 600, de lo contrario Certbot generara advertencias. chmod 600 /root/certs/.ovhapi
Instalamos cerbot en el HA1
#Instalamos python3-pipaptinstallpython3-pip#Instalamos certbot y el complemento de ovhpip3installcertbotpip3installcertbot-dns-ovh
Generando certificados
Una vez que tenemos todo listo, podemos generar nuestros certificados, solo los dominios administrados en su cuenta OVH pueden funcionar.
# generación del certificado para rotasim.com y * .rotasim.com# estos son dos certificados separados pero se agruparán en un solo archivocertbotcertonly--dns-ovh--dns-ovh-credentials~/.ovhapi-drotasim.com-d*.rotasim.com# alternativamente, si ejecuta las líneas de comando en dos etapas (por lo tanto, sin -d * .rotasim.com para la anterior)
# obtenemos un archivo por certificadocertbotcertonly--dns-ovh--dns-ovh-credentials~/.ovhapi-d*.rotasim.com# si quieres hacer un script de la generación# debemos especificar que no sea interactivocertbot certonly --dns-ovh --dns-ovh-credentials ~/.ovhapi --non-interactive --agree-tos --email nombre@email.com -d rotasim.com -d *.rotaism.com
Vamos a crear el siguiente script en la carpeta root/certs para poder tener los certificados de todos nuestros dominios y sincronizados con los dos HaProxys
vim/root/certs/certs.sh
con el siguiente contenido, el cual comprobara la lista de dominios que tenemos en el ficheros domains_ssl.txt y si no esta creado el certificado lo solicitara, acordarse de cambiar el email.
Tendremos un segundo script que se lanzara cuando se acabe de solicitar el dominio para para preprar los certificados para HA y crear la lista de certificados que necesitamos