Let’s Encrypt na reverznom proxy nginx

V minulom blogu sme vytvárali reverzný proxy server nginx a dnes by sme skúsili zabezpečiť backendy, pomocou skriptu od certbotu. Na zabezpečenie použijeme certifikačnú autoritu Let’s Encrypt, ktorá ako jedna z mála vydáva certifikáty zadarmo. Aj keď certifikáty sa vydávajú len na 90 dní, nám to vôbec nebude prekážať.

Prečo zabezpečiť web komunikáciu

V začiatkoch webu, fungovala komunikácia medzi serverom a klientom na protokole http (hypertext transfer protocol) na štandardnom http porte 80. Webové servery sú väčšinou prednastavené aby počúvali na tomto porte. Webová komunikácia funguje na báze server-klient. Obvyklé sa klient pýta (dotazuje) a server generuje odpovede. Ak by web fungoval dnes na takej úrovni ako pred 30 rokmi (prehliadanie textových stránok, obrázkov atď…) tak žiadne šifrovanie by sme nepotrebovali. Dnes však fungujú na webe rôzne eshopy, e-banking a mnoho ďalších webových aplikácii, kde sa prenášajú citlivé údaje. Z tohto pohľadu je http protokol veľmi nebezpečný. Cez http sa prenáša všetko v nezašifrovanej podobe, takže MiTM by mohol zachytiť akúkoľvek komunikáciu (server-klient). Preto v roku 1994 spoločnosť Nestscape Comunication vyvinula protokol https pre svoj webový prehliadač Nestscape Navigator.

Ako funguje https

Https (Hyper Text Transfer Protocol Secure) funguje presne ako http, ale navyše sa prenos dát pred odoslaním zašifruje. Štandardný port pre https je 443. Dnes sa na šifrovanie používa protokol TLS, čo je vlastne novšia verzia SSL, ale zaužívaná skratka ostala SSL.

  • SSL – Secure socket Layer
  • TLS – Transport Layer Security

Naviazanie spojenia klienta s webovým serverom (webovou stránkou ) prebieha následovne.

  • Server odošle prehliadaču kópiu svojho asymetrického verejného kľúču.
  • Prehliadač vytvorí jednorazový symetrický kľúč relácie (symmetric session key) a zašifruje ním asymetrický verejný kľúč servera, ktorý odošle následne späť serveru.
  • Server dešifruje prijatý kľúč použitím svojho privátneho asymetrického kľúča a získa tak symetrický kľúč relácie.
  • Server a prehliadač nadviažu spojenie a všetky odoslané a prijaté dáta šifrujú/dešifrujú pomocou vytvoreného symetrického kľúča relácie. Ten sa používa len na jednu reláciu a po jej ukončení sa ďalej nepoužíva.

Ešte je dôležité uviesť aj to, že SSL/TLS šifrovanie sa aplikuje medzi serverom a klientom. V našom prípade je klient webový prehliadač a server je reverzný proxy nginx. Následná komunikácia medzi reverzným proxy nginx a webovým serverom apache2 prebieha nešifrovane na http porte 80. Keďže webový server je v bezpečnej sieti, tak šifrovanie medzi frontendom a backendami je zbytočné.

CA Let’s Encrypt

Asi najznámejšou certifikačnou autoritou, ktorá vydáva certifikáty zdarma je Let’s Encrypt. Táto CA používa na vydávanie certifikátov, protokol ACME a o všetko sa stará agent certbot (existujú aj iný agenti, ale Let’s Encrypt odporúča použiť certbot) . CA nevydáva certifikáty hocikomu, kto o ne požiada. Žiadateľ o certifikát musí preukázať, že doména skutočne patri jemu. Ak CA overí vlastníka domény, tak vydá certifikát. Za pomoci certbotu je tento proces takmer plne automatizovaný a vyžaduje od admina len niekoľko ťukov do klávesnice. Veľmi peknú prednášku o Let’s Encrypt mal Ondřej Caletka na LinuxDays 2015, kde podrobne vysvetľoval ako to funguje.

Let’s Encrypt je certifikačná autorita, ktorej dôveruje väčšina webových prehliadačov (Google Chrome, Mozzila, Opera, Edge …), takže nemusíme mať obavu, že nám webový prehliadač označí web stránku za nebezpečnú. Asi takto to môže vyzerať ak používame certifikát, ktorý nie je podpísaný dôveryhodnou certifikačnou autoritou a prehliadač mu nedôveruje

Samozrejme toto nemusí byť vždy problémom. Ak sme si generovali a podpisovali certifikáty vlastnou CA založenou na knižnici openssl, tak je úplne jasné, že žiadny webový prehliadač im nebude dôverovať. My však vieme, že tomu certifikátu môžeme dôverovať a na web môžeme bez problémov pristúpiť

Presmerovanie adresy bez www na www

Pred rokmi, keď som zakladal prvé domény, tak som sa rozhodoval, či budem použivať v URL variantu s www, alebo bez www. Neviem či som sa rozhodol správne, alebo nesprávne, ale www (subdomain) integrujem do každej domény. Keď sme inštalovali reverzný proxy server, tak sme vytvárali aj konfiguračný súbor pre backendové servery a tam som neriešil žiadne www. Ak sme testovali backendy, tak sme do URL zadávali len doménové mená, pred ktoré sa automaticky doplnil typ protokolu http://

first-domain.com   --> http://first-domain.com
second-domain.com  --> http://second-domain.com

