13 cze

Jak utworzyć samopodpisany (self-signed) certyfikat SSL dla Nginx w Ubuntu 16.04

TLS (ang. Transport Layer Security) jest rozwinięciem protokołu SSL (ang. Secure Socket Layer), który jest dodatkową warstwą zabezpieczenia bezpieczeństwa dla stron www. Wykorzystuje się dla szyfrowania ruchu sieciowego.

Wykorzystując tą technologię, serwery mogą śmiało wysyłać zapytania i dane pomiędzy serwerem i klientami bez możliwości przechwycenia danych przez osoby trzecie. System certyfikacji także pomaga użytkownikom sprawdzić tożsamości strony internetowej do której on jest podłączony.

W tym poradniku pokażemy Ci, jak utworzyć samopodpisany (self-signed) certyfikat SSL dla wykorzystania z serwerem www Nginx w Ubuntu 16.04.

Uwaga: samopodpisany certyfikat zabezpieczy szyfrowaną komunikację pomiędzy serwerem, a klientem. Jednak, przez to, że on nie został podpisany przez żaden z autoryzowanych centrum certyfikacji, użytkownicy nie mogą zweryfikować tożsamości Twojego serwera.

Taki certyfikat można użyć w przypadku braku powiązanej z serwerem domeny internetowej i kiedy strona niedostępna innym użytkownikom. Jeżeli nie masz domeny – lepiej wykupić podpisany CA certyfikat. Jak skorzystać z darmowego certyfikatu SSL od Lets Encrypt – opisaliśmy tutaj.

Zaczniemy

Przed rozpoczęciem procesu tworzenia certyfikatu musisz posiadać użytkownika z uprawnieniami sudo. Jak utworzyć takiego użytkownika – opisaliśmy w artykule o Wstępnej konfiguracji serwera.

Również pasowałoby mieć zainstalowany serwer WWW Nginx. Jeżeli chcesz zainstalować cały zestaw LEMP (Linux, Nginx, MySQL, PHP) na serwerze VPS możesz użyć tej instrukcji.

W przypadku spełnienia poprzednich warunków możemy rozpocząć.

Tworzenie certyfikatu SSL

Protokół TLS/SSL działa z wykorzystaniem połączonych publicznych i prywatnych kluczy. Klucz SSL jest przechowywany na serwerze w tajemnice. Jest on używany do szyfrowania wysylającej treści do klientów/użytkowników. Certyfikat SSL jest publicznie dostępny i przekazuje się podczas żądania treści. On może być wykorzystany do odszyfrowania przekazanych zapytań, które były podpisane właściwym certyfikatem SSL.

Możemy utworzyć samopodpisany (self-signed) klucz oraz certyfikat przy pomocy OpenSSL jednym poleceniem:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/ssl/private/nginx-selfsigned.key -out /etc/ssl/certs/nginx-selfsigned.crt

Zostaniesz poproszony o odpowiedzi na kilku zapytań. Zanim przejdziemy dalej, rzućmy okiem na to, co oznacza to górne polecenie:

  • openssl: jest podstawowym narzędziem do tworzenia i zarządzania certyfikatami OpenSSL, kluczami i innymi plikami.
  • req: to polecenie wyznacza rodzaj podpisanego certyfikatu, w naszym przypadku X.509. X.509 jest standardem kluczy publicznych .
  • -x509: wskazuje dla poprzedniego polecenia to, że certyfikat będzie podpisany własnym podpisem.
  • -nodes: ta opcja mówi, że nie będziemy zabezpieczać wygenerowany OpenSSL certyfikat dodatkowym hasłem.
  • -days 365: ta opcja określa czas, w ciągu jakiego certyfikat będzie ważnym. Ustawiamy go na 1 rok.
  • -newkey rsa:2048: to oznacza, że chcemy utworzyć nowy certyfikat i klucz jednocześnie.
  • -keyout: ten wiersz określa OpenSSL, gdzie umieścić nasz generowany klucz prywatny.
  • -out: tutaj określamy gdzie umieścić certyfikat, który zostanie stworzony.

Jak już wspomnieliśmy wcześniej to polecenie utworzy i klucz prywatny i certyfikat.

Dalej należy odpowiedzieć na wszystkie zapytania. W polu Common Name (e.g. server FQDN or YOUR name) należy  podać nazwę domeny, związanej z serwerem, albo jego publiczny adres IP.

Odpowiedź
Country Name (2 letter code) [AU]:PL
State or Province Name (full name) [Some-State]:Rzeszow
Locality Name (eg, city) []:Rzeszow
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Hostovita sp. z o.o.
Organizational Unit Name (eg, section) []:Hostovita
Common Name (e.g. server FQDN or YOUR name) []:adres_ip_serwera
Email Address []:admin@hostovita.pl

