Grup 3 - Implementar HTTPS i HSTS (HTTPS only) (Azure)

De Wiket
Salta a la navegació Salta a la cerca

Tornar a Projecte IETI Cloud - Grup 3.

Tasca

27. Implementar HTTPS i HSTS (HTTPS only) sobre el cloud extern (Azure).

Informe

Modificarem els nostres serveis de Docker desplegats sobre la màquina virtual d'Azure per tal d'implementar els canvis necessaris per a establir connexions HTTPS amb HSTS.

Enregistrament d'un nom de domini

Per començar a configurar l'HTTPS del nostre servidor haurem d'enregistrar un nom de domini. Utilitzarem Freenom per adquirir un nom de domini (grup3ieti.tk) pel nostre servidor Azure. Utilitzarem l'opció de DNS dins de Freenom per associar aquest nom de domini a l'adreça IP de la nostra màquina virtual d'Azure.

Panell d'administració de Freenom


Per tal de gestionar els certificats SSL i diferents serveis que tindrem disponibles des de Docker, farem ús de subdominis dins de grup3ieti.tk per tal de reencaminar cap al servei corresponent mitjançant un reverse proxy. Per aconseguir això hem d'afegir dos registres més al DNS de Freenom per tal de dirigir al tràfic als subdominis. Utilitzarem el subdomini classroom.grup3ieti.tk per l'aplicació classVRroom i wordpress.grup3ieti.tk per la pàgina d'higiene postural.

Registres dins el DNS de Freenom


Implementació d'un Reverse Proxy amb Docker

Donada la limitació d'infraestructura al voltant d'Azure, haurem de desplegar tots els serveis en una sola màquina virtual. És per això que podem aprofitar l'ús d'un reverse proxy per tal de redirigir les peticions cap al port dels diferents serveis dockeritzats dins la maquina virtual d'Azure. D'aquesta manera podem també instal·lar un únic certificat dins l'Apache que farà de reverse proxy, de manera que la comunicació entre els clients i la màquina Azure sigui estigui protegida.

En primer lloc, necessitarem un servidor Apache instal·lat amb els mòduls necessaris habilitats. Per tal de facilitar i automatitzar lleugerament el desplegament d'un reverse proxy farem ús d'un contenidor Docker, construït però des d'un Dockerfile personalitzat. Per tal de crear aquesta Dockerfile personalitzada ens hem basat en una imatge de Docker Hub que acompleix un propòsit molt similar al que nosaltres necessitem.

L'estructura proposada per aquest sistema de desplegament, quedarà doncs de la següent manera:

.
├── Dockerfile
├── docker-compose.yml
└── proxy-conf
    ├── sites
    │   ├── site1.conf
    │   └── site2.conf
    └── start.sh

