PI Guide/ Apache e Nginx, accoppiata perfetta

Così i due famosi Web server collaborano fra loro per rendere gli hosting space più sicuri ed efficienti

I Web server odierni offrono grandi performance ed elevati livelli di sicurezza. Fra questi spiccano sicuramente Apache e Nginx, resi famosi dalle grandi potenzialità e prestazioni. Tuttavia, a volte, i vantaggi dell'uno non sono visibili nell'altro, ma fortunatamente riescono a cooperare tra loro consentendo all'utente di fruire di funzionalità aggiuntive come il load balancing e il reverse proxy.
In questa guida scopriremo dunque come usare Nginx come reverse proxy di Apache, andando a creare un'interfaccia completamente trasparente per l'utente che instrada una richiesta a un sito Web hostato su Apache. Il proxy Nginx si preoccuperà di ricevere tutte le richieste del client come se fosse lui il server che ospita il sito Web, le instraderà ad Apache che gli restituirà la risorsa richiesta e si preoccuperà di recapitarla all'utente ignaro del meccanismo che c'è alla base. L'utente non si accorgerà dei passaggi intermedi. Questa pratica consente di mantenere un elevato livello di sicurezza per il vero server, che non si troverà a dialogare direttamente con i client, e consente di attuare anche una procedura di buffering per gestire le richieste multiple, così da ottimizzare i tempi di risposta. Realizzeremo il reverse proxy con i due Web server e scopriremo come attuare anche delle politiche di sicurezza. Tutti i file di configurazione sono disponibili al download su questa pagina Web.

Perché un reverse proxy?
Il reverse proxy è in grado fare da filtro per far sì che ogni richiesta instradata dal client venga prima analizzata dal reverse proxy che si comporterà in modo da soddisfare la richiesta del client o rifiutarla. Spesso l'uso di un reverse proxy può essere utile per evitare attacchi DDoS diretti al server o come detto in precedenza può funzionare da load balancer usando vari server per lo stesso space senza farlo capire all'utente finale. Quest'ultimo effettua le sue richieste in modo trasparente, ma non è in grado di capire cosa avviene dietro le quinte: otterrà solo ciò di cui necessita. Vedremo a breve che provando ad aprire una pagina Web inesistente, seppur il sito Web sia caricato su Apache, sarà Nginx a rispondere con un messaggio di errore.

Apache sa cosa deve fare
Cominciamo con l'installare il Web server e con l'effettuare i primi settaggi.
Per installare un nuovo web server Apache sulla nostra macchina GNU/Linux, lanciamo il comando sudo apt-get -y install apache2. Attendiamo che vengano scaricati tutti i pacchetti e passiamo alla configurazione.

Per configurare Apache lanciamo sudo nano /etc/apache2/ports.conf e modifichiamo la porta di ascolto, ad esempio con la porta 7600. Cambiamo dunque la riga Listen 80 con Listen 7600 e salviamo il file.


Editiamo anche /etc/apache2/sites-available/000-default.conf e modifichiamo la linea VirtualHost inserendo come IP 127.0.0.1 e 7600 come porta. La linea dovrà dunque essere <VirtualHost 127.0.0.1:7600>.


Ricordiamo che Nginx deve funzionare da proxy. Per fare ciò faremo uso del campo X-Forwarded-For passando l'IP del client originale che ha effettuato la richiesta. Affinché avvenga in automatico basterà installare una libreria con sudo apt-get -y install libapache2-mod-rpaf.


Una doverosa precisazione
Tutti i software usati nei nostri test sono disponibili per la maggior parte delle distro GNU/Linux. Tuttavia l'IP forwarding del client è stato attuato in modo del tutto automatico su Ubuntu/Debian grazie a una libreria. Su altre distribuzioni diventa invece necessario usare configurazioni differenti. Dovremo editare il file /etc/apache2/apache2.conf e modificare LogFormat. Dovremo commentare #LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined e aggiungere LogFormat "%{X-Forwarded-For}i %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined.

Nginx è il nostro proxy
Ora vediamo invece come configurare Nginx affinché funga da proxy, instradando così tutto il traffico su Apache.
Dopo aver riavviato Apache con sudo service apache2 restart, installiamo nginx con il comando sudo apt-get -y install nginx e creiamo un link per avviare il servizio con sudo systemctl enable nginx.service.


