Certbot i OVH

Posted on Mon 12 December 2022 in Linux, Wirtualizacja

Odnawianie certyfikatów Letsencrypt na hostach schowanych za firewallem może być przyjemne trzeba to zrobić raz i porządnie.

Dlaczego w ogóle istnieje ten problem i czego dotyczy? W moim przypadku najczęściej serwerów pocztowych, które nie tylko znajdują się firewallem ale na które nie mogę dynamicznie przekierować portów 80 i 443, aby odpowiedzieć na żądanie z Letsencrypt.

Ale po co przekierowywać te porty? Bo wystawianie nowego certyfikatu to proces składający się z kilku etapów w których wymieniana jest informacja między hostem, a serwerem Letsencrypt (LE). Komunikacja odbywa się przez porty 80 i 443.

W skrócie: w pewnym momencie serwer LE chce "pogadać" z serwerem HTTP na hoście na który wskazuje rekord DNS domeny, dla której wystawiamy nowy certyfikat (lub go odnawiamy), żeby przekonać się, że mamy do tego prawo. A prawo mamy jeśli jesteśmy adminem tego serwera.

No, ale co zrobić jeśli na firewallu porty 80 i 443 już są przekierowane na innego hosta?

Jeśli domena utrzymywana jest u dostawcy obsługiwanego modułem Certbota, sprawę mamy załatwioną bo innym sposobem autoryzacji jest udowodnienie, że mamy prawo do ustawiania rekordów DNS dla tej domeny.

Jeśli DNS obsługiwany jest przez OVH to problem rozwiązuje moduł do Certbota o nazwie: certbot-dns-ovh. Metoda jest prosta, najpierw modułowi zezwalamy na dostęp do API w OVH, dzięki temu może on dopisywać i usuwać rekordy w DNS. Rekordy te służą poświadczeniu, że my to rzeczywiście my i że mamy prawo poprosić o nowy certyfikat.

Instalujemy certbota (źródłem niech będzie SNAP, "paczkowany" bywa zbyt stary).

Tu instaluję na Debianie 10 (buster), inne distra mają podobnie.

Najpierw snap i certbot:

sudo apt update
sudo apt install snapd
sudo snap install core
sudo snap refresh core
sudo apt remove certbot
sudo snap install --classic certbot
sudo ln -s /snap/bin/certbot /usr/bin/certbot

Kontener w Proxmoxie ma inaczej

W kontenerze na Proxmoxie powyższa instalacja nie powiedzie się, można kombinować z ustawieniami 'fuse':

Snap requires a bit more work. There may soon be a 'fuse' flag for the features option, but fuse can be dangerous. For now you have to do this:
- For unprivileged containers:
1) Put this in /etc/pve/lxc/$vmid.conf:

Code:

...
features: mount=fuse,nesting=1
lxc.mount.entry = /dev/fuse dev/fuse none bind,create=file 0 0
2) Inside the container: `apt install squashfuse`
- For privileged containers, also add:

Code:

...
# EDIT:
# We need to allow apparmor administration, by default mac_admin is dropped for privileged containers.
# Note that you do not want this for un-trusted containers...
lxc.cap.drop =
lxc.cap.drop = mac_override sys_time sys_module sys_rawio
Alternatively to squashfuse, privileged containers could use loop devices, but I wouldn't recommend it...
Note that enabling `fuse` in a container does not play well with backups, or anything that causes an `lxc-freeze` command to be executed on the container, as this can cause deadlocks in the kernel.

https://forum.proxmox.com/threads/ubuntu-snaps-inside-lxc-container-on-proxmox.36463/#post-230060

Ale wolę szybsze i bezpieczniejsze rozwiązanie czyli instalacja za pomocą PIP:

sudo apt-get remove certbot
sudo apt update
sudo apt install python3 python3-venv libaugeas0
sudo python3 -m venv /opt/certbot/
sudo /opt/certbot/bin/pip install --upgrade pip
sudo /opt/certbot/bin/pip install certbot certbot
sudo ln -s /opt/certbot/bin/certbot /usr/bin/certbot

Moduł Node do OVH

zainstalujmy go w /opt:

cd /opt
sudo git clone https://github.com/mcdado/certbot-dns-ovh.git
cd certbot-dns-ovh

Moduł używa Node.js więc pierwszym krokiem jest zainstalowanie Node na naszym serwerze. Najlepszym sposobem jest ominięcie instalacji z paczek i użycie NVM, a to ponieważ Node podlega szybkim zmianom, wkrótce więc może okazać się, że jest nieaktualny.

NVM to Node Version Manager, nazwa wyjaśnia wszystko. Instalacja jest trywialna:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.37.2/install.sh | bash

