18 settembre 2014

Installare un Forward proxy HTTPS con Squid


Un HTTP proxy server è un servizio di rete a livello applicativo (HTTP) residente su un server in grado di svolgere diversi compiti come il "caching" ossia conservare le risorse chieste in precedenza per fornirle successivamente a chiunque le richieda riducendo l'utilizzo di banda. Il "filtering" ossia imporre delle restrizioni sui contenuti accessibili. Troviamo anche i "reverse proxy", proxy installati in un'azienda dove i dipendenti possono accedere alle risorse interne da casa o da altrove, viene adottato questo tipo di configurazione per policy di sicurezza.
Infine troviamo anche il suo inverso, che solitamente è il proxy a cui ci riferiamo comunemente quando parliamo solamente di "proxy" cioè il "forward proxy", un proxy che inoltra delle richieste provenienti da più client verso uno o più server.

La configurazione di un proxy può essere di tipo "trasparente", cioè il server proxy risiede sulla stessa macchina che fa il routing/firewall, e tramite alcune regole, il traffico viene automaticamente dirottato sul proxy, senza che l'utente ne abbia la minima percezione.

L'altra modalità di configurazione del proxy che interesserà in questa guida è tramite le impostazioni del client sulle quali si inseriscono i parametri (IP, porta, credenziali) per accedervi.

Con questa guida illustrerò come configurare un forward proxy sia lato client che lato server.
Questo tipo di proxy risulta molto utile nei casi in cui la rete attraverso la quale siamo connessi ci impone alcuni limiti di porta (mancato funzionamento client Mail, SSH, ecc..), o qualche sito ci impone limiti di accesso geografico. O più semplicemente abbiamo un certo server impostato per accettare connessioni solo da uno specifico IP.
Vedremo come impostare una triangolazione per eludere questi vincoli.

Come detto prima, un proxy HTTP è in grado di interpretare il protocollo, ed offre una modalità chiamata "CONNECT", che permette di stabilire una connessione TCP/UDP diretta tra il client e l'origin server. Questa modalità è sfruttata soprattutto per consentire connessioni https per visualizzare siti protetti, ossia tunnel SSL dentro i quali può viaggiare http senza possibilità di attacchi MITM (man-in-the-middle), questa modalità può essere anche bloccata sul proxy facendo in modo che l'utente non possa visitare siti HTTPS o qualunque cosa non sia http plain.

Ai nostri fini sarà obbligatorio utilizzare il metodo "CONNECT", altrimenti il proxy server non sarebbe in grado di veicolare tutto ciò che è diverso da HTTP.

Illustrerò l'installazione del proxy server "Squid" sia in modalità "--enable-ssl" che in modalità standard, la scelta dipende dalle esigenze:

connettendoci da una rete tramite proxy, il segmento che dovrà passare nel firewall sarà proprio quello tra il client e il proxy.
Ci sono firewall poco pervasivi, che si limitano a far passare tutto, basta che sia attraverso le porte ammesse, che molto spesso sono solo quelle utilizzate per l'http (80) ed https (443). ci sono firewall un pò più stringenti che fanno "packet inspection" ossia si assicurano che ciò che sta passando sia effettivamente traffico in linguaggio HTTP, senza però analizzare ciò che passa attraverso il canale creato con il metodo CONNECT, infine troviamo firewall che effettuano un "deep packet inspection", cioè viene analizzato anche ciò che passa attraverso il suddetto canale tramite CONNECT, e viene consentito il traffico solo qualora ci sia un tunnel che abbia le sembianze SSL, cosa inevitabile se ci si connette ad un sito https. Per evitare ciò, possiamo andare incontro ad una soluzione immediata: Invece di applicare una cifratura ssl relativa solamente al tunnel creato con il metodo CONNECT, impostiamo un livello ci cifratura al proxy stesso in modo tale che il firewall attraverso cui stiamo passando non abbia alcuna possibilità di analizzare il traffico non distinguendolo da una semplice sessione di una pagina web HTTPS. Per fare questo ci serve quello che chiamiamo "forward proxy HTTPS"