Riavviamo nginx con service nginx restart per verificare che il link appena creato funzioni. Dovremmo trovarci in una situazione in cui il Web server Apache rimane in ascolto sulla porta 7600 e Nginx, invece, sulla porta 80.


I parametri del proxy da modificare si trovano nel file proxy_params che editiamo con nano /etc/nginx/proxy_params. Possiamo ad esempio aggiungere proxy_intercept_errors on; per rimandare i codici di errore superiori a 300 sulla pagina Nginx dedicata.


Con client_max_body_size e client_body_buffer_size possiamo limitare la dimensione dei file in upload. Oppure attiveremo i buffer del proxy con proxy_buffering on, proxy_buffer_size e proxy_buffers per avere risposte più rapide dal proxy.


Altri due utili parametri possono essere proxy_temp_file_write_size e proxy_max_temp_file_size che permettono di limitare la dimensione massima dei file temporanei dei quali farà uso Nginx quando il buffer per qualsiasi motivo non sarà più sufficiente.


Infine, il parametro proxy_read_timeout consente di definire un tempo massimo fra una lettura e l'altra. Se non avvengono letture dal proxy entro questo lasso di tempo, la connessione viene chiusa. Naturalmente, il timeout non influenza il trasferimento in corso.


Ultimi ritocchi
Arrivati a questo punto, non resta che settare Apache e Nginx affinché puntino allo stesso spazio Web. In altre parole: facciamo puntare i vhost di Apache e Nginx sulla stessa cartella contenente il sito Web.

Per verificare dove punti Apache lanciamo il comando sudo nano /etc/apache2/sites-available/000-default.confe verifichiamo DocumentRoot.


Per configurare il vhost di Nginx lanciamo invece il comando nano /etc/nginx/sites-available/default. Controlliamo che il parametro listen punti sulla porta 80 e verifichiamo che la cartella root del nostro Web space sia identica a quella Apache, /var/www/html.


Prima di chiudere il file di configurazione, inseriamo nel campo location il parametro proxy_pass http://localhost:7600; e include /etc/nginx/proxy_params; per caricare i parametri che abbiamo visto in precedenza.


Per caricare la nuova configurazione lanciamo ora il comando service nginix reload. Carichiamo i file del nostro sito Web nella cartella /var/www/html e puntiamo su una pagina inesistente sul server. Vedremo un messaggio di errore, ma possiamo notare che la porta usata è la 7600.


Più sicuri con SSL
Per blindare il nostro Web server possiamo includere dei certificati di sicurezza.
Accediamo alla directory di Nginx con cd /etc/nginx/ e da qui lanciamo il comando sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/cert.key -out /etc/nginx/cert.crt per creare i certificati di sicurezza SSL.


Inseriamo tutti i dati per creare il certificato e successivamente lanciamo il comando sudo nano /etc/nginx/sites-available/default. Creiamo un nuovo campo server e inseriamo return 301 https://$host$request_uri; così da effettuare il redirect automatico su HTTPS.


Modifichiamo il campo server creato in precedenza cancellando i campi relativi alla porta 80 e togliendo il commento dal campo listen per la porta 443. Così facendo, metteremo il server in ascolto sulla porta necessaria per l'SSL e facendola puntare alla root web.


Al campo listen 443 aggiungiamo le voci ssl_certificate /etc/nginx/cert.crt; e ssl_certificate_key /etc/nginx/cert.key;. Ciò ci permette di caricare i certificati creati nei passi precedenti. Aggiungiamo anche ssl on; per attivare SSL.


Infine, inseriamo ssl_session_cache builtin:1000 shared:SSL:10m; ssl_protocols TLSv1 TLSv1.1 TLSv1.2; e ssl_ciphers HIGH:!aNULL:!eNULL:!EXPORT:!CAMELLIA:!DES:!MD5:!PSK:!RC4; ssl_prefer_server_ciphers on; e salviamo il file.


Per caricare la nuova configurazione lanciamo il comando service nginx reload e se tutto è andato per il verso giusto, quando visiteremo la pagina http://ip_hosting verremo reindirizzati alla pagina https://ip_hosting, ovvero verrà utilizzato il protocollo sicuro HTTPS.