Securizar Apache con mod_md y Let’s Encrypt

Apache incluye un módulo llamado mod_md. Podemos usarlo para el aprovisionamiento de certificados a través del protocolo ACME. Este artículo explica cómo instalar, configurar y poner en marcha Apache con un módulo mod_md para asegurar el tráfico con el certificado gratuito Let’s Encrypt TLS/SSL en un servidor Debian.

mod_md hace dos cosas:

  • Proporciona certificados SSL para sus dominios desde Let’s Encrypt (u otra autoridad certificadora que admita el protocolo ACME).

  • Ofrece un sólido OCSP Stapling de certificados SSL, lo cual es importante para una carga rápida de las páginas en los navegadores modernos.

Ambas funciones trabajan bien juntas, pero se puede utilizar una sin la otra.

Let’s Encrypt es una Autoridad de Certificación (CA) que emplea el protocolo ACME. Es posible usar Let’s Encrypt para emitir certificados TLS/SSL gratuitos para Apache, Nginx y otros servidores. En este tutorial, usarás mod_md para obtener un certificado TLS/SSL gratuito para Apache en Debian y configurarás tu certificado para que se renueve automáticamente también. Nuestro ejemplo de configuración es el siguiente:

  • Dominio – www.dominio.edu.ar

  • Puerto HTTPS – 443

  • Archivo de configuración del host virtual – /etc/apache2/sites-available/www.dominio.edu.ar.conf

Instalar mod_md para Let’s Encrypt

En primer lugar resulta necesario aclarar que el soporte para la versión 2 del protocolo ACME se incorpora con la versión 2.4.41 de Apache httpd.

Podemos verificar la versión instalada con:

$ apache2 -v

ó

$ apachectl -v

Entonces, si la versión es menor a la indicada resulta imprescindible actualizar Apache.

Instalamos Apache y mod_md:

apt install apache2 libapache2-mod-md

Habilitamos los módulos md y ssl:

a2enmod md ssl

Para activar la nueva configuración es necesario reiniciar apache

systemctl reload apache2

Configurar el certificado SSL

Verificamos que Apache está escuchando en el puerto 80:

# netstat -tulpn | grep ':80'
tcp6       0      0 :::80                   :::*                    LISTEN      323897/apache2 

ó

# ss -tulpn | grep ':80'
tcp   LISTEN 0      511                *:80              *:*    users:(("apache2",pid=4002583,fd=4),("apache2",pid=323899,fd=4),("apache2",pid=323898,fd=4),("apache2",pid=323897,fd=4))

Todos los clientes deben conectarse al servidor a través del puerto 80. De lo contrario, no será validado para el certificado Let’s Encrypt. Desde tu escritorio, ejecuta:

curl -I http://www.dominio.edu.ar

La salida del comando curl valida que podemos conectarnos al puerto 80 TCP:

HTTP/1.1 200 OK
Date: Sat, 19 Dic 2020 12:45:43 GMT
Server: Apache/2.4.46 (Debian)
Last-Modified: Wed, 06 May 2020 19:15:29 GMT
ETag: "15e-5a4ff965902a3"
Accept-Ranges: bytes
Content-Length: 350
Vary: Accept-Encoding
Connection: close
Content-Type: text/html

Creamos el archivo de configuración para md

nano /etc/apache2/conf-available/md.conf

Agregamos las directivas mínimas necesarias

# Habilitamos los dominios que serán administrados
MDomain dominio.edu.ar www.dominio.edu.ar

# Agree to the Let’s Encrypt terms of service
MDCertificateAgreement accepted

# Optional: where certs/keys are stored (default: /var/lib/apache2/md)
MDStoreDir /var/lib/apache2/md

MDPrivateKeys RSA 4096

# Correo de contacto para el registro
MDDefaultContacts         "mailto:admin@dominio.edu.ar"

# Autoridad de certificación
MDCA                      "https://acme-v02.api.letsencrypt.org/directory"

MDRequireHttps permanent

