Let's Encrypt w praktyce
Ostatnia zmiana: 2020-11-04 07:12

Macie własny router? Udostępniacie stronę www? Też was denerwuje że przeglądarka wyświetla to:



zamiast tego?



Ta "zielona kłódka" to nic innego jak informacja że strona jest bezpieczna (to dla nietechnicznych), cała komunikacja jest odpowiednio szyfrowana i strona jest faktycznie tym czym się przedstawia. Uzyskanie certyfikatu było dość kosztowne bo wystawiały go instytucje które były przez systemy operacyjne znane i określane jako "zaufane". Wraz z rozwojem internetu (i większymi ruchami na rzecz prywatności w sieci) rośnie zapotrzebowanie na szyfrowanie wszystkich możliwych połączeń. Wiele popularnych witryn bazuje obecnie tylko https, przekierowując zwykły ruch na ten bezpieczny. Na początku 2016 roku pojawił się Lets Encrypt, instytucja która wykonała swoistą rewolucję w internecie oferujące darmowe certyfikaty dla witryn, z których może skorzystać praktycznie każdy. Ograniczeniem takiego certyfikatu jest czas ważności określony na 3 miesiące (inaczej mówiąc - trzeba odnawiać wystawiony certyfikat co 3 miesiące, inaczej straci ważności) oraz brak możliwości wystawienia certyfikatu typu wildcard (na wszystkie subdomeny, co ma się zmienić z początkiem przyszłego roku).

Poniższy poradnik prezentuje metodę wygenerowania darmowego certyfikatu dla domeny internetowej oraz uruchomienie serwera www który z takiego certyfikatu skorzysta. Dzięki temu zapewniamy sobie bezpieczeństwo (szyfrowanie ruchu), strona przejdzie pomyślną weryfikację przez przeglądarki internetowe oraz pozbędziemy się denerwującego komunikatu o problemach z zabezpieczeniami.

Co jest potrzebne:

  • router z zainstalowanym serwerem www. W tym poradniku wykorzystany został uhttpd który standardowo jest dostępny w LEDE/OpenWrt/Gargoyle, choć nic nie stoi na przeszkodzie aby wygenerowany certyfikat wykorzystać dla serwera apache czy lighttpd.
  • publiczny adres IP na interfejsie wan. Do wystawienia certyfikatu niezbędne jest przeprowadzenie pewnej weryfikacji, a żeby można było to zrobić niezbędny jest publiczny adres IP do którego pośrednio odwoła się serwis weryfikujący. W ostateczności może wystarczyć przekierowanie portu 80 z routera dostawcy na nasz router. W każdym razie musimy zapewnić swobodny dostęp z internetu do naszego urządzenia.
  • domena. Certyfikat wystawiany jest na domenę, więc musimy albo taką domenę gdzieś wykupić i wskazać ją na nasz router i adres IP lub założyć darmową domenę typu Dynamic DNS. Na potrzeby tego poradnika wykorzystano nazwę domeny host.ddns.net. Przy realizacji projektu wg tego poradnika należy pamiętać aby podać nazwę swojej domeny w każdym poleceniu w którym występuje!
Całość przetestowano na LEDE 17.01/OpenWrt 18.06

Instalacja serwera www

Jeżeli go jeszcze nie mamy w systemie:


    # opkg update
    # opkg install uhttpd libustream-openssl ip6tables kmod-ip6tables

Wraz z serwerem instalujemy obsługę https przez serwer oraz ipv6, ponieważ będzie to potrzebne aby skrypt weryfikacyjny działał poprawnie.

Dostęp do serwera www z internetu

Otwieramy porty 80 i 443 na wanie:


    # uci add firewall rule
    # uci set firewall.@rule[-1].src=wan
    # uci set firewall.@rule[-1].target=ACCEPT
    # uci set firewall.@rule[-1].proto=tcp
    # uci set firewall.@rule[-1].dest_port=80
    # uci add firewall rule
    # uci set firewall.@rule[-1].src=wan
    # uci set firewall.@rule[-1].target=ACCEPT
    # uci set firewall.@rule[-1].proto=tcp
    # uci set firewall.@rule[-1].dest_port=443
    # uci commit firewall
    # /etc/init.d/firewall restart

Sprawdzenie działania

Uruchamiamy serwer http:


    # /etc/init.d/uhttpd start

Na tym etapie musi być istnieć dostęp do serwera - wprowadzamy w przeglądarce adres http://host.ddns.net, musi zgłosić się nam strona lub zawartość katalogu (w zależności od tego czy i co mamy w routerze). Jeżeli nie ma dostępu - należy sprawdzić firewalla, ustawienie serwera lub to czy mamy publiczny adres IP na wanie, czy poprawnie działa domena, czy poprawnie został zaktualizowany adres w przypadku Dynamic DNS.
Jeżeli wszystko działa to ponownie wyłączamy serwer:


    # /etc/init.d/uhttpd stop

Generowanie certyfikatu

W sieci dostępnych jest wiele skryptów ułatwiających generowanie certyfikatu. My posłużymy się tym co domyślnie jest w LEDE - pakietem o nazwie acme:


    # opkg install acme ca-certificates socat wget
    # /etc/init.d/acme disable

Jego konfiguracja znajduje się w pliku /etc/config/acme i należy ją zmodyfikować wskazując domenę dla której chcemy wystawić certyfikat:


    # uci set acme.@acme[0].debug='1'
    # uci set acme.@acme[0].account_email='adres@email.com'
    # uci set acme.example.enabled='1'
    # uci set acme.example.update_uhttpd='1'
    # uci -q del acme.example.domains
    # uci -q del acme.example.use_staging
    # uci add_list acme.example.domains='host.ddns.net'
    # uci commit acme

