Nel precedente articolo avevamo visto come fosse possibile creare un certificato digitale per il nostro server ricorrendo al toolkit OpenSSL. Al termine della procedura eravamo in possesso dei seguenti file:
my-CA.key
: chiave privata della CAmy-CA.crt
: certificato della CAmy-server.key
: chiave privata del servermy-server.csr
: richiesta di certificato del servermy-server.crt
: certificato del server
In queste pagine vedremo come ottenere una connessione cifrata SSL utilizzando alcuni dei file elencati e configurando opportunamente Apache. Ricordo i presupposti di partenza: l'ambiente di riferimento è una linux box con Fedora Core 6 a bordo, un web server Apache 2.x dotato del modulo mod_ssl. Se la distribuzione che utilizzate è diversa non preoccupatevi: probabilmente il modulo è già installato, si tratterà eventualmente di abilitarlo.
Immaginiamo di disporre di un unico IP pubblico 11.22.33.44 e quindi di adottare una configurazione "name-based" per i virtual host, ovvero più host mappati sul medesimo indirizzo IP. Supponiamo ancora di aver già configurato un host virtuale www.miosito.it, cui aggiungeremo un secondo host virtuale secure.miosito.it, con il quale scambiare dati cifrati.
Quanto illustrato avrà carattere puramente esemplificativo senza pretese di completezza. L'uso di connessioni SSL in ambiente di produzione va accuratamente studiato e valutato in base alle necessità, alla sensibilità ed al valore delle informazioni scambiate. È necessario comprendere adeguatamente il significato di ciascuna direttiva adattandola alle esigenze del proprio ambiente di lavoro. In altre parole il puro e semplice copia ed incolla è a vostro rischio e pericolo. Fatte le doverose precisazioni possiamo partire con la configurazione.
Prepariamo la struttura
Assunti i privilegi di root creiamo in /etc/httpd una directory atta a contenere chiavi e certificati che chiameremo, con uno sforzo di fantasia, ssl. Copiamo ora i file necessari:
[root]# cp my-server.crt /etc/httpd/ssl [root]# cp my-server.key /etc/httpd/ssl [root]# cp my-CA.crt /etc/httpd/ssl
Rammento che nel precedente articolo avevamo provveduto a proteggere tali file con permessi restrittivi in modo che fossero leggibili solo da root.
A questo punto, se la DocumentRoot per il virtual host già configurato è /var/www/html, creiamo una seconda DocumentRoot per secure.miosito.it ed una directory per i file di log:
[root]# mkdir /var/www/secure [root]# mkdir /var/www/ssl_log
Creiamo un semplice file index.html contenente la frase "ssl funziona!" ed inseriamolo all'interno della directory /var/www/secure: ci sarà utile quando vorremo testarne il funzionamento.
In una installazione standard da pacchetti Rpm in ambiente Fedora, il file di configurazione principale /etc/httpd/httpd.conf riporta la direttiva di inclusione:
Include conf.d/*.conf
Con essa vengono inclusi, in ordine alfabetico, tutti i file con estensione .conf presenti in /etc/httpd/conf.d/. Ovviamente non tutti i moduli hanno necessità di un file di configurazione, potremo trovare ad esempio perl.conf o php.conf. Tra questi individuiamo il nostro obbiettivo: ssl.conf.
Configuriamo Apache
Per rendere più flessibile la gestione degli host virtuali basati sul nome, preferisco solitamente creare tanti file di configurazione quanti sono i domini che devo gestire, includendoli poi nel file di configurazione principale. Nel nostro esempio però immaginiamo di aver definito in httpd.conf l'host www.miosito.it ed utilizziamo ssl.conf per configurare secure.miosito.it. A questo proposito facciamo attenzione: se vogliamo usare mod_ssl la direttiva NameVirtualHost deve riportare l'indicazione della porta altrimenti Apache farà i capricci:
NameVirtualHost 11.22.33.44:80
Il nostro host www.miosito.it avrà una configurazione del tipo:
<VirtualHost 11.22.33.44:80> ServerAdmin webmaster@miosito.it DocumentRoot /var/www/html/ ServerName www.miosito.it .......................... </VirtualHost>
Chiaramente i puntini di sospensione rappresentano tutte le altre possibili direttive.
Con questo primo approccio utilizzeremo l'impianto base predisposto di default per ciò che concerne le configurazioni globali, andando a personalizzare solo la sezione relativa all'host virtuale.
Facciamo una copia di backup del file originale ssl.conf poi apriamolo e cancelliamo le righe da <VirtualHost _default_:443>
a </VirtualHost>
. Prima di procedere modificando il file di configurazione analizziamo le principali direttive globali:
LoadModule ssl_module modules/mod_ssl.so Listen 443 AddType application/x-x509-ca-cert .crt SSLPassPhraseDialog builtin SSLRandomSeed startup file:/dev/urandom 256 SSLRandomSeed connect builtin
La prima direttiva semplicemente carica il modulo all'avvio, la seconda impone al web server di ascoltare sulla porta 443 quella standard per le connessioni SSL.
Con AddType
aggiungiamo il MIME-type per downlodare i certificati.
L'opzione builtin
di SSLPassPhraseDialog
stabilisce che la pass phrase relativa alla chiave privata del server venga inserita da terminale, diversamente si potrebbe prevedere la chiamata ad un programma esterno.
Infine la direttiva SSLRandomSeed
viene utilizzata per indicare una o più fonti d'inizializzazione dello Pseudo Random Number Generator (PRNG) usato da OpenSSL. La prima direttiva si riferisce alla fase di avvio mentre la seconda alla fase in cui viene instaurata una connessione.
Passiamo ora al nostro host secure.miosito.it:
<VirtualHost 11.22.33.44:443> ServerAdmin webmaster@miosito.it DocumentRoot /var/www/secure/ ServerName secure.miosito.it ErrorLog /var/www/ssl_log/error_log CustomLog /var/www/ssl_log/access_log ........................................ <IfModule mod_ssl.c> SSLEngine on SSLProtocol all -SSLv2 #certificato del server: SSLCertificateFile /etc/httpd/ssl/my-server.crt #chiave privata del server: SSLCertificateKeyFile /etc/httpd/ssl/my-server.key #chain del certificato del server: SSLCertificateChainFile /etc/httpd/ssl/my-CA.crt #Certificate Authority (CA): SSLCACertificateFile /etc/httpd/ssl/my-CA.crt SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+EXP SetEnvIf User-Agent ".*MSIE.*" nokeepalive ssl-unclean-shutdown downgrade-1.0 force-response-1.0 </IfModule> </VirtualHost>
Innanzitutto notiamo che nella definizione del contenitore <VirtualHost>
dobbiamo indicare la porta 443 in luogo dell'80. Tralasciamo le prime direttive, non strettamente attinenti, e passiamo ad analizzare la sezione IfModule. Poi:
- Con
SSLEngine
abilitiamo l'utilizzo del protocollo SSL/TLS: la direttiva funziona come switch on/off, il valore di default è off. SSLProtocol
stabilisce quali protocolli dovranno usare i client per instaurare la connessione. Nel nostro caso conall
abilitiamo contemporaneamente SSLv2, SSLv3, TLSv1, poi con -SSLv2 inibiamo l'uso di SSL versione 2.- Le direttive
SSLCertificateFile
eSSLCertificateKeyFile
specificano la posizione in cui abbiamo memorizzato il certificato e la chiave privata del server. SSLCertificateChainFile
punta ad un file opzionale in cui vengono raccolti tutti i certificati che costituiscono la "catena di fiducia" per il certificato del server, nel nostro caso costituita unicamente dalla nostra CA casalinga.- La posizione del certificato della CA viene fornita con la direttiva
SSLCACertificateFile
. SSLCipherSuite
specifica quali tipi di cifratura i client possono negoziare nella fase in cui si instaura la connessione. Le diverse suite vengono indicate con una stringa rappresentativa e separate mediante i due punti. Come al solito i segni "+" e "-" servono ad aggiungere o escludere. Con "!" non solo escludiamo una suite, ma impediamo che possa essere aggiunta in seguito. Ad esempio!ADH
esclude la cifratura anonima Diffie-Hellman. Per maggiori dettagli consultate la documentazione ufficiale, per un elenco delle suite potete anche digitareopenssl ciphers -v
.- Lo scopo dell'ultima direttiva è sopperire ad eventuali incompatibilità nell'implementazione degli standard SSL da parte di alcuni browser....non si fanno nomi ma solo cognomi.
Testiamo la configurazione
Giunti a questo punto non ci resta che salvare le modifiche ad ssl.conf e provare la nuova configurazione riavviando il web server:
[root]# service httpd restart
La prima sorpresa, neanche tanto imprevedibile, è la richiesta della pass phrase per la chiave privata del server. Dovremo inserirla ad ogni riavvio ed anche in fase di boot se abbiamo configurato il nostro server per lanciare in automatico Apache. Questa misura di sicurezza può rappresentare un inconveniente specie se, per qualche motivo, il server viene riavviato e noi non siamo nei paraggi. Se vogliamo un sistema più comodo ma, ribadisco, molto meno sicuro possiamo procedere così:
[root]# cp my-server.key my-server.key.pass [root]# openssl rsa -in my-server.key.pass -out my-server.key Enter pass phrase for my-server.key.pass: writing RSA key
Da questo momento Apache ripartirà senza chiedere nulla. Come primo test verifichiamo lo stato delle connessioni:
[root]# netstat -tanp | grep httpd tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 31057/httpd tcp 0 0 0.0.0.0:443 0.0.0.0:* LISTEN 31057/httpd
Una risposta simile a questa mostra che Apache è in ascolto sia sulla porta 80 che sulla porta 443.
Ora la prova finale: apriamo il nostro browser e digitiamo l'indirizzo https://secure.miosito.it. All'instaurarsi della connessione ci apparirà una finestra di allerta che richiede di accettare o meno il certificato proveniente dal server. Questo perché il browser non può verificarne l'attendibilità dato che la nostra CA fatta in casa non gli è nota a priori. Diverso sarebbe se il certificato fosse firmato ad esempio da VeriSign. Se decidiamo di prendere per buono il certificato e chiediamo di proseguire ci mostrerà la pagina index.html con la frase "ssl funziona!". Un discorso a parte meriterebbe Internet Explorer 7 che, con l'obbiettivo di aumentare il livello di sicurezza, risponde con una pagina che, agli occhi del navigatore medio, risulta simile ad un errore. Inoltre non offre contestualmente la possibilità di accettare il certificato né in modo temporaneo né permanente.
Per evitare tutto ciò sarebbe necessario importare il certificato della nostra CA e del server all'interno del browser, purtroppo lo spazio a disposizione non concede di approfondire l'argomento.
Conclusioni
In queste pagine abbiamo visto come sia possibile implementare una connessione SSL con OpenSSL, Apache e mod_ssl tutti prodotti open source e liberamente utilizzabili. La scelta di assumere il ruolo di CA, indubbiamente economica e valida in alcune circostanze, non potrà essere adottata in generale specie in applicazioni di commercio elettronico. Quanto descritto si adatta comunque anche ad un certificato firmato da una CA accreditata.
Ribadisco che le configurazioni hanno carattere sperimentale adatte ad impratichirsi con l'ambiente SSL e dovrebbero essere completate da altre direttive. Sarebbe ad esempio buona regola forzare l'uso del protocollo SSL in modo che non possa essere utilizzata per errore una connessione in chiaro. Andrebbe evitata, invece, la possibilità di tale connessione sui restanti domini. Spesso si renderà necessario un meccanismo di autenticazione dei client o mediante nome utente e password o attraverso la richiesta e la verifica di certificati da parte del server. Lascio tutto questo alla vostra iniziativa ed alla consultazione della documentazione su SSL in generale, su mod_ssl in particolare e sul toolkit OpenSSL.