# Subdominios
MDomain sub1.dominio.edu.ar
MDomain sub2.dominio.edu.ar
MDomain sub3.dominio.edu.ar

<Location "/md-status">
    SetHandler md-status
    Require ip 127.0.0.1
</Location>

Donde,

  • MDDefaultContacts administrador@dominio.edu.ar: Disponible desde Apache ≥ 2.4.40. mod_md usará esta dirección al registrar tu dominio con la Autoridad de Certificación. Hasta Apache ≤ 2.4.35 se utilizaba la forma MDContactEmail admin@dominio.edu.ar. Es posible definir contactos distintos por dominio.

  • MDCA: Disponible desde Apache ≥ 2.4.48. Indica el endpoint de la Autoridad de Certificación. Hasta Apache ≤ 2.4.43 se utilizaba la forma MDCertificateAuthority https://acme-v02.api.letsencrypt.org/directory. Es posible utilizar https://acme.zerossl.com/v2/DV90, pero implica registro de cuenta en ZeroSSL.

  • MDCertificateAgreement accepted: Es necesario aceptar las condiciones del Acuerdo de suscripción

  • MDomain www.dominio.edu.ar: Declarar un nombre de dominio que debe ser administrado por mod_md para emitir y renovar certificados. Se puede usar un nombre de dominio completo como www.dominio.edu.ar o dominio.edu.ar. Asegúrate de que coincide con ServerAlias.

  • MDPrivateKeys RSA 4096: Establece el tipo y el tamaño de las claves privadas generadas.

  • MDRequiereHttps: Fuerza la redirección a HTTPS

Opcional,

  • MDRenewWindow : Si no se especifica, el valor predeterminado es 33%. Si la validez de los certificados cae por debajo de la duración especificada, mod_md obtendrá nuevos certificados. Cada certificado tiene una validez de 90 días, el 33% son 30 días. Para establecerlo por días, especifique d.

Habilitamos el módulo

a2enconf md

Editamos /etc/apache2/sites-available/www.dominio.edu.ar.conf:

# En caso que no hayamos definido subdominio en la configuración de mod_md, descomentar esta linea. 
# MDomain ventana.edu.ar
# Y la siguiente es para tener un contacto específico para este dominio
# MDDefaultContacts "mailto:ventana@midominio.edu.ar"

  <VirtualHost *:443>
     ServerName dominio.edu.ar

     SSLEngine on
     Protocols h2 http/1.1

     DocumentRoot /var/www/dominio.edu.ar
     <Directory "/var/www/dominio.edu.ar">
        Options FollowSymLinks
        AllowOverride All
        Require all granted
     </Directory>

     ErrorLog ${APACHE_LOG_DIR}/error_dominio.edu.ar.log
     CustomLog ${APACHE_LOG_DIR}/access_dominio.edu.ar.log combined
  </VirtualHost>

Para incrementar el nivel de seguridad, y dado que muchas prácticas de TLS/SSL evolucionan rápido, siempre se recomienda verificar que la configuración de nuestro servidor usando las recomendaciones de Mozilla o SSL Labs Best Practices.

Activar mod_rewrite y mod_headers de Apache

Ya hemos declarado una regla de reescritura en nuestra configuración, así que necesitamos varios módulos. Por lo tanto:

a2enmod rewrite headers md http2
To activate the new configuration, you need to run:
systemctl restart apache2

Comprobamos si hay errores de configuración

apache2ctl configtest
Syntax OK

Obtener un certificado SSL usando mod_md

Hasta ahora, instalamos el mod_md para Apache, habilitamos todos los módulos esenciales. Es hora de reiniciar nuestro servidor Apache para obtener el certificado TLS/SSL.

systemctl restart apache2

Tan pronto como Apache 2 se reinicie, mod_md solicitará un certificado para el dominio a la Autoridad de Certificación. Normalmente tarda hasta un minuto. Se puede comprobar el registro de errores del servidor o la página de mod_status de Apache para ver si la petición ha sido satisfactoria o no. Esto lo que muestra archivo error.log:

tail -f /var/log/apache2/error.log

