Virtual Host docker redirect http to https Apache

Artículo creado por: Elzer Pineda

Para: https://backtrackacademy.com/

Link: https://backtrackacademy.com/articulo/virtual-host-docker-redirect-http-to-https-apache

Unos meses atrás estaba configurando un ambiente de contenedores para unos sitios web en un servidor y llego la fase del proyecto de colocar https a los tres (3) sitios configurados en el mismo servidor.

Empecé a leer sobre cómo podemos utilizar nuestro virtual host y utilizar los módulos de reverse proxy de apache para lograr tener nuestras redirecciones internas a nuestros contenedores por localhost (127.0.0.1).

 

¿Qué es un reverse proxy?

Un reverse Proxy es una implementación de seguridad perimetral de redes bajo la cual los servidores web NO son expuestos directamente en internet, sino que se expone un único servidor web (que actúa como frontera perimetral) de manera tal que los demás servidores internos solo puedan ser alcanzados a través del servidor web perimetral.

Mediante el uso de Reverse Proxy se obtienen las siguientes ventajas:

  • Basta con una sola IP Pública para publicar varios servidores web (incluso empleando diferentes nombres de dominio simultáneamente), ya que el Reverse Proxy está en capacidad de reconocer el servidor de destino específico hacia el cual se realizan las peticiones y direccionar el tráfico de manera adecuada.
  • Se elimina la necesidad de instalar y administrar varios certificados digitales en varios servidores web para el cifrado de las comunicaciones, dado que el Reverse Proxy está en capacidad de centralizar todos los certificados digitales y encargarse de cifrar todos los contenidos. De esta manera, el CPU de cada servidor web se destina 100% a servir los contenidos web, mientras el Reverse Proxy se encarga 100% de la seguridad perimetral al frente de las peticiones de los servidores.
  • Podemos redireccionar a cualquier puerto interno que tengamos en nuestros servidores o contenedores y lograr exponer la aplicacion con un solo puerto.

Para nuestras pruebas empezaremos configurando nuestros tres contenedores que alojaran nuestras aplicaciones de WordPress.

He desarrollado un docker-compose para agilizar este proceso y enfocarnos en la parte de configuración del virtual host.

A continuación, el docker-compose para levantar tres WordPress en Docker en diferentes puertos de escucha:

Contenido del docker-compose.yml
WordPress:
image: wordpress
links:
— mariadb: mysql
environment:
— WORDPRESS_DB_PASSWORD=password
ports:
— “127.0.0.1:8001:80”
volumes:
-. /html:/var/www/html
mariadb:
image: mariadb
environment:
— MYSQL_ROOT_PASSWORD=password
— MYSQL_DATABASE=wordpress
volumes:
— ./database:/var/lib/mysql

wordpress2:
image: wordpress
links:
— mariadb: mysql
environment:
— WORDPRESS_DB_PASSWORD=password
ports:
— “127.0.0.1:8002:80”
volumes:
-./html:/var/www/html
mariadb:
image: mariadb
environment:
— MYSQL_ROOT_PASSWORD=password
— MYSQL_DATABASE=wordpress1
volumes:
— ./database:/var/lib/mysql

wordpress3:
image: wordpress
links:
— mariadb: mysql
environment:
— WORDPRESS_DB_PASSWORD=password
ports:
— “127.0.0.1:8003:80”
volumes:
-./html:/var/www/html
mariadb:
image: mariadb
environment:
— MYSQL_ROOT_PASSWORD=password
— MYSQL_DATABASE=wordpress3
volumes:
— ./database:/var/lib/mysql

Con el comando docker-compose up -d levantaremos nuestro ambiente y lograr tener un resultado como el siguiente:

Ahora tenemos tres WordPress ejecutándose en el servidor con acceso por tres diferentes puertos.

WordPress 1: redireccionando el puerto 8001 al 80
WordPress 2: redireccionando el puerto 8002 al 80
WordPress 3: redireccionando el puerto 8003 al 80

La problemática en su momento era como accedíamos a los tres sitios de WordPress bajos sus dominios y sin necesidad de colocar los puertos expuestos y desplegando el sitio en https.

Aplicando la teoría explicada en los puntos anteriores armamos nuestros virtual host utilizando el módulo mod_proxy para redireccionar todo nuestro tráfico a nuestros contenedores desplegados en un mismo servidor.

