HAProxy con terminazione SSL e certificati multipli

logo-medHAProxy è una soluzione open source per la realizzazione di architetture ad alta affidabilità in load balancing, in particolare per quanto riguarda applicazioni web.
Vediamo quindi come configurarlo per ottenere una architettura multi server web, in grado di gestire anche la terminazione SSL sul proxy. La connessione risulterà quindi protetta fino al proxy, le comunicazioni al di là di esso saranno connessioni standard, ma confinate all’interno della rete privata tra i server che eseguono l’applicazone web.
Installiamo HAProxy tramite il gestore dei pacchetti, nel nostro caso APT su Ubuntu 14.04:

$ sudo apt-get install haproxy

Una volta installato passiamo alla configurazione. Ci sono tre sezioni, una generale, una dedicata al frontend e una al backend. Per frontend intendiamo come si presenta il proxy verso l’esterno, le porte su cui deve essere in ascolto, i protocolli che gestisce e le regole di smistamento ai backend. Per backend, intendiamo le connessione a valle del proxy verso i server che eseguono fisicamente l’applicazione web.
Vediamo la configurazione generale:

global
log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin
stats timeout 30s
user haproxy
group haproxy
daemon

# Default SSL material locations
ca-base /etc/ssl/certs
crt-base /etc/ssl/private

# Default ciphers to use on SSL-enabled listening sockets.
# For more information, see ciphers(1SSL).
ssl-default-bind-ciphers kEECDH+aRSA+AES:kRSA+AES:+AES256:RC4-SHA:!kEDH:!LOW:!EXP:!MD5:!aNULL:!eNULL
ssl-default-bind-options no-sslv3

defaults
log global
mode http
option forwardfor
option http-server-close
option httplog
option dontlognull
timeout connect 5000
timeout client 350000
timeout server 350000
errorfile 400 /etc/haproxy/errors/400.http
errorfile 403 /etc/haproxy/errors/403.http
errorfile 408 /etc/haproxy/errors/408.http
errorfile 500 /etc/haproxy/errors/500.http
errorfile 502 /etc/haproxy/errors/502.http
errorfile 503 /etc/haproxy/errors/503.http
errorfile 504 /etc/haproxy/errors/504.http

Qui viene definita la modalità di comunicazione generale, in questo caso per il protocollo HTTP, con aggiunta dell’opzione di forward per inserire negli header HTTP l’indirizzo IP del richiedente originale. Questo header aggiuntivo è utile nel caso in cui sia necessario leggere l’indirizzo IP del client, in quanto i server web dietro al proxy vedono sempre come IP sorgente quello del proxy stesso.
Vediamo quindi come configurare la sezione frontend:

frontend http-frontend
bind 127.0.0.1:80 # -- può essere modificato con l'IP pubblico del server
option tcplog
mode http
default_backend wwwbackend

frontend https-frontend
bind 127.0.0.1:443 ssl crt /etc/haproxy/mysite.net.pem crt /etc/haproxy/othersyte.net.pem
option tcplog
mode http
default_backend wwwbackend_s

In questo caso, abbiamo definito due porte, una web normale e una web SSL, abbiamo definito due percorsi differenti, poi vedremo perchè nella configurazione del backend. Ogni configurazione definisce su quale backend devono essere instradate le connessioni in ingresso.
La sezione relativa alla porta SSL ha in più la parte di configurazione relativa ai certificati, che devono essere nel formato PEM. I file possono essere creati a partire dal certificato e dalla relatiiva chiave privata, nel seguente modo:

$ sudo cat /etc/ssl/mysite.net/mysite.net.crt /etc/ssl/mysite.net/mysite.net.key \
| sudo tee /etc/ssl/mysite.net/mysite.net.pem

Definiamo ora i backend. Per questa particolare configurazione ho duplicato i backend e messo il server web Apache in ascolto su due porte, 81 e 82. Questo trucco mi consente di definire due diverse sezioni VirtualHost, ad esempio se voglio costruire un redirect automatico dal sito http a quello https:

backend wwwbackend
mode http
balance roundrobin
server 1-www 192.168.0.1:81 check # host web1
server 2-www 192.168.0.2:81 check # host web2

backend wwwbackend_s
mode http
balance roundrobin
server 1-www 192.168.0.1:82 check # host web1
server 2-www 192.168.0.2:82 check # host web2

Il bilanciamento in questo caso è round-robin, quindi ogni server web riceverà una richiesta a turno.
A questo punto non ci resta che riavviare il servizio HAProxy:

$ sudo service haproxy restart

Possiamo testare il corretto funzionamente con un semplice script in PHP:

<?php print gethostname() . "\n"; ?>

Richiamando lo script tramite broowser, noterete che verrà stampato il nome del primo server web, ad esempio “web1”. Ricaricando la pagina con F5, verrà invece stampato il nome del secondo server, ad esempio “web2”. Le successive richieste al server web saranno alternate tra un server e l’altro.

Annunci

Rispondi

Inserisci i tuoi dati qui sotto o clicca su un'icona per effettuare l'accesso:

Logo WordPress.com

Stai commentando usando il tuo account WordPress.com. Chiudi sessione / Modifica )

Foto Twitter

Stai commentando usando il tuo account Twitter. Chiudi sessione / Modifica )

Foto di Facebook

Stai commentando usando il tuo account Facebook. Chiudi sessione / Modifica )

Google+ photo

Stai commentando usando il tuo account Google+. Chiudi sessione / Modifica )

Connessione a %s...