Aba utworzone pliki będą umieszczone w podkatalogach w /etc/ssl.

Następnie za pomocą OpenSSL utwórzmy grupę Diffie-Hellman dla jeszcze większego bezpieczeństwa.

Możemy to zrobić wpisując:

sudo openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048

Ten proces może potrwać kilka minut, ale jak on się skończy będziesz miał silną grupę DH w folderze /etc/ssl/certs/dhparam.pem, którą wykorzystamy w naszej konfiguracji.

Konfiguracja Nginx dla wykorzystania SSL

Stworzyliśmy nasz klucz oraz certyfikat w katalogu /etc/ssl. Teraz musimy zmienić naszą konfigurację Nginx, aby korzystać z tego protokołu.

Dokonamy kilku zmian w konfiguracji:

  1.  Stworzymy fragment konfiguracji z użyciem naszego certyfikatu SSL i lokalizacją naszego klucza.
  2. Stworzymy fragment konfiguracji, zawierający mocne ustawienia SSL, który może być wykorzystany dla jakiegokolwiek certyfikatu w przyszłości.
  3. Zmienimy nasze server bloki w Nginx dla obsługi SSL i skorzystamy z dwóch wcześniejszych fragmentów.

Ta metoda konfiguracji Nginx pozwoli nam zachować czytelność pliku konfiguracyjnego i umieścić wspólne ustawienia  w moduły wielokrotnego użytku.

Tworzenie fragmentu wskazującego na klucz i certyfikat SSL

Po pierwsze, stwórzmy nowy plik z ustawieniami Nginx w katalogu /etc/nginx/snippets.

Aby poprawnie zlokalizować ten plik, nazwiemy go self-signed.conf:
sudo nano /etc/nginx/snippets/self-signed.conf

W tym pliku ustawimy folder ssl_certificate z naszym certyfikatem i ssl_certificate_key dla klucza. W naszym przypadku plik będzie wyglądał następująco:

/etc/nginx/snippets/self-signed.conf
ssl_certificate /etc/ssl/certs/nginx-selfsigned.crt;
ssl_certificate_key /etc/ssl/private/nginx-selfsigned.key;

Po dodaniu tych linii – zapisz i zamknij plik.

Tworzenie fragmentu z mocną konfiguracją szyfrowania

Następnie tworzymy jeszcze jeden fragment, który pozwoli nam określić niektóre parametry SSL. Pozwoli to nam ustawić Nginx w taki sposób, żeby serwer był bardziej zabezpieczony od ataków.

Parametry, które ustawimy, mogą być wykorzystane również w przyszłych konfiguracjach Nginx i dla tego damy właściwą nazwę plikowi:

sudo nano /etc/nginx/snippets/ssl-params.conf

Dodamy do pliku następną informację z lokalizacją pliku Diffie-Hellman ssl_dhparam:

/etc/nginx/snippets/ssl-params.conf
# from https://cipherli.st/
# and https://raymii.org/s/tutorials/Strong_SSL_Security_On_nginx.html

ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
ssl_ecdh_curve secp384r1;
ssl_session_cache shared:SSL:10m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;

ssl_dhparam /etc/ssl/certs/dhparam.pem;

Zapisz i zamknij plik.

Konfiguracja Nginx dla SSL

Teraz już posiadamy fragmenty kodu za pomocą których możemy zmodyfikować konfigurację Nginx, aby włączyć SSL.

Liczymy, że korzystasz z default server block w pliku konfiguracyjnym w folderze /etc/nginx/sites-available. Jeżeli używasz innego server bloku, należy zamienić go w następujących poleceniach.

Zanim przejdziemy dalej, zrobimy kopie zapasową naszego pliku konfiguracyjnego:
sudo cp /etc/nginx/sites-available/default /etc/nginx/sites-available/default.bak

Otwórzmy plik z server block:
sudo nano /etc/nginx/sites-available/default

Plik będzie się zaczynał z podobnego do tego kodu:

/etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;

    # SSL configuration

    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    . . .

Będziemy wprowadzać zmiany w tej konfiguracji, aby niezaszyfrowane zapytania HTTP automatycznie się przekierowywali na szyfrowany protokół HTTPS. To zapewnia maksymalne bezpieczeństwo dla naszych stron internetowych. Jeśli chcesz zezwolić HTTP i HTTPS, skorzystaj z alternatywnej konfiguracji.

Podzielimy bloki z konfiguracją na dwa bloki. Po pierwszych dwóch listen dodajmy server_name, i ustawmy na domenę naszego serwera albo adresu IP. Następnie ustawimy przekierowanie na drugi blok.

/etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name domena_czy_adres_IP;
    return 302 https://$server_name$request_uri;
}

    # SSL configuration

    # listen 443 ssl default_server;
    # listen [::]:443 ssl default_server;

    . . .

