Avevo necessità di attivare la comunicazione sicura, al mio blog. Ho riconfigurato quindi, il web server per esporre il servizio in HTTPS (HTTP Over SSL), fornendo l’identità digitale del dominio, firmata da un ente di certificazione, riconosciuto come tale.
In questo appunto, descriverò la procedura utilizzata per ottenere l’identità digitale certificata, in maniera tale che i visitatori possano fruire dei contenuti senza problemi, e contestualmente mettere in sicurezza il canale di amministrazione, sul quale viaggiano le mie credenziali di blogger.
Mi son rivolto quindi all’ente di certificazione LetsEncrypt, che fornisce il servizio di signing tramite protocollo acme (acronimo di Automatic Certificate Management Environment), grazie al quale potrò automatizzare l’intero ciclo di vita di certificato X509 (richiesta, revoca e rinnovo).
PASSO 1 : installare un acme client.
E’ necessario installare un acme client, sul server che eroga il servizio web. Nel mio caso ho usato l’implementazione acme-client, perchè già preinstallato in OpenBSD 7.x. Letsencrypt consiglia Certbot di EFF (Electronic Frontier Foundation), disponibile per sistemi GNU/Linux, BSD (OpenBSD, FreeBSD) ed altri.
PASSO 2 : configurare acme-client.
Ho creato un file di configurazione, partendo da un modello presente in /etc/examples
alfree$ cat /etc/examples/acme-client.conf # # $OpenBSD: acme-client.conf,v 1.4 2020/09/17 09:13:06 florian Exp $ # authority letsencrypt { api url "https://acme-v02.api.letsencrypt.org/directory" account key "/etc/acme/letsencrypt-privkey.pem" } authority letsencrypt-staging { api url "https://acme-staging-v02.api.letsencrypt.org/directory" account key "/etc/acme/letsencrypt-staging-privkey.pem" } domain example.com { alternative names { secure.example.com } domain key "/etc/ssl/private/example.com.key" domain full chain certificate "/etc/ssl/example.com.fullchain.pem" sign with letsencrypt }
Nei primi 2 blocchi son definite le Authority, ossia i canali per raggiungere il servizio di signing fornito. Letsencrypt-staging definisce l’ambiente di test, molto consigliato per effettuare tutte le prove preventive del caso, in maniera tale da non sovraccaricare l’Autority di produzione. Account key è un’identità temporanea, generata a run-time da acme-client per potersi autenticare a Letsencrypt.
Il blocco di domain definisce il dominio da certificare, in cui bisognerà specificare :
- fqdn (e gli eventuali altervative names separati da virgola o spazi)
- identità digitale (chiave privata, certificato richiesto etc.)
- authority (tra quelle precedentemente definite) da contattare per il signing, revoca o rinnovo.
Non è necessario creare nessuno di questi file, ci penserà acme-client a gestire il tutto, noi dobbiamo occuparci semplicemente del file di configurazione.
Di seguito la mia versione del file di configurazione per acme-client, utilizzata per i primi test :
alfree$ cat /home/granito/ssl/letsencrypt/acme-client.conf # # $OpenBSD: acme-client.conf,v 1.4 2020/09/17 09:13:06 florian Exp $ # authority letsencrypt { api url "https://acme-v02.api.letsencrypt.org/directory" account key "/home/granito/ssl/letsencrypt/letsencrypt-privkey.pem" } authority letsencrypt-staging { api url "https://acme-staging-v02.api.letsencrypt.org/directory" account key "/home/granito/ssl/letsencrypt/letsencrypt-staging-privkey.pem" } domain granito.org.uk { alternative names { www.granito.org.uk } domain key "/home/granito/ssl/letsencrypt/granito.org.uk.key" domain certificate "/home/granito/ssl/letsencrypt/granito.org.uk.crt" domain full chain certificate "/home/granito/ssl/letsencrypt/granito.org.uk.fullchain.pem" sign with letsencrypt-staging }
Le impostazioni modificate le ho evidenziate. Essenzialmente ho posizionato tutti i file necessari: configurazione acme-client ed identità digitale (privata, certificato e chain) nella home directory dell’owner (/home/granito) che amministra il dominio (granito.org.uk). In questa prima fase invocherò il servizio di staging (sign with).
Passo 3: Creazione della directory acme-challenge.
E’ necessario infine creare la directory .well-known/acme-challenge al di sotto della document-root del webserver. In questa directory acme-client andrà a run-time a copiare un token generato da letsencrypt, e servirà a verificare che il richiedente sia attestato sul medesimo server collegato al nome di dominio (fqdn) da validare.
Sembra complicato ma in realtà il processo è molto semplice, l’unica difficoltà è la mia, nel cercare descrivere il tutto, senza impicciarmi troppo : – )
Passo 4: Richiesta di Signing (TEST/Staging)
Quindi il processo di richiesta di signing può o meno funzionerà così :
- acme-client genera un’identità per l’autenticazione a letsencrypt (account key), con cui quest’ultimo lo identificherà e traccerà, valido per le successive richieste
- acme-client invocherà il servizio di signing di letsencrypt puntanto all’endpoint specificato (sign with), fornendo l’account key per l’autenticazione.
- letsencrypt per verificare che il richiedente sia realmente l’amministratore del dominio, genererà un token usa-e-getta che fornirà al client, chiamato challenge. Tale token-file verrà copiato da acme-client nella seguente directory $WEBSERVER_DOCUMENT_ROOT/.well-known/acme-challenge. Letsencrypt si aspetta di trovarlo, puntanto alla url https://granito.org.uk/.well-known/acme-challenge. Effettuerà la stessa verifica per ogni “Alternative Names” definito nel file di configurazione, quindi nel mio caso specifico si aspetterà di trovare il challenge anche alla url http://www.granito.org.uk/.well-known/acme-challenge/
- acme-client a questo punto genererà la chiave privata e la richiesta di certificato, interstata al dominio specificato (domain). Invierà la richiesta di certificato alla CA Letsencrypt per il signing.
- letsencrypt in risposta fornirà il certificato (richiesta di certificato, firmata)
A questo punto facciamo un test, continuando a puntare all’ambiente letsencrypt di staging :
(***Annotazione*** Non so perché ma alcune volte il processo di signing, si interrompe sulla verifica del token, oi rilanciandolo riprende dal punto in cui si è fermato).
alfree$ doas ./granito.org.uk_acme-client.sh acme-client: /home/granito/ssl/letsencrypt/staging/granito.org.uk.key: generated RSA domain key acme-client: /home/granito/ssl/letsencrypt/staging/letsencrypt-privkey.pem: generated RSA account key acme-client: https://acme-staging-v02.api.letsencrypt.org/directory: directories acme-client: acme-staging-v02.api.letsencrypt.org: DNS: 172.65.46.172 acme-client: acme-staging-v02.api.letsencrypt.org: DNS: 2606:4700:60:0:f41b:d4fe:4325:6026 acme-client: dochngreq: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/14070714883 acme-client: challenge, token: MpwYvA-ADwhWDEFY8rOYghwY0Qtf_876To83eNm0Z5w, uri: https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/14070714883/VMD6fg, status: 0 acme-client: /home/granito/granito.org.uk/.well-known/acme-challenge/MpwYvA-ADwhWDEFY8rOYghwY0Qtf_876To83eNm0Z5w: created acme-client: dochngreq: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/14070714893 acme-client: challenge, token: AolrK3kgZrdqCRRiRSK0BfBUEYPUEIdj_oQEAIznFzI, uri: https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/14070714893/8Oim_Q, status: 0 acme-client: /home/granito/granito.org.uk/.well-known/acme-challenge/AolrK3kgZrdqCRRiRSK0BfBUEYPUEIdj_oQEAIznFzI: created acme-client: https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/14070714883/VMD6fg: challenge acme-client: https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/14070714893/8Oim_Q: challenge acme-client: order.status 0 acme-client: dochngreq: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/14070714883 acme-client: challenge, token: MpwYvA-ADwhWDEFY8rOYghwY0Qtf_876To83eNm0Z5w, uri: https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/14070714883/VMD6fg, status: 2 acme-client: dochngreq: https://acme-staging-v02.api.letsencrypt.org/acme/authz-v3/14070714893 acme-client: challenge, token: AolrK3kgZrdqCRRiRSK0BfBUEYPUEIdj_oQEAIznFzI, uri: https://acme-staging-v02.api.letsencrypt.org/acme/chall-v3/14070714893/8Oim_Q, status: 2 acme-client: order.status 1 acme-client: https://acme-staging-v02.api.letsencrypt.org/acme/finalize/163892463/19226354123: certificate acme-client: order.status 2 acme-client: unhandled status: 2 acme-client: bad exit: netproc(28371): 1 [===--- Rieseguo ---===] alfree$ doas ./granito.org.uk_acme-client.sh acme-client: https://acme-staging-v02.api.letsencrypt.org/directory: directories acme-client: acme-staging-v02.api.letsencrypt.org: DNS: 172.65.46.172 acme-client: acme-staging-v02.api.letsencrypt.org: DNS: 2606:4700:60:0:f41b:d4fe:4325:6026 acme-client: https://acme-staging-v02.api.letsencrypt.org/acme/finalize/163892463/19226363633: certificate acme-client: order.status 3 acme-client: https://acme-staging-v02.api.letsencrypt.org/acme/cert/2bbe9ae72438da313960ef27fb3353b46b5c: certificate acme-client: /home/granito/ssl/letsencrypt/staging/granito.org.uk.crt: created acme-client: /home/granito/ssl/letsencrypt/staging/granito.org.uk.fullchain.pem: created alfree$
Il certificato creato puntando allo staging sono firmati da una Autority fittizia, quindi chiaramente non sono utilizzabili.
alfree# openssl x509 -in /home/granito/ssl/letsencrypt/staging/granito.org.uk.crt -text Certificate: Data: Version: 3 (0x2) Serial Number: 2b:be:9a:e7:24:38:da:31:39:60:ef:27:fb:33:53:b4:6b:5c Signature Algorithm: sha256WithRSAEncryption Issuer: C=US, O=(STAGING) Let's Encrypt, CN=(STAGING) Counterfeit Cashew R10 Validity Not Before: Sep 19 11:49:36 2024 GMT Not After : Dec 18 11:49:35 2024 GMT Subject: CN=granito.org.uk Subject Public Key Info: Public Key Algorithm: rsaEncryption RSA Public-Key: (4096 bit) Modulus: __CUT__ Exponent: 65537 (0x10001) X509v3 extensions: X509v3 Key Usage: critical Digital Signature, Key Encipherment X509v3 Extended Key Usage: TLS Web Server Authentication, TLS Web Client Authentication X509v3 Basic Constraints: critical CA:FALSE X509v3 Subject Key Identifier: A4:46:93:D9:E0:3A:AE:A5:BE:58:03:BF:26:BA:EC:BE:B8:B3:79:83 X509v3 Authority Key Identifier: keyid:A4:52:46:EA:58:A8:8F:68:D8:B7:B1:90:D1:4A:42:4A:8F:6B:28:71 Authority Information Access: OCSP - URI:http://stg-r10.o.lencr.org CA Issuers - URI:http://stg-r10.i.lencr.org/ X509v3 Subject Alternative Name: DNS:granito.org.uk, DNS:www.granito.org.uk X509v3 Certificate Policies: Policy: 2.23.140.1.2.1 CT Precertificate SCTs: Signed Certificate Timestamp: Version : v1 (0x0) Log ID : __CUT__ Timestamp : Sep 19 12:48:06 2024 GMT Extensions: none Signature : ecdsa-with-SHA256 __CUT__ Signed Certificate Timestamp: Version : v1 (0x0) Log ID : __CUT__ Timestamp : Sep 19 12:48:06 2024 GMT Extensions: none Signature : ecdsa-with-SHA256 __CUT__ Signature Algorithm: sha256WithRSAEncryption __CUT__ -----BEGIN CERTIFICATE----- __CUT__ -----END CERTIFICATE-----
[to be continue]
Riferimenti
[1] Protocollo IEFT/ACME (Automatic Certificate Management Environment)
[2] Wikipedia ACME Protocol
[3] LetsEncrypt (Ente di Certificazione)
[4] OpenBSD acme-client man
[5] EFF Certbot
[6] EFF (Electronic Frontier Foundation)