Guía Completa: pfSense con DDNS de Cloudflare, Certificados Let’s Encrypt y HAProxy para Proxy Inverso y Balanceo de Carga de servicios

Hoy tenemos ganas de fiesta, así que ponte cómodo/a que hoy configuraremos:

  • Un firewall pfSense para que genere/renueve de forma automática (utilizando el plugin ACME) certificados Let’s Encrypt wildcard (*.dominio.com) para poder utilizar con ese certificado todos los subdominios que queramos (azul.dominio.com, rojo.dominio.com, etc)
  • Añadiremos a pfSense un HAproxy como proxy inverso para poder proveer varios servicios internos sin necesidad de tener que abrir tropecientos puertos NAT en el router (bueno, solo abriremos uno, el 443 del SSL)
  • Todo esto lo haremos a nivel doméstico, así que, de paso, añadiremos un servicio de DNS dinámico (DDNS) en pfSense para que se encargue de gestionar el cambio de IP pública, que somos muy vagos.
  • Utilizaremos Cloudflare como gestor DNS del dominio, esto nos permitirá en el plugin ACME de pfSense utilizar su API de acceso para poder validar dominios y generar/renovar los certificados necesarios. El plugin ACME permite utilizar decenas de proveedores DNS, pero en este artículo utilizaremos Cloudflare por ser el más “famoso”

Gracias al proxy inverso de HAproxy, podremos redirigir a los usuarios a determinados servicios según la URL a la que quieran acceder.

Además, configuraremos en el HAproxy el SSL Offloading. Esto significa que la conexión cifrada SSL entre el cliente y el servidor terminará en el propio HAproxy que estará en medio, y las conexiones que haga el HAproxy hacia los servicios internos, se harán utilizando HTTP. Esto nos simplificará la administración de los servicios internos, ya que, al renovar el certificado, solo lo haremos en el HAproxy y no en todos y cada uno de los servicios.

En nuestro ejemplo, trabajaremos con el dominio principal jaimepons.com (sí, ya sé ya sé, pero no tengo otro disponible que no utilice), y según el subdominio que soliciten los usuarios, los redirigiremos a un servicio o a otro. En nuestro ejemplo trabajaremos con dos subdominios: rojo.jaimepons.com y azul.jaimepons.com

HAproxy además, nos puede proveer de balanceador de carga, es decir, podemos no solo redirigir al usuario al servidor que toca, sino que podemos tener una granja de servidores e ir distribuyendo las peticiones, esto nos dará resiliencia ante caídas de algún servicio. ¡Así que, ya puestos, también lo haremos, que no se respire miseria!

Bien, una vez descrito lo que haremos, pasemos a enumerar los pasos a realizar:

  1. Crear topología de red (para saber qué demonios vamos a montar)
  2. Instalación de pfSense CE (versión gratuita comunitaria, que somos pobres)
  3. Crear varias VM’s con varios servicios. Para este artículo, lo haremos con varios servidores WEB apache, que es sencillo y el resultado será muy visual.
  4. Instalar y configurar cliente DDNS en pfSense (utilizaremos el propio Cloudflare para hacerlo) para actualizar la IP pública (WAN) del pfSense.
  5. Instalación y configuración del plugin ACME en pfSense, encargado de solicitar/renovar los certificados SSL en Let’s Encrypt.
  6. Instalación y configuración de HAproxy
  7. Tener hijos, plantar un árbol y escribir un libro ¿espera… esto iba aquí?
    Notas finales

1. Crear topología de Red:

Esta será nuestra topología de red. En ella vemos que tenemos un Router ISP que da acceso a internet. No sabemos la IP pública (WAN) porque es dinámica. Dicho router tiene un NAT del puerto 443 (HTTPs) hacia el pfSense. Dado que pfSense estará “dentro” de nuestra red interna, la IP WAN será una IP interna de nuestra red. Esto es importante señalarlo porque es sobre esta IP WAN de pfSense desde donde configuraremos pfSense y habrá que hacer unos cambios posteriores a su instalación.

Ya en pfSense, tendremos una LAN conectada a todos los webservers. Utilizaremos el balanceador de HAproxy para tener dos servidores por cada servicio:

  • azul.jaimepons.com lo sirven dos webservers
  • rojo.jaimepons.com lo sirven dos webservers

2. Instalar pfSense CE:

Bueno, qué os voy a contar que no sepáis ya sobre instalar un pfSense. Lo único que debéis saber es que la versión CE ahora está medio escondida dentro de un Netgate Installer, y te hacen bajar una ISO más rara que un perro verde.

Total, que hay una web de netgate desde donde puedes bajar la versión CE directamente:
https://atxfiles.netgate.com/mirror/downloads/

En nuestro caso, bajamos la última versión disponible para x64:
https://atxfiles.netgate.com/mirror/downloads/pfSense-CE-2.7.2-RELEASE-amd64.iso.gz

La descomprimimos y ya tenemos la ISO CE lista para instalar.

Para este artículo, utilizaremos VirtualBox, pero se puede utilizar cualquier entorno de virtualización. Dado que virtualbox es multiplataforma, todo lo aquí expuesto se puede replicar en un entorno Windows, Linux, Mac.

Hay que recordar que el Router ISP tiene un NAT configurado del puerto 443 a la IP WAN del pfsense. Siendo esto tan trivial, no lo abordaremos aquí. ¡Es abrir un puerto en el router por dios! Creamos la máquina virtual con dos adaptadores de red (uno para WAN conectado en modo bridge con la red de nuestro Router ISP y uno para LAN conectado en modo Internal, para que solo las máquinas virtuales conectadas a esa red puedan verse, y de paso, mediante pfSense controlaremos qué tráfico permitimos hacia/desde esas máquinas), un mínimo de RAM y CPU y a volar.

Al final de la instalación del pfSense tendremos esto:

Dado que la IP 192.168.13.10 de la WAN es parte de nuestra red interna de casa, tenemos que configurar pfSense para que nos deje acceder a la consola de administración, ya que, por defecto, pfSense bloquea cualquier conexión a su WAN.

Para ello, deshabilitamos un momento el firewall de pfsense desde la consola:

Pulsamos 8 (Shell), y ejecutamos “pfctl -d”:

Esto nos permitirá acceder a la consola de administración por el adaptador WAN de pfSense (user:admin / pass:pfsense):

Seguimos el asistente inicial configurando hostname, dns, servidores de hora, etc. Cuando lleguemos al adaptador WAN (que estará configurado en IP estática) debemos desmarcar estas opciones para que no nos autobloqueemos al acceder:

Cuando terminemos el asistente, al pulsar Finish, se volverá a activar el firewall. Debemos repetir el paso de deshabilitar el firewall momentáneamente:

Y ya estamos dentro:

Ahora, para asegurarnos que podamos entrar a la consola en el futuro, creamos dos reglas que permitan el acceso a la WAN a los puertos 443 y 8443.

El 443 lo utilizará HAproxy para escuchar y redirigir las peticiones a los servicios internos
El 8443 lo utilizaremos para la consola de administración de pfSense para securizar el acceso y que no sea accesible desde Internet. No te olvides pulsar en Apply Changes!:

Cambiamos el puerto de administración de la consola al 8443:

Y ya estamos dentro otra vez, con el firewall activado y sin ningún problema:

Nota: Por defecto, pfSense bloquea todo el tráfico entrante al adaptador WAN y permite todo el tráfico de salida del adaptador LAN. Esto lo dejaremos así en este artículo, ya que en la LAN tendremos los webservers, y queremos instalar unos Ubuntu, actualizarlos e instalar apache, y para eso, necesitamos internet en esos equipos.

3. Crear VM’s webservers

A la hora de crear las vm’s en VirtualBox que albergan los websevers, hay que tener en cuenta que debemos conectarlas al mismo switch virtual interno “switch-interno” para que estén en la LAN del pfSense y puedan tener las IP’s correspondientes del rango 192.168.1.0/24:

¡Pues ale, a crear VM’s! Creamos 4 Ubuntu servers con Apache.

A cada uno de ellos le configuraremos un archivo index.html con un contenido diferente. De esta forma veremos a qué servidor estamos accediendo en todo momento:

Rápido y sencillo:

  • Instalar y actualizar Ubuntu server
  • apt install apache2
  • editar /var/www/html/index.html

Truqui truqui secreti: Monta el servidor 1, actualiza SO, configura IP manual, instala apache, configura archivo index.html y apágalo. Luego, clona 3 servidores más como Linked Clone del primero (generando MAC nueva). Arranca el 2, configura IP e index.html, luego el 3, luego el 4 y luego arranca el 1. Te ahorrarás mucho tiempo y recursos

4. Configurar cliente DDNS con Cloudflare

Aunque hay centenares de servicios de DDNS (no-ip, dyndns, etc), dado que utilizamos Cloudflare para gestionar los DNS del dominio jaimepons.com, vamos a utilizar su servicio de DDNS. Para ello, vamos a crear una API key que permita modificar los registros DNS del dominio jaimepons.com.

Nos vamos a nuestro perfil de Cloudflare, pulsamos en Tokens API y en Crear Token:

Utilizamos la plantilla de “Editar zona DNS”:

Esa API key solo debe tener acceso a editar cierto dominio:

Y creamos el token:

El token que nos muestra, solo se verá esta vez. En el momento que cierres la ventana ya no lo podrás recuperar más. Si te olvidas de apuntarlo, deberás eliminarlo y crear uno de nuevo, así que ¡apúntalo!, que lo necesitaremos en un par de lugares:

