26 kwi

Jak skonfigurować Nginx i HTTP/2 na Ubuntu 16.04

Nginx jest szybkim i niezawodnym otwartym (open-source) rozwiązaniem web serwera. Osiągnął taki sukces z dużej ilości powodów, takich jak wysoka skalowalność, łatwość w konfiguracji, zużycie małej ilości pamięci, wsparcie przeróżnych protokołów.

Jednym z takich obsługiwanych protokołów jest HTTP/2, który pojawił się na rynku nie tak dawno. Wcześniej pisaliśmy o wprowadzeniu HTTP/2 na wszystkich współdzielonych serwerach Hostovita.pl. Jego główną zaletą jest znaczne przyspieszenie ładowania zasobów dla stron internetowych.

Za pomocą tego materiału nauczysz się jak instalować i konfigurować HTTP/2 na serwerach VPS z Nginx`em.

Wymagania

Zanim zaczniemy konfiguracje, musimy przygotować następne rzeczy:

  • Serwer z zainstalowanym systemem Ubuntu 16.04 czy 14.04
  • Użytkownika z uprawnieniami grupy sudo (sprawdź Początkową konfigurację Ubuntu 16.04)
  • Zarejestrowaną domenę (możesz wykupić ją u nas w atrakcyjnych cenach)
  • Upewnij się, że domena czy poddomena jest skierowana na serwer
  • Certyfikat SSL (który jest dostępny na naszej stronie)

Jeżeli posiadasz wszystkie wyżej wymienione elementy – to możemy zacząć.

Różnica pomiędzy HTTP 1.1 a HTTP/2

HTTP/2 jest nową wersją “Hypertext Transport Protocol”, który jest wykorzystywany w sieci Internet do przekazania stron internetowych z serwera do przeglądarki użytkownika. HTTP/2 jest pierwszą poważną aktualizacją HTTP z 1999 roku, kiedy strony jeszcze mieli tylko jeden plik i w jakim od razu był CSS. Internet trochę się zmienił za ostatnie 16 lat, prawda? I teraz spotykamy się z ograniczeniami HTTP 1.1 – bo on ogranicza prędkość transmisji treści dla wszystkich nowoczesnych stron www (poprzednia część strony musi skończyć się ładować przed rozpoczęciem kolejnej), teraz średnio każda nowoczesna witryna wymaga pobranie około 100 różnych plików, dla którego tworzy się osobne połączenie z serwerem (każde połączenie jest powiązane z przekazaniem obrazku, plików .js, .css itp.).

HTTP/2 rozwiązuje problemy z wprowadzeniem absolutnie nowych funkcji:

  • Wszystkie zapytania do serwera lecą równolegle, a nie w kolejce jeden za drugim
  • Nagłówki HTTP teraz mają postać skompresowanych
  • Strona przekazuje się jako plik binarny, nie jako tekst, co jest dużo wydajniejszym
  • Serwer teraz może wysyłać treść jeszcze przed zapytaniem od przeglądarki, co pozwoli przyspieszyć stronę dla użytkowników, które mają duże opóźnienia

Na początku protokół HTTP/2 nie wymagał szyfrowania, ale programiści najpopularniejszych przeglądarek Google Chrome i Mozilla Firefox zdecydowali się na podwyższenie bezpieczeństwa i wykorzystanie HTTP/2 tylko dla połączeń HTTPS. Właśnie dlatego musisz posiadać certyfikat SSL dla migracji na nowy protokół.

Instalacja najnowszej wersji Nginx

Wsparcie i obsługa protokołu HTTP/2 została realizowana tylko w wersji Nginx 1.9.5, ale niestety repozytorium Ubuntu posiada domyślną wersje 1.4.6.

Na szczęście twórcy Nginx mają własne repozytorium dla systemu Ubuntu, skąd zawsze można pobrać ostatnią i aktualną wersję oprogramowania. Dodajmy najpierw ją do listy naszych apt repozytorium.

Przede wszystkim, musimy uzyskać podpisany klucz PGP wspominanego repozytorium, co będzie gwarantowało nam to, że wszystkie pakiety, które sciągniemy z repozytorium będą autentyczne i będą podpisane autorem.

wget -qO - http://nginx.org/keys/nginx_signing.key | sudo apt-key add -

Dalej, możemy dodać nowy repozytorium do listy źródeł naszej systemy paczek:

sudo echo -e "deb http://nginx.org/packages/mainline/ubuntu/ `lsb_release -cs` nginx\ndeb-src http://nginx.org/packages/mainline/ubuntu/ `lsb_release -cs` nginx" | sudo tee /etc/apt/sources.list.d/nginx.list

Teraz, kiedy nasze systemy zarządzania pakietów/wtyczek (w Ubuntu i Debian to się nazywa apt) wiedzą o nowym repozytorium, musimy zaktualizować listę dostępnych pakietów i, wreszcie, zainstalować najnowszą wersję nginx:

sudo apt-get update
sudo apt-get install nginx

Możesz sprawdzić wersję nginx, wpisując:

sudo nginx -v

Wynik powinien być podobny do nginx version: nginx/1.9.x.

W przypadku problemów z instalacją właściwej wersji Nginx, prosimy skompilować ostatnią wersję za pomocą tej instrukcji.

W kolejnych krokach zmodyfikujemy domyślny plik konfiguracyjny Nginx, który będzie zarządzał naszą stroną

 

Zmiana portu

W pierwszej kolejności zmienimy port dla naszej strony z 80 na 443.

Otwórzmy plik konfiguracyjny:

sudo nano /etc/nginx/conf.d/default.conf

Musimy wskazać nginx`owi przez jaki port będzie działała nasza strona, bo domyślnie dla HTTP jest to 80.