Il server Squid, se usato come proxy httpS, va compilato con dovuti parametri e va configurato in una maniera più elaborata, mentre la modalità HTTP normale è molto semplice, in quanto troviamo il pacchetto già precompilato nei repository.

NOTA: Squid compilato con SSL abilitato può accettare anche la configurazione che non prevede httpS.


Modalità HTTP (senza SSL):


prendiamo come riferimento un server Linux Debian, ed installiamo il proxy server chiamato "Squid"

apt-get install squid3

spostiamoci nella directory di configurazione /etc/squid/ e rinominiamo il file di configurazione preesistente:

mv squid.conf squid.conf.old

apriamo l'editor di testo e creiamo un nuovo file chiamato "squid.conf" in cui inseriremo la seguente configurazione:

NOTA: fare molta attenzione all'ordine delle direttive perchè è determinante. Invertendo l'ordine di esse, il comportamento del server cambia.

imposta il nome al server:

(1) visible_hostname nomeserver.server

una ACL definisce un livello di controllo al quale possiamo in serguito assegnare diversi comportamenti.
in questo caso viene creata una acl di nome "local_net" che identifica una rete di una subnet definita:

(2) acl local_net src 192.168.1.0/24

la seguente identifica il metodo di accesso "CONNECT"

(3) acl CONNECT method CONNECT

identifica la porta 443

(4) acl ssl port 443

definisce il programma che si occupa dell'autenticazione (ncsa_auth) al proxy server e il file contenente l'account che in seguito andremo ad impostare

(5) auth_param basic program /usr/lib/squid3/ncsa_auth /etc/squid3/credenziali

identifica le entità che necessitano l'autenticazione

(6) acl auth proxy_auth REQUIRED

le seguenti direttive invece sono gli accessi permessi alle varie acl, dobbiamo immaginarle come un flusso che viene processato riga per riga e viene sottoposto all'azione della direttiva quando si verifica il "match".
Il controllo viene eseguito in ordine di scrittura; ad esempio la (7) permette l'accesso senza autenticazione agli utenti appartenenti alla stessa rete LAN, quindi essi non vengono coninvolti in tutte le altre condizioni riguardanti il solo accesso. La (8) invece impone l'accesso http con autenticazione al flusso non matchato dalla prima, la (9) invece permette l'accesso a tutti gli IP, con relativa autenticazione a causa della seconda regola.

(7) http_access allow local_net
(8) http_access allow auth

(9) http_access allow all

potremmo anche restringere l'accesso limitando la modalità "CONNECT" alla sola porta ssl con la seguente direttiva posta prima della (7), oppure se vogliamo limitare la restrizioni ad eccezione degli utenti LAN, prima della (9):

http_access deny CONNECT !ssl

infine impostiamo la porta sulla quale Squid accetterà connessioni

(10) http_port 443

salviamo il file ed usciamo dall'editor di testo.

impostiamo l'autenticazione:

installiamo il seguente pacchetto perchè è necessario a creare il file contenente il nome utente e password

apt-get install apache2-utils

in successione eseguiamo

htpasswd -c /etc/squid3/credenziali <nomeutente>

inseriamo la password relativa al nome utente.

possiamo avviare il server Squid con il seguente comando (script init):

/etc/init.d/squid start




Configurazione client:

spostiamoci sul client ed apriamo il programma con cui vogliamo connetterci, troviamo la sezione proxy ed impostiamo:

tipo proxy: HTTP
IP: <indirizzo_IP_server_squid>
porta: 443

utente: <nomeutente>
password: <password>

ora non ci resta che connetterci sperando che sia andato tutto a buon fine.


------------------------------------------------------------------------------------



Modalità HTTPS:


Prepariamo l'ambiente alla compilazione del sorgente Squid con i seguenti comandi:

apt-get update