Dins el directori proxy-conf disposarem d'una script (start.sh) que executarà les tasques d'activació de les configuracions dins del subdirectori sites.

 1 #!/bin/bash
 2 
 3 #Copy sites to Apache2 directory
 4 cp /opt/proxy-conf/sites/*.conf /etc/apache2/sites-available
 5 
 6 #Enable all sites
 7 ls /etc/apaceh2/sites-available/ -1A | a2ensite *.conf
 8 
 9 #Apache gets grumpy about PID files pre-existing
10 rm -f /var/run/apache2/apache2.pid
11 
12 #Launch Apache2 on Foreground
13 /usr/sbin/apache2ctl -D FOREGROUND

Seguidament, el nostre Dockerfile partirà des de la imatge Debian Bullseye, on instal·larem tots els serveis necessaris i activarem els mòduls d'Apache requerits pel nostre projecte. Després mourem el directori proxy-conf des del directori del projecte fins a /opt/proxy-conf, des d'on finalment executarem l'script start.sh per tal de dur a terme el trasllat dels fitxers i la seva activació.

 1 #Base new image on Debian Bullseye
 2 FROM debian:bullseye as build
 3 
 4 #Update, then install Apache2 and other useful tools
 5 RUN set -eux; \
 6         apt update; \
 7         apt install -y \
 8                 apache2 \
 9                 nano
10 
11 #Disable Apache2 default site and remove all configuration files from sites-available
12 RUN set -eux; \
13         a2dissite 000-default.conf; \
14         rm -f /etc/apache2/sites-available/*.conf
15 
16 #Enable required Apache2 modules then stop Apache2 service
17 RUN set -eux; \
18         a2enmod proxy; \
19         a2enmod proxy_http; \
20         a2enmod ssl; \
21         a2enmod rewrite; \
22         a2enmod headers; \
23         service apache2 stop
24 
25 #Expose ports 80 for HTTP and 443 for HTTPS
26 EXPOSE 80 443
27 
28 #Copy the contents of proxy-conf to /opt/proxy-conf
29 COPY ./proxy-conf /opt/proxy-conf
30 #Make start.sh executable then run it as entry point
31 RUN chmod +x /opt/proxy-conf/start.sh
32 ENTRYPOINT ["/opt/proxy-conf/start.sh"]

Finalment, haurem d'afegir aquest Dockerfile com un servei més dins el nostre docker-compose.yml. Afegirem 3 bind volumes: el directori de letsencrypt, per tal de tenir accés als certificats generats amb Certbot; el fitxer /etc/timezone, per tal de sincronitzar la zona horària amb la màquina virtual d'Azure; i el fitxer /etc/localtime, per tal de sincronitzar també l'hora i dia de la màquina Azure.

 1 proxy:
 2      depends_on:
 3        - wp
 4      build: .
 5      image: local/apache-proxy:v1
 6      restart: unless-stopped
 7      volumes:
 8        - /etc/letsencrypt:/opt/ssl
 9        - /etc/timezone:/etc/timezone:ro
10        - /etc/localtime:/etc/localtime:ro
11      ports:
12        - "80:80"
13        - "443:443"

Un cop tenim aquesta estructura funcionant dins el nostre projecte, podem afegir fitxers de configuració de sites d'Apache dins la carpeta proxy-conf ➡ sites i aquests es carregaran automàticament quan aixequem els contenidors mitjançant un docker-compose up -d --build.

Configuració d'un site amb Reverse Proxy

Com estem configurant els nostres serveis mitjançant subdominis, farem servir virtual hosts on utilitzarem la directiva ServerName per tal d'encaminar els clients cap al contenidor corresponent. El nostre site de WordPress constarà doncs de 2 virtual hosts: un pel port 80, des del qual reescriurem tot al tràfic cap al port 443; i un pel port 443, on certificarem la connexió i l'encaminarem cap al contenidor de WordPress (reverse proxy).

 1 <VirtualHost *:80>
 2         ServerName grup3ieti.tk
 3         ServerAlias wordpress.grup3ieti.tk
 4 
 5         RewriteEngine On
 6         RewriteCond %{SERVER_NAME} =wordpress.grup3ieti.tk
 7         RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
 8 </VirtualHost>
 9 <VirtualHost *:443>
10         ServerName grup3ieti.tk
11         ServerAlias wordpress.grup3ieti.tk
12 
13         Header always set Strict-Transport-Security "max-age=15780000; includeSubDomains"
14 
15         SSLEngine On
16         SSLProxyEngine On
17         SSLCertificateFile /opt/ssl/live/grup3ieti.tk/fullchain.pem
18         SSLCertificateKeyFile /opt/ssl/live/grup3ieti.tk/privkey.pem
19         Include /opt/ssl/options-ssl-apache.conf
20 
21         RequestHeader set X-Forwarded-Proto https
22         ProxyPreserveHost On
23 
24         ProxyPass / http://wp/
25         ProxyPassReverse / http://wp/
26 
27         ErrorLog ${APACHE_LOG_DIR}/wordpress.grup3ieti.tk-error.log
28         CustomLog ${APACHE_LOG_DIR}/wordpress.grup3ieti.tk-access.log combined
29 </VirtualHost>

En el virtual host del port 80, simplement reescriurem totes les connexions cap a la mateixa URL però amb HTTPS, tot mitjançant les directives RewriteCond i RewriteRule. En el virtual host del port 443, afegim les següents directives per una varietat de propòsits:

  • Header always set Strict-Transport-Security — Aquesta directiva força el mode HSTS pel nostre site. El valor max-age representa cada quant un navegador haurà de comprovar si el nostre site continua emprant HSTS. El valor includeSubDomains aplicara aquesta directiva també a tots els subdominis.
  • RequestHeader set X-Forwarded-Proto https — Aquesta directiva afegeix la capçalera X-Forwarded-Proto amb el valor https, útil quan tractem amb la imatge de WordPress per Docker, que habilita la càrrega de recursos mitjançant HTTPS trobar aquesta capçalera.
  • ProxyPreserveHost — Aquesta directiva serveix per instruir a l'Apache que preservi les capçaleres del host original quan construeix la petició de cara al servei objectiu del reverse proxy.
  • ProxyPass i ProxyPassReverse — Aquestes dues directives apunten cap a la direcció on el reverse proxy ha d'encaminar la petició. Com hem estructurat el projecte completament amb Docker, podem utilitzar directament el nom del servei com a direcció valida.

Generació de certificats SSL amb Certbot

Per tal de disposar de certificats SSL signats per una autoritat reconeguda hem utilitzat LetsEncrypt mitjançant Certbot. Els certificats generats per Certbot es guarden dins /etc/letsencrypt/live/(nom de domini)/, ruta sobre la qual apliquem un bind mount dins el docker-compose.yml per poder accedir als certificats des de /opt/ssl/. Per generar els certificats em d'assegurar que els nostres subdominis estiguin inclosos, d'altra manera alguns navegadors podrien invalidar el certificat d'un subdomini per no trobar-hi una coincidència exacta.

certbot certonly -d grup3ieti.tk,www.grup3ieti.tk,wordpress.grup3ieti.tk,classroom.grup3ieti.tk

Un cop finalitzada la comanda anterior, podrem accedir a les claus pel nostre domini des del directori /opt/ssl/live/grup3ieti.tk/ en els fitxers de configuració dels sites d'Apache.

Referències