Para utilizar el servicio de DDNS, necesitamos también el Zone ID del dominio. En la consola principal del dominio, podemos verlo:

Por último, creamos un registro DNS, que luego el cliente DDNS de pfSense irá actualizando. En este caso, genero un registro llamado ddns.jaimepons.com que apunta a 8.8.8.8.

Esta IP inicial nos da igual, porque en el momento que configuremos DDNS en pfSense la IP se actualizará a nuestra IP pública de internet, y así de paso confirmamos que funciona correctamente.

Es hora de ir a pfSense a configurar el DDNS:

Añadimos un nuevo cliente, seleccionamos Cloudflare, añadimos como hostname el registro “ddns” que hemos creado anteriormente, en dominio escribimos jaimepons.com y ahora la parte interesante: en username, escribimos el Zone ID, y en password el API Token. Rellenamos y guardamos:

Si ha ido todo bien, veremos esta pantalla:

Y en Cloudflare, veremos el registro DNS actualizado:

¡Mira que bien, ya tenemos un DDNS gratuito con Cloudflare!

Ahora solo tenemos que ir creando CNAMES de los subdominios que nos interesen y que apunten a ddns.jaimepons.com. Creamos azul y rojo.

5. Configuración del plugin ACME (Let’s Encrypt)

Nos vamos al Package Manager, lo buscamos y lo instalamos:

Abrimos Services > Acme certificates y nos vamos a la pestaña de Account Keys.

Para los que no sepan cómo funciona Let’s Encrypt, este necesita una cuenta de correo para enviar las alertas de renovación de certificados. Por ello, antes de solicitar el certificado, hay que registrar una cuenta de correo junto con una Account Key, que es la que se utilizará para trabajar con Let’s Encrypt.

Así que venga, seleccionamos un servidor Let’s Encrypt PRODUCTION (importante lo de PRODUCTION, ya que los servidores con la palabra STAGING son servidores de prueba, que te generarán un certificado válido, pero las CA raíces no están en los navegadores y hará saltar una alerta indicándote que el certificado no es de confianza), añadimos un correo, generamos una nueva Account key asociada pulsando en “Create new Account Key” y pulsamos en “Register ACME Account Key”.

Cuando veas en “Register ACME Account Key” el check de OK en forma de V, pulsa en Save

Vamos a la pestaña de Certificates y creamos uno.

Para ello le ponemos un Name (yo le pongo el mismo dominio para poderlo encontrar fácilmente después), seleccionamos la “Acme Account” que acabamos de crear, en Domain SAN list añadimos *.jaimepons.com para que nos genere un certificado de tipo Wildcard, seleccionamos Cloudflare como proveedor de DNS, y pegamos la API Token que hemos generado en pasos anteriores (¿la habías copiado verdad? ¿verdad?). Por último, pulsamos en Save

Una vez configurado el domino, pulsamos en “Issue/Renew” para solicitar el primer certificado o renovación del mismo. Esto luego lo automatizaremos y así nos olvidaremos de hacerlo cada 3 meses cuando caduque el certificado.

Si ha ido todo bien veremos un chorizo de color verde indicando que se ha generado el nuevo certificado:

Ahora, si vamos a System > Certificates > Certificates podemos ver que ya lo tenemos disponible en pfSense.

Por último, dentro del plugin de ACME, en el apartado de General Settings, marcaremos la opción de “Cron Entry” para que pfSense renueve el certificado de forma automática:

Nota para frikis: ¿Cómo funciona todo esto de la API de Cloudflare (aplicable a otros proveedores)?

Lo que hace el plugin ACME es conectarse a los servidores de Let’s Encrypt solicitando un certificado y diciendo que el método de validación sea el de crear un registro DNS en el dominio. Este método confirma que tienes plenos derechos administrativos en el dominio, si puedes modificar sus DNS, eres Dios para ese dominio.

Let’s Encrypt acepta la petición y le indica a ACME que cree un registro DNS en el dominio con un texto en particular.

El script, utilizando la API Key de Cloudflare, genera ese registro y espera unos 30 segundos a que Let’s Encrypt lo valide por si mismo. Cuando Let’s encrypt detecta ese registro en los DNS del dominio, da por validado el dominio y emite el certificado. El plugin ACME recibe el certificado y elimina el registro DNS creado anteriormente mediante la API Key de Cloudflare.

6. Configuración de HAproxy

Bueeeeno, por fin! ¡Menudo chorizo hasta llegar aquí! Llegamos al hueso del asunto. Ya tenemos pfSense listo, DDNS funcionando, el certificado Let’s Encrypt instalado y los webservers esperando peticiones. Vamos a por el HAproxy, así que a instalar el plugin:

