Aby skonfigurować serwer HTTPS, należy włączyć parametr ssl na głównych gniazdach nasłuchujących w bloku server, a także wskazać lokalizację plików z certyfikatem serwera i kluczem prywatnym:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
}
Certyfikat serwera jest publiczny. Jest on wysyłany każdemu klientowi łączącemu się z serwerem. Klucz prywatny należy przechowywać w pliku z ograniczonym dostępem (uprawnienia dostępu muszą pozwalać głównemu procesowi nginx na odczyt tego pliku). Klucz prywatny można również przechowywać w jednym pliku z certyfikatem:
ssl_certificate www.example.com.cert;
ssl_certificate_key www.example.com.cert;
uprawnienia dostępu do pliku należy również ograniczyć. Mimo że zarówno certyfikat, jak i klucz są przechowywane w jednym pliku, klientowi wysyłany jest tylko certyfikat.
Dzięki dyrektywom ssl_protocols i ssl_ciphers można ograniczyć połączenia tak, aby używane były tylko „mocne” wersje i szyfry SSL/TLS. Począwszy od wersji 1.0.5, nginx domyślnie używa „ssl_protocols SSLv3 TLSv1” i „ssl_ciphers HIGH:!aNULL:!MD5”, więc jawne ich skonfigurowanie ma sens tylko dla starszych wersji nginx. Począwszy od wersji 1.1.13 i 1.0.12, nginx domyślnie używa „ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2”.
Wiadomo, że szyfry z trybem CBC są podatne na szereg ataków, w szczególności na atak BEAST (patrz CVE-2011-3389). Konfiguracja szyfrów może zostać zmieniona tak, aby preferowany był RC4-SHA:
ssl_ciphers RC4:HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
Optymalizacja serwera HTTPS
Operacje SSL zużywają dodatkowe zasoby procesora. W systemach wieloprocesorowych należy uruchamiać wiele procesów roboczych, nie mniej niż liczba dostępnych rdzeni procesora. Najbardziej wymagającą dla procesora operacją jest uzgadnianie parametrów SSL (SSL handshake), w ramach których generowane są parametry kryptograficzne sesji. Istnieją dwa sposoby zmniejszenia liczby tych operacji wykonywanych dla każdego klienta: używanie trwałych (keepalive) połączeń, które pozwalają na obsługę wielu żądań w ramach jednego połączenia, oraz ponowne wykorzystanie parametrów sesji SSL, aby zapobiec konieczności wykonywania uzgadniania parametrów SSL dla równoległych i kolejnych połączeń. Sesje są przechowywane w pamięci podręcznej sesji SSL, udostępnianej między procesami roboczymi i konfigurowanej dyrektywą ssl_session_cache. W 1 megabajcie pamięci podręcznej mieści się około 4000 sesji. Domyślny czas wygaśnięcia pamięci podręcznej wynosi 5 minut. Można go wydłużyć za pomocą dyrektywy ssl_session_timeout. Oto przykład konfiguracji zoptymalizowanej pod kątem systemu wielordzeniowego z 10-megabajtową udostępnioną pamięcią podręczną sesji:
worker_processes auto;
http {
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
server {
listen 443 ssl;
server_name www.example.com;
keepalive_timeout 70;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers HIGH:!aNULL:!MD5;
...
Łańcuchy certyfikatów SSL
Niektóre przeglądarki mogą wyświetlać ostrzeżenie dotyczące certyfikatu podpisanego przez powszechnie znany urząd certyfikacji, podczas gdy inne przeglądarki akceptują ten sam certyfikat bez problemu. Dzieje się tak, ponieważ urząd, który wydał certyfikat, podpisał go certyfikatem pośrednim, którego nie ma w bazie danych certyfikatów powszechnie zaufanych urzędów certyfikacji, dystrybuowanej wraz z przeglądarką. W takim przypadku urząd certyfikacji dostarcza „pęczek” certyfikatów, który należy dołączyć do certyfikatu serwera. Certyfikat serwera należy umieścić przed pęczkiem certyfikatów w połączonym pliku:
$ cat www.example.com.crt bundle.crt > www.example.com.chained.crt
Otrzymany plik należy wskazać w dyrektywie ssl_certificate:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.chained.crt;
ssl_certificate_key www.example.com.key;
...
}
Jeśli certyfikat serwera i pęczek certyfikatów zostały połączone w niewłaściwej kolejności, nginx odmówi uruchomienia i wyświetli komunikat o błędzie:
SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed
(SSL: error:0B080074:x509 certificate routines:
X509_check_private_key:key values mismatch)
ponieważ nginx spróbuje użyć klucza prywatnego z pierwszym certyfikatem z pęczka zamiast certyfikatu serwera.
Przeglądarki zazwyczaj przechowują otrzymane certyfikaty pośrednie podpisane przez zaufane urzędy certyfikacji, dlatego popularnie używane przeglądarki mogą już posiadać wymagane certyfikaty pośrednie i nie wyświetlać ostrzeżenia o certyfikacie wysłanym bez dołączonego do niego łańcucha certyfikatów. Upewnienie się, że serwer wysyła pełny łańcuch certyfikatów, można za pomocą narzędzia wiersza poleceń openssl, na przykład:
$ openssl s_client -connect www.godaddy.com:443
...
Certificate chain
0 s:/C=US/ST=Arizona/L=Scottsdale/1.3.6.1.4.1.311.60.2.1.3=US
/1.3.6.1.4.1.311.60.2.1.2=AZ/O=GoDaddy.com, Inc
/OU=MIS Department/CN=www.GoDaddy.com
/serialNumber=0796928-7/2.5.4.15=V1.0, Clause 5.(b)
i:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
/OU=http://certificates.godaddy.com/repository
/CN=Go Daddy Secure Certification Authority
/serialNumber=07969287
1 s:/C=US/ST=Arizona/L=Scottsdale/O=GoDaddy.com, Inc.
/OU=http://certificates.godaddy.com/repository
/CN=Go Daddy Secure Certification Authority
/serialNumber=07969287
i:/C=US/O=The Go Daddy Group, Inc.
/OU=Go Daddy Class 2 Certification Authority
2 s:/C=US/O=The Go Daddy Group, Inc.
/OU=Go Daddy Class 2 Certification Authority
i:/L=ValiCert Validation Network/O=ValiCert, Inc.
/OU=ValiCert Class 2 Policy Validation Authority
/CN=http://www.valicert.com//emailAddress=info@valicert.com
...
W tym przykładzie podmiot („s”) certyfikatu nr 0 serwera www.GoDaddy.com jest podpisany przez wydawcę („i”), który z kolei jest podmiotem certyfikatu nr 1, podpisanego przez wydawcę, który z kolei jest podmiotem certyfikatu nr 2, podpisanego przez powszechnie znanego wydawcę ValiCert, Inc., którego certyfikat jest przechowywany we wbudowanej w przeglądarki bazie danych certyfikatów (która w ciemnej piwnicy znajduje się w domu, który zbudował Jack).
Jeśli nie dodano pęczka certyfikatów, zostanie wyświetlony tylko certyfikat serwera nr 0.
Połączony serwer HTTP/HTTPS
Można skonfigurować pojedynczy serwer, który obsługuje zarówno żądania HTTP, jak i HTTPS:
server {
listen 80;
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
...
}
Do wersji 0.7.14 SSL nie można było włączyć selektywnie dla poszczególnych gniazd nasłuchujących, jak pokazano powyżej. SSL można było włączyć tylko dla całego serwera za pomocą dyrektywy ssl, co uniemożliwiało skonfigurowanie połączonego serwera HTTP/HTTPS. Aby rozwiązać ten problem, dodano parametr ssl dyrektywy listen. Dlatego używanie dyrektywy ssl we współczesnych wersjach nie jest zalecane.
Wybór serwera HTTPS na podstawie nazwy
Typowy problem pojawia się przy konfiguracji dwóch lub więcej serwerów HTTPS nasłuchujących na tym samym adresie IP:
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
W takiej konfiguracji przeglądarka otrzyma domyślny certyfikat serwera, czyli www.example.com, niezależnie od żądanego nazwy serwera. Wynika to z zachowania protokołu SSL. Połączenie SSL jest nawiązywane przed wysłaniem żądania HTTP przez przeglądarkę, a nginx nie zna żądanej nazwy serwera. W związku z tym może on zaoferować tylko domyślny certyfikat serwera.
Najstarszą i najbardziej niezawodną metodą rozwiązania tego problemu jest przypisanie każdemu serwerowi HTTPS własnego adresu IP:
server {
listen 192.168.1.1:443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
...
}
server {
listen 192.168.1.2:443 ssl;
server_name www.example.org;
ssl_certificate www.example.org.crt;
...
}
Certyfikat SSL z wieloma nazwami
>Istnieją również inne metody, które pozwalają na używanie tego samego adresu IP jednocześnie dla wielu serwerów HTTPS. Wszystkie one mają jednak swoje wady. Jedną z takich metod jest użycie certyfikatu z wieloma nazwami w polu SubjectAltName, na przykładwww.example.com oraz www.example.org. Jednak długość pola SubjectAltName jest ograniczona.
Inną metodą jest użycie certyfikatu wielodomenowego (wildcard), na przykład *.example.org. Taki certyfikat chroni wszystkie subdomeny określonej domeny, ale tylko na określonym poziomie. Pasuje do niego www.example.org, ale nie pasują example.org oraz www.sub.example.org. Powyższe dwie metody można łączyć. Certyfikat może jednocześnie zawierać zarówno dokładne nazwy, jak i nazwy wielodomenowe w polu SubjectAltName, na przykład example.org oraz *.example.org.
Lepiej umieścić informacje o pliku certyfikatu z wieloma nazwami oraz pliku klucza prywatnego na poziomie konfiguracji http, aby wszystkie serwery dziedziczyły ich jedyną kopię w pamięci:
ssl_certificate common.crt;
ssl_certificate_key common.key;
server {
listen 443 ssl;
server_name www.example.com;
...
}
server {
listen 443 ssl;
server_name www.example.org;
...
}
