Mercurial > hg > nginx-site
view xml/it/docs/http/configuring_https_servers.xml @ 2894:438a9cfa4fae
Added info about setting r.headersOut in njs reference.
author | Yaroslav Zhuravlev <yar@nginx.com> |
---|---|
date | Fri, 30 Sep 2022 16:42:42 +0100 |
parents | 6303d4e343a8 |
children |
line wrap: on
line source
<!-- Copyright (C) Igor Sysoev Copyright (C) Nginx, Inc. --> <!DOCTYPE article SYSTEM "../../../../dtd/article.dtd"> <article name="Configurazione di server HTTPS" link="/it/docs/http/configuring_https_servers.html" lang="it" translator="Angelo Papadia" rev="6" author="Igor Sysoev" editor="Brian Mercer"> <section> <para> Per configurare un server HTTPS, bisogna configurare il parametro <literal>ssl</literal> nel <link doc="ngx_http_core_module.xml" id="listen">socket in ascolto</link> del blocco <link doc="ngx_http_core_module.xml" id="server"/>, e specificare dove sono i file del certificato del server e della relativa chiave private: <programlisting> server { listen 443 <b>ssl</b>; server_name www.example.com; ssl_certificate <b>www.example.com.crt</b>; ssl_certificate_key <b>www.example.com.key</b>; ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2; ssl_ciphers HIGH:!aNULL:!MD5; ... } </programlisting> Il certificato del server e' pubblico: e' inviato a tutti i client che si connettono al server; la chiave privata al contrario non e' pubblica, e dovrebbe essere salvata in un file con restrizioni d'accesso, e comunque non leggibile dal processo master di nginx. In alternativa, la chiave privata puo' essere salvata nel medesimo file del certificato: <programlisting> ssl_certificate www.example.com.cert; ssl_certificate_key www.example.com.cert; </programlisting> pure in questo caso i diritti d'accesso al file dovrebbero essere ristretti. Anche quando certificato e chiave privata sono salvati entrambi in un unico file, solo il certificato e' inviato al client. </para> <para> Le direttive <link doc="ngx_http_ssl_module.xml" id="ssl_protocols"/> e <link doc="ngx_http_ssl_module.xml" id="ssl_ciphers"/> possono essere usate per limitare l'uso alle sole versioni e cifrature forti di SSL/TLS nelle connessioni. nginx usa per default “<literal>ssl_protocols SSLv3 TLSv1</literal>” e “<literal>ssl_ciphers HIGH:!aNULL:!MD5</literal>” sin dalla versione 1.0.5, per cui una configurazione esplicita ha senso solo per le versioni di nginx piu' vecchie. Dalle versioni 1.1.13 e 1.0.12 nginx usa per default “<literal>ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2</literal>”. </para> <para> La modalita' di cifratura CBC e' potenzialmente vulnerabile ad una serie di attacchi, in particolare ad un attacco BEST (vedi <link url="http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2011-3389">CVE-2011-3389</link>). La configurazione della cifratura puo' essere modificata in maniera da utilizzare RC4-SHA: <programlisting> ssl_ciphers RC4:HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; </programlisting> </para> </section> <section id="optimization" name="Ottimizzazione di server HTTPS"> <para> Le operazioni SSL utilizzano pesantemente la CPU. Su sistemi multiprocessore e' bene avviare processi worker in numero almeno pari a quello dei core. L'operazione piu' gravosa per la CPU e' l'handshake SSL. Ci sono due modi per minimizzare il numero di tali operazioni per client: il primo consiste nell'abilitare connessioni keepalive per inviare diverse richieste tramite un'unica connessione; il secondo prevede di riutilizzare i parametri della sessione SSL in maniera tale da evitare l'handshake SSL per connessioni parallele e susseguenti. Le sessioni sono salvate in una cache di sessione SSL, condivisa fra i worker e configurata dalla direttiva <link doc="ngx_http_ssl_module.xml" id="ssl_session_cache"/>. Un megabyte di cache contiene circa 4000 sessioni. Il timeout di default della cache e' di 5 minuti; puo' essere aumentato intervenendo sulla direttiva <link doc="ngx_http_ssl_module.xml" id="ssl_session_timeout"/>. Segue una configurazione di esempio ottimizzata per un sistema multicore con 10 megabyte di cache di sessione condivisa: <programlisting> <b>worker_processes auto</b>; http { <b>ssl_session_cache shared:SSL:10m</b>; <b>ssl_session_timeout 10m</b>; server { listen 443 ssl; server_name www.example.com; <b>keepalive_timeout 70</b>; 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; ... </programlisting> </para> </section> <section id="chains" name="Catene di certificati SSL"> <para> Capita talvolta che alcuni certificati server firmati da autorita' di certificazione ben note siano tranquillamente accettati da alcuni browser, ma mostrino invece problemi con altri. Cio' succede quando' l'autorita' emittente ha firmato il certificato usandone uno intermedio che non e' presente nell'elenco delle autorita' di certificazione distribuito con uno specifico browser. In tal caso l'autorita' fornisce un gruppo di certificati che dovrebbero essere concatenati al certificato server firmato. Il certificato server deve comparire prima dei certificati concatenati nel file risultante: <programlisting> $ cat www.example.com.crt bundle.crt > www.example.com.chained.crt </programlisting> Il file che ne deriva va usato con la direttiva <link doc="ngx_http_ssl_module.xml" id="ssl_certificate"/>: <programlisting> server { listen 443 ssl; server_name www.example.com; ssl_certificate www.example.com.chained.crt; ssl_certificate_key www.example.com.key; ... } </programlisting> Se il certificato server ed il gruppo di certificati sono stati concatenati nell'ordine sbagliato, nginx non riuscira' a partire e mostrera' il seguente messaggio di errore: <programlisting> SSL_CTX_use_PrivateKey_file(" ... /www.example.com.key") failed (SSL: error:0B080074:x509 certificate routines: X509_check_private_key:key values mismatch) </programlisting> dato che nginx ha tentato di usare la chiave privata non con il certificato server ma con il primo certificato del gruppo. </para> <para> Di solito i browser salvano i certificati intermedi che ricevono se sono firmati da autorita' di certificazione riconosciute, per cui browser molto usati potrebbero gia' avere i certificati intermedi richiesti, e quindi non avere problemi anche quando ricevono un certificato privo della relativa concatenazione di certificati. Comunque, per assicurare che il server invii la concatenazione di certificati completa, e' possibile usare da linea di comando il programma <command>openssl</command>, ad esempio: <programlisting> $ 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/<b>CN=www.GoDaddy.com</b> /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=<b>ValiCert, Inc.</b> /OU=ValiCert Class 2 Policy Validation Authority /CN=http://www.valicert.com//emailAddress=info@valicert.com ... </programlisting> In questo esempio, il soggetto (“<i>s</i>”, vale a dire "<i>subject</i>") del certificato server #0 <literal>www.GoDaddy.com</literal> e' firmato da un emittente (“<i>i</i>”, vale a dire "<i>issuer</i>") che a sua volta e' il soggetto del certificato #1, il quale e' firmato da un emittente che e' il soggetto del certificato #2, che e' finalmente firmato dalla autorita' di certificazione ben nota <i>ValiCert, Inc.</i>, il cui certificato e' presente nella base dati precaricata del browser ("che al mercato mio padre compro'"). </para> <para> Se il gruppo di certificati non fosse stato aggiunto, sarebbe stato visualizzato il solo certificato #0. </para> </section> <section id="single_http_https_server" name="Un server unico per HTTP e HTTPS"> <para> E' possibile configurare un singolo server che tratti sia richieste HTTP, sia richieste HTTPS: <programlisting> server { listen 80; listen 443 ssl; server_name www.example.com; ssl_certificate www.example.com.crt; ssl_certificate_key www.example.com.key; ... } </programlisting> <note> Prima della versione 0.7.14, SSL non poteva essere abilitato selettivamente per singoli socket in ascolto, come nell'esempio precedente: SSL poteva solo essere abilitato per l'intero server, usando la direttiva <link doc="ngx_http_ssl_module.xml" id="ssl"/>, e rendendo quindi impossibile la configurazione di un server unico per HTTP e HTTPS. Il parametro <literal>ssl</literal> della direttiva <link doc="ngx_http_core_module.xml" id="listen"/> e' stato aggiunto per risolvere questo problema. L'uso della direttiva <link doc="ngx_http_ssl_module.xml" id="ssl"/> e' pertanto sconsigliato nelle versioni recenti. </note> </para> </section> <section id="name_based_https_servers" name="Server HTTPS name-based"> <para> Quando si configurano due o piu' server HTTPS in ascolto su un singolo indirizzo IP, sorge spesso un problema: <programlisting> 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; ... } </programlisting> Con questa configurazione un browser riceve il certificato del server di default, vale a dire <literal>www.example.com</literal>, indipendentemente da quale sia il nome del server richiesto. Cio' e' causato dal comportamento del protocollo SSL: la connessione SSL si stabilisce prima che il browser invii una richiesta HTTP, percio' quando nginx ancora non sa quale sara' il nome del server richiesto; per tale ragione, non puo' fare altro che offrire il certificato del server di default. </para> <para> Il metodo classico per risolvere questo problema consiste nell'assegnare un indirizzo IP distinto a ciascun server HTTPS: <programlisting> 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; ... } </programlisting> </para> <section id="certificate_with_several_names" name="Un certificato SSL con molti nomi"> <para> Ci sono altre maniere tramite cui condividere un singolo indirizzo IP fra molti server HTTPS, tutte comunque non prive di problemi. Ad esempio, e' possibile usare un certificato con diversi nomi di server nel campo SubjectAltName, per esempio <literal>www.example.com</literal> and <literal>www.example.org</literal>, tuttavia la lunghezza del campo SubjectAltName e' limitata. </para> <para> Un'altra tecnica prevede l'uso di un certificato il cui nome e' definito con caratteri jolly, per esempio <literal>*.example.org</literal>. Un certificato con caratteri jolly va bene per tutti i sottodomini del dominio specificato, ma per un solo livello: in questo caso ad esempio verra' riconosciuta corrispondenza con <literal>www.example.org</literal>, ma non con <literal>example.org</literal> e <literal>www.sub.example.org</literal>. I due metodi mostrati possono essere combinati: nel campo SubjectAltName un certificato puo' contenere sia nomi esatti sia nomi con caratteri jolly, ad esempio <literal>example.org</literal> e <literal>*.example.org</literal>. </para> <para> Nel caso in cui si usi un certificato con nomi multipli, e' bene indicare la posizione del relativo file e della chiave nel livello <i>http</i> della configurazione, in maniera da avere una singola copia in memoria da far ereditare a tutti i server: <programlisting> 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; ... } </programlisting> </para> </section> <section id="sni" name="Server Name Indication"> <para> Una soluzione piu' generale per l'uso di server HTTPS multipli su un singolo indirizzo IP e' data dalla <link url="http://en.wikipedia.org/wiki/Server_Name_Indication">estensione TLS Server Name Indication</link> (SNI, RFC 6066), che consente ad un browser di indicare il nome del server richiesto durante l'handshake SSL e, percio', permette al server di sapere quale certificato dovrebbe essere usato durante la connessione. Purtroppo, SNI ha un supporto piuttosto limitato nei browser; al momento e' supportato a partire dalle seguenti versioni: </para> <para> <list type="bullet"> <listitem> Opera 8.0; </listitem> <listitem> MSIE 7.0 (ma solo su Windows Vista o superiore); </listitem> <listitem> Firefox 2.0 e altri browser che usano Mozilla Platform rv:1.8.1; </listitem> <listitem> Safari 3.2.1 (la versione per Windows supporta SNI su Vista o superiore); </listitem> <listitem> Chrome (la versione per Windows supporta SNI su Vista o superiore). </listitem> </list> <note> Con SNI e' possibile passare solo nomi di dominio, tuttavia alcuni browser potrebbero erroneamente consentire di passare come nome anche l'indirizzo IP del server. E' bene comunque non fare affidamento su questo comportamento. </note> </para> <para> Per poter usare SNI in nginx, e' necessario che sia supportato sia nella libreria OpenSSL con cui il binario e' stato compilato, sia nella libreria a cui e' linkato dinamicamente in esecuzione. OpenSSL supporta SNI sin dalla versione 0.9.8f, a patto che sia stata compilata con l'opzione di configurazione <nobr>“--enable-tlsext”</nobr>; dalla versione 0.9.8j tale opzione e' abilitata per default. Se nginx e' compilato con il supporto a SNI, allora l'esecuzione con il parametro “-V” mostra: <programlisting> $ nginx -V ... TLS SNI support enabled ... </programlisting> Di contro, se nginx e' stato compilato con il supporto a SNI, ma la libreria OpenSSL a cui e' linkato dinamicamente ne e' priva, viene mostrato: <programlisting> nginx was built with SNI support, however, now it is linked dynamically to an OpenSSL library which has no tlsext support, therefore SNI is not available </programlisting> </para> </section> </section> <section id="compatibility" name="Compatibilita'"> <para> <list type="bullet"> <listitem> Il parametro “-V” mostra lo stato del supporto a SNI dalla versione 0.8.21 e 0.7.62 in poi. </listitem> <listitem> Il parametro <literal>ssl</literal> della direttiva <link doc="ngx_http_core_module.xml" id="listen"/> e' supportato dalla versione 0.7.14 in poi; prima della versione 0.8.21 poteva essere specificato solo insieme al parametro <literal>default</literal>. </listitem> <listitem> SNI e' supportato dalla versione 0.5.32 in poi. </listitem> <listitem> La cache condivisa di sessione SSL e' supportata dalla versione 0.5.6 in poi. </listitem> </list> </para> <para> <list type="bullet"> <listitem> Versioni 0.7.65, 0.8.19 e successive: i protocolli SSL default sono SSLv2, TLSv1, e TLSv1.2 (se supportati dalla libreria OpenSSL). </listitem> <listitem> Versioni 0.7.64, 0.8.18 e precedenti: i protocolli SSL default sono SSLv2, SSLv3, e TLSv1. </listitem> </list> </para> <para> <list type="bullet"> <listitem> Versioni 1.0.5 e successive: i sistemi di cifratura SSL default sono “<literal>HIGH:!aNULL:!MD5</literal>”. </listitem> <listitem> Versioni 0.7.65, 0.8.20 e successive: i sistemi di cifratura SSL default sono “<literal>HIGH:!ADH:!MD5</literal>”. </listitem> <listitem> Versione 0.8.19: i sistemi di cifratura SSL default sono “<literal>ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM</literal>”. </listitem> <listitem> Versioni 0.7.64, 0.8.18 e precedenti: i sistemi di cifratura SSL default sono<br/> “<literal>ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP</literal>”. </listitem> </list> </para> </section> </article>