Roadrunner squid 2.7

Dunque, un amico mi scrive dicendo che ha un portatile con sopra Linux (anche io) ed e’ stufo di cambiare le impostazioni del proxy su ogni client ogni volta che va nella propria azienda, ogni volta che va nell’altra sede, quando usa una chiavetta per connettersi, quando si attacca ad una wifi.

 

Chi me lo chiede presume, giustamente, che anche io usi un portatile (sono un consulente) con sopra installato Linux (sono un consulente) e che quindi abbia trovato la soluzione (sono un consulente).

Dunque, si puo’ fare usando squid. Ovvero, dicendo a squid di fare alcune cose. Vediamo di scrivere due righe di requisiti. Il nostro squid deve:

  1. Capire se il PC si trovi nella rete aziendale o in quella di casa o attaccato ad una chiavetta mobile.
  2. Se si trova in una rete aziendale, deve usare i server proxy per connettersi , usando quelli giusti.
  3. Se non si trova nella rete aziendale, deve collegarsi direttamente.
  4. Se qualche programma sgrauso non accetta la configurazione del proxy e cerca di uscire, va rediretto sul proxy in maniera trasparente.

In questo modo, configureremo sempre e solo il proxy “localhost:8080” come proxy su Gnome, KDE,  etc, e al massimo ci verra’ chiesta la password per autenticarci nel proxy.

Assumo di usare squid 2.7, come faccio io.

Per prima cosa, dobbiamo definire su squid le porte ove ci mettiamo in ascolto:


icp_port 0
http_port localhost:8080 http11
http_port localhost:8081 transparent
server_http11 on
half_closed_clients off


Allora, chiudiamo le porte icp perche’ non ci servono, visto che usiamo HTTP 1.1. Settiamo squid per lavorare in due modi. Il primo e’ HTTP 1.1 (RFC 2616) e l’altro in modo trasparente. Le richieste che arrivano sulla porta 8080 sono quelle fatte con http, quindi nei settaggi dei programmi potete anche scrivere tranquillamente localhost:8080 come proxy.

A questo punto, gli diciamo che esistono i proxy aziendali.


cache_peer 10.1.2.3 parent 8080 0   proxy-only name=azienda1 connect-timeout=2 login=PASS

cache_peer 10.2.3.4 parent 8080 0  proxy-only name=azienda2 connect-timeout=2 login=PASS

….

cache_peer 10.3.4.5 parent 8080 0   proxy-only name=aziendaN connect-timeout=2 login=PASS

dead_peer_timeout 2 seconds

acl all src 0.0.0.0/0.0.0.0

cache_peer_access azienda0 allow all
cache_peer_access azienda1 allow all
….
cache_peer_access aziendaN allow all


In questo modo stiamo dicendo a squid che esistono tanti proxy, che sono 10.1.2.3 , 10.2.3.4, 10.3.4.5 (possiamo aggiungerne quanti ne vogliamo), gli stiamo dicendo di usare loro come cache, gli stiamo dicendo di provare per due secondi a connettersi, e se non riescono li scartiamo, e di passare al client la richiesta di autenticazione se c’e’ (cosi’ la prima volta che vi connettete vi appare la richiesta di password e username).

Il risultato e’ che se decide di usare i proxy aziendali, squid li cerchera’ tutti, e se siete nella sede 1 ovviamente non trovera’ quelli della sede 2, e usera’ quelli giusti. Insomma, potrete usare l’elenco di tutti i proxy che conoscete aggiungendo righe cosi’. Con l’ultima istruzione potrete accorgervi anche se un server cui eravate connessi muore, e cercarne un altro dopo due secondi che non risponde.

Con il terzo blocco gli abbiamo detto che non esistono particolari regole per l’uso dei proxy, tantevvero che lo permettiamo sempre. Puo’ sembrare una regola strana, ma teniamo conto che squid e’ un proxy nato per agire su piu’ reti, come dispositivo di sicurezza (cioe’ separando le reti), quindi avremmo potuto scrivere cose piu’ complicate. Per un portatile collegato con una sola interfaccia alla volta non ci servono particolari regole.

A questo punto bisogna dire che lo squid deve usare i proxy aziendali in certe condizioni, e quindi scrivete cosi’:


never_direct allow work
never_direct deny !work

always_direct allow !work
always_direct deny  work


Quello che abbiamo fatto e’ chiamare “work” la condizione ove usare i proxy aziendali, e poi gli abbiamo detto che se “work” e’ vera allora dobbiamo usare quelli, mentre se e’ falsa dobbiamo andare direttamente. Gli abbiamo anche vietato di fare l’opposto, che non si sa mai quando anal sia un file di configurazione.

A questo punto dobbiamo aggiungere un pochino di intelligenza a squid, per farli capire se siamo al lavoro o meno. Squid infatti accetta delle ACL , cioe’ delle regole, che sono costituite da uno script esterno, il quale puo’ fare tutto quello che volete a patto di rispettare alcune regole con le quali comunicare con squid.

Cosi’,gli diciamo di creare una regola “work”, prendendo il risultato da uno script che scriveremo a manina.


external_acl_type script children=1 %SRC /etc/squid/is_work.sh

acl work external script


Ecco che gli abbiamo detto che esiste un particolare tipo di regola, che invoca uno script. Tale script si trova in un posto particolare, e riceve sullo standard input un parametro, che e’ l’ IP sorgente. Di cui non faremo nulla, ma ci serve per temporizzare le risposte, come vedremo dopo.