/etc/nginx/conf.d/default.conf
listen 80;

Protokół HTTP/2 nie będzie działać dla większośći użytkowników jeżeli zostawimy przekazywanie danych poprzez 80-ty. Zmieńmy port na 443, który jest wykorzystywany do szyfrowanych połączeń HTTPS.

/etc/nginx/conf.d/default.conf
listen 443 ssl http2;

Zwróć uwagę na to, że oprócz ssl dodaliśmy również i http2 na końcu linii. Ostatnia zmienna wskazuje Nginx korzystać z protokółu HTTP/2 dla wspieranych przeglądarek.

Zmiana nazwy serwera (Server Name)

W następnej linii po listen jest server_name. Tutaj musimy powiedzieć Nginx`owi jaka domena będzie powiązana z danym plikiem config. Domyślnie server_name jest ustawiony na localhost, co oznacza, że plik config odpowiada za wszystkie przychodzące żądania/połączenia. Jednak trzeba zmienić localhost na naszą domenę:

/etc/nginx/conf.d/default.conf
server_name example.com;

Teraz musimy zapisać nasz plik konfiguracyjny. Kliknij Ctrl+O , aby zapisać plik i Ctrl+X , aby zamknąć edytor nano.

Dodanie ścieżki do certyfikatów SSL

Następnie trzeba skonfigurować Nginx dla certyfikatu SSL. Jeśli nie wiesz, co to jest certyfikat SSL lub nie posiadasz takiego – możesz go kupić na stronie Certyfikaty SSL.

Utwórz katalog do przechowywania certyfikatów SSL wewnątrz konfiguracyjnego folderu Nginx:

sudo mkdir /etc/nginx/ssl

Skopiuj swój certyfikat i klucz prywatny do folderu. Możesz także zmienić nazwę plików tak, aby pokazać, do jakich domen oni należą (przyda się to w przyszłości, gdy będziesz mieć więcej niż jedną domenę). Zmieniamy example.com na swoją aktualną domenę:

sudo cp /path/to/your/certificate.crt /etc/nginx/ssl/example.com.crt
sudo cp /path/to/your/private.key /etc/nginx/ssl/example.com.key

Teraz znowu otwórzmy plik konfiguracyjny i skonfigurujmy SSL.

W nowej linii wewnątrz bloku server, zlokalizuj ścieżki do swoich certyfikatów.

ssl_certificate /etc/nginx/ssl/example.com.crt;
ssl_certificate_key /etc/nginx/ssl/example.com.key;

Przekierowanie zapytań z HTTP na HTTPS

Ponieważ jesteśmy zainteresowani w przekazaniu treści tylko przez HTTPS, to musimy powiedzieć Nginx`owi, co on powinien zrobić, gdy serwer otrzyma zapytanie przez HTTP.