Teraz, keď weby opatrujeme SSL certifikátmi, tak (zatiaľ) nastavíme v konfiguračných súboroch presmerovanie na http://www. Ak klient do webového prehliadača zadá jednu z možnosti (viď prvý stĺpec), tak webový prehliadač mu vždy vráti (viď druhý stĺpec).

first-domain.com              --> http://www.first-domain.com
http://first-domain.com       --> http://www.first-domain.com
www.first-domain.com          --> http://www.first-domain.com
http://www.first-domain.com   --> http://www.first-domain.com

Nasledujúca konfigurácia je pre jednu doménu a v tejto chvíli pridáva do URL len www (https budeme riešiť neskôr)

server {
    listen 80;
    server_name first-domain.com;
    return 301 http://www.first-domain.com$request_uri;
}

server {
    listen 80;
    server_name www.first-domain.com;

    location / {
        proxy_pass http://192.168.1.111;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Inštalácia klienta a získanie certifikátu

Inštalácia je tak jednoduchá, že to zvládne úplne každý. Aby proces získania certifikátu bol úspešný musíme splniť niektoré podmienky.

  • Nainštalovaný Nginx (Apache)
  • Musíme mať založenú doménu
  • DNS záznam ktorý prepojí doménu s IP adresou servera
  • NAT portu 80 (alebo 443) na IP adresu servera
sudo apt-get update && sudo apt upgrade
sudo apt-get install certbot
sudo apt-get install python-certbot-nginx

V predošlom blogu sme v lokálnej sieti založili 2 domény first-domain.ddns.net a second-domain.ddns.net. Získanie certifikátu ukážem len pre jednu doménu. Vzhľadom k tomu, že doménu máme aj bez www aj s www, tak na DNS servery musíme mať k doméne vytvorene CNAME. Teraz môžeme spustiť proces generovania certifikátu. Plugin nginx sa postará aj o úpravu a reload konfiguračného súboru.

sudo certbot --nginx -d first-domain.ddns.net -d www.first-domain.ddns.net

Skript nám položí niekoľko otázok na ktoré musíme zodpovedať. Červenými pruhmi som prekryl doménové meno a zelenou čiarou som označil čo musíme vyplniť. Nasledujúci popis je pod obrázkom.

  • Skript nás vyzve aby sme zadali emailovú adresu
  • Po prečítaní podmienok a súhlasom s registráciou na ACME dáme A
  • Ak chceme byť informovaný o novinkách EFF dáme Y
  • Presmerovanie http na https, dáme 2

Ak vyberieme na poslednej otázke Please choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access možnosť 2, tak skript upraví konfiguračný súbor, kde nastaví redirect s http na https. My sa nemusíme o nič starať. Certbot do konfiguračného súboru doplnil ešte cesty k vygenerovaným certifikátom (takto nejak bude vyzerať nginx konfiguračný súbor).

server {
    server_name first-domain.ddns.net;
    return 301 http://www.first-domain.ddns.net$request_uri;

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/first-domain.ddns.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/first-domain.ddns.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    server_name www.first-domain.ddns.net;

    location / {
        proxy_pass http://192.168.1.111;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/first-domain.ddns.net/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/first-domain.ddns.net/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}

server {
    if ($host = first-domain.ddns.net) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name first-domain.ddns.net;
    return 404; # managed by Certbot

}

server {
    if ($host = www.first-domain.ddns.net) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name www.first-domain.ddns.net;
    return 404; # managed by Certbot

}

Za každým riadkom, prip. blokom, ktorý automaticky upravil certbot je komentár. Ak teraz klient do webového prehliadača zadá jednu z možnosti (viď prvý stĺpec), tak vždy mu webový prehliadač vráti (viď druhý stĺpec).

first-domain.com              --> https://www.first-domain.com
http://first-domain.com       --> https://www.first-domain.com
https://first-domain.com      --> https://www.first-domain.com
www.first-domain.com          --> https://www.first-domain.com
http://www.first-domain.com   --> https://www.first-domain.com
https://www.first-domain.com  --> https://www.first-domain.com

Obnova certifikátov

Let’s Encrypt vystavuje certifikáty vždy na 90 dní. Ak táto doba uplynie, certifikáty sa stanú neplatné. Pokiaľ sme inštalovali certbot pomocou baličkovacieho manažéra (apt), tak o obnovu sa prakticky bude starať certbor. Ak si to chceme preveriť, tak pozrieme či existuje /etc/cron.d/certbot, alebo môžeme v terminály, zadať nasledujúci príkaz.

sudo systemctl list-timers
cerbot-timer

Skript na obnovu sa spúšťa každých 12 hodín a ak je do expirácie certifikátu menej ako 30 dní, tak certifikát sa automaticky obnoví. Ak by nastal nejaký problém pri obnovovaní, tak certbot nás o tom informuje emailom. Ak sa chceme presvedčiť, či je všetko v poriadku, tak môžeme spustiť obnovu na sucho. Ak skript dokončí proces bez chyby, tak na konci nám zagratuluje

sudo certbot renew --dry-run

Záver

Ako sme videli v tomto blogu, tak zavedenie bezplatných certifikátov od spoločnosti Let’s Encrypt spočíva v inštalácii certbotu a zadaní jedného príkazu. Avšak celý systém musi byť na to vopred pripravený. Všetko ostatné vrátane úpravy konfiguračných súborov a budúceho obnovenia certifikátov je plne automatické. Dôležité je pochopiť ako https funguje, ale to nebolo cieľom tohto blogu. Odporúčam pozrieť video, kde to Ondřej Caletka všetko vysvetľuje.

Použitá literatúra

Leave a Reply

Vaša e-mailová adresa nebude zverejnená. Vyžadované polia sú označené *