Dopodiche’ creiamo una regola , una acl, che e’ del tipo “script” e si chiama, guardacaso, “work”.

Adesso ci siamo: abbiamo detto a squid di usare i proxy aziendali quando uno script dice che la regola “work” e’ vera.Dobbiamo solo scrivere lo script.

Dunque, squid partira’ avviando un’interfaccia che parla con quello script. Ne avvia, per come lo abbiamo configurato, una sola.(children =1). Questa interfaccia apre lo standard input dello script e quando serve gli scrive l’ IPsorgente del programma che richiede una pagina. Dopodiche’ si aspetta la risposta.

Questo spiega come mai gli abbiamo fatto passare un parametro inutile in input: vogliamo che il nostro script risponda solo DOPO che viene interrogato, e sappiamo che viene interrogato solo perche’ squid ci passa un parametro.

Andiamo allo script. I requisiti di base di questo script sono:

  1. Esso rimane running sinche’ c’e’ lo standard input aperto. Se per disgrazia lo script esce, squid si sforza di riavviarne un altro, ma se succede troppo di frequente squid si ferma loggando un errore.Inoltre, se succede DAVVERO troppo di frequente, la CPU arrivera’ al 100%. Quindi, lo script tiene aperto SEMPRE lo standard input.
  2. Esso restituisce sullo standard output la stringa “OK” se vogliamo che “work” sia considerata vera.
  3. Esso restituisce sullo standard output la stringa “ERR” se vogliamo che “work” sia considerata falsa. (potrebbe anche restituire un messaggio di errore dopo “ERR”, ma non ci serve altra complessita’.

Cosi’, scriviamo uno script di questo genere (che metteremo dove indicato nella regola di squid che ho mostrato sopra):


#!/bin/bash

while (read GARBAGE)
do
MYIP=`/sbin/ifconfig eth0 |grep addr|awk {‘print $2’}| awk -F : {‘print $2’} | xargs echo`
case $MYIP in
10*)
echo “OK”
;;
*)
echo “ERR”
;;
esac
sleep 2
done


La prima riga dello script non fa altro che restituire l’indirizzo IP associato all’interfaccia eth0, (in rosso). Dopodiche’, apre lo standard input con il “read GARBAGE”, e lo tiene aperto all’infinito, avendo cura di scrivere, dopo ogni richiesta, OK o ERR a seconda che l’ IP della scheda sia compreso in una rete 10* oppure no.

Faccio notare che potete giocare con i “case” e le condizioni come volete, per creare la vostra logica a seconda del vostro ambiente: quello che leggete e’ solo un esempio. Ho messo uno “sleep 2” perche’ se qualcosa dovesse andare storto non vi si saturera’ la CPU al 100% e il PC rimarra’ interattivo abbastanza da spegnere squid.

Quando squid partira’, si mettera’ in ascolto sulle due porte indicate, e fara’ partire un’istanza del vostro script, e ogni volta che farete una richiesta HTTP chiedera’ allo script se “work” e’ vera o meno. Se e’ vera usera’ i proxy aziendali, altrimenti andra’ direttamente su internet.

Rimane da fare la regoletta di iptables che vi permettera’ di redirigere i programmi “stupidi” , cioe’ non configurabili, verso il proxy, che agira’ in maniera trasparente.

Dovremo intercettare tutte le chiamate che vanno verso la porta 80 e ridirigerle in maniera trasparente verso la porta 8081 di localhost, dite voi. Vorreste scrivere una cosa come questa:


iptables -t nat -A OUTPUT -o eth0  -p tcp –dport 80 -j DNAT –to 127.0.0.1:8081


E volete farlo perche’ google dice cosi’, e siete troppo pigri per leggere i manuali.

E invece no: se fate cosi’, neanche lo squid potra’ raggiungere server http, perche’ il suo stesso traffico verra’ rediretto su se’ medesimo: quella regola li’, che trovate con google, e’ fatta per server che hanno DUE interfacce, e quindi non agiscono mai sulla porta che squid usa per andare su internet.

Dovete creare una regola di iptables che colpisca qualsiasi pacchetto, eccetto quelli di squid. Inoltre, siccome non usate sempre la stessa interfaccia (magari usate la wlan0, e poi ppp0, e cosi’ via senza poter prevedere cosa userete)

Come si fa? Semplice: usando il  comando giusto di iptables:


iptables -t nat -A OUTPUT  -p tcp -m owner ! –uid-owner proxy –dport 80 -j DNAT –to 127.0.0.1:8081


Come vedete, stiamo usando un modulo particolare, che e’ “owner”. “Owner” e’ un modulo di iptables che si carica come modulo del kernel e vi permette di selezionare i pacchetti a seconda dell’utente che li ha generati.

Cosi’, siccome squid gira nel nostro esempio come utente “proxy”, quello che faremo sara’ redirigere SOLO i pacchetti che NON appartengono all’utente squid verso la porta locale, e lascieremo che squid possa uscire verso la rete. In questo modo, anche i client “stupidi” (o quelli che vi scordate di configurare) saranno costretti ad usare squid.

E come vedete, la regola non specifica interfacce alcune, cosi’ non dovrete riconfigurare nulla quando cambiate interfaccia.

E avete il vostro roadrunner squid.

Uriel

Lascia un commento

Il tuo indirizzo email non sarà pubblicato.