Na dole naszego pliku konfiguracyjnego, stwórzmy nowy blok server dla przekierowania wszystkich żądań HTTP na HTTPS (musisz zmienić w server_name – nazwę domeny):

/etc/nginx/conf.d/default.conf
server {
       listen         80;
       server_name    example.com;
       return         301 https://$server_name$request_uri;
}

Ignorując zakomentowane linie Twój plik konfiguracyjny będzie wyglądał w następny sposób:

server {
    listen       443 ssl http2;
    server_name  example.com;
    ssl_certificate /etc/nginx/ssl/example.com.crt;
    ssl_certificate_key /etc/nginx/ssl/example.com.key;
    location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }
}
server {
       listen         80;
       server_name    example.com;
       return         301 https://$server_name$request_uri;
}

Zapisujemy zmiany za pomocą klawiszy Ctrl+O i kombinacją Ctrl+X zamykamy plik.

Resetujemy Nginx

Aby zmiany zostały zastosowane, należy ponownie uruchomić serwer Nginx.

sudo service nginx restart

Sprawdźmy czy nasz serwer jest uruchomiony i działa poprawnie. Otwórz przeglądarkę i przejdź na stronę pod Twoją domeną (zastąp example.com na twoją domenę):

example.com

Jeżeli wszystko zostało skonfigurowane poprawnie, musisz być automatycznie przekierowany na HTTPS. Teraz sprawdźmy, czy protokół HTTP/2 działa: otwórzmy w przeglądarce Chrome Narzędzia Developer Tools (F12) i przeładujmy stronę (F5). Następnie przejdź do zakładki Network (Sieć), kliknij na nagłówku tabeli, który zaczyna się od Name (Nazwa), kliknij prawym przyciskiem myszki na niego i wybierz opcję Protokół.
Jak widać, pojawiło się znaczenie h2 (które jest skrótem od HTTP/2) w nowej kolumnie dla przekazywanej treści Twojej strony internetowej.

http2_console

Teraz nasz serwer jest w stanie przekazywać treść strony internetowej za pomocą protokołu HTTP/2, ale są jeszcze kilku rzeczy, które musimy zmienić żeby używać serwer w produkcji.

Optymalizacja Nginx dla najlepszej wydajności

W tym kroku należy skonfigurować plik konfiguracyjny Nginx dla lepszej wydajności i bezpieczeństwa.

Przede wszystkim, otwórzmy nginx.conf wpisując w konsoli:
sudo nano /etc/nginx/nginx.conf

Włączenie Connection Credentials Caching

HTTP w porównaniu do HTTPS potrzebuje stosunkowo więcej czasu, aby ustawić połączenie między serwerem a użytkownikiem. Aby zminimalizować tą różnicę w szybkości ładowania strony, włączymy buforowanie danych logowania (connection credentials caching). Oznacza to, że zamiast tworzenia nowej sesji na każde zapytania strony, serwer użyje już zapisaną wersję połączenia.

Aby włączyć buforowanie sesji, należy dodać następne linie do bloku http w pliku nginx.conf:

/etc/nginx/nginx.conf
ssl_session_cache shared:SSL:5m;
ssl_session_timeout 1h;

ssl_session_cache określa rozmiar bufora, który będzie zawierać informacje na temat sesji. 1 MB może przechowywać informacje dla około 4000 sesji. Wartość w 5 Mb będzie więcej niż wystarczająco dla większości użytkowników, ale jeżeli planujesz naprawdę duży ruch, można użyć tej wartości.

ssl_session_timeout ogranicza czas przechowywania danej sesji w pamięci podręcznej. Wartość ta nie powinna być zbyt duża (ponad godzinę), ale i ustawienie zbyt niskiej też nie będzie miało sensu.

 

Optymalizacja szyfrowania

Cipher posiada kilku algorytmów kryptograficznych, które opisują dokładnie jak przekazywane dane muszą być szyfrowane. HTTP/2 ma ogromną czarną listę starych i niebezpiecznych szyfrów, których musimy unikać.

