Configuración de Certificados SSL para Servidores Web

Obtención Automática de Certificados Let's Encrypt

Aplicable a sistemas Linux

Instalación de Certbot

# Actualizar repositorios
sudo apt-get update

# Para servidores con Nginx
sudo apt-get install certbot python3-certbot-nginx

# Para servidores con Apache
sudo apt-get install certbot python3-certbot-apache

Generación e Instalación del Certificado

# Con Nginx
sudo certbot --nginx

# Con Apache
sudo certbot --apache

Durante el proceso, se solicitará:

  • Dirección de correo electrónico para notificaciones
  • Aceptación de los términos del servicio
  • Opción de compartir datos con la EFF
  • Selección de dominios a proteger (permite múltiples)

Configuración de Renovación Automática

Los certificados Let's Encrypt tienen una validez de 90 días. Se recomienda configurar una tarea de renovación automática. Certbot crea una tarea cron por defecto. Para verificar su funcionamiento:

sudo certbot renew --dry-run

Obtención Manual de Certificados Let's Encrypt

sudo apt-get update
sudo apt-get install certbot
sudo certbot certonly --standalone -d midominio.com

Los certificados generados se almacenan en /etc/letsencrypt/live/midominio.com/. Posteriormente, es necesario configurar el servidor web apuntando a dichos archivos.

Para la renovación periódica, editar el crontab:

sudo crontab -e

Agregar la siguiente línea para ejecutar la renovación a medianoche diariamente:

0 0 * * * certbot renew --quiet

Creación de Certificados Autofirmados

Archivo de Extensiones del Dominio

El archivo ext_dominio.conf define las extensiones del certificado:

authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @nombres_alternativos

[nombres_alternativos]
DNS.1 = localhost
IP.2 = 127.0.0.1
IP.3 = 192.168.1.50
DNS.4 = *.ejemplo.local
DNS.5 = panel.ejemplo.local
DNS.6 = api.ejemplo.local

Las entradas IP permiten certificar direcciones IP específicas, mientras que las entradas DNS sirven para nombres de dominio. Se pueden incluir múltiples de ambas.

Script de Generación de Certificados

Ejecución: sudo ./generar_certificado.sh api.ejemplo.local

#!/bin/bash

# Estructura de directorios
CARPETA_RAIZ="certificados"
CARPETA_CA="$CARPETA_RAIZ/autoridad"
CARPETA_CERTS="$CARPETA_RAIZ/sitios"

mkdir -p "$CARPETA_CA" "$CARPETA_CERTS"

# Validar argumento
SITIO="$1"
if [ -z "$SITIO" ]; then
    echo "Uso: $0 <dominio>"
    exit 1
fi

# Rechazar comodines
if [[ "$SITIO" == *"*."* ]]; then
    echo "Los certificados con comodines generan advertencias de seguridad"
    exit 1
fi

CORREO="admin@empresa.com"
IDENTIFICADOR="$SITIO"
NOMBRE_CA="raiz-$IDENTIFICADOR"

cd "$CARPETA_CA"

# Crear clave privada de la CA con protección
openssl genrsa -des3 -out "$NOMBRE_CA.key" 2048

# Generar certificado raíz (válido 10 años)
openssl req -x509 -new -nodes -key "$NOMBRE_CA.key" -sha256 \
    -days 3650 -out "$NOMBRE_CA.crt" \
    -subj "/CN=$SITIO/O=Miservicios/OU=Infraestructura/L=Madrid/ST=Madrid/C=ES/emailAddress=$CORREO"

cd "../$CARPETA_CERTS"

# Generar clave privada del sitio
openssl genrsa -out "$IDENTIFICADOR.key" 2048

# Crear solicitud de firma (CSR)
openssl req -new -key "$IDENTIFICADOR.key" -out "$IDENTIFICADOR.csr" \
    -subj "/CN=$SITIO/O=Miservicios/OU=Infraestructura/L=Madrid/ST=Madrid/C=ES/emailAddress=$CORREO"

# Firmar el certificado con la CA (válido 10 años)
openssl x509 -req -in "$IDENTIFICADOR.csr" -out "$IDENTIFICADOR.crt" \
    -days 3650 -CA "../$CARPETA_CA/$NOMBRE_CA.crt" \
    -CAkey "../$CARPETA_CA/$NOMBRE_CA.key" -CAcreateserial \
    -extfile "../ext_dominio.conf"

# Mostrar información del certificado
openssl x509 -in "$IDENTIFICADOR.crt" -noout -text

# Verificar cadena de confianza
openssl verify -CAfile "../$CARPETA_CA/$NOMBRE_CA.crt" "$IDENTIFICADOR.crt"

echo "Proceso completado exitosamente."

Script para Imporatr en Windows

Archivo instalar_raiz.bat para agregar la CA al almacén de certificados de Windows:

@echo off
chcp 65001 > nul

for %%f in (autoridad\*.crt) do (
    echo Procesando %%f
    C:\Windows\System32\certutil -store Root | findstr /C:"%%~nf" > nul
    if errorlevel 1 (
        C:\Windows\System32\certutil -addstore -f "Root" "%%f"
        echo Importado correctamente
    ) else (
        echo %%f ya existe en el almacén, omitiendo
    )
)

echo.
echo Instalación finalizada
pause

Configuración de Nginx con SSL

servidor {
    escuchar 443 ssl;

    ssl_certificate /var/certificados/sitios/api.ejemplo.local.crt;
    ssl_certificate_key /var/certificados/sitios/api.ejemplo.local.key;

    ssl_session_timeout 10m;
    ssl_session_cache shared:SSL:100m;
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers on;

    nombre_servidor api.ejemplo.local;

    raiz /var/www/aplicacion/publico;

    indice index.php index.html;

    # Proxy para conexiones WebSocket
    ubicacion /ws {
        proxy_pass http://127.0.0.1:9090;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "Upgrade";
        proxy_set_header X-Cliente-Real $remote_addr;
    }

    # Archivos estáticos
    ubicacion ~ ^/(recursos|archivos)/ {
        try_files $uri =404;
    }

    # Enrutamiento principal
    ubicacion / {
        try_files $uri $uri/ /index.php?$query_string;
    }

    # Manejo de PHP
    fastcgi_read_timeout 300s;
    ubicacion ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/run/php/php8.3-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
}

La configuración mostrada utiliza directivas con nombres en español para mayor claridad, aunque Nginx requiere las directivas originales en inglés. Adapte los valores según su entorno de producción.

Etiquetas: SSL Let's Encrypt Certbot Nginx Certificados TLS

Publicado el 6-2 06:25