haproxy es el mejor software de proxies

haproxy es un programa de proxy inverso y balanceo de carga, que te permite traer sitios webs de dentro a fuera. O si tienes varios mirrors de tu sitio web, balancear la carga entre todos ellos para que no sea solo un server principal el que se come toda la mierda.

mi colega nitrobear es un crack de Linux y lo que rodea ese concepto, pero no sabe demasiado sobre proxys y proxys inversos, así que, ya que estoy aquí, explico un poco los proxies, proxies inversos, balanceadores de carga, que métodos de balancear cargas hay y demás cosas.

Un proxy es el de toda la vida. Es el servidor que hace las cosas por ti para que tu no tengas que hacerlas. Le mandas un request al proxy y el proxy hace la consulta HTTP (o TCP) por ti, y el servidor que reiba la request verá la IP del proxy. No la tuya.

Un proxy inverso es eso, un proxy inverso. En vez de tu estar haciendole una petición al servidor, es el servidor el que le hace una petición a otro servidor. Por esto se llama proxy inverso. Porque estás haciendo que haproxy (o nginx, también) hagan de cliente HTTP para luego servirte el sitio.

Como es ampliamente configurable, puedes configurar nginx para que puedas tener la root del server HTTP en el servidor local, y tener, por ejemplo /blog en otro servidor, simplemente haciendo proxy_pass a otro servidor (o a otro puerto de la máquina local).

Un balanceador de carga es lo que dice su nombre, como los sitios web están en internet y cualquier tio con una conexión puede visitarlos, es posible que entren mas de la cuenta y el server explote porque tiene demasiada carga. Por esa razón tengo múltiples mirrors de este sitio web en distintos servidores. Para que ningún servidor se coma la toda la carga, sino que se vaya distribuyendo a través de varios nodos.

Tener varios mirrors de un sitio web permite que, aunque un servidor muera, siga estando disponible. Esto se llama High Availability (o HA), lo que permite que duermas tranquilo sabiendo que con tal de que haya un servidor funcionando, el sitio web funciona. Lo único que aumenta son los recursos usados.

haproxy soporta ser un proxy inverso y un balanceador de carga. Ya que su nombre significa “High Availability Proxy”. Haproxy es software libre (obviamente) y está publicado bajo la GPLv2. Aunque también tiene su versión comercial y corporativa que supongo que será igual pero en vez de un canal IRC, tienen un ticket system para el soporte.

Realmente no me voy a molestar en explicar como instalar haproxy. Tu sabrás que distro tienes y sabrás como instalar software en ella. Busca haproxy en los repositorios de tu distribución y tira para adelante. Que muy seguramente los tiene. Y si no lo tiene, usa una distribución real. Que estás usando un Linux como servidor, no como escritorio. ¿Qué es eso de tener Arch Linux en un servidor? Eso es querer sufrir a lo tonto.

Configuración básica de haproxy

Vamos a plantear un escenario imaginario donde tenemos una VLAN con servidores por todo el mundo, que como están en una VLAN están todos conectados entre sí. El webserver principal que da al Internet de fuera tiene una IP 10.0.0.1, y los nodos backup son, por decir 10.0.0.2 y 10.0.0.3

Las máquinas 10.0.0.2 y 10.0.0.3 están ejecutando el sitio web en el puerto 80801.

Bien, la configuración de haproxy se encuentra en /etc/haproxy/haproxy.cfg. Ahora mismo no recuerdo si traía algún default en Debian. Pero estos son los parámetros default que yo tengo y me han funcionado:

global

     log /dev/log   local0
     log /dev/log   local1 notice
     chroot /var/lib/haproxy
     stats socket /run/haproxy/admin.sock mode 660 level admin
     stats timeout 30s
     user haproxy
     group haproxy
     daemon

     # Default SSL material locations
     ca-base /etc/ssl/certs
     crt-base /etc/ssl/private

     # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
        ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
        ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
        ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets


defaults
    log global
    mode tcp
    option tcplog
    option dontlognull
    option forwardfor
    retries 3
    timeout connect 5000
    timeout client 5000
    timeout server 5000

Realmente no creo que haya demasiado que explicar ahí. Pues con leer como se llaman los parámetros y el contenido de los valores te aclaras tu solo.

Con esto haproxy ya podría iniciar pero no haría nada. Ni siquiera bindearía a ningún puerto. Porque no le has dicho absolutamente nada. haproxy para funcionar necesita un frontend (lo que visita el usuario final, que entra a tu sitio web) y un backend (a lo que haproxy le hace una petición para obtener el contenido del sitio y dárselo luego al usuario). Puedes tener tantos frontends como quieras pero solo uno por puerto. haproxy al igual que nginx soporta múltiples dominios. Cosa que explicaremos luego.

