Jeg bruker nginx og certbot for noen tjenester jeg verter. Sistnevnte er et Python script som kan skaffe og automatisk fornye TLS-sertifikater, fortrinnsvis ved å bruke Let’s Encrypt sin HTTP-01 Challenge. Dette fungerer ved at den endrer nginx sin konfigurasjon til å levere en fil på en bestemt URL, som skal bevise at du som forespør et sertifikat også har kontroll over nettsiden.
I morges opplevde jeg at et par av tjenestene hadde utløpte sertifikater.
Rettere sagt fikk jeg en tekstmelding fra en forvirret bruker.
Jeg gikk på server og prøvde å fornye sertifikatene manuelt med sudo certbot renew.
Jeg fikk en feilmelding som så omtrent slik ut:
Certbot failed to authenticate some domains (authenticator: nginx).
The Certificate Authority reported these problems:
Domain: <DOMENENAVN>
Type: unauthorized
Detail: <IPv6-adresse>: Invalid response from
http://<DOMENENAVN>/.well-known/acme-challenge/<CHALLENGE-ID>: 404
Da gir det mening at sertifikatene er utløpt, certbot ikke klarer å fornye dem.
En ting som slo meg var at den prøvde å gjøre det til serverens IPv6-adresse.
Jeg hadde nylig lagt inn en AAAA (altså IPv6) rad i DNS for de påvirkede tjenestene, uten noen videre testing på om det fungerte.
Dette var kilden til feilen. I nginx må du eksplistitt spesifisere at en virtual host skal gjelde begge adressefamilier.
Om du bruker certbot har du sannsynligvis denne typen blokker i nginx-konfigurasjonen din, virtual hosts som lytter for HTTP-trafikk, og omdirigerer det til HTTPS:
server {
if ($host = <DOMENENAVN>) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name <DOMENENAVN>;
return 404; # managed by Certbot
}
Denne spesifiserer listen 80;, hvilket betyr at den mottar trafikk til IPv4 på port 80.
For at blokken også skal være gjeldene for IPv6-trafikk, må du også legge inn listen [::]:80;.
Dette løste problemet og gjorde det mulig for Let’s Encrypt å nå utfordringsfilen.
En ganske amatørmessig feil å gjøre, som kunne lett vært unngått med enten bedre testing av konfigurasjonsendringer, eller kontinuerilg overvåkning av sertifikater som er i ferd med å utløpe. Uansett var det ikke katastrofalt, og god lærdom. Jeg skal sette opp bedre overvåkning snart, jeg lover.
P.S.
En ting å legge merke til er at på den aktuelle serveren var default virtual hosten i nginx slått på.
Denne lytter eksplistitt på begge adressefamilier, så nginx-prosessen måtte også gjøre det.
Om den hadde vært slått av, kan det være nginx ikke hadde lyttet på IPv6 i det hele tatt, og Let’s Encrypt
hadde fått en TCP-rejection fra serveren.
Da kan det være Let’s Encrypt hadde falt tilbake til IPv4, og fornyelsen hadde gått gjennom.
Dette er spekulasjon, jeg har ikke testet.
Tips: legger du til en liten -v så det blir sudo certbot renew -v, forteller den deg også hva den gjør.
Slik var det klart for meg at den skrev om nginx sin konfigurasjon
på en måte som burde gjøre det mulig å aksessere HTTP-01 utfordringslenken i HTTP virtual hosten til nettsiden.