apt-get install build-essential libldap2-dev libpam0g-dev libdb-dev dpatch cdbs libsasl2-dev debhelper libcppunit-dev libkrb5-dev comerr-dev libcap2-dev 
libexpat1-dev libxml2-dev libcap2-dev dpkg-dev curl libssl-dev libssl1.0.0 libssl1.0.0-dbg libcurl4-openssl-dev

scarichiamo ed estraiamo il sorgente di Squid, entrando nella directory appena estratta:

wget http://www.squid-cache.org/Versions/v3/3.2/squid-3.2.5.tar.gz
tar xzf squid-3.2.5.tar.gz
cd  squid-3.2.5

avviamo la fase di compilazione ed installazione con questi tre comandi:

./configure --enable-ssl
make
make install

spostiamoci nella directory di configurazione di Squid:

cd /usr/local/squid/etc/

adesso sarà necessario creare la coppia di certificati SSL, usiamo questi tre comandi, possiamo ignorare tutte le informazioni richieste durante la fase di creazione di essi tranne che per la password che dobbiamo inserire e ricordarci, e il "COMMON NAME", che dovrà essere lo stesso del nome del proxy server, possiamo usare direttamente l'IP del proxy server come COMMON NAME.

openssl req -new > name.csr
openssl rsa -in privkey.pem -out name.key
openssl x509 -in name.csr -out name.crt -req -signkey name.key -days 730

adesso rinominiamo il vecchio file di configurazione col seguente comando:

mv /usr/local/squid/etc/squid.conf /usr/local/squid/etc/squid.conf.old

apriamo un editor di testo e nella stessa directory creiamo un file chiamato squid.conf che andremo ad editare nel seguente modo:

NOTA: fare molta attenzione all'ordine delle direttive perchè è determinante. Invertendo l'ordine di esse, il comportamento del server cambia.

imposta il nome al server:

(1) visible_hostname nomeserver.server

una ACL definisce un livello di controllo al quale possiamo in serguito assegnare diversi comportamenti.
in questo caso viene creata una acl di nome "local_net" che identifica una rete di una subnet definita:

(2) acl local_net src 192.168.1.0/24

la seguente identifica il metodo di accesso "CONNECT"

(3) acl CONNECT method CONNECT

identifica la porta 443

(4) acl ssl port 443

definisce il programma che si occupa dell'autenticazione (ncsa_auth) al proxy server e il file contenente l'account che in seguito andremo ad impostare

(5) auth_param basic program /usr/local/squid/libexec/basic_ncsa_auth /usr/local/squid/etc/credenziali

identifica le entità che necessitano l'autenticazione

(6) acl auth proxy_auth REQUIRED

le seguenti direttive invece sono gli accessi permessi alle varie acl, dobbiamo immaginarle come un flusso che viene processato riga per riga e viene sottoposto all'azione della direttiva quando si verifica il "match".
Il controllo viene eseguito in ordine di scrittura; ad esempio la (7) permette l'accesso senza autenticazione agli utenti appartenenti alla stessa rete LAN, quindi essi non vengono coninvolti in tutte le altre condizioni riguardanti il solo accesso. La (8) invece impone l'accesso http con autenticazione al flusso non matchato dalla prima, la (9) invece permette l'accesso a tutti gli IP, con relativa autenticazione a causa della seconda regola.

(7) http_access allow local_net
(8) http_access allow auth

(9) http_access allow all

potremmo anche restringere l'accesso limitando la modalità "CONNECT" alla sola porta ssl con la seguente direttiva posta prima della (7), oppure se vogliamo limitare la restrizioni ad eccezione degli utenti LAN, prima della (9):

http_access deny CONNECT !ssl

infine impostiamo la porta sulla quale Squid accetterà connessioni con le rispettive chiavi pubbliche e private:

(10) https_port 443 cert=/usr/local/squid/etc/name.crt key=/usr/local/squid/etc/name.key

impostiamo l'autenticazione:

installiamo il seguente pacchetto perchè è necessario a creare il file contenente il nome utente e password

