Nginx tip & tricks

Da Webmobili Wiki.

Varnish Cache server non supporta SSL perché lo sviluppatore non ha voglia di includerlo (fonte non ha voglia).

Per ovviare al problema è necessario installare nginx , un web-server/reverse-proxy in grado di catturare la chiamata https e redirigerla a Varnish.

Procedura per installazione

Sulla macchina che ha già VARNISH, installare nginx

sudo apt-get install nginx

L'installazione andrà a buon fine ma verrà mostrato un errore, nginx non riesce a partire perché Varnish è già attivo sulla porta 80. È necessario configurarlo in modo che accolga solo le richieste https.

Per prima cosa dobbiamo generare un certificato autofirmato

sudo mkdir /etc/nginx/ssl
sudo openssl req -x509 -nodes -days 3650 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

Alla domanda sul common name è necessario scrivere il nome della macchina sul dominio (lo stesso di a /etc/hostname). Il certificato generato vale solo 10 anni, cambiare il parametro days a piacimento


Ora apriamo la configurazione di nginx e lo istruiamo per rispondere alle richieste https

sudo nano /etc/nginx/sites-enabled/default

Il seguente è la configurazione del server di test BRUNOPROXY, il valore di server_name deve corrispondere con il common name che è stato dato al certificato.

# Default server configuration
#
server {
	# listen 80 default_server;
	# listen [::]:80 default_server;

	# SSL configuration
	#
	listen 443 ssl default_server;
	listen [::]:443 ssl default_server;


	#root /var/www/html;

	# Add index.php to the list if you are using PHP
	# index index.html index.htm index.nginx-debian.html;

	server_name BRUNOPROXY;
	ssl_certificate /etc/nginx/ssl/brunoproxy.crt;
	ssl_certificate_key /etc/nginx/ssl/brunoproxy.key;

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to displaying a 404.
		#try_files $uri $uri/ =404;
		proxy_pass http://127.0.0.1:80;
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto https;
		proxy_set_header X-Forwarded-Port 443;
		proxy_set_header Host $host;
	}
}

Ora tutte le richieste HTTPS passano da nginx che a sua volta le rigira a Varnish sulla porta 80 (riga proxy_pass http://127.0.0.1:80). Vengono servite col certificato autofirmato che non deve essere usato in ambiente di produzione.

Facciamo un restart di ngix

sudo service nginx start

e per testare andare su https://IPPUBBLICO. In caso di Varnish che punta a Windows si arriverà all'IIS. Non è necessario configurare IIS con SSL, possono essere tutti normali websites.

Aggiungere domini certificati

Per aggiungere un VirtualHost con certificato autentico aggiungere un file dentro alla cartella /etc/nginx/sites-available con la configurazione personalizzata che utilizzi i certificati giusti. Per renderlo disponibile creare un symlink dentro alla cartella /etc/nginx/sites-enabled e restartare nginx.

Esempio pratico:

  • Copiare i file del certificato (crt e key) nella cartella /etc/nginx/ssl/.

N.B. Se si dispone del file .cer basta rinominare l'estensione in .crt

  • Creare il virtual host
sudo touch /etc/nginx/sites-available/nomesito.com
sudo nano /etc/nginx/sites-available/nomesito.com

e scriverci dentro qualcosa come

server {
	listen 443;
	ssl on;
	ssl_certificate /etc/nginx/ssl/nomesito.com_ssl_certificate.crt;
	ssl_certificate_key /etc/nginx/ssl/nomesito.com_ssl_certificate.key;
	
	server_name nomesito.com;

	location / {
		proxy_pass http://127.0.0.1:80;
		proxy_set_header X-Real-IP  $remote_addr;
		proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
		proxy_set_header X-Forwarded-Proto https;
		proxy_set_header X-Forwarded-Port 443;
		proxy_set_header Host $host;
	}
}


  • Pubblicare il virtual host su nginx
sudo ls -s /etc/nginx/sites-available/nomesito.com /etc/nginx/sites-enabled
sudo service nginx restart



Redirect http to https

Per colpa della configurazione del routing il redirect verso https non può essere fatto a livello applicativo.
Infatti succederebbe la seguente cosa:

  1. La chiamata http arriva al Varnish
  2. Varnish la dirotta verso la macchina Win con IIS
  3. IIS dal suo rewriter trasforma la richiesta in https
  4. Il giro ricomincia passando questa volta da Nginx
  5. Da qui si torna a Varnish, il quale non sapendo gestire una richiesta https, dirotta una normale richiesta http alla macchina Win con IIS
  6. IIS dal suo rewriter trasforma la richiesta in https e sitorna al punto 4. generando un loop infinito



SOLUZIONE:
La gestione del redirect verso HTTPS dev'essere affidata a Varnish. fonte
Dentro al file /etc/varnish/default.vlc aggiungere queste 2 parti di codice

sub vcl_recv {
  # Gestione redirect Https
  if(req.http.X-Forwarded-Proto !~ "(?i)https") {
    set req.http.location = "https://" + req.http.host + req.url;
    return (synth(750, "Permanently moved"));
  }

  # altri contenuti
}

sub vcl_synth {

  # ... altri contenuti

  else if(resp.status == 750) {
    set resp.http.Location = "https://" + req.http.host + req.url;
    set resp.status = 301;
    return (deliver);
  }
}

In questo modo si evita il loop infinito. IMPORTANTE ricordarsi che dev'essere Varnish ad occuparsi del redirect https, mai l'applicativo.