También puedes usar el comando grep:

grep 'The Managed Domain' /var/log/apache2/error.log

El siguiente ejemplo indica que LE nos ha expedido un certificado gratuito de TLS/SSL:

[Wed Dic 19 10:17:38.112849 2020] [md:notice] [pid 21777:tid 139807872861952] AH10059: The Managed Domain www.dominio.edu.ar has been setup and changes will be activated on next (graceful) server restart. Por supuesto que también podemos visitar la url estado del servidor.

Reiniciamos el servidor Apache 2 para activar el certificado:

systemctl reload apache2

Probar la conexión segura de Apache

Todo lo que tienes que hacer es escribir el siguiente comando o usar un navegador web para asegurarte de que estás recibiendo una conexión HTTPS:

curl -I https://www.dominio.edu.ar

Otra alternativa es utilizar el servicio de prueba de servidores de SSL Labs.

Monitoreo de estado de certificados

Ahora que configuramos Apache con mod_md y conseguimos un certificado TLS/SSL, es hora de monitorear el estado de nuestro certificado.

https://www.dominio.edu.ar/server-status

ó

curl https://www.dominio.edu.ar/md-status
{
  "version": "2.4.45",
  "managed-domains": [
    {
      "name": "www.dominio.edu.ar",
      "domains": [
        "www.dominio.edu.ar",
        "web.dominio.edu.ar"
      ],
      "contacts": [
        "mailto:administrador@dominio.edu.ar"
      ],
      "transitive": 1,
      "ca": {
        "proto": "ACME",
        "url": "https://acme-v02.api.letsencrypt.org/directory",
        "agreement": "accepted"
      },
      "state": 2,
      "renew-mode": 1,
      "renew-window": "33%",
      "warn-window": "10%",
      "must-staple": false,
      "cert": {
        "valid-from": "Wed, 19 Dec 2020 12:17:37 GMT",
        "valid-until": "Tue, 19 Mar 2021 12:17:37 GMT",
        "serial": "040E339A0A7D2224819A550BBB4596279F67",
        "sha256-fingerprint": "d78933fa946cb71810111876049defa4feb6820c319c69918ba925b463bbd11c"
      },
      "renew": false
    }
  ]
}

¿Dónde están mis archivos de certificados TLS/SSL?

Es necesario listar el contenido del directorio /etc/apache2/md:

# ls -l /etc/apache2/md/

Veremos los archivos de la siguiente manera:

total 76K
drwxr-xr-x   9 root     root 4,0K sep 11 14:01 .
drwxr-xr-x   9 root     root 4,0K sep 10 19:44 ..
drwxr-xr-x   3 root     root 4,0K dic 19  2020 accounts
drwx------ 716 root     root  36K oct 14 00:00 archive
drwxr-xr-x   2 www-data root 4,0K oct 13 16:56 challenges
drwx------  25 root     root 4,0K oct 14 00:00 domains
-rw-------   1 root     root  116 dic 19  2020 md_store.json
drwxr-x---   2 www-data root 4,0K dic 19  2020 ocsp
drwxr-xr-x   5 www-data root 4,0K oct 14 00:00 staging
drwx------  35 root     root 4,0K oct 14 00:00 tmp

Listamos el directorio de dominios:

# ls -l /etc/apache2/md/www.dominio.edu.ar

Aquí están los archivos TLS/SSL para tu dominio:

total 28K
drwx------  2 root root 4,0K sep 11 13:56 .
drwx------ 25 root root 4,0K oct 14 00:00 ..
-rw-------  1 root root 7,5K sep 10 16:54 job.json
-rw-------  1 root root  744 sep 11 13:56 md.json
-rw-------  1 root root 3,2K sep 10 16:54 privkey.pem
-rw-------  1 root root 3,9K sep 10 16:54 pubcert.pem

Generador de configuración SSL de moz://a

En este enlace podrás obtener los detalles de configuración necesarios para tu sistema. Solo deberás escoger el tipo de servidor web, su versión y la del certificado OpenSSL.