TLS jest ogólnie przyjętym standardem zapewniania poufności i integralności transmisji danych między serwerem a klientem. Kluczowym elementem tego protokołu jest certyfikat podpisany przez Urząd Certyfikacji (eng. CA). Urząd Certyfikacji to zwykle specialistyczna firma, uwierzytelniająca podmioty, którym podpisuje certyfikaty, pobierając za to dość spore opłaty. Na szczęście kilka lat temu powstał Let's Encrypt. Urząd Certyfikujący non-profit, który pozwala podpisać certyfikat naszej strony w sposób całkowicie automatyczny, w dodatku za darmo.
(Tłumaczenie Certificate Authority jako Urząd Certyfikujący brzmi trochę groteskowo moim zdaniem, ale takie się przyjęło)
Realizacja
Zaopatrzenie serwera nginx w certyfikat podpisany przez Let's Encrypt składa się z trzech etapów.
Przygotowanie serwera na autoryzację
Po pierwsze muszę poprawnie ustawić serwery DNS, tak aby zmiany
zdążyły się spropagować na cały świat.
Domyślny czas życia rekordu DNS to 86400 sekund - 1 dzień.
Proces dodawania rekordów na serwerach DNS linode opisałem
w notatce Instalacja domeny na serwerach DNS linode
.
Muszę przygotować konfigurację nginx
a na automatyczną autoryzację
przez serwery Let's Encrypt.
Najpierw przygotowuję strukturę katalogów.
(root) $ mkdir /var/www/certbot
(root) $ mkdir /var/log/certbot
Serwer zostanie uwierzytelniony za pomocą endpointu
.well-known/acme-challenge
.
Przygotowuję tymczasową konfigurację, przedstawioną
na listingu 1.
Przekierowuje wszelkie zapytania na endpoint
/.well-known/acme-challenge
do katalogu /var/www/certbot
.
Katalog powinien być domyślnie pusty.
server {
server_name mucka.pro;
listen 80;
listen [::]:80;
access_log /var/log/nginx/mucka_pro.access_log main;
error_log /var/log/nginx/mucka_pro.error_log info;
location ^~ /.well-known/acme-challenge {
default_type "text/plain";
root /var/www/certbot;
}
# Rest of configuration
}
/etc/nginx/conf.d/mucka_pro.conf
Przeładowuję konfigurację nginx
a.
(root) $ rc-service nginx reload
Generowanie i podpisywanie certyfikatu
Do generowania i automatycznego podpisywania certyfikatu służy biblioteka certbot. Instaluję ją z repozytorium gentoo.
(root) $ emerge -av certbot
Uruchamiam certbot
jako argumenty podając nazwę domeny i
przygotowany katalog.
(root) $ certbot certonly --webroot --agree-tos --email xxx@xxx.com --logs-dir /var/log/certbot --webroot-path /var/www/certbot/ --domain mucka.pro -n
Saving debug log to /var/log/certbot/letsencrypt.log
Requesting a certificate for mucka.pro
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/mucka.pro/fullchain.pem
Key is saved at: /etc/letsencrypt/live/mucka.pro/privkey.pem
This certificate expires on 2025-05-26.
These files will be updated when the certificate renews.
Plik konfiguracyjny potrzebny do odnowienia domeny zapisał się w
/etc/letsencrypt/renewal/mucka.pro.conf
.
Sam certyfikat zapisał się w katalogu
/etc/letsencrypt/archive/mucka.pro/
ale my będziemy wykorzystywać
linki symboliczne z katalogu /etc/letsencrypt/live/mucka.pro
.
Przygotowanie serwera na pracę z certyfikatem
Posiadając podpisany certyfikat mogę skonfigurować nginx'a do
szyfrowanej komunikacji.
Nową konfigurację przedstawiłem na listingu 2.
Połączenia nieszyfrowane (na port 80) przekierowuje na szyfrowane.
Z wyjątkiem konfiguracji acme-challenge
która będzie potrzebna
do regularnego odnawiania certyfikatu.
Połączenia szyfrowane na port 433 traktuje tak jak wcześniej
nieszyfrowane.
Za pomocą dyrektyw ssl_certificate
ustawiam ścieżki do
wygenerowanych kluczy.
Pozostała konfiguracja pozostaje bez zmian.
server {
server_name mucka.pro;
listen 80;
listen [::]:80;
location ^~ /.well-known/acme-challenge {
default_type "text/plain";
root /var/www/certbot;
}
location / {
return 301 https://$host$request_uri;
}
}
server {
server_name mucka.pro;
listen 443 ssl;
listen [::]:443 ssl;
access_log /var/log/nginx/mucka_pro.access_log main;
error_log /var/log/nginx/mucka_pro.error_log info;
ssl_certificate /etc/letsencrypt/live/mucka.pro/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mucka.pro/privkey.pem;
# Rest of configuration
}
/etc/nginx/conf.d/mucka_pro.conf
Przeładowuję konfigurację nginx
a.
(root) $ rc-service nginx reload
Serwer jest gotowy do pracy. Strona https://mucka.pro/ obsługuje szyfrowany ruch.
Odnawianie certyfikatu
Certyfikat Let's Encrypt jest ważny przez 90 dni. Powinien być odnawiany co 30 dni.
Aby zautomatyzować odnawianie certyfikatu umieszczę prosty skrypt w
katalogu /etc/cron.monthly
.
Umieszając zadanie w crontab
ryzykował bym, że jeśli serwer nie
będzie włączony na początku miesiąca, odnawianie domeny w danym
miesiącu nie było by wykonane.
Anacron uruchomi zaległe zadanie przy następnym starcie systemu.
#!/usr/bin/env bash
/usr/bin/certbot renew --quiet
/usr/bin/logger "Certbot renew finished with status: $?"
/usr/sbin/rc-service nginx reload
/etc/cron.monthly/certbot
Podsumowanie
Zapewnienie poufności i integralności treści w internecie jest obowiązkiem ich dostawcy. Żyjemy we wspaniałych czasach, w których jest to proste do implementacji.