Następnie instalacja samego Node:

nvm install node

Domyślne instalowana jest najnowsza wersja, inne można wyświetlić tą komendą:

nvm list-remote

Mamy Node, pora zrobić resztę pracy, po której będzie można zapomnieć o ręcznym odnawianiu certyfikatów.


OVH: Appkey i AppSecret

Wchodzimy na ten adres: https://eu.api.ovh.com/createApp/

logujemy się na konto z domeną i generujemy App Key oraz App Secret. Pola "nazwa" oraz "opis" służą nam, ludziom, do pamiętania czemu służy konkretny klucz.

Teraz następuje kolejny krok autoryzacji aplikacji, w konsoli, nadal w katalogu /opt/certbot-dns-ovh odpalamy:

node bin/authorize.js --endpoint=ovh-eu --app_key=yourappkey --app_secret=yourappsecret

Jeśli wystąpi błąd mówiący o braku modułu "dotenv" należy go zainstalować:

.. code:: html

   npm install dotenv

Oczywiście w miejsce "yourappkey" i "yourappsecret" podstawiamy App Key i App Secret z poprzedniego kroku.

W konsoli pojawia się odpowiedź, mniej więcej taka:
{ validationUrl: 'https://eu.api.ovh.com/auth/?credentialToken=jed…', consumerKey: '69X…', state: 'pendingValidation' }

Zapamiętujemy klucz klienta (consumerKey). Kopiujemy URL do przeglądarki i zatwierdzamy dostęp do API, wybieramy też przez jaki czas dane te będą ważne. Sam wybrałem, że w nieskończoność bo... tak.

Znajdujący się w katalogu: /opt/certbot-dns-ovh plik .env.example kopiujemy do .env:

cd /opt/certbot-dns-ovh
cp .env.example .env

Edytujemy .env, wstawiając odpowiednie wartości uzyskane we wcześniejszych krokach:

OVH_ENDPOINT="ovh-eu"
OVH_APP_KEY="tutaj klucz czyli App Key"
OVH_APP_SECRET="tu sekret App Secret"
OVH_CUSTOMER_KEY="klucz kienta czyli consumerKey wyświetlony w konsoli"
DNS_TIMEOUT="tu możemy zwiększyć czas oczekiwania z domyślnych 60 sekund"

Przedostatni krok to uzyskanie certyfikatu, jeśli się powiedzie to mamy potwierdzenie, że nic nie spapraliśmy:

sudo certbot certonly --manual --preferred-challenges=dns --manual-auth-hook '/opt/certbot-dns-ovh/bin/create-record.js' --manual-cleanup-hook '/opt/certbot-dns-ovh/bin/delete-record.js' -d mojadomena.pl -d www.mojadomena.pl

Odnawianie: cron i systemd

Jeśli się udało to za pomocą komendy:

sudo crontab -e

edytujemy crontaba i wstawiamy na końcu linijkę:

@weekly certbot renew --quiet

czyli jako root uruchamiamy:

crontab -e

i wklejamy powyższą linijkę.

W nowych "linuksach" crontab nie zawsze działa, zamieszczam więc poniżej wersję dla systemd.

Plik: /etc/systemd/system/certbot-renewal.service:

[Unit]
Description=Certbot Renewal

[Service]
ExecStart=/usr/bin/certbot renew

Plik: /etc/systemd/system/certbot-renewal.timer (odpala certbot-renewal co tydzień):

[Unit]
Description=Timer for Certbot Renewal

[Timer]
OnBootSec=300
OnUnitActiveSec=1w

[Install]
WantedBy=multi-user.target

I jeszcze plik: /etc/letsencrypt/renewal-hooks/post/00-restart-mail.sh, któremy należy nadać bit uruchomienia:

#!/bin/bash
systemctl restart postfix
systemctl restart dovecot.service
sudo chmod +x /etc/letsencrypt/renewal-hooks/post/00-restart-mail.sh

Po skopiowaniu powyższych plików należy odświeżyć konfigurację systemd:

systemctl daemon-reload

No i zostaje uruchomienie serwisu:

systemctl start certbot-renewal.timer
systemctl enable certbot-renewal.timer

Aby sprawdzić czy timer działa:

systemctl status certbot-renewal.timer

Jak to się dzieje, że po tych zabiegach Cerbot już "wie" jak odnawiać certyfikaty?

Potrafi to, bo w katalogu /etc/letsencrypt/renewal powstaje plik z konfiguracją. Nosi on nazwę domeny z końcówką .conf. Czyli w przypadku domeny mojadomena.pl będzie to:

/etc/letsencrypt/renewal/mojadomena.pl.conf

Zajrzyj do środka do zrozumiesz.