Para utilizar especificamente los módulos de mod_proxy; Apache tiene muchos módulos incluidos que están disponibles pero no activados en una instalación nueva. Primero, necesitaremos habilitar los que usaremos en este tutorial.

Los módulos que necesitamos son el propio mod_proxy y varios de sus módulos adicionales, que extienden su funcionalidad para soportar diferentes protocolos de red.

Específicamente, usaremos: 

· mod_proxy, el módulo principal del proxy para redirigir las conexiones; permite que Apache actúe como una puerta de enlace a los servidores de aplicaciones subyacentes.

· mod_proxy_http, que añade el soporte para el proxy de las conexiones HTTP.

· mod_proxy_balancer y mod_lbmethod_byrequests, que agregan características de balanceo de carga para múltiples servidores backend.

Para habilitar estos cuatro módulos, ejecute los siguientes comandos en forma sucesiva para efectuar los cambios: 

· sudo a2enmod proxy
· sudo a2enmod proxy_http
· sudo a2enmod proxy_balancer

Para poner en marcha estos cambios, reinicie el Apache.

sudo systemctl reiniciar apache2

A continuación, la configuración completa del virtual host para redireccionar nuestro tráfico a nuestros contenedores con algunas características de excepciones de SSl debido a que nuestras pruebas las estamos realizando con certificados autofirmados.

NOTA: toda la configuración debe estar en un solo archivo ubicada en la ruta configurada de apache /etc/apache/site-avalible/wordpress.conf y habilitado el archivo de  configuracion para que se hagan efecto los cambios.

Los comandos para habilitar nuestro virtual host en apache: 

Habilitamos nuestro virtual host:
* sudo a2ensite wordpress.conf
* sudo systemctl restar apache2


Las siguiente configuracion debe estar completa en nuestro virtual host wodpress.conf
<VirtualHost *:443>
ServerName word1.local
ProxyPreserveHost On
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPass /
http://127.0.0.1:8001/
ProxyPassReverse /
http://127.0.0.1:8001/
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warnSSLEngine onSSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCertificateFile /etc/pki/tls/certs/word1.crt
SSLCertificateKeyFile /etc/pki/tls/private word1.key
CustomLog logs/ssl_request_log \
“%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \”%r\” %b”
</VirtualHost>


<VirtualHost *:443>
ServerName word2.local
ProxyPreserveHost On
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPass / http://127.0.0.1:8002/
ProxyPassReverse / http://127.0.0.1:8002/
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warnSSLEngine onSSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCertificateFile /etc/pki/tls/certs/word2.crt
SSLCertificateKeyFile /etc/pki/tls/private word2.key
CustomLog logs/ssl_request_log \
“%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \”%r\” %b”<
</VirtualHost>


<VirtualHost *:443>
ServerName word3.local
ProxyPreserveHost On
SSLProxyEngine on
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
ProxyPass / http://127.0.0.1:8003/
ProxyPassReverse / http://127.0.0.1:8003/
ErrorLog logs/ssl_error_log
TransferLog logs/ssl_access_log
LogLevel warnSSLEngine onSSLProtocol all -SSLv2 -SSLv3
SSLProxyProtocol all -SSLv2 -SSLv3
SSLHonorCipherOrder on
SSLCertificateFile /etc/pki/tls/certs/word3.crt
SSLCertificateKeyFile /etc/pki/tls/private word3.key
CustomLog logs/ssl_request_log \
“%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \”%r\” %b”
</VirtualHost>

Hay tres directivas aquí importantes que debemos tomar en cuenta para la configuración

· ProxyPreserveHost hace que Apache pase la cabecera original del Host al servidor backend. Esto es útil, ya que hace que el servidor backend conozca la dirección utilizada para acceder a la aplicación.

· ProxyPass es la directiva principal de configuración del proxy. En este caso, especifica que todo lo que esté bajo la URL raíz (/) debe ser mapeado al servidor backend en la dirección dada. Por ejemplo, si Apache recibe una petición de /example, se conectará a http://your_backend_server/example y devolverá la respuesta al cliente original.

· ProxyPassReverse debe tener la misma configuración que ProxyPass. Le dice a Apache que modifique las cabeceras de respuesta del servidor backend. Esto asegura que si el servidor backend devuelve un encabezado de redirección de ubicación, el navegador del cliente será redirigido a la dirección del proxy y no a la dirección del servidor backend, lo que no funcionaría como se pretende.