Będziemy korzystać z bardzo popularnego zestawu szyfrów, bezpieczeństwo których zostało potwierdzone przez Internetowych gigantów, takich jak CloudFlare. I to nie pozwali nam na korzystanie z szyfrowania MD5 (które było uznane jako niebezpieczne jeszcze z 1996 roku, ale mimo to, jest stosowane powszechne, nawet po dzień dzisiejszy).

Dodamy te dwie linie po ssl_session_timeout.

/etc/nginx/nginx.conf
ssl_prefer_server_ciphers on;
ssl_ciphers EECDH+CHACHA20:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5;

Włączenie Strict Transport Security (HSTS)

Chociaż zrobiliśmy już przekierowanie wszystkich zapytań z HTTP na HTTPS w naszym plik konfiguracyjny Nginx, musimy również włączyć HSTS, aby uniknąć przekierowań.

Jeśli przeglądarka znajdzie nagłówek HSTS – ona nie będzie próbowała połączyć się z serwerem poprzez zwykły protokół HTTP za podany okres czasu. Nieważne jaka treść, wszystko będzie przekazywane z wykorzystaniem szyfrowanego połączenia HTTPS.

Musimy dodać tylko jedną linię do pliku:

/etc/nginx/nginx.conf
add_header Strict-Transport-Security "max-age=15768000" always;

Znaczenie max-age jest ustawiane w sekundach. 15768000 sekund równa się 6 miesięcy.

Domyślnie ten nagłówek nie będzie dodany do subdomen. Jeżeli masz subdomeny i chcesz włączyć dla nich też HSTS – należy dodać zmienną includeSubDomains na końcu wiersza:

/etc/nginx/nginx.conf
add_header Strict-Transport-Security "max-age=15768000; includeSubDomains: always;

Więc teraz możesz zapisać zmiany w pliku  Ctrl+O i zamknąć go za pomocą Ctrl+X.

Zwiększenie bezpieczeństwa podczas wymianą kluczami

Pierwszy krok w tworzeniu bezpiecznego połączenia – wymiana prywatnego klucza pomiędzy serwerem a klientem. Ale problem jest w tym, że do tego momentu polączenie między nimi nie jest zaszyfrowane i przesyłane dane są widoczny osobom trzecim. Dlatego musimy użyć algorytm Diffie–Hellman–Merkle. Techniczne szczegóły tego algorytmu nie da się wyjaśnić w dwóch słowach, bo on jest dość skomplikowanym.

Domyślnie Nginx używa 1028 bitowy Efemeryczny klucz Diffie-Hellmana, który można w łatwy sposób dekodować. W celu zapewnienia maksymalnego bezpieczeństwa, musimy zbudować nasz własny, bezpieczniejszy klucz.

Aby to zrobić, wpiszemy w konsoli następne polecenie:

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

Należy pamiętać, że musimy wygenerować ustawienia DH w tym samym folderze, gdzie są nasze certyfikaty SSL. W tym przykładzie, certyfikaty znajdują się w/etc/nginx/ssl/. To jest spowodowane tym, że Nginx zawsze szuka klucze DHE użytkownika w folderze z certyfikatami i używa ich, jeżeli te klucze tam istnieją.

Zmienna po ścieżce do pliku (w naszym przypadku 2048) określa długość klucza. Klucz z długością 2048 bit jest dość bezpiecznym według rekomendacji od Mozilla Foundation, ale jeżeli chcesz jeszcze bezpieczniejszego rozwiązania – możesz zmienić go do 4096.

Proces tworzenia klucza trwa około 5 minut.

Teraz musimy ponownie uruchomić serwer Nginx, aby zastosować zmiany.

sudo service nginx restart

Wnioski

Teraz twoje połączenie SSL jest bezpieczne i może być stosowane do przekazywania poufnych informacji. Jeśli chcesz sprawdzić swoje połączenie SSL, możesz uruchomić test twojego serwera na stronie Qualys SSL Lab. Jeżeli wszystko jest prawidłowo skonfigurowane, uzyskasz A+ z bezpieczeństwa.

Na razie wszystko, Twój serwer Nginx jest gotowy. Jak widać, HTTP/2 to doskonałe rozwiązanie dla poprawy prędkości przesyłania danych, i jak widać, jest to dość łatwe do konfiguracji.