Crear un CA para firmar certificados SSL
Problema: estamos practicando SSL/TLS y queremos ir más allá de los certificados auto-firmados. Además es un incordio estar añadiendo las excepciones de seguridad en los programas cliente, y además quiero usar comodines en los dominios.
Solución: crear una clave privada+certificado de una CA, usarla para firmar certificados, e importar esa CA a Firefox y Thunderbird para que confien en ella.
Procedimiento
Practicamente todo está tomado de este fantástico artículo Crear autoridad certificadora (CA) y certificados autofirmados en Linux. ¡Muchas gracias Antonio Guillen!
Basicamente lo que ves aquí es una simplificación de ese artículo.
Creamos un directorio vacío como base, aquí va a estar la CA.
export BASE='/root/ca' mkdir $BASE cd $BASE
mkdir certs csr crl newcerts private chmod 700 private touch index.txt touch index.txt.attr echo 1000 > serial
Creamos el fichero openssl.conf
, puedes ver el contenido al final.
Creamos la clave privada de la CA
openssl genrsa -aes256 -out ./private/ca.key.pem 4096 chmod 400 ./private/ca.key.pem
Generamos el certificado de la CA (En Common Name ponemos lo que queramos)
URL=luisantolin.com export SAN=DNS:$URL openssl req -config openssl.conf -key private/ca.key.pem -new -x509 -days 7300 -sha256 -extensions v3_ca -out certs/ca.cert.pem chmod 444 certs/ca.cert.pem
Crear una clave privada para nuestro sitio web.
URL="*.miweb.com" DOMINIO=$(echo $URL | sed 's/*\.//g' ) openssl genrsa -out ./private/${DOMINIO}.key.pem 2048 chmod 400 ./private/${DOMINIO}.key.pem
Generar la solicitud de certificado (en Common Name ponemos el DOMINIO)
URL="*.miweb.com" DOMINIO=$(echo $URL | sed 's/*\.//g' ) export SAN=DNS:$URL,DNS:$DOMINIO openssl req -config openssl.conf -key private/${DOMINIO}.key.pem -new -sha256 -out csr/${DOMINIO}.csr.pem
Firmar la solicitud de certificado con la CA
openssl ca -config openssl.conf -policy policy_loose -extensions v3_req -days 3650 -notext -md sha256 -in csr/${DOMINIO}.csr.pem -out certs/${DOMINIO}.cert.pem chmod 444 certs/${DOMINIO}.cert.pem
Convertimos el certificado en DER, por si nos lo piden en ese formato, tenerlo ya
openssl x509 -in certs/${DOMINIO}.cert.pem -out certs/${DOMINIO}.cert.der -outform DER
Ahora hay colocar el certs/DOMINIO.cert.pem y el private/DOMINIO.key.pem al servidor (Apache, o Postfix, o Dovecot), en donde corresponda en cada caso.
Por ultimo hay que importar el certs/ca.cert.pem en los clientes. En Mar-2021, para Firefox Linux y para Thunderbird Linux, en Ubuntu 20.04 LTS el procedimiento es trivial, basta con ir a opciones, buscar certificados, ahi CAs e importar el PEM.
openssl.conf
[ ca ] # man ca default_ca = CA_default [ CA_default ] # Directory and file locations. dir = ./ certs = ./certs crl_dir = ./crl new_certs_dir = ./newcerts database = ./index.txt serial = ./serial RANDFILE = ./private/.rand # The root key and root certificate. private_key = ./private/ca.key.pem certificate = ./certs/ca.cert.pem # For certificate revocation lists. crlnumber = ./crlnumber crl = ./crl/ca.crl.pem crl_extensions = crl_ext default_crl_days = 30 # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 name_opt = ca_default cert_opt = ca_default default_days = 375 preserve = no policy = policy_strict [ policy_strict ] # The root CA should only sign intermediate certificates that match. # See the POLICY FORMAT section of man ca. countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional [ policy_loose ] # Allow the intermediate CA to sign a more diverse range of certificates. # See the POLICY FORMAT section of the ca man page. countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional [ req ] # Options for the req tool (man req). default_bits = 2048 distinguished_name = req_distinguished_name string_mask = utf8only # SHA-1 is deprecated, so use SHA-2 instead. default_md = sha256 # Extension to add when the -x509 option is used. x509_extensions = v3_ca # Extension for SANs req_extensions = v3_req [ v3_req ] # Extensions to add to a certificate request # Before invoke openssl use: export SAN=DNS:value1,DNS:value2 basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment subjectAltName = ${ENV::SAN} [ req_distinguished_name ] # See <https://en.wikipedia.org/wiki/Certificate_signing_request>. countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name localityName = Locality Name 0.organizationName = Organization Name organizationalUnitName = Organizational Unit Name commonName = Common Name emailAddress = Email Address # Optionally, specify some defaults. countryName_default = CO stateOrProvinceName_default = Coruscant localityName_default = Ciudad Galactica 0.organizationName_default = Consejo Jedi organizationalUnitName_default = CJ emailAddress_default = consejo@templo.jedi.org [ v3_ca ] # Extensions for a typical CA (man x509v3_config). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ v3_intermediate_ca ] # Extensions for a typical intermediate CA (man x509v3_config). subjectKeyIdentifier = hash authorityKeyIdentifier = keyid:always,issuer basicConstraints = critical, CA:true, pathlen:0 keyUsage = critical, digitalSignature, cRLSign, keyCertSign [ usr_cert ] # Extensions for client certificates (man x509v3_config). basicConstraints = CA:FALSE nsCertType = client, email nsComment = "OpenSSL Generated Client Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment extendedKeyUsage = clientAuth, emailProtection [ server_cert ] # Extensions for server certificates (man x509v3_config). basicConstraints = CA:FALSE nsCertType = server nsComment = "OpenSSL Generated Server Certificate" subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer:always keyUsage = critical, digitalSignature, keyEncipherment extendedKeyUsage = serverAuth [ crl_ext ] # Extension for CRLs (man x509v3_config). authorityKeyIdentifier=keyid:always [ ocsp ] # Extension for OCSP signing certificates (man ocsp). basicConstraints = CA:FALSE subjectKeyIdentifier = hash authorityKeyIdentifier = keyid,issuer keyUsage = critical, digitalSignature extendedKeyUsage = critical, OCSPSigning