La configuración básica para servir un sitio web en haproxy balanceado es:

frontend mysite
         mode http
         bind 10.0.0.1:80
         default_backend site_backend

backend site_backend
        mode http
        balance roundrobin
        option forwardfor
        timeout connect 10s
        timeout server 1m
        server foo 10.0.0.2:8080
        server bar 10.0.0.3:8080

Y realmente no hay mas. Reinicias haproxy con systemctl o lo que sea que uses y podrías visitar 10.0.0.1:80 y ver hacer F5 como un esquizofrénico y verás como la carga se irá balanceando. Grandes mentes se preguntarán que es un “roundrobin” y un “forwardfor”. Un roundrobin es un método de balancear carga que significa ir en orden. La primera request va a un servidor y la segunda al otro. El fordwardfor es para que se logee la IP del usuario.

El tema es que esto solo soporta HTTP y no HTTPS, como somos modernos tenemos que soportar HTTPS. Lo cual es una cosa bastante sencilla. Ya que solo hace uso de un archivo.txt que es una lista de archivos de certificados. Tiene que ser un certificado por dominio y que sea fullchain y privkey. En ese orden2. Haz de poner la ruta absoluta a ese certificado en un archivo .txt.

/etc/haproxy/ssl/mysite.pem

Tendrás que decirle al frontend que escuche en el puerto 443 y pasarle la lista de certificados:

frontend mysite
         mode http
         bind 10.0.0.1:80
         bind 10.0.0.1:443 ssl crt-list /etc/haproxy/list.txt
         http-request redirect scheme https unless { ssl_fc } # con esto mandas las request HTTP a HTTPS.
         default_backend site_backend

Los backends no tienen porqué tener TLS. Ya que esto al usuario final no le importa. Lo que le importa al navegador es que entre el frontend del sitio y el navegador haya TLS. No de los otros servers al server al que requestea. Al otro server ni siquiera lo ves (de ahí que sea un proxy inverso).

Soporte de dominios

Bien, ¿Y si quiero poner mas de un dominio que?. Pues haproxy los soporta y de una forma mas cómoda que nginx si hablamos la verdad. Fijaros que en el frontend hay un “default_backend”. Pues ese es lógicamente el backend por defecto. Pero hay ACLs para cambiar el backend que se usa, y uno de esos backends es el dominio que se está visitando:

frontend mysite
         acl host_foobar hdr(host) -i foobar.com
         acl host_lain hdr(host) -i lain.lain
         mode http
         bind 10.0.0.1:80
         bind 10.0.0.1:443 ssl crt-list /etc/haproxy/list.txt
         http-request redirect scheme https unless { ssl_fc } # con esto mandas las request HTTP a HTTPS.
         default_backend site_backend

         use_backend foobarbar if host_foobar
         use_backend lain if host_lain

backend mysite
# ...

backend foobar
     mode http
     balance roundrobin
     option forwardfor
     timeout connect 10s
     timeout server 1m
     server foobar 10.0.0.2:8081

backend lain
     mode http
     balance roundrobin
     option forwardfor
     timeout connect 10s
     timeout server 1m
     server foobar 10.0.0.3:8081

Reinicias haproxy. foobar.com apuntaría al 10.0.0.2 y lain.lain apuntaría a 10.0.0.3:8081. Cualquier otra forma de acceso al servidor llevaría al “mysite

Monitorización de esta cosa

Cuando tienes un 3 servidores a lo mucho haproxy está gracioso. Luego es un dolor de cabeza. Gracias a Jesucristo esta cosa viene con un monitor web de los frontends y backends que tienes. Que se puede activar añadiendo este bloque de configuración a tu haproxy.cfg:

listen stats
     bind :25000
     mode http
     stats enable
     stats uri /

Reinicias haproxy y entras al puerto 25000 de tu load balancer y tendrías que tener el pánel de monitorización el cual tiene toda clase de información útil sobre los nodos que estás usando, su estado, cuanto tiempo llevan vivos/muertos y su consumo de ancho de banda. Recomendaría encarecidamente bindear este monitor a una IP de dentro mas que de fuera. Para que solo la gente con acceso pensado tenga acceso al mismo.

Conclusión

haproxy… Otro de esos programas que te curan la depresión

Footnotes:

1

: Podrías poner también el servidor web (y tener otro mirror) en la máquina 10.0.0.1. Pero si se cae esta máquina se caería el haproxy también y te quedarías sin web. Pero podrías hacerlo igual.

2

cat fullchain.pem privkey.pem >> mydomain.pem Y esa cosa haproxy la entiende.