Następnie musimy dodać nowy blok Server zawierający resztę konfiguracji. Można odkomentować dwie listen dyrektywy, które wykorzystują port 443. Możemy dodać HTTP2 do tych linii, aby włączyć HTTP/2 w tym bloku. Po tym, trzeba tylko włączyć dwa fragmenty plików konfiguracyjny:

/etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name server_domain_or_IP;
    return 302 https://$server_name$request_uri;
}

server {

    # SSL configuration

    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;

    . . .

Zapisz i zamknij plik jak skończysz.

(Konfiguracja alternatywna) włączamy ruch przez HTTP i HTTPS

Jeżeli chcesz lub musisz mieć przekazywanie zaszyfrowanej i niezaszyfrowanej treści, musisz skonfigurować Nginx trochę inaczej. Wcale nie polecamy tego robić, jeżeli można tego uniknąć.

/etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;

    server_name domena_czy_adres_IP_serwera;
    include snippets/self-signed.conf;
    include snippets/ssl-params.conf;

    . . .

Zapisz i zamknij plik.

Konfiguracja zapory sieciowej

Jeżeli masz włączoną zaporę ufw, jak to było wskazane w poprzednich artykułach, musisz zmienić jej ustawienia, aby włączyć ruch przez SSL. Na szczęście, Nginx rejestruje kilka profili ufw podczas instalacji.

Możemy zobaczyć dostępne profile wpisując:
sudo ufw app list

Dostaniesz podobną listę:

Odpowiedź
Available applications:
  Nginx Full
  Nginx HTTP
  Nginx HTTPS
  OpenSSH

Można wyświetlić bieżące ustawienia przy pomocy polecenia:
sudo ufw status

Odpowiedź będzie wyglądała następująco, co oznacza, że tylko ruch poprzez HTTP jest dozwolony:

Odpowiedź
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx HTTP                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx HTTP (v6)            ALLOW       Anywhere (v6)

Dodatkowo udostępnimy możliwość ruchu przez HTTPS, więc zostawimy profil “Nginx Full” i usuniemy profil “Nginx HTTP”:
sudo ufw allow 'Nginx Full'
sudo ufw delete allow 'Nginx HTTP'

Teraz status musi wyglądać następująco:
sudo ufw status

Odpowiedź
Status: active

To                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Nginx Full                 ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Nginx Full (v6)            ALLOW       Anywhere (v6)

Włączamy zmiany w Nginx

Teraz jak dokonaliśmy zmian w serwerze www i firewallu, możemy zresetować Nginx dla wprowadzenia naszych zmian.

Po pierwsze, musimy sprawdzić poprawność zmian na błędy syntaktyczne. Możemy zrobić to przy pomocy:
sudo nginx -t

Jeżeli wszystko przeszło pomyślnie, dostaniesz wynik:

Odpowiedź
nginx: [warn] "ssl_stapling" ignored, issuer certificate not found
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Należy zwrócić uwagę na ostrzeżenie na początku. Jak wspomnialiśmy wcześniej, to ostrzeżenie wyświetla się, ponieważ nasz certyfikat jest samopodpisanym nie może korzystać z protokołu SSL do bindowania danych.
Jeżeli dostałeś taki wynik, jak wyżej – to znaczy że nie masz błędów w nim i możesz ponownie uruchomić Nginx:
sudo systemctl restart nginx

Testowanie szyfrowania

Teraz możemy sprawdzić SSL na naszym serwerze.

Otwórz przeglądarkę i wpisz https:// i następnie domenę czy adres IP serwera:

https://domena_czy_adres_IP

Przez to, zę nasz certyfikat nie został podpisany przez żadną instytucję, otrzymamy takie ostrzeżenie:

self_signed_warning[1]

Jest to normalnie, teraz musimy przejść do Zaawansowanych (Advanced) i kliknąć w link:

warning_override[1]

Ustawienie stałego przekierowania

Jeżeli kod działa poprawnie i jesteś pewien w tym, żeby przepuścić cały ruch przez zaszyfrowany protokół musisz zmienić rodzaj przekierowania na stałe.

Otwórz plik konfiguracyjny i znajdź server block
sudo nano /etc/nginx/sites-available/default

Znajdź return 302 i zmień na return 301:

/etc/nginx/sites-available/default
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    server_name server_domain_or_IP;
    return 301 https://$server_name$request_uri;
}

. . .

Zapisz i zamknij plik.

Sprawdź plik na możliwe błędy:
sudo nginx -t

Uruchom ponownie Nginx dla zmiany przekierowania:
sudo systemctl restart nginx

Wnioski

Skonfigurowałeś serwer www Nginx dla wykorzystania bezpiecznego połączenia HTTPS, co pozwoli bezpiecznie obsługiwać żądania użytkowników strony.