apt-get install apache2-utils

in successione eseguiamo

htpasswd -c /usr/local/squid/etc/credenziali <nomeutente>

diamo i permessi alla seguente directory in modo tale che Squid ci possa scrivere:

chown -R nobody /usr/local/squid/var/logs/

infine eseguiamo questi due comandi. Il primo verifica che la configurazione sia giusta, il secondo fa partire il server squid.

/usr/local/squid/sbin/squid -z
/usr/local/squid/sbin/squid start




Configurazione Client:

la maggior parte dei client proxy inclusi nei programmi attualmente in circolazione non supporta nativamente HTTPS, quindi saremo costretti ad
utilizzare un wrapper che implementi il livello SSL, uno di questi è stunnel, disponibile per varie piattaforme al seguente link:

https://www.stunnel.org/downloads.html

stunnel a seconda di come lo si configura si può comportare sia da client che da server. Nel nostro caso il server lo farà Squid, quindi lo useremo solo come client per fornire il supporto SSL mancante.

supponendo di essere su un client windows, editiamo il file di configurazione:

C:\Programmi\stunnel\stunnel.conf

rimuoviamo tutto il contenuto ed inseriamo le seguenti righe:

verify = 0
client = yes
fips = no 
[ssl2http]
accept = 127.0.0.1:8080
connect = <indirizzo_IP_server_squid>:443

salviamo il file e copiamo nella directory C:\Programmi\stunnel\ i file name.crt e name.key che abbiamo generato sul server.

avviamo il server stunnel cliccando dal menù programmi "stunnel GUI start" controllando che venga caricato correttamente senza errori.

apriamo il programma con cui vogliamo connetterci, troviamo la sezione proxy ed impostiamo:

tipo proxy: HTTP
IP: 127.0.0.1
porta: 8080

utente: <nomeutente>
password: <password>

salviamo e proviamo a connetterci.

NOTA: dopo la prima connessione, stunnel scaricherà in locale il certificato pubblico del server. Potremmo aggiungere alcune righe al file di configurazione di stunnel affinchè alle successive connessioni possa verificare che il certificato che invierà il server sia sempre quello e quindi possa autenticarlo per prevenire ipotetici attacchi MITM.

per fare ciò basta cliccare sull'interfaccia grafica di stunnel e cliccare sul certificato da "Save Peer Certificate". Dopo ciò, editiamo il file di configurazione aggiungendo la riga:

CAfile = peer-ssl2http.pem

dovremo anche modificare il valore di "verify" da 0 a 3.

Sottolineo che è una procedura assolutamente facoltativa utile solo in casi di estrema sicurezza.


potremmo trovare utile un forward proxy https per un altro scopo: avendo un tunnel cifrato tra il client browser e il proxy server si può evitare che in tale segmento i cookie transitino in chiaro.

attualmente esiste anche un browser "Chromium" che supporta nativamente proxy https, ma bisogna installare il certificato manualmente sul computer locale copiando sul client il file name.crt. (per installarlo su Windows basta cliccarci sopra), tale certificato in fase di creazione deve avere lo stesso nome di dominio o indirizzo IP del proxy server, mancando una delle dette condizioni, il browser restituirà errore di certificato non valido.

possiamo avviare chromium usando un proxy https col seguente comando:

chrome --proxy-server=https://<indirizzo_IP_server_squid>:443

alternativamente possiamo utilizzare qualsiasi altro browser con l'ausilio di stunnel.

NOTA: a volte capita di incontrare tra le impostazioni proxy di alcuni client la voce "HTTPS", voglio sottolineare che ciò non significa che il client supporti la cifratura del proxy, ma semplicemente vuol dire che il proxy che dobbiamo inserire deve supportare la modalità "CONNECT" in quanto quel client non parla linguaggio HTTP ed ha necessità di creare un tunnel in cui trasferire i dati, modalità CONNECT necessaria per proxy che permettono di visitare siti web HTTPS.