Zamiast adres@email.com podajemy oczywiście swój rzeczywisty adres email.
I to już koniec konfiguracji. Uruchamiamy generowanie (uhttpd musi być w tym czasie wyłączony!):


    # /etc/init.d/uhttpd stop
    # /etc/init.d/acme start

Czekamy cierpliwie na zakończenie procesu. W logu systemowym można znaleźć dużą liczbę informacji związanych z weryfikacją domeny i generowaniem certyfikatu. Wynikiem działania skryptów będzie katalog z nazwą podanej domeny w katalogu /etc/acme:


    # ls /etc/acme
    account.conf
    ca
    http.header
    host.ddns.net

a w nim oczekiwane klucze i certyfikaty:


    # ls -1 /etc/acme/host.ddns.net/
    ca.cer
    fullchain.cer
    host.ddns.net.cer
    host.ddns.net.conf
    host.ddns.net.csr
    host.ddns.net.csr.conf
    host.ddns.net.key

Ponieważ przy konfiguracji acme była zaznaczone opcja aktualizacji uhttpd, to on także został zmieniony i ma wpisane aktualne certyfikaty:


    # uci show uhttpd.main.cert
    uhttpd.main.cert='/etc/acme/host.ddns.net/fullchain.cer'
    # uci show uhttpd.main.key
    uhttpd.main.key='/etc/acme/host.ddns.net/host.ddns.net.key'

Weryfikacja działania

Można sprawdzić nasz certyfikat:


    # openssl x509 -text -noout -in /etc/acme/host.ddns.net/fullchain.cer
    Certificate:
        Data:
            Version: 3 (0x2)
            Serial Number:
                04:48:5d:3b:3a:bf:0a:36:fd:2e:22:5e:6b:ac:82:xx:xx:xx
            Signature Algorithm: sha256WithRSAEncryption
                Issuer: C=US, O=Let's Encrypt, CN=Let's Encrypt Authority X3
                    Validity
                        Not Before: Nov 17 17:51:07 2017 GMT
                        Not After : Feb 15 17:51:07 2018 GMT
                    Subject: CN=host.ddns.net
                    Subject Public Key Info:
                        Public Key Algorithm: rsaEncryption
                            Public-Key: (2048 bit)
                                Modulus:
                                    00:b1:5e:29:b4:73:40:14:3c:4f:d8:e2:2f:af:86:
                                    e2:d4:3b:f2:04:23:26:d6:cd:c8:63:f9:4a:62:6b:
    ...

Co dalej? Wchodzimy przeglądarką na https://host.ddns.net, powinna pojawić się oczekiwana "zielona kłódka". Jeżeli tak jest - gratulacje. Dostałeś +1 do bezpieczeństwa.

Mała uwaga: certyfikat wystawiany jest na domenę, nie adres IP. Wpisanie https://192.168.1.1 spowoduje wyświetlenie błędu certyfikatu, ponieważ nie zgadza się domena dla której certyfikat został wystawiony.

Odnowienie certyfikatu

Skrypt acme instaluje się samodzielnie w cronie:


    # cat /etc/crontabs/root
    0 0 * * * /etc/init.d/acme start

Należy to zmienić, ponieważ bez wymuszenia i tak nie uda się odświeżyć certyfikatu wcześniej niż na miesiąc przed jego wygaśnięciem. Przy próbie odnowienia, w logu pojawi się informacja:


    # logread
    ...
    Fri Nov 17 21:41:34 2017 daemon.info run-acme[7286]: Found previous cert config. Issuing renew.
    Fri Nov 17 21:41:35 2017 daemon.err run-acme[7286]: Lets find script dir.
    Fri Nov 17 21:41:35 2017 daemon.err run-acme[7286]: _SCRIPT_='/usr/lib/acme/acme.sh'
    Fri Nov 17 21:41:35 2017 daemon.err run-acme[7286]: _script='/usr/lib/acme/acme.sh'
    Fri Nov 17 21:41:35 2017 daemon.err run-acme[7286]: _script_home='/usr/lib/acme'
    Fri Nov 17 21:41:35 2017 daemon.err run-acme[7286]: Using config home:/etc/acme
    Fri Nov 17 21:41:35 2017 daemon.info run-acme[7286]: https://github.com/Neilpang/acme.sh
    Fri Nov 17 21:41:35 2017 daemon.info run-acme[7286]: v2.6.8
    Fri Nov 17 21:41:35 2017 daemon.err run-acme[7286]: Using config home:/etc/acme
    Fri Nov 17 21:41:35 2017 daemon.err run-acme[7286]: DOMAIN_PATH='/etc/acme/host.ddns.net'
    Fri Nov 17 21:41:35 2017 daemon.info run-acme[7286]: Renew: 'host.ddns.net'
    Fri Nov 17 21:41:35 2017 daemon.err run-acme[7286]: Using config home:/etc/acme
    Fri Nov 17 21:41:35 2017 daemon.info run-acme[7286]: Skip, Next renewal time is: Tue Jan 16 18:51:10 UTC 2018
    Fri Nov 17 21:41:35 2017 daemon.info run-acme[7286]: Add '--force' to force to renew.
    Fri Nov 17 21:41:35 2017 daemon.info run-acme[7286]: Running post checks (cleanup).


Należy ustawić więc w cronie np. uruchomienie co 1 miesiąc lub po prostu uruchamiamy skrypt ręcznie w razie potrzeby.