Min arbejdsgiver har i årevis postet penge ud på certifikater. Det er løbet op i et pænt beløb gennem tiden. Så da jeg blev opmærksom på Let’s Encrypt og muligheden for gratis certifikater, var jeg ikke sen til at hoppe med på vognen.
Indholdsfortegnelse
Hvem/hvad er Let’s Encrypt?
“Let’s Encrypt” er et projekt i regi af Internet Security Research Group (ISRG), som blev grundlagt i 2013 med det formål at fremme offentligt tilgængelige projekter inden for digital infrastruktur. Gruppen blev fra starten sponsoreret af Mozilla, Electronic Frontier Foundation, University of Michigan, Cisco og Akamai.
Det første projekt blev Let’s Encrypt certificate authority som er en CA (certificate authority) der udsteder certifikater helt gratis og med mulighed for at automatisere processen gennem klienten “Certbot”. Dette naturligvis med henblik på at højne sikkerheden og give alle mulighed for at kryptere deres internet services på en nem måde.
Hvad er begrænsningen?
Let’s Encrypt udsteder kun DV certifikater:
- DV = Domain Validation. Et certifikat hvor domænet er valideret, dvs. at den der har fået certifikatet udstedt, har bevist sin kontrol over domænet
- OV = Organisation Validation. Certifikatets indehaver har udover kontrol over domænet også bevist virksomhedens identitet
- EV = Extended Validation. Udover DV og OV skal virksomheden bevise sin legale, fysiske og operationelle eksistens og sin eksklusive ret til domænet
Let’s Encrypt certifikater er gyldige i 3 måneder
- Købte certifikater kan være gyldige i helt op til 3 år, hvorimod et Let’s Encrypt certifikat kun er gyldigt i 3 måneder. Denne begrænsning behøver dog ikke have nogen praktisk betydning, da certbot klienten hele tiden holder øje med certifikater der er ved at udløbe og automatisk fornyer dem.Let’s Encrypt skriver selv følgende om denne tidsbegræsning:
- They limit damage from key compromise and mis-issuance. Stolen keys and mis-issued certificates are valid for a shorter period of time.
- They encourage automation, which is absolutely essential for ease-of-use. If we’re going to move the entire Web to HTTPS, we can’t continue to expect system administrators to manually handle renewals. Once issuance and renewal are automated, shorter lifetimes won’t be any less convenient than longer ones.
Er et DV certifikat godt nok?
Det der er vigtigt er, at ingen kan se eller sniffe data der udveksles mellem en service og en klient. Hvis du benytter en hjemmeside uden kryptering (http) mens du er forbundet til en Wi-Fi f.eks. på en Cafe, kan andre på Cafeen følge med i og læse alle de data der sendes frem og tilbage mellem din enhed og hjemmesiden. Hvis hjemmesiden er sikret med SSL (https) er data krypteret og folk kan stadig se der flyver data frem og tilbage, men kan ikke læse det.
Uanset om du har et DV, OV eller EV certifikat, er data krypteret. Så hvad det angår er et DV certificat ganske udmærket. Hvorvidt certifikat-udstederen har valideret din organisation og kender din identitet, har intet at gøre med det vigtige: Krypteringen. Er det vigtigt for dine kunder at CA’en har tjekket at din identitet og den lovlige registrering af dit firma? Næppe. Ingen almindelige mennesker tjekker den slags. Deres tillid til en hjemmeside baserer sig på helt andre metoder. De har måske fået en hjemmeside anbefalet eller har tjekket TrustPilot, eller har måske kommunikeret med med dig pr mail eller telefon inden købet. Langt de fleste gør absolut ingenting. Så nej, et OV eller EV certifikat er sjældent vigtigt for en helt almindelig online butik. Måske for en bank eller offentlig myndighed der ligger inde med mange følsomme data.
Men hvad med den grønne bar?
Der var en overgang meget hype om “den grønne bar” med firmanavn, som mange browsere viste på sider med EV certifikat. Det bevæger man sig væk fra nu. Google har f.eks. besluttet at deres Chrome browsere i fremtiden kun skal indikere hvis en side IKKE er sikker. Og hvis forskellen på de forskellige certifikater således udviskes, er der absolut intet der taler for at bruge penge på dem… medmindre man henvender sig til et publikum der rent faktisk tjekker den slags. Det gør 99,99% af befolkningen ikke.
Let’s Encrypt på Ubuntu 18.04
Installer Certbot
1 2 3 4 5 6 |
# apt-get update # apt-get install software-properties-common # add-apt-repository universe # add-apt-repository ppa:certbot/certbot # apt-get update # apt-get install certbot python-certbot-apache |
Let’s Encrypt på Ubuntu 20.04
Installer Certbot
1 2 |
# apt-get update # apt install certbot python3-certbot-apache |
Vælg mellem DNS eller HTTP challenge
For at kunne modtaget et certifikat, skal du bevise at du har kontrol over domænet. Det kan enten ske via DNS ved at tilføje en TXT record, eller ved at lade certbot placere en fil som Let’s Encrypt kan nå via det domæne der ønskes certifikat til.
Hvis du vælger DNS bør undersøge om du har mulighed for at automatisere tilføjelsen af en TXT record, da alternativet er, at du manuelt fornyer certifikatet hver 3 måned. Den åbenlyse fordel ved brug af DNS metoden, er at den giver mulighed for wildcart certifikater.
Så hvis du har få domæner og mange subdomæner til disse, kan DNS være en fordel, hvorimod brug af mange forskellige domæner med få subdomæner kan tale for brug af HTTP challenge.
Certifikat via HTTP challenge
Konfiguration af webserver
Når du genererer et certifikat med certbot vha en HTTP challenge, placerer certbot en fil i en angivet mappe, og den skal Let’s Encrypt serveren kunne tilgå via det domæne du ønsker certifikat til.
Lad os antage jeg har domænet eksempel.dk og jeg gerne vil udstede et certifikat til test.eksempel.dk. Let’s Encrypt vil nu tilgå challenge filen via test.eksempel.dk på port 80. Det betyder ikke noget om du har en SSL redirect eller andet halløj konfigureret. Det er Let’s Encrypt ligeglad med. Jeg har derfor lavet mit setup således at enhver forespørgsel på en challenge fil, gives til acme.eksempel.dk. På den måde slipper jeg for at lave en challenge konfiguration under alle virtuelle hosts jeg opretter i fremtiden.
Standalone
Det mest simple er at lade Certbot selv agere webserver ved oprettelse/fornyelse af certifikater. Dette kræver dog at port 80 eller 443 er ledig.
Apache
Linierne herunder har jeg placeret i en *.conf fil under /etc/apache2/conf-available
1 2 3 4 5 6 7 8 9 10 11 |
<If "%{HTTP_HOST} != 'acme.eksempel.dk'"> RedirectMatch "^/.well-known/(.*)$" http://acme.eksempel.dk/.well-known/$1 </If> #Tilføj disse linier for at komme udenom evt beskyttelse med adgangskode #Normalt vil man altid bruge <Directory> til den slags, men da vi rammer domænet #inden vi kommer til acme.eksempel.dk, er vi nød til at bypass'e beskyttelsen med #<Location> <Location /.well-known/acme-challenge/> Require all granted </Location> |
Det næste jeg gør, er at oprette et dedikeret sted til challenge filen
1 2 3 |
# mkdir -p /var/www/letsencrypt/challenge # mkdir /var/www/letsencrypt/dummy # chown www-data:www-data /var/www/letsencrypt/challenge |
Og så skal jeg tilføje min acme.eksempel.dk virtuelle host
/etc/apache2/sites-available/acme.eksempel.dk.conf
1 2 3 4 5 |
<VirtualHost *:80> ServerName acme.eksempel.dk DocumentRoot /var/www/letsencrypt/dummy Alias /.well-known/acme-challenge/ /var/www/letsencrypt/challenge/.well-known/acme-challenge/ </VirtualHost>sfsd |
Og til sidst huske at aktivere om nødvendigt og genstarte Apache
1 2 3 |
a2enconf konfig a2ensite acme.eksempel.dk apachectl restart |
Nginx
Der er nok en god grund, men i Nginx kan man ikke lave en global konfiguration med location
der gælder alle virtuelle hosts. Så her har jeg lavet en fil som jeg inkluderer i konfigurationen for port 80.
/etc/nginx/acme.conf
1 2 3 |
location ^~ /.well-known/acme-challenge/ { rewrite ^(.*) http://acme.eksempel.dk$1 permanent; } |
Alternativ: I mit tilfælde er der både Nginx og Apache på samme server, og acme.eksempel.dk serveres fra Apache. Derfor laver jeg blot en rewrite:
1 2 3 4 |
location ^~ /.well-known/acme-challenge/ { root /var/www/letsencrypt/challenge allow all; } |
Husk genstart af Nginx: service nginx restart
Test af webserver konfiguration
Når et certifikat oprettes vil certbot
lave stien .well-known/acme-challenge/filnavn
under /var/www/letsencrypt challenge
. Let’s Encrypt vil herefter forsøge at tilgå ~.well-known/acme-challenge/filnavn
for det domæne certifikatet skal gælde. For at teste at din webserver konfiguration virker, kan du derfor oprette den sti, og se om du kan tilgå den i din browser:
1 2 |
mkdir -p /var/www/letsencrypt/challenge/.well-known/acme-challenge touch /var/www/letsencrypt/challenge/.well-known/acme-challenge/test.txt |
Smid evt lidt indhold i test.txt, som f.eks. “hello world” eller lign. Gå derefter til http://et-af-dine-domæner.dk/.well-known/acme-challenge/test.txt. Hvis du får en 404 fejl, må du tilbage til tegnebrættet…
Husk at slette mappen igen når du er færdig med at teste:
1 |
rm -rf /var/www/letsencrypt/challenge/.well-known |
Oprettelse af certifikater
Nu har vi gjort alt det forarbejde der kun skal udføres een gang. Nu kan vi generere det første certifikat. Jeg har gjort brug af følgende parametre, afhængig af omstændighederne.
- certonly Certbot kan konfigurere din virtuelle host for dig, men det foretrækker jeg at gøre selv, da jeg allerede har virtuelle hosts med ssl. Og jeg vil helst ikke have at certbot laver rod i det.
- –webroot Placer filer i en mappe til verifikation (challenge)
- –webroot-path Sti til mappen som challenge filen skal placeres i
- –email Email til registrering og anden kontakt. Flere adresser kan angives separeret med komma, eks: u1@eksempel.dk,u2@eksempel.dk.
- –agree-tos Accepter ACME Subscriber Agreement
- -d [domain] De domæner certifikatet skal gælde for
- –no-eff-email Føj ikke email adressen til EFF maillisten
- –preferred-challenges Kommasepareret liste med prioriterede challenge typer
- –noninteractive Undlad at blokere skriptet ved at afvente brugerinput (praktisk vedr. cron)
- Test parametre:
- –debug-challenges Afvent bruger interaktion før challenges slettes
- –dry-run Benyt “sandkasse” servere da dette er en test
De to sidste parametre, fjernes når du er klar til at lave et egentligt certifikat.
Jeg har lavet et lille shell script der husker parametrene for mig, så jeg nemt at kan oprettet et certifikat:
Det ser således ud:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
./letsencrypt-add-domain.sh This script is used to generate a new ssl certificate for a (sub)domain ------------ Domain (e.g. test.eksempel.dk) []: salg.eksempel.dk Is this a test? (y/n) [y]: n Debug challenges (y/n) [n]: n certbot certonly --webroot --email dns@eksempel.dk --webroot-path /var/www/letsencrypt/challenge --agree-tos --no-eff-email -d salg.eksempel.dk --preferred-challenges http-01 --noninteractive Is this okay (y/n) [n]: y Script is executed Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator webroot, Installer None Obtaining a new certificate Performing the following challenges: http-01 challenge for salg.eksempel.dk Using the webroot path /var/www/letsencrypt/challenge for all unmatched domains. Waiting for verification... Cleaning up challenges IMPORTANT NOTES: - Congratulations! Your certificate and chain have been saved at: /etc/letsencrypt/live/test.eksempel.dk/fullchain.pem Your key file has been saved at: /etc/letsencrypt/live/test.eksempel.dk/privkey.pem Your cert will expire on 2020-03-11. To obtain a new or tweaked version of this certificate in the future, simply run certbot again. To non-interactively renew *all* of your certificates, run "certbot renew" - If you like Certbot, please consider supporting our work by: Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate Donating to EFF: https://eff.org/donate-le |
Og her er indholdet af scriptet:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
#!/bin/sh dryrun="--dry-run" debugchallenge="--debug-challenges" echo "This script is used to generate a new ssl certificate for a (sub)domain" echo "------------" printf "Domain (e.g. test.eksempel.dk) []: " read newdomain printf "Is this a test? (y/n) [y]: " read istestdry printf "Debug challenges (y/n) [n]: " read istestchallenge commandstr="certbot certonly --webroot \n --email dns@eksempel.dk \n --webroot-path /var/www/letsencrypt/challenge \n --agree-tos \n --no-eff-email \n -d ${newdomain} \n --preferred-challenges http-01 \n --noninteractive" if [ $istestdry != "n" ];then commandstr="${commandstr}\n ${dryrun}" fi if [ $istestchallenge = "y" ];then commandstr="${commandstr}\n ${debugchallenge}" fi echo $commandstr printf "\nIs this okay (y/n) [n]: " read isokay if [ $isokay = "y" ];then echo "Script is executed" command="$(echo "${commandstr}" | tr -d '\n')" $command else echo "Aborting script" fi |
Fremover vil certbot automatisk (via cron) sørge for at forny certifikaterne når den detekterer at et certifikat udløber inden for de næste 30 dage. Dette kræver en genstart af webserveren, og det skal jeg derfor gøre selv. Men vi opdaterer og genstarter vores servere jævnligt, så det vil ske under alle omstændigheder.
Certifikat via DNS challenge
Det er faktisk ret meget mere simpelt at oprette et certifikat via DNS challenge, fordi man helt undgår at konfigurere sin webserver. Du sætter bare certbot igang, og den vil så typisk bede dig oprette to TXT records.
Ulempen er at processen kun kan automatiseres, hvis din DNS udbyder supporterer det.
Certbot benytter den autoritative DNS server for dit domæne, og du behøver derfor ikke vente på at din TXT record slår igennem på diverse DNS servere, før du trykker [Enter].
Jeg plejer derudover at lade TXT records stå, og så fjerne dem jeg benyttede sidst, når jeg indsætter nye ifbm fornyelse af certifikaterne.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
$ certbot certonly --manual --no-eff-email --preferred-challenges dns --server https://acme-v02.api.letsencrypt.org/directory --agree-tos -d 'example.com,*.example.com' Saving debug log to /var/log/letsencrypt/letsencrypt.log Plugins selected: Authenticator manual, Installer None Cert is due for renewal, auto-renewing... Renewing an existing certificate Performing the following challenges: dns-01 challenge for example.com dns-01 challenge for example.com - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - NOTE: The IP of this machine will be publicly logged as having requested this certificate. If you're running certbot in manual mode on a machine that is not your server, please ensure you're okay with that. Are you OK with your IP being logged? - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - (Y)es/(N)o: Y - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please deploy a DNS TXT record under the name _acme-challenge.example.com with the following value: -D4hlKY64K09cETGFu10FTVrz-hJ6ZZL__kua2uEbOQ Before continuing, verify the record is deployed. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Press Enter to Continue - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Please deploy a DNS TXT record under the name _acme-challenge.example.com with the following value: 6d1nDOsNni6vj7AG21nS_HscertYmPUc-aWl4SlTB_M Before continuing, verify the record is deployed. (This must be set up in addition to the previous challenges; do not remove, replace, or undo the previous challenge tasks yet. Note that you might be asked to create multiple distinct TXT records with the same name. This is permitted by DNS standards.) - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Press Enter to Continue Waiting for verification... Cleaning up challenges |
Voila!
Fjerne et domæne
Hvis du af en eller anden årsag ikke længere ønsker at certbot automatisk fornyer certifikatet for et domæne, kan du fjerne det som følger:
1 2 3 4 5 6 |
$ sudo certbot delete --cert-name mit.eksempel.dk Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Deleted all files relating to certificate mit.eksempel.dk. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
Bemærk at folderen vedr. dette domæne og alle filer deri, fjernes fuldstændig fra /etc/letsencrypt/live/. Hvis domænet skal køre videre indtil certifikaterne udløber, bør du derfor kopiere dem først.
Liste over certifikater
Du kan liste alle certifikater med kommandoen herunder.
1 |
$ certbot certificates |
Eksempel på output:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
Saving debug log to /var/log/letsencrypt/letsencrypt.log - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Found the following certs: Certificate Name: subdomain1.example.com Domains: subdomain1.example.com Expiry Date: 2022-04-03 11:16:15+00:00 (VALID: 51 days) Certificate Path: /etc/letsencrypt/live/subdomain1.example.com/fullchain.pem Private Key Path: /etc/letsencrypt/live/subdomain1.example.com/privkey.pem Certificate Name: subdomain2.example.com Domains: subdomain2.example.com Expiry Date: 2022-04-23 17:12:24+00:00 (VALID: 72 days) Certificate Path: /etc/letsencrypt/live/subdomain2.example.com/fullchain.pem Private Key Path: /etc/letsencrypt/live/subdomain2.example.com/privkey.pem Certificate Name: subdomain3.example.com Domains: subdomain3.example.com Expiry Date: 2022-05-06 08:39:56+00:00 (VALID: 84 days) Certificate Path: /etc/letsencrypt/live/subdomain3.example.com/fullchain.pem Private Key Path: /etc/letsencrypt/live/subdomain3.example.com/privkey.pem - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |