{"id":9,"date":"2018-09-12T22:25:20","date_gmt":"2018-09-12T20:25:20","guid":{"rendered":"http:\/\/10.12.14.100\/?p=9"},"modified":"2018-09-15T16:31:29","modified_gmt":"2018-09-15T14:31:29","slug":"squid-proxy-halb","status":"publish","type":"post","link":"http:\/\/gbiondi.tech2.it\/index.php\/2018\/09\/12\/squid-proxy-halb\/","title":{"rendered":"Squid Proxy HA+LB"},"content":{"rendered":"\n<p><em>Qualche tempo fa, mi \u00e8 stato chiesto di implementare un sistema proxy in alta affidabilit\u00e0 da un mio cliente. Ho notato che in rete non c&#8217;e&#8217; un howto per costruire un sistema del genere, allora ho pensato di scrivere qualche nota.<\/em><\/p>\n\n\n\n<p><em>Elenco dei requisiti:<\/em><\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><em>Il sistema proxy non deve avere delle licenze da pagare ne one-shot ne annualmente; insomma, deve essere gratis.<\/em><\/li><li><em>Deve servire circa 150 utenti possibilmente senza rallentamenti anche in caso di failover del primo nodo.<\/em><\/li><li><em>Non deve essere soggetto a sospensione del servizio dovuti a manutenzione (pianificati) o guasti (non pianificati).<\/em><\/li><li><em>Il sistema proxera&#8217; le richieste solo se aderenti ai dati presenti su\u00a0tre white-list a cura dal personale IT contenenti indirizzi IP, URL e domini.<\/em><\/li><li><em>Deve essere emessa una notifica in caso di down del nodo primario in modo che il personale IT sia a conoscenza che il sistema proxy sta funzionando in maniera degradata.<\/em><\/li><li><em>Il sistema si deve automaticamente ritornare sul nodo MASTER quando il problema su di esse \u00e8 cessato.<\/em><\/li><li><em>In modalita&#8217; normale sarebbe preferibile che il sistema processi le richieste in parallelo, bilanciando il carico tra le due macchine (active-active e non active-passive)<\/em><\/li><\/ol>\n\n\n\n<h2 class=\"wp-block-heading\">Briefing<\/h2>\n\n\n\n<p>Dunque, la prima cosa da decidere,\u00a0 il sistema operativo, gratis significa Linux o BSD.. io lavoro da circa vent&#8217;anni con Redhat (ora a pagamento) e quindi oggi lavoro con CentOS il quale \u00e8 basato sugli stessi sorgenti. Non ho trovato in rete un vero HOW-TO sul come fare questo progetto, quindi ho deciso di scriverne uno, in italiano. Per il sistema proxy, non c&#8217;e&#8217; tanto da pensare, il cliente ha gia&#8217; le liste in formato testo adatte a squid, qundi direi che il sistema proxy \u00e8 squid. Inoltre \u00e8 un software che c&#8217;e&#8217; da sempre (non so se sia nato prima Linux o prima squid) quindi \u00e8 affidabile e soprattutto open-source. Per quanto riguarda le White-list basta montarle su una share di un file server per avere tre liste sempre aggiornate su entrambi i proxy. Poi mi sono pensato un trucchetto in caso il file server contenente le White-list non fosse disponibile in modo che gli squid continuino a funzionare, su White-list non aggiornate ma continuino ad andare (e si potrebbero anche aggiornare ogni tanto via script). Ora manca un modulo che mi permetta di avere una sorta di alta affidabilit\u00e0: un modulo che in caso rilevi un problema possa migrare un indirizzo IP sulla macchina secondaria. Keepalived \u00e8 la mia scelta. Il motivo \u00e8 che ci ho gia&#8217; lavorato e che mi piace per la sua semplicit\u00e0. I nodi comunicano tra loro in Multicast e sembra che questo demone sia molto leggero per il sistema. Per fornire il servizio dei proxy active-active ho pensato che HAPROXY potrebbe fornirmi il necessario. L&#8217;idea \u00e8 stata di mettere in ascolto HAPROXY su qualsiasi IP della macchina linux su porta 3128 porta classica di Squid, e inoltrare in modalit\u00e0 tcp le richieste ai due Squid presenti sulle due macchine, controllando che siano attivi via istruzione check effettuato da HAPROXY. Ovviamente ho dovuto modificare la porta di ascolto degli Squid. Quindi in modalit\u00e0 normale, ovvero quando tutto \u00e8 correttamente funzionante, la macchina MASTER invia tramite HAPROXY le richieste dei client ad entrambi gli Squid in modait\u00e0\u00a0round-robin che per le sessioni http sembra sia\u00a0la migliore strategia.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Il sistema operativo<\/h2>\n\n\n\n<p>\n\nLavoro da un mare di tempo con CentOS e non mi viene proprio voglia di cambiare, quindi i due nodi saranno due linux box con CentOS V7.5. Finita l&#8217;installazione io ho effettuato le seguenti personalizzazioni:\n\n<\/p>\n\n\n\n<ol class=\"wp-block-list\"><li><em>\ufeffDisabilitato Selinux<\/em><\/li><li><em>Installato net-tools &#8211; Per avere ifconfig<\/em><\/li><li><em>Installato procps &#8211; Per avere killall che serve a keepalive<\/em><\/li><li><em>Disabilitato e rimosso dall&#8217;autostart Firewalld<\/em><\/li><li><em>Impostato in \/etc\/sysctl.conf la linea &#8220;net.ipv4.ip_nonlocal_bind = 1&#8221; che serve per ascoltare anche su ip che non esistono sulla macchina.<\/em><\/li><\/ol>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Keepalived<\/h2>\n\n\n\n<p>\n\nCi sono diversi sistemi per avere una coppia di Linux box ad alta affidabilita&#8217;, ma io sono di quelli che &#8220;cavallo che vince non si cambia&#8221;: ho gia&#8217; lavorato con keepalived e quindi implemento cio&#8217; che conosco. Secondo me semplice come configurazione e si installa facilmente perch\u00e9 \u00e8 di &#8216;serie&#8217; su CentOS, ti basta fare:\n\n<\/p>\n\n\n\n<p>\n\n[root@nodo1 ~]# yum install keepalived\n\n<\/p>\n\n\n\n<p>\n\n# cat \/etc\/keepalived\/keepalived.conf<br\/>global_defs {<br\/>\u00a0 enable_script_security<br\/>\u00a0 script_user root<br\/>\u00a0 notification_email {<br\/><a>gbiondi@tech2.it<\/a><br\/>\u00a0 }<br\/>\u00a0 notification_email_from\u00a0<a>node1@tech2.it<\/a><br\/>\u00a0 smtp_server localhost<br\/>\u00a0 smtp_connect_timeout 30<br\/>}\n\n<\/p>\n\n\n\n<p>\n\nvrrp_script chk_squid {<br\/>\u00a0\u00a0 script &#8220;\/usr\/bin\/killall -0 squid&#8221;\u00a0\u00a0\u00a0\u00a0\u00a0 # verify the pid existance<br\/>\u00a0\u00a0 interval 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # check every 2 seconds<br\/>\u00a0\u00a0 weight 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # add 2 points of prio if OK<br\/>}\n\n<\/p>\n\n\n\n<p><\/p>\n\n\n\n<p>\n\nvrrp_script chk_haproxy {<br\/>\u00a0\u00a0 script &#8220;\/usr\/bin\/killall -0 haproxy&#8221;\u00a0\u00a0\u00a0\u00a0\u00a0 # verify the pid existance<br\/>\u00a0\u00a0 interval 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # check every 2 seconds<br\/>\u00a0\u00a0 weight 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # add 2 points of prio if OK<br\/>}\n\n<\/p>\n\n\n\n<p>\n\nvrrp_instance VI_1 {<br\/>\u00a0\u00a0 interface eth0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # interface to monitor<br\/>\u00a0\u00a0 state MASTER<br\/>\u00a0\u00a0 virtual_router_id 54\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # Assign one ID for this route<br\/>\u00a0\u00a0 priority 101\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # 101 on master, 100 on backup<br\/>\u00a0\u00a0 advert_int 1<br\/>\u00a0\u00a0 smtp_alert<br\/>\u00a0\u00a0 virtual_ipaddress {<br\/>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a010.12.14.140\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # the virtual IP<br\/>\u00a0\u00a0 }<br\/>\u00a0\u00a0 track_script {<br\/>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 chk_squid<br\/>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 chk_haproxy<br\/>\u00a0\u00a0 }<br\/>}\n\n<\/p>\n\n\n\n<p>\n\nIn sostanza si vedono bene i due &#8216;vrrp_script&#8217; che controllano che i due processi siano UP e il &#8216;vrrp_instance&#8217; che \u00e8 il cuore di keepalived. Questo \u00e8 lo script del MASTER, quindi quando si sveglia si mette come MASTER e si autoassegna un priorita&#8217;. Si assegna un &#8216;router_id&#8217; che serve al demone per comunicare con l&#8217;altro nodo via unicast. Inoltre quando deve operare perch\u00e9 qualcosa \u00e8 andato storto (non vede l&#8217;altro nodo) ci avvisa via smtp. Il resto non credo che ci sia bisogno di spiegazioni. Allego anche lo script del secondo nodo per completezza:\n\n<\/p>\n\n\n\n<p>\n\nglobal_defs {<br\/>\u00a0 enable_script_security<br\/>\u00a0 script_user root<br\/>\u00a0 notification_email {<br\/><a>gbiondi@tech2.it<\/a><br\/>\u00a0 }<br\/>\u00a0 notification_email_from\u00a0<a>node2@tech2.it<\/a><br\/>\u00a0 smtp_server localhost<br\/>\u00a0 smtp_connect_timeout 30<br\/>}\n\n<\/p>\n\n\n\n<p>\n\nvrrp_script chk_squid {<br\/>\u00a0\u00a0 script &#8220;\/usr\/bin\/killall -0 squid&#8221;\u00a0\u00a0\u00a0\u00a0\u00a0 # verify the pid existance<br\/>\u00a0\u00a0 interval 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # check every 2 seconds<br\/>\u00a0\u00a0 weight 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # add 2 points of prio if OK<br\/>}\n\n<\/p>\n\n\n\n<p>\n\nvrrp_script chk_haproxy {<br\/>\u00a0\u00a0 script &#8220;\/usr\/bin\/killall -0 haproxy&#8221;\u00a0\u00a0\u00a0\u00a0\u00a0 # verify the pid existance<br\/>\u00a0\u00a0 interval 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # check every 2 seconds<br\/>\u00a0\u00a0 weight 2\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # add 2 points of prio if OK<br\/>}\n\n<\/p>\n\n\n\n<p>\n\nvrrp_instance VI_1 {<br\/>\u00a0\u00a0 interface\u00a0 eth0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # interface to monitor<br\/>\u00a0\u00a0 state BACKUP<br\/>\u00a0\u00a0 virtual_router_id 54\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # Assign one ID for this route<br\/>\u00a0\u00a0 priority 100\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # 101 on master, 100 on backup<br\/>\u00a0\u00a0 advert_int 1<br\/>\u00a0\u00a0 smtp_alert<br\/>\u00a0\u00a0 virtual_ipaddress {<br\/>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 10.12.14.140\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 # the virtual IP<br\/>\u00a0\u00a0 }<br\/>\u00a0\u00a0 track_script {<br\/>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 chk_squid<br\/>\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 chk_haproxy<br\/>\u00a0\u00a0 }<br\/>}\n\n<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">HAProxy<\/h2>\n\n\n\n<p>\n\nIl demone HAProxy \u00e8 il responsabile per il bilanciamento di carico dei proxy Squid. Esso riceve le richieste dei client su porta 3128 (ho scelto questa porta in quanto tutti sono abituati al fatto che se c&#8217;e&#8217; un proxy Squid questo ascolta su questa porta) e inoltra le sessioni sui proxy Squid attivi in quel momento. Il demone conosce il proxy attivo il quanto effettua un check su entrambi i proxy Squid in modo da esere a conoscenza su quale Squid inoltrare le richieste. Il demone HAProxy \u00e8 in grado di inoltrare migliaia di sessioni senza avere problemi di performance, leggete la documentazione e i test che sono stati effettuati su questo software se siete curiosi. Allego i file di configurazione dei due HAProxy montati sulle due macchine linux: i due file sono uguale su entrambe le macchine linux. Precisiamo che in questo particolare caso ci limitamo ad avere &#8216;solo&#8217; due proxy Squid, ma si potrebbe aggiungere altre macchine linux, queste con i solo demone Squid configurato, per avere un cluster con un parallelismo maggiore di due. Si potrebbe avere altre due macchine linux con Squid montato e utilizzare quattro Squid per servire i nostri utenti.\n\n<\/p>\n\n\n\n<p>\n\nglobal<br\/>daemon<br\/>maxconn 256<br\/>defaults<br\/>mode tcp<br\/>timeout connect 5000ms<br\/>timeout client 50000ms<br\/>timeout server 50000ms\n\n<\/p>\n\n\n\n<p>\n\nfrontend squid_frontend<br\/>bind *:3128\n\n<\/p>\n\n\n\n<p>\n\ndefault_backend squid_backend<br\/>backend squid_backend<br\/>server node1 10.12.14.141:8001 check<br\/>server node2 10.12.14.142:8001 check<br\/># Add more IPs here as required<br\/>balance roundrobin\n\n<\/p>\n\n\n\n<p>listen stats # Define a listen section called &#8220;stats&#8221;<br\/>bind :9000 # Listen on localhost:9000<br\/>mode http<br\/>stats enable # Enable stats page<br\/>stats hide-version # Hide HAProxy version<br\/>stats realm Haproxy\\ Statistics # Title text for popup window<br\/>stats uri \/haproxy_stats # Stats URI<br\/>stats auth amin:paperina # Authentication credentials<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Squid<\/h2>\n\n\n\n<p>\n\nProxy Squid. Squid \u00e8 un proxy che conosciamo tutti: chi ha messo in pista una macchina proxy con linux lo ha fatto con Squid. E&#8217; robusto, e&#8217; mantenuto aggiornato, e&#8217; gratis e funziona, non c&#8217;e&#8217; bisogno di provare qualcosa d&#8217;altro. Nel nostro sistema proxy, viene usato molto semplicemente con delle white-list, c&#8217;e&#8217; un minimo di configurazione da fare ma la cosa piu&#8217; importate \u00e8 il cambio di porta di ascolto, nel nostro caso da 3128 viene modificata in 8001. Poi c&#8217;e&#8217; il discorso delle white-list ma non mi pare che sia un argomento da trattare.. non ci interessa l&#8217;autenticazione, ma anche qui si trova tutto in rete. Invece voglio dirvi come ho fatto a fare in modo che, se per caso la share che condivide le white-list non fosse disponibile ,il sistema comunque continui a funzionare. Ho semplicemente copiate le white-list interessate nella directory \/mnt\/wl &#8211; certo che nel momento del problema non saranno aggiornate, ma sempre meglio che rimanere senza che su un sistema che lavora in white list significa non navigare piu&#8217; da nessuna parte&#8230; e poi si potrebbe fare in modo via script che ogni giorno venga smontata la share, copiate le whitelist e rimontata la share..\n\n<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusioni<\/h2>\n\n\n\n<p>\n\nIl sistema sta funzionando correttamente, per ora non sono stati riscontrati disservizi, purtroppo non \u00e8 sottoposto ad un carico pesantissimo, i due nodi sfiorano carico &#8216;1&#8217; negli ultimi 5 minuti solo all&#8217;inizio delle ore mattutine e pomeridiane\n\n<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"http:\/\/10.12.14.100\/wp-content\/uploads\/2018\/09\/image-3.png\" alt=\"\"\/><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>Qualche tempo fa, mi \u00e8 stato chiesto di implementare un sistema proxy in alta affidabilit\u00e0 da un mio cliente. Ho notato che in rete non c&#8217;e&#8217; un howto per costruire un sistema del genere, allora ho pensato di scrivere qualche nota. Elenco dei requisiti: Il sistema proxy non deve avere delle licenze da pagare ne &hellip; <\/p>\n<p class=\"link-more\"><a href=\"http:\/\/gbiondi.tech2.it\/index.php\/2018\/09\/12\/squid-proxy-halb\/\" class=\"more-link\">Leggi tutto<span class=\"screen-reader-text\"> &#8220;Squid Proxy HA+LB&#8221;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":true,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-9","post","type-post","status-publish","format-standard","hentry","category-proxy-halb"],"_links":{"self":[{"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/posts\/9","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/comments?post=9"}],"version-history":[{"count":10,"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/posts\/9\/revisions"}],"predecessor-version":[{"id":57,"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/posts\/9\/revisions\/57"}],"wp:attachment":[{"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/media?parent=9"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/categories?post=9"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/gbiondi.tech2.it\/index.php\/wp-json\/wp\/v2\/tags?post=9"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}