--- title: "Cómo gestionar certificados SSL/TLS con OpenSSL en Linux" description: "Genera claves y CSR con OpenSSL, crea certificados autofirmados y una CA interna, convierte formatos, verifica cadenas y controla la caducidad en Ubuntu 24.04." category: "Seguridad del Servidor" language: es source: https://cubepath.com/es/docs/seguridad-del-servidor/gestion-de-certificados-ssl-tls-con-openssl updated: 2026-09-25 --- # Cómo gestionar certificados SSL/TLS con OpenSSL en Linux OpenSSL es la herramienta de línea de comandos estándar para trabajar con claves privadas y certificados X.509 en Linux. En este tutorial usarás OpenSSL 3 en Ubuntu 24.04 para generar una clave privada, crear una solicitud de firma de certificado (CSR) con nombres alternativos, emitir un certificado autofirmado, montar una pequeña CA interna para tus servicios privados, instalar el certificado en Nginx, convertir entre formatos y comprobar fechas, cadenas y coincidencia de claves. Para sitios públicos lo habitual es obtener certificados gratuitos y automáticos de Let's Encrypt con Certbot. OpenSSL sigue siendo imprescindible para generar CSR para una CA comercial, para servicios internos y para diagnosticar cualquier problema de certificados. ## Requisitos previos - Un servidor con Ubuntu 24.04 LTS, por ejemplo un VPS de CubePath. OpenSSL viene instalado por defecto. - Un usuario no root con privilegios `sudo`. - Para la parte de Nginx: Nginx instalado y el puerto 443 abierto en el firewall (`sudo ufw allow 'Nginx Full'`). - Un nombre de dominio o nombre interno para el certificado. En los ejemplos se usa `your_domain`; sustitúyelo por el tuyo. Comprueba la versión de OpenSSL: ```bash openssl version ``` ```output OpenSSL 3.0.13 30 Jan 2024 (Library: OpenSSL 3.0.13 30 Jan 2024) ``` Trabaja en un directorio propio con permisos restringidos: ```bash mkdir -p ~/certs && chmod 700 ~/certs && cd ~/certs ``` ## Paso 1: Generar una clave privada La clave privada es el secreto del certificado: quien la tenga puede suplantar tu servidor. Genera una clave ECDSA P-256, que es rápida y compatible con todos los navegadores y clientes actuales: ```bash openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -out your_domain.key chmod 600 your_domain.key ``` Si necesitas compatibilidad con clientes muy antiguos, genera en su lugar una clave RSA de 3072 bits: ```bash openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:3072 -out your_domain.key ``` Comprueba que la clave es válida: ```bash openssl pkey -in your_domain.key -noout -text | head -n 1 ``` ```output Private-Key: (256 bit) ``` > Nota: estas claves no llevan frase de contraseña, porque el servidor web necesita leerlas al arrancar sin intervención. La protección es el permiso `600` y que el archivo nunca salga del servidor. ## Paso 2: Crear una solicitud de firma de certificado (CSR) La CSR contiene la clave pública y los nombres para los que quieres el certificado. Es lo que se envía a la CA. Los navegadores solo validan el campo **Subject Alternative Name (SAN)**, no el `CN`, así que incluye ahí todos los nombres: ```bash openssl req -new -key your_domain.key -out your_domain.csr \ -subj "/C=ES/O=Tu Empresa/CN=your_domain" \ -addext "subjectAltName=DNS:your_domain,DNS:www.your_domain" ``` Revisa el contenido y verifica la firma de la CSR: ```bash openssl req -in your_domain.csr -noout -subject -verify openssl req -in your_domain.csr -noout -text | grep -A1 'Subject Alternative Name' ``` ```output Certificate request self-signature verify OK subject=C = ES, O = Tu Empresa, CN = your_domain X509v3 Subject Alternative Name: DNS:your_domain, DNS:www.your_domain ``` Si vas a usar una CA comercial, envía el contenido de `your_domain.csr` (nunca la clave) en su formulario. Te devolverá el certificado y normalmente uno o varios certificados intermedios. ## Paso 3: Crear un certificado autofirmado Un certificado autofirmado sirve para pruebas y entornos de desarrollo. Los navegadores mostrarán un aviso porque nadie de confianza lo ha firmado. Puedes crear clave y certificado en un solo comando: ```bash openssl req -x509 -newkey ec -pkeyopt ec_paramgen_curve:P-256 -noenc \ -keyout selfsigned.key -out selfsigned.crt -days 365 \ -subj "/CN=your_domain" \ -addext "subjectAltName=DNS:your_domain" ``` La opción `-noenc` deja la clave sin cifrar y `-days` fija la validez. Comprueba el resultado: ```bash openssl x509 -in selfsigned.crt -noout -subject -issuer -dates ``` ```output subject=CN = your_domain issuer=CN = your_domain notBefore=Sep 25 10:12:03 2026 GMT notAfter=Sep 25 10:12:03 2027 GMT ``` Emisor y sujeto son iguales: esa es la señal de un certificado autofirmado. ## Paso 4: Montar una CA interna para servicios privados Si tienes varios servicios internos (paneles, APIs privadas, bases de datos con TLS), es mejor crear tu propia autoridad certificadora, instalarla como confiable en tus máquinas y firmar con ella los certificados. Así evitas los avisos sin depender de una CA pública. Crea la clave de la CA. Esta sí debe llevar frase de contraseña, porque solo la usarás al firmar: ```bash openssl genpkey -algorithm EC -pkeyopt ec_paramgen_curve:P-256 -aes-256-cbc -out ca.key chmod 600 ca.key ``` Crea el certificado raíz de la CA, válido diez años: ```bash openssl req -x509 -new -key ca.key -sha256 -days 3650 -out ca.crt -subj "/O=Tu Empresa/CN=Tu Empresa CA interna" ``` Comprueba que tiene la marca de CA: ```bash openssl x509 -in ca.crt -noout -ext basicConstraints ``` ```output X509v3 Basic Constraints: critical CA:TRUE ``` Para firmar el certificado del servidor, crea un archivo con las extensiones que debe llevar: ```bash nano your_domain.ext ``` ```ini basicConstraints = CA:FALSE keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth subjectAltName = DNS:your_domain, DNS:www.your_domain ``` Firma la CSR del paso 2 con la CA. OpenSSL pedirá la frase de contraseña de `ca.key`: ```bash openssl x509 -req -in your_domain.csr -CA ca.crt -CAkey ca.key -CAcreateserial \ -out your_domain.crt -days 397 -sha256 -extfile your_domain.ext ``` La validez de 397 días coincide con el máximo que aceptan los navegadores para certificados de servidor. Verifica que el certificado está firmado por tu CA: ```bash openssl verify -CAfile ca.crt your_domain.crt ``` ```output your_domain.crt: OK ``` Para que las máquinas de tu red confíen en esta CA, copia `ca.crt` (nunca `ca.key`) a cada una y añádela al almacén del sistema. En Ubuntu y Debian: ```bash sudo cp ca.crt /usr/local/share/ca-certificates/tu-empresa-ca.crt sudo update-ca-certificates ``` ```output Updating certificates in /etc/ssl/certs... 1 added, 0 removed; done. ``` > Importante: guarda `ca.key` fuera del servidor, en un lugar cifrado. Quien la obtenga puede emitir certificados válidos para cualquier nombre en las máquinas que confíen en tu CA. ## Paso 5: Instalar el certificado en Nginx Coloca la clave y el certificado en las rutas estándar de Ubuntu. Si tu CA te entregó certificados intermedios, Nginx necesita el certificado del servidor seguido de los intermedios en un único archivo: ```bash cat your_domain.crt intermediate.crt > your_domain.fullchain.crt ``` Con la CA interna del paso anterior no hay intermedios, así que basta con copiar `your_domain.crt`. Instala los archivos con los permisos correctos: ```bash sudo install -m 644 your_domain.crt /etc/ssl/certs/your_domain.crt sudo install -m 600 -o root -g root your_domain.key /etc/ssl/private/your_domain.key ``` Edita el bloque `server` de tu sitio: ```bash sudo nano /etc/nginx/sites-available/your_domain ``` ```nginx server { listen 443 ssl; listen [::]:443 ssl; http2 on; server_name your_domain www.your_domain; ssl_certificate /etc/ssl/certs/your_domain.crt; ssl_certificate_key /etc/ssl/private/your_domain.key; ssl_protocols TLSv1.2 TLSv1.3; root /var/www/html; } ``` Si usas una cadena con intermedios, apunta `ssl_certificate` al archivo `fullchain`. Valida y recarga: ```bash sudo nginx -t sudo systemctl reload nginx ``` ## Paso 6: Verificar un certificado en un servidor `openssl s_client` se conecta al servidor igual que un navegador y muestra el certificado que entrega. La opción `-servername` envía el nombre por SNI, imprescindible cuando hay varios sitios en la misma IP: ```bash openssl s_client -connect your_domain:443 -servername your_domain /dev/null | openssl x509 -noout -subject -issuer -dates ``` Para ver la cadena completa y el resultado de la verificación: ```bash openssl s_client -connect your_domain:443 -servername your_domain -showcerts /dev/null | grep -E 'Verify return code|^ [0-9] s:' ``` ```output 0 s:CN = your_domain Verify return code: 0 (ok) ``` Un código distinto de `0` indica el problema, por ejemplo `21 (unable to verify the first certificate)` cuando falta el intermedio. Con la CA interna, añade `-CAfile ca.crt` si la máquina desde la que compruebas aún no confía en ella. ## Paso 7: Comprobar que clave, CSR y certificado coinciden Un error clásico es instalar un certificado con una clave que no le corresponde; Nginx fallará con `key values mismatch`. Compara el hash de la clave pública de cada archivo: ```bash openssl pkey -in your_domain.key -pubout | sha256sum openssl req -in your_domain.csr -noout -pubkey | sha256sum openssl x509 -in your_domain.crt -noout -pubkey | sha256sum ``` Los tres hashes deben ser idénticos. ## Paso 8: Convertir entre formatos Cada plataforma espera un formato distinto. Estas son las conversiones más habituales: | Formato | Extensiones | Uso típico | |---|---|---| | PEM | `.pem`, `.crt`, `.key` | Texto Base64. Nginx, Apache, HAProxy. | | DER | `.der`, `.cer` | Binario. Java y algunos dispositivos. | | PKCS#12 | `.pfx`, `.p12` | Clave, certificado y cadena en un archivo protegido. Windows, IIS. | PEM a DER y vuelta: ```bash openssl x509 -in your_domain.crt -outform der -out your_domain.der openssl x509 -in your_domain.der -inform der -out your_domain.pem ``` Empaquetar clave, certificado y cadena en PKCS#12 (pedirá una contraseña de exportación): ```bash openssl pkcs12 -export -out your_domain.pfx -inkey your_domain.key -in your_domain.crt -certfile ca.crt ``` Extraer de un `.pfx` el certificado y la clave por separado: ```bash openssl pkcs12 -in your_domain.pfx -clcerts -nokeys -out extraido.crt openssl pkcs12 -in your_domain.pfx -nocerts -noenc -out extraido.key chmod 600 extraido.key ``` ## Paso 9: Controlar la caducidad Un certificado caducado deja el servicio inaccesible para los clientes. La opción `-checkend` comprueba si caduca dentro de un número de segundos y devuelve un código de salida, así que es ideal para scripts. Por ejemplo, para 30 días: ```bash openssl x509 -in /etc/ssl/certs/your_domain.crt -noout -checkend 2592000 ``` ```output Certificate will not expire ``` Si faltan menos de 30 días, imprime `Certificate will expire` y sale con código `1`. Puedes usarlo en tu sistema de monitorización o en una tarea programada que te avise. Para certificados públicos, la solución definitiva es la renovación automática con Certbot. ## Solución de problemas **`key values mismatch` al recargar Nginx.** La clave no corresponde al certificado. Compara los hashes del paso 7 y usa la clave con la que generaste la CSR. **El navegador dice que el certificado no es válido para el nombre.** El nombre no está en el SAN. Revisa con `openssl x509 -in your_domain.crt -noout -ext subjectAltName` y vuelve a emitir el certificado con todos los nombres. **`unable to get local issuer certificate` o `Verify return code: 21`.** Falta el certificado intermedio en la cadena. Crea el archivo `fullchain` del paso 5 con el certificado del servidor primero y los intermedios después. **Nginx no arranca con `Permission denied` al leer la clave.** Nginx lee la clave como root al arrancar; comprueba que el archivo existe en la ruta indicada y que pertenece a `root` con permisos `600`. ## Conclusión Has generado claves y CSR con SAN, creado certificados autofirmados y una CA interna, instalado un certificado en Nginx, verificado cadenas y coincidencia de claves, convertido entre formatos y comprobado la caducidad con OpenSSL. Con estos comandos puedes diagnosticar prácticamente cualquier problema de certificados. Como siguientes pasos puedes: - Obtener certificados públicos gratuitos y renovarlos automáticamente con Certbot y Let's Encrypt. - Endurecer la configuración TLS de Nginx con HSTS y OCSP stapling. - Añadir la comprobación de caducidad de tus certificados a tu sistema de monitorización.