A grandes rasgos, para poder trabajar con HAproxy en modo proxy inverso, tenemos que entender dos cosas: los Backends y los Frontends

Los Backends son los servidores destino que quieres publicar, en nuestro caso, son los 4 servidores web.

Los Frontend son los puertos de escucha (en nuestro caso el 443 de HTTPs), sobre los que analizarás las peticiones que hagan los usuarios (la web a la quieren acceder), y en base a unos “filtros” (¿quiere ir a azul.jaimepons.com o a rojo.jaimepons.com?) podrás enlazar dichas peticiones con determinados backends.

Vamos a ello. Primero crearemos el Backend azul.jaimepons.com:

Vamos a la pestaña Backend, creamos uno nuevo y ponemos en nombre algo descriptivo como “azul”, en Server list añadimos los dos servidores que darán servicio:

Vale, tenemos dos servidores, pero… ¿a cuál nos conectaremos realmente?

Aquí interviene el algoritmo de balanceo de carga. Hay varios, y dependiendo del servicio que utilices querrás uno u otro, pero para el ejemplo que nos ocupa utilizaremos el algoritmo Round Robin, es decir, cada nueva petición irá alternándose entre el servidor 1 y el servidor 2.

La primera vez que se pida azul.jaimepons.com irá al 1, la segunda al 2, la tercera al 1, la cuarta al 2, etc

Haremos lo mismo para el Backend de rojo.jaimepons.com. Cuando tengamos los dos configurados veremos esto:

Fijaos que hay un “Check”. Ese Check lo que hace por defecto HAproxy es validar cada segundo que el servidor web esté activo y respondiendo. Si en algún momento un servidor se “cae”, ya no lo tendrá en cuenta a la hora de enviar peticiones y las peticiones se distribuirán entre los servidores que aún estén disponibles.

Ahora le toca el turno al Frontend. ¡Allá vamos!

Vamos a la pestaña Frontend, creamos uno nuevo y configuramos varias partes. La primera es la IP de escucha (WAN Address), el puerto (443) y el SSL Offloading, es decir, forzamos a que la conexión SSL cliente-servidor termine en el HAproxy (por eso hemos instalado el certificado wildcard *.jaimepons.com aquí). El Name puede ser cualquier cosa.

Ahora llegamos a la parte más importante del Frontend, determinar a qué Backend enviar la petición según la URL que nos estén solicitando.

En ACL (Access Control List) le decimos que cuando el host que nos estén pidiendo coincida con azul.jaimepons.com, la ACL que se activará se llamará “acl_azul”.

Luego en Actions le decimos que cuando la ACL “acl_azul” se active, se mande esa petición al Backend “azul”.

Y lo mismo para rojo.jaimepons.com, no creo que haga falta repetirlo 🙂

Una vez completado todo, guardamos y aplicamos cambios.

Vale, ya tenemos configurados el Frontend y los Backend, ahora falta el último paso, ¡activar HAproxy!, establecer las conexiones máximas por proceso y activar las estadísticas (suuuuuper interesante): Abre Setting y configúralo

Bueno bueno, ¿lo probamos?

Abrimos el navegador y lanzamos varias ventanas… parece que el balanceo funciona:

¿Y qué dicen las estadísticas? Deberían mostrar que todos los servidores están OK. Veámoslo en Stats:

Demasiado pequeño, pulsamos en “Fullscreen Stats” (nueva ventana) o directamente en “Stats FS”:

¡Perfecto! Los 4 servidores están OK

¿Y si fallara alguno? Vamos a apagar 2 servidores, uno del rojo y uno del azul, a ver qué pasa:

Como era de esperar por el Check que hace cada segundo, HAproxy lo detecta. ¿Y qué pasará con el RoundRobin? Abramos de nuevo los navegadores y refresquemos las webs varias veces:

¡Magnífico! ¡Funciona! No me lo creo ni yo jajajaja. Siempre muestra el único servidor disponible en cada servicio.

Volver a meter dentro del balanceador el resto de servidores es tan sencillo como volverlos a encender. HAproxy los volverá a detectar y los meterá de nuevo en el balanceo.

7. Notas finales

Bueno, hemos llegado al final, espero que te hayas entretenido lo suficiente y que te haya ayudado a comprender un poco mejor como funcionan todas estas tecnologías.

Evidentemente hay muchas más opciones, casos de uso, formas de interconectar los equipos, etc pero para ver un caso de uso “doméstico” donde la mayoría de la gente no va a configurar su pfSense como enrutador ISP y va a tener el router de su compañía delante haciendo NAT, creo que esta topología de red es ideal para quien le interese hacer pruebas dentro de su red sin romper nada y trabajando con máquinas virtuales que puedes desecharlas tantas veces como quieras

Bye

@jaumepons

Scroll al inicio
WordPress Appliance - Powered by TurnKey Linux