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.