V tomto krátkém článku si ukážeme, jak si vygenerovat vlastní certifikační autoritu a s její pomocí podepisovat vlastní self-signed certifikáty, které budou mít vyplněné subjectAltName (Subject Alternative Name) a díky tomu budou v pořádku fungovat v Chromu 58 a vyšším. Hodit se vám to bude hlavně pro vývoj, kdy si chceme lokálně zprovoznit https připojení a chceme, aby se tvářilo jako důvěryhodné. Ale případně si takto můžeme generovat certifikáty třeba i pro intranetové domény a v nejhorším případě i pro veřejné domény.
Proč se vůbec dělat s vlastní certifikační autoritou a nevytvářet pouze vlastní self-signed certifikáty? Hlavní výhoda je, že do systému/prohlížeče (třeba Firefox má vlastní úložiště certifikátů) stačí naimportovat certifikát certifikační autority a pak všechny podepsané certifikáty touto autoritou budou automaticky důvěryhodné. Podotýkám, že nejsem bezpečnostní ani linux expert a pouze jsem pospojoval návody, které jsem našel do funkčního celku. Je tedy možné, že něco by šlo řešit elegantněji, případně nebudu používat úplně správnou terminologii. Nebojte se mě opravit v komentářích 🙂 Tento návod je funkční minimálně na Debianu Jessie a Stretch, ale je dost pravděpodobné, že poběží na více systémech.
Nejprve si vygenerujeme certifikační autoritu. Zde jsou dvě možnosti, pokud chceme a nebo nechceme mít soukromý klíč chráněný heslem. Jde o zjednodušený návod z https://datacenteroverlords.com/2012/03/01/creating-your-own-ssl-certificate-authority/. Pokud nechceme mít soukromí klíč chráněný heslem, použijeme příkaz:
sudo openssl genrsa -out /etc/ssl/private/rootCA-Development.key 2048
A pokud chceme, přidáme přepínač -des3
takto:
sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA-Development.key 2048
Následující postup je už stejný:
sudo chmod 600 /etc/ssl/private/rootCA-Development.key sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA-Development.key -sha256 -days 3650 -subj "/C=CZ/ST=Prague/L=Prague/O=Development" -out /etc/ssl/certs/rootCA-Development.pem
Samořejmě si můžete upravit parametry v -subj
. Jejich význam je C=country, ST=state, L=locality a O=organization. Soubor /etc/ssl/certs/rootCA-Development.pem
si pak naimportujeme jako důvěryhodný do systému nebo prohlížeče (tady si každý musí vygooglit jak to udělat ve svém systému/prohlížeči).
Zbývá nám si jenom vytvoříme skript, který nám bude generovat samotné certifikáty pro domény. Do jednoho certifikátu může zadat jednu a více domén. Vždy se generuje wildcard certifikát, takže bude platný i pro všechny subdomény. Z toho důvodu domény zadáváme bez www. Vytvoříme tedy skript s název generate-certificate
:
sudo nano /usr/local/bin/generate-certificate
S obsahem:
#!/bin/bash ### # How to generate certificate authority: # -> without password: # sudo openssl genrsa -out /etc/ssl/private/rootCA-Development.key 2048 # -> with password: # sudo openssl genrsa -des3 -out /etc/ssl/private/rootCA-Development.key 2048 # # sudo chmod 600 /etc/ssl/private/rootCA-Development.key 2048 # sudo openssl req -x509 -new -nodes -key /etc/ssl/private/rootCA-Development.key -sha256 -days 3650 -subj "/C=CZ/ST=Prague/L=Prague/O=Development" -out /etc/ssl/certs/rootCA-Development.pem ### if [ "$EUID" -ne 0 ]; then echo "Please run as root" exit 1 fi if [ $# -eq 0 ]; then echo "Please specify domain(s)." echo "Usage: $0 <main domain> [another domain] [another domain] ..." exit 2 fi ROOTCA="Development" # -> for certificate authority with password uncomment the line below: #read -p "Enter rootCA-${ROOTCA}.key password: " PASSWORD DOMAIN=$1 CONF="/tmp/$DOMAIN.openssl.cnf" PRIVATE_KEY="/etc/ssl/private/$DOMAIN.key" CERTIFICATE_REQUEST="/etc/ssl/certs/$DOMAIN.crt.req" CERTIFICATE="/etc/ssl/certs/$DOMAIN.crt" ANOTHER_DOMAINS="" ANOTHER_DOMAINS_INFO="" ANOTHER_DOMAIN_INDEX=3 for ANOTHER_DOMAIN in ${@:2} do ANOTHER_DOMAINS="${ANOTHER_DOMAINS}DNS.${ANOTHER_DOMAIN_INDEX} = ${ANOTHER_DOMAIN}"$'\n' ANOTHER_DOMAIN_INDEX=$((ANOTHER_DOMAIN_INDEX + 1)) ANOTHER_DOMAINS="${ANOTHER_DOMAINS}DNS.${ANOTHER_DOMAIN_INDEX} = *.${ANOTHER_DOMAIN}"$'\n' ANOTHER_DOMAIN_INDEX=$((ANOTHER_DOMAIN_INDEX + 1)) ANOTHER_DOMAINS_INFO="-> ${ANOTHER_DOMAIN}"$'\n' done cat > $CONF <<-EOF [req] default_bits = 2048 prompt = no x509_extensions = v3_req distinguished_name = dn [dn] C = CZ ST = Prague L = Prague O = $ROOTCA CN = *.$DOMAIN [v3_req] subjectAltName = @alt_names [alt_names] DNS.1 = $DOMAIN DNS.2 = *.$DOMAIN $ANOTHER_DOMAINS EOF openssl genrsa -out $PRIVATE_KEY 2048 chmod 600 $PRIVATE_KEY openssl req -new -config $CONF -key $PRIVATE_KEY -out $CERTIFICATE_REQUEST openssl x509 -req -in $CERTIFICATE_REQUEST -CA /etc/ssl/certs/rootCA-${ROOTCA}.pem -CAkey /etc/ssl/private/rootCA-${ROOTCA}.key \ -CAcreateserial -out $CERTIFICATE -days 3650 -sha256 -extfile $CONF -extensions 'v3_req' # -> for certificate authority with password uncomment the line below and remove this line and the one up # -CAcreateserial -out $CERTIFICATE -days 3650 -sha256 -extfile $CONF -extensions 'v3_req' -passin pass:$PASSWORD rm $CERTIFICATE_REQUEST rm $CONF chmod 600 $PRIVATE_KEY echo "Self signed certificate ${CERTIFICATE} and private key ${PRIVATE_KEY} for main domain ${DOMAIN} were generated with 10 years expiration time" if [ -z "$ANOTHER_DOMAINS_INFO" ]; then echo "Another domains:" echo ${ANOTHER_DOMAINS_INFO} fi
A nastavíme skript jako spustitelný:
sudo chmod a+x /usr/local/bin/generate-certificate
Pokud jsme vygenerovali soukromý klíč pro certifikační autoritu chráněný heslem, odkomentujeme řádek začínající #read -p ...
a u příkazu openssl x509 ...
odkomentujeme třetí řádek a druhý vymažeme. Skript se nás pak před generováním vždy zeptá na heslo. Můžeme ještě upravit informace o certifikátu v sekci [dn]
stejně jako jsme upravili informace o certifikační autoritě.
Nakones si ukážeme jednoduchý příklad. Certifikát, pro domény domain1.com
a domain2.org
vygenerujeme takto:
sudo generate-certificate domain1.com domain2.org
Vygenerovaný certifikát je pak v souborech /etc/ssl/private/domain1.com.key
(privátní klíč) a /etc/ssl/private/domain1.com.crt
(certifikát). Tyto soubory pak už jen použijeme v nastavení nginx, Apache, případně jiného softwaru. A bude platit pro domény domain1.com
, *.domain1.com
, domain2.org
a *.domain2.org
.