Newsgroup: it.comp.os.linux.sys
Titolo: il pippone di varnish su SSL e la doppia morale dei suoi sviluppatori

Chissà quanti di noi si sono chiesti come mai varnish non supporta SSL e 
quanti di noi sono andati a cercare info sul sito. 
La spiegazione inizia con una denigrazione (magari ben giustificata) del 
codice di openssl e vengono anche mostrati alcuni pezzi di codice a loro 
dire dimostrazione evidente della malvagità degli sviluppatori di openssl. 
Clicchi quindi 'next page': se vuoi usare SSL, ti consigliamo di mettere 
Nginx di fronte a varnish...... Con openssl, che evidentemente smette di essere
malvagio. 
Morale: se una cosa non la sai fare, dillo "non la so fare", ma non ti 
inventare ca$$ate.

 inventare ca$$ate.
 
Non che necessariamente condivida la scelta degli sviluppatori di
varnish (che, credo, saranno costretti a fare retrofront e supportare
SSL, dato che HTTP in chiaro andr� rapidamente sparendo, almeno per siti
non amatoriali), per� mi pare che tu abbia letto in quella pagina altro
da ci� che la pagina dice...
 
https://www.varnish-cache.org/docs/trunk/phk/ssl.html
 
 
per gli altri
 

 per gli altri
 
la pagine è proprio quella. 
Intendiamoci: a me piace Varnish, e mi piace pure tanto. 
Premettiamo anche il codice di nginx è addirittura più piccolo del codice 
di varnish. 
Premettiamo anche che nutro il dubbio che pure qualche appliance possa 
utilizzare openssl (F5 mi pare che usi openssl).
 
Adesso spiegami in che modo tutti gli svantaggi che vengono specificati ed 
enumerati affliggerebbero solo varnish e non nginx. 
Siamo sempre lì: se ti poni il problema delle performance, metterai 
comunque il terminatore da un'altra parte. Ma cosa cambia tra avere un 
terminatore nginx + openssl e un ipotetico terminatore varnish + openssl? 
 
Poi, quel che ho detto io c'è su quella pagina e la colpa viene 
innanzitutto addossata alla qualità di un codice che poi ti dicono di 
usare da un'altra parte. Questo è il loro incipit:
 
Take this example in a comment, randomly found in s3-srvr.c:
 
/* Throw away what we have done so far in the current handshake,
 * which will now be aborted. (A full SSL_clear would be too much.)
 * I hope that tmp.dh is the only thing that may need to be cleared
 * when a handshake is not completed ... */
 
 
 

Il Sat, 07 Jun 2014 09:57:57 +0000, Max_Adamo ha scritto:
 
[CUT]
 
 
Questa è una pagina a caso del loro sito dove parlano di nginx posto 
davanti a varnish: 
https://www.varnish-cache.org/trac/wiki/VCLExampleRedirectInVCL
 
 
 
-- 
Massimilano Adamo

 Take this example in a comment, randomly found in s3-srvr.c:
 
 
Il fatto è che stai prendendo una frase e costruendo il contensto intorno.
 
Il succo di quella pagina non è l'incipit che riporti[1], ma questo:
 
«
But let us assume that a good SSL library can be found, what would
Varnish do with it ?
 
We would terminate SSL sessions, and we would burn CPU cycles doing
that. You can kiss the highly optimized delivery path in Varnish goodbye
for SSL, we cannot simply tell the kernel to put the bytes on the
socket, rather, we have to corkscrew the data through the SSL library
and then write it to the socket.
 
Will that be significantly different, performance wise, from running a
SSL proxy in separate process ?
 
No, it will not, because the way varnish would have to do it would be to
... start a separate process to do the SSL handling.
»
 
 
E, in particolare:
 
«
Would I be able to write a better stand-alone SSL proxy process than the
many which already exists ?
 
Probably not, unless I also write my own SSL implementation library,
including support for hardware crypto engines and the works.
»
 
 
Che non dice esattamente "dato che OpenSSL fa cagare, non lo voglio,
tiè!"....
 
 
 
[1] per quanto che il codice di OpenSSL sia terrificante è opinione
abbastanza comune.

 Varnish do with it ?
 
 
Non ci allooppiamo :) Per un motivo semplice: diciamo la stessa cosa. 
 
La differenza consiste nel fatto che io non condivido l'approccio di 
quella pagina parte degli sviluppatori... mi sembra come quando tizio non 
riusciva a tirar fuori un driver decente per la pennetta DVB 
non_mi_ricordo_quale e dava la colpa alla pessima qualità del codice dei 
lettori multimediali per linux. VCL: uguale su win, su linux non va bene 
su linux?
 
Quella pagina sul sito di varnish io me la sarei risparmiata, per il 
semplice fatto che la mer$$ quando la rigiri fa più puzza. 
 
Inoltre, non me ne frega niente di avere il supporto SSL su Varnish. Non 
lo userei comunque, perché trovo più corretto centralizzare la gestione 
della sicurezza e del patching. Revocare un wild card certificate (che 
tendo ad usare quasi sempre) o mettere una patch su un solo appliance e 
cosa ben diversa da andare scovare N server con certificati che scadono e 
con openssl afflitto dal bug del giorno... potrei chiedere al team di 
networking di farmi un semplice tcp load-balancing e io mi gestisco SSL. 
Me lo fanno senza problemi e sono pure felici. Poi però mi arrivano le 
segnalazioni da security: please upgrade your version of openssl, your 
certificate expiration is getting closer: e allora vai nell'altro edificio 
dove c'è la cassaforte con il notebook dove abbiamo la CA e genero il 
certificato.... ma manco me lo sogno :) 
 
-- 
Massimiliano Adamo

Quella pagina sul sito di varnish io me la sarei risparmiata
 
Scusami, ma non sono d'accordo. Il senso di quella pagina e' spiegare come
mai, "a causa del come e' fatto varnish", metterci SSL sopra avrebbe poco,
e anzi forse proprio nessun, senso; sia come sviluppatori, e sia dal punto
di vista degli utenti finali.
 
Leonardo
 
-- 
 
Questi non hanno speranza di morte; e la lor cieca vita e' tanto bassa,
Che 'nvidiosi son d'ogne altra sorte. Fama di loro il mondo esser non lassa;
Misericordia e Giustizia li sdegna; non ragioniam di lor, ma guarda e passa.

 Leonardo
 
si, ma non puoi (in altre pagine dello stesso sito) suggerire la soluzione 
Nginx, che probabilmente fa la stessa identica cosa che Varnish farebbe se 
avesse SSL. E lì che non torna più niente. 
 
 
 
-- 
Massimiliano Adamo


fra l'altro diventa tutto assolutamente inutile. 
Qualcuno dice in giro che Varnish potrebbe essere il 5% più veloce di Nginx 
sui contenuti statici, ma quando il collo di bottiglia diventano la 
terminazione SSL e la rete tra il terminatore ed il server verso cui fai 
SSL off-loading, che vantaggio trai dall'avere una terminazione SSL che fa 
SSL off-loading su un server che ti fa guadagnare il 5%?
E' veramente un mistero.
 
 
-- 
Massimiliano Adamo

 E' veramente un mistero.
 
Secondo me solo perchè ce lo vuoi vedere.
 
L'unica ragion d'essere di varnish è erogare dati da cache in maniera
efficiente, e con SSL non lo può fare.
 
 
Ergo, non ha alcun senso aggiungere SSL a varnish:
 
dato che le prestazioni (il cui bottleneck sarebbe SSL) sarebbero le
stesse, tantovale usare un altro proxy o -se già si usa varnish per il
caching della componente in chiaro- metterli un altro proxy davanti con
il solo compito di terminare SSL.
 
 
IOW, tu e la pagina con cui tanto ti sei incarognito state dicendo
esattamente la stessa cosa...
 
 
 
 
Ciò detto, se vogliam parlare di architettura...
 
Una bancata di proxy che facciano solo la terminazione SSL si fa facile.
Basta mantenere la stickiness sull'IP sorgente e si salva anche il
caching delle chiavi per gran parte delle casistiche.
 
Viceversa, mantenere una bancata di proxy cache in parallelo è più
oneroso: più proxy aggiungi, minore sarà l'hit-rate sulla cache, dato
che le richieste si distribuiranno e così le entry cachate; comportando
maggior carico sui backend.
 
A meno di non mettere in piedi meccanismi simil-sibling per cui le entry
in cache vengono ridistribuite a tutti i proxy della bancata (cosa che,
comunque, aumenta il livello di stress portato ai proxy stessi, dato che
una richiesta da un altro proxy è pur sempre una richiesta).
 
Ergo, il fatto di avere terminazione SSL e caching eseguiti dallo stesso
oggetto non è un vantaggio in situazioni ad alto carico, dato che la
saturazione delle prestazioni per SSL giunge facilmente prima che per la
cache.
 
 
Il fatto di avere una terminazione ssl a monte ti consente di scalare il
numero di connessioni SSL in maniera indipendente dalle problematiche di
caching.
 
E il fatto di avere dietro al primo tier una cache più performante può
essere di considerevole aiuto.
 
 
 
[1] ad onor del vero, esiste pur sempre la possibilità di eseguire
caching a più livelli, con una bancata "ampia" di cache che puntano ad
un secondo e più ristretto tier di cache, che poi punta ai webserver.

 avesse SSL.
 
Fa sicuramente (beh. Quasi) la stessa cosa che farebbe varnish se avesse
SSL. Ma PROPRIO PER QUESTO, che la faccia varnish e' inutile.
 
O anzi: se varnish potesse avere SSL a costo zero, sarebbe inutile. Dato
che non puo', dato che avere SSL in corpo sarebbe DANNOSO ad altre cose,
ecco che averlo non e' semplicemente "inutile", ma proprio peggio.
 
Sostanzialmente, varnish ha fatto la scelta di trattare bene HTTP, anche
a spese di SSL. Si puo' caso mai criticare QUESTA scelta, si'. Potresti,
quindi, dire "potevano aggiungere l'ennesima iterazione di SSL di serie,
anche se cio' mi avrebbe peggiorato le prestazioni qualora avessi deciso
di non usarlo".
 
E pero', suoneresti un po' strano, non ti pare, visto che tu APPUNTO hai
deciso di non usarlo? :-)
 
Di fatto, staresti dicendo "Vorrei che varnish mi funzionasse peggio".


 Di fatto, staresti dicendo "Vorrei che varnish mi funzionasse peggio".
 
Traduzione: gli sviluppatori di Nginx non hanno capito proprio nulla. Ma 
per fortuna ci sono gli avventori di icol.* :)
Leonardo, sono pipponi quasi filosofici... e la filosofia mal si addice 
agli agli informatici. 
Non perché la filosofia sia un male, ma perché è proprio l'informatico che 
quando esula dal 2+2 dell'informatica finisce spesso per toppare. 
Ragion per cui addito la pagina in cui viene mostrato codice definito 
malvagio, per poi passare a motivazioni un po' improbabili, e per poi 
finire con il suggerire una cosa che sa tanto di "varnish + OpenSSL" :)
 
-- 
Massimiliano Adamo

Il Sun, 08 Jun 2014 18:41:40 +0000, Max_Adamo ha scritto:
 
[ CUT] 
 
inoltre, è sempre buona norma non parlar male del codice altrui, perché: 
 
1. tu (varnish community) non sei in grado di fare qualcosa di meglio 
(altrimenti lo avresti fatto).
2. dove ti giri e giri c'è quasi sempre OpenSSL. Apache, F5, Checkpoint 
Nginx... quindi una alternativa al codice malvagio ad oggi non esiste e se 
non la usi su varnish, finisci per usarla altrove. 
 
Quindi, per questo, e per quel che ho detto prima, quella pagina di 
giustificazioni infantili continua a non piacermi. 
 
-- 
Massimiliano Adamo

per fortuna ci sono gli avventori di icol.* :)
 
Ma no, dai. Sono due strumenti *diversi*. Gli sviluppatori di nginx hanno
fatto un'altra cosa.
 
Io, pedditte, quando ho avuto bisogno di supportare SSL, ho messo stunnel
davanti all'endpoint in chiaro. E se e' per quello quando devo agganciare
qualche cosa ad HTTP ci metto davanti Apache (o Tornado).


inoltre, è sempre buona norma non parlar male del codice altrui
 
Su questo... I'm of two minds. Diciamo che anch'io cercherei di non parlarne
male, almeno non a livello di scelte di design - del resto appunto non parlo
male ne' di nginx ne' di varnish - pero', e' anche vero che quanno ce vo' ce
vo'.


 per fortuna ci sono gli avventori di icol.* :)
 
Oppure sei tu che non hai capito una cosa essenziale: Nginx e Varnish sono 
due cose completamente differenti che solo per caso fanno un lavoro simile
 
Enrico

 agganciare qualche cosa ad HTTP ci metto davanti Apache (o Tornado).
 
 
non mi paiono molto performance wise queste soluzioni, Apache in 
particolare non è piccolo e snello... se quelli di varnish suggeriscono 
Nginx di fronte a varnish una ragione ci sarà ;)
 
visto che tessi le lodi di varnish, ti è mai capitato di dover fare delle 
sticky session senza client.ip e con il solo x-forwarded-for? 
Bello eh! Devi mettere codice C embedded nel file di configurazione di 
Varnish per sopperire alle mancanze di varnish. 
Oppure le redirect fatte in 3 mosse... salvo poi scoprire che qualcuno si 
è accorto della minchiata è ha fatto il modulo libvmod-redirect
 
La morale è che varnish è veloce perché praticamente non fa un cazzo di 
quel che alla fine ti serve veramente. Aggiungi il codice C, aggiungi il 
modulo X, il modulo Y .... e alla scopri che Varnish è diventato il 20% 
più lento di nginx :)
 
 
-- 
Massimiliano Adamo


Enrico... questa affermazione è quantomeno comica. Evidentemente non 
conosci ne l'uno ne l'altro prodotto, preferisco pertanto chiudere la 
discussione in tronco. 
 
-- 
Massimiliano Adamo

 vero che quanno ce vo' ce vo'.
 
Leonardo, non so se ti riferisci ancora ad openssl. 
In questo caso sono costretto a ripetermi fino alla nausea: non puoi 
scaricare la colpa sulla comunità openssl se non sei in grado fornire una 
alternativa che prescinda da openssl stesso, o scadere nel ridicolo 
proponendo alternative che fanno a loro volta uso di openssl. 
Difatto, le FAQ ufficiali di Varnish mostrano diversi esempi con Nginx e 
dove ti giri e giri c'è quasi sempre e solo openssl. 
Stunnel non è una soluzione high-end. 
 
p.s.: non so cosa usa cisco. 
 
-- 
Massimiliano Adamo


C{
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
}C
 
sub vcl_recv {
 
C{
//
// This is a hack from Igor Gariev (gariev hotmail com):
// Copy IP address from "X-Forwarded-For" header
// into Varnish's client_ip structure.
// This works with Varnish 3.0.1; test with other versions
//
// Trusted "X-Forwarded-For" header is a must!
// No commas are allowed. If your load balancer something other
// than a single IP, then use a regsub() to fix it.
//
struct sockaddr_storage *client_ip_ss = VRT_r_client_ip(sp);
struct sockaddr_in *client_ip_si = (struct sockaddr_in *) client_ip_ss;
struct in_addr *client_ip_ia = &(client_ip_si->sin_addr);
char *xff_ip = VRT_GetHdr(sp, HDR_REQ, "\020X-Forwarded-For:");
 
if (xff_ip != NULL) {
// Copy the ip address into the struct's sin_addr.
inet_pton(AF_INET, xff_ip, client_ip_ia);
}
}C
 
client.identity = client.ip
 
 
Dimmi te, se dopo aver messo 'sta roba nel file di configurazione Varnish 
continuerà ad essere più veloce di Nginx. 
 
Anche in questo caso varnish dice che gli altri sono cattivi e che se lo 
fai varnish non sarà più una scheggia. Poi fa pure il fico, perché ti fa 
la sticky session computando un hash sull'ip sorgente e associandolo allo 
stesso server del backend (se è vivo). 
Ma come fai a fare una sticky session basata sugli IP se sei dietro a un 
firewall e l'unica cosa che hai è un header che viene dal firewall? 
 
Stesso discorso con i plugin: varnish con i plugin sarà sempre veloce 
quanto il varnish che di fatto non fa un cazzo?
 
-- 
Massimiliano Adamo

 discussione in tronco. 
 
Direi che non li conosci tu i prodotti, dal momento che sono due cose
molto diverse. Il fatto che proxino tutti e due traffico http non li
rende la stessa cosa.
 
 
-- 
Flavio Visentin
 
Scientists discovered what's wrong with the female brain: on the left
side, there's nothing right, and on the right side, there's nothing left

 discussione in tronco.
 
Ma perchè dopo anni proviamo tutti ancora gusto a risponderti ?
 
Forse perchè siamo così bastardi da volerti lasciare ogni volta 
l'opportunità per mostrare la tua preparazione ?
 
 

 rende la stessa cosa.
 
Parliamo della componente HTTP proxy? Possiamo dire che *per quanto 
riguarda la componente della quale parliamo* stiamo comparando mele con 
mele? 
So che c'è un errore di fondo in quel che dico io: in questo modo potrei 
applicare lo stesso ragionamento per Apache. Verissimo. In questo senso ho 
sbagliato. 
Tuttavia, paragonare un programma di 400KB, con un altro programma di 
400KB, con l'uno riesce a fare le stesse cose dell'altro (anche se non il 
contrario), non mi sembra del tutto fuorviante o fuori dal mondo. 
 
Ho fatto notare che un paio di cose che dicono quelli di varnish non sono 
verità assoluta e sono o bugie o mezze verità. 
1. In Varnish dicono che la componente openssl è troppo più grande del 
codice stesso di Varnish, per poter pensare a fare un wrapper verso openssl 
stesso. Ebbene, nginx che è addirittura leggermente più piccolo lo fa 
(anche perché qualcuno dovrà pur sporcarsi le mani e se non lo fai tu, 
dovrà farlo qualcun altro). 
2. la filosofia di Varnish è quella di lasciar fuori tutte le funzioni 
(delle quali spesso non riesci a fare a meno, ivi incluso ssl e tanto 
tanto altro) con il fine di poter dire: noi siamo i più veloci. Poi basta 
un niente per modificare il default attivando quel che nella pratica ti 
serve quasi sempre ed ecco che varnish non è più quello di prima. 
3. la storia del codice openssl, lascia anch'essa il tempo che trova, 
poiché ad oggi non vedo alternative in nessun modo. Gli appliance e le 
alternative usano tutti openssl.
 
 
-- 
Massimiliano Adamo


ti rispondo solo per dirti che non ti rispondo nemmeno. Se ti va leggi la 
mia risposta a zipman. Se non ti va lascia perdere. 
 
-- 
Massimiliano Adamo

 alternative usano tutti openssl.
 
 
p.s.: vedi mia risposta a Leonardo Serni, dove spiego perché Varnish non 
fa tutto quel che dovrebbe fare. 
 
Quelle 3 righe di codice C, che sono ben note agli sviluppatori, non 
saranno mai implementate in Varnish, per ragioni vagamente simili a quelle 
di openssl: perché gli farebbero perdere il primato di programma più 
veloce. 
Li capisco bene: ogni riga di codice sbagliata degraderebbe le perfomance, 
ma di fatto, nella maggior parte dei casi di utilizzo non puoi fare a meno 
di certe funzioni: SSL e l'IP deli client dietro a un firewall non sono 
un'opzione ma sono spesso una necessità. 
Pertanto le proprietà che vengono attribuite a varnish sono molto 
virtuali. Non è vero che guarisce l'azheimer e i bambini malati. Fa solo 
proxying, lo fa bene, ma vuol essere scarno by design. 
Gli stessi plugin, te li danno in modalità codice sorgente, tanto per 
rimarcare la distanza e poter dire: non ti lamentare se varnish con i 
plugin non è la scheggia che ti abbiamo promesso. 
Anche se devo ammettere che l'architettura a plugin è una gran figata. 
 
 
-- 
Massimiliano Adamo

Il Mon, 09 Jun 2014 09:06:44 +0000, Max_Adamo ha scritto:
 
[ SNIP ]
 
ahah... una mezza cavolata adesso credo di averla detta veramente. Non è 
proprio una cavolata ma non vi dico cosa :) 
 
uno a zero per varnish :)
 
 
-- 
Massimiliano Adamo


NO. Non ho detto una cavolata: 
http://nginx.org/en/docs/http/ngx_http_realip_module.html
 
 
Nginx fa in modo estremamente semplice quel che Varnish non fa.
Ma tanto potrei scrivere tutto e il contrario di tutto, perché vi magnate 
di tutto. 
 
-- 
Massimiliano Adamo


questo è strafico e devo convincere i colleghi a passare a nginx:
 
set_real_ip_from  
192.168.1.0/24
;
set_real_ip_from  192.168.2.1;
set_real_ip_from  2001:0db8::/32;
real_ip_header    X-Forwarded-For;
real_ip_recursive on;
 
in base all'ip di provenienza, stabilisce qual è il real_ip: 
se la connessione arriva dalla rete interna non tocca niente altrimenti 
usa l'x-forwarded-for. 
 
E non solo: "If recursive search is enabled, the original client address 
that matches one of the trusted addresses is replaced by the last non-
trusted address sent in the request header field." 
 
Se capisco bene questa è roba buona (che non conoscevo prima). Con Varnish 
io non sto riuscendo a fare una whitelist effettiva con dei server che 
stanno dentro amazon, ma in questo modo dovrei riuscirci. 
Il collega ha chiesto al team di networking di farlo... e probabilmente F5 
fa questa cosa che io con Varnish non posso fare. 
 
va detto che questa funzione non è attiva per default e che nginx va 
compilato con --with-http_realip_module
 
-- 
Massimiliano Adamo


 
Mi va, tranqui.
A quale risposta ti riferisci, in particolare ?
Hai risposto 5 volte, correggendoti e smentendoti ogni volta.
 

 questo ï¿œ strafico e devo convincere i colleghi a passare a nginx:
 
Oppure basta imparare a configurare varnish.


 Oppure basta imparare a configurare varnish.
 
sono io quello che non conosce il prodotto? :)
 
varnish consente di scrivere: client.identity = client.ip
 
e consente anche di scrivere: http.x-forwarded-for = client.ip
 
Il problema è che, by design, non consente di fare il contrario.
Ovvero non puoi scrivere: client.ip = http.x-forwarded-for
e pertanto non puoi partire dall'x-f-f per arrivare al client.identity 
 
Se poi parlavi d'altro allora parliamo d'altro, ma non fare confusione.
 
Per fare quel che dici devi inserire il seguente codice C nel file di 
configurazione di varnish e verrà compilato a runtime (e farai una parte 
di quel che fa Varnish): 
 
C{
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
}C
 
sub vcl_recv {
 
C{
struct sockaddr_storage *client_ip_ss = VRT_r_client_ip(sp);
struct sockaddr_in *client_ip_si = (struct sockaddr_in *) client_ip_ss;
struct in_addr *client_ip_ia = &(client_ip_si->sin_addr);
char *xff_ip = VRT_GetHdr(sp, HDR_REQ, "\020X-Forwarded-For:");
 
if (xff_ip != NULL) {
inet_pton(AF_INET, xff_ip, client_ip_ia);
}
}C
 
client.identity = client.ip
 
 
Adesso funziona, ma varnish diventa una merda. 
 
 
-- 
Massimiliano Adamo

 non puoi partire dall'x-f-f per arrivare al client.identity
 
la sintassi (teorica) dovrebbe essere: 
set req.http.x-forwarded-for = client.ip 
 
peccato che funziona solo se viene scritta al contrario. 
 Rispondo alla tua maniera: impara tu a usare varnish... ;) e non dirmi di 
imparare a configurare una cosa che varnish non può fare. 
 
Se poi l'hack è quel che ti ho detto io... beh, stikazzi, io lo uso ma è 
sconsigliato dagli sviluppatori. 
 
-- 
Massimiliano Adamo

 Leonardo, non so se ti riferisci ancora ad openssl.
 
No no, parlavo in generale. Io mi riservo il diritto di dire male di un sacco
di cose anche se non sono in grado di fare di meglio, e anche se naturalmente
cerco di NON dire male senza una valida ragione. Ma se ce l'ho, parlo eccome.
 
Anche perche', se mi dovessi accontentare di gente che scrive codice non piu'
solido di come lo scrivo io, guidatori non migliori di me, chirurghi non piu'
bravi di quanto sia io, eccetera...
 
...be'; sarei morto da tanto di quel tempo che non varrebbe la pena :-)


 visto che tessi le lodi di varnish
 
No, no, no. Scusa, ma non ci siamo.
 
Io sto dicendo che varnish ha degli use case: e se lo usi FUORI da questi e'
comprensibile che possa fare onco ai vermi.
 
Potrebbe anche darsi che tutti gli utenti di varnish siano dei coglioni e il
programma faccia onco anche DENTRO i propri use case; ma questa probabilita'
diciamo che la tengo in secondo piano.
 
Non mi pare che questo sia un 'tessere le lodi'...


e pertanto non puoi partire dall'x-f-f per arrivare al client.identity
 
Scusa, non ti seguo. Quello che vuoi fare di norma non e' impostare il client
IP all'X-Forwarded-For o che so io; quello e' un MEZZO per fare qualcosa. Che
cos'e' questo qualcosa?
 
Diciamo che a monte di varnish arrivi una richiesta con un certo ip e un dato
xff.
 
Diciamo che vuoi sapere l'IP remoto.
 
Diciamo che hai un firewall o load balancer o chi per esso che si mangia l'ip
(nel senso che ovviamente a valle vedi il suo), ma non aggiorna l'xff: allora
sei nella pegola comunque, perche' il dato si e' perso.
 
Se invece l'host davanti a varnish mette qualcosa di utile nell'xff, a te che
te ne frega di metterlo dentro il campo ip? Lascialo nell'xff e parsa quello,
(in)affidabile come sara'.
 
Oppure, vedi come si fa perche' il firewall o chi per lui metta il dato in un
punto a cio' preposto; che l'xff di regola _NON_ lo e'. X-Client-IP, magari -
mi pare HAProxy faccia cosi'.
 
Non puoi usare varnish (o qualunque altra cosa!) per rimpeciottare il sistema
alla bell'e meglio, e poi prendertela pure con varnish se c'ha sudato :-D


Leonardo, 
Il tuo ragionamento ha una sua logica, che però non è la logica di varnish.  
La client affinity si può impostare solo tramite il parametro client.ip, che non è  l'x-f-f o l'hardware che più ti piace: x-pippo andrebbe anche bene. 
Il problema è che by design non si può fare, perché ammazza le prestazioni, non perché gli sviluppatori non sanno farlo. 
L'hack è quello suggerito da me. 
Se avete dubbi leggere la documentazione. 
P. S. Anche nginx non lo fa fare per impostazione predefinita e bisogna ricompilare il pacchetto con l'opzione del caso.  
 

Devo togliere la correzione automatica nella tastiera di Android. 
Hardware = header... spero che il resto bene o male si capisca ^_^

La client affinity si può impostare solo tramite il parametro client.ip,
 
...aspe': allora il discorso cambia ancora. Client affinity... vuoi fare load
balancing di tipo client-directed? Avere qualcosa tipo sticky session?
 
	# 
	# O magari non ho capito un apascio. Stacce.
	# 
	if (req.http.x-forwarded-for) {
		set client.identity = req.http.x-forwarded-for;
	}
 
...ma bisogna sempre che, se c'e' qualcuno davanti, non smantrugi gli header.
 
O nel caso di un front-end nginx e di varnish per il contenuto statico:
 
; Nginx
 
	proxy_set_header  X-Real-IP  $remote_addr;
 
; varnish
 
	set client.identity = req.http.X-Real-Ip;
 
Se uno vuole usare "client.ip", perche' essendo un oggetto supporta ACL piu'
comodose, si trova davanti al fatto che un oggetto non puo' essere assegnato
a bào con facilita'. Una possibile alternativa potrebbe essere
 
	if (! (
        	req.http.X-Real-IP ~ "^10\." ||
	        req.http.X-Real-IP ~ "^192\.168\." ||
	        req.http.X-Real-IP ~ "^169\.254\." ||
		req.http.X-Real-IP ~ "^224\." ||
	)) {
		...
	}
 
...oppure mettere un flag dentro NginX, per dire.
 
La "regola d'oro" e' sempre trovare chi sa fare bene (o economicamente, o in
fretta, o qualsiasi cosa importi) le cose e poi farle fare a lui. Pigiare le
cose dove non ci stanno e', diciamo "spesso", via, non sempre, ma spesso, un
mettere il sedere nelle pedate :-(


 La "regola d'oro" e' 
 
niet, non ci sono regole d'oro.
 
leggete la documentazione.... 
 
 
-- 
Massimiliano Adamo

 leggete la documentazione....
 
 
e counque ci vuole poco a constatarlo (anche senza documentazione). Basta 
lanciare "varnishncsa": al posto dell'IP vedrai tre trattini. Che vorrà 
dire che il tentativo di sovracrittura del client.ip è fallito 
miseramente. 
Poi lanci varnishncsa -f che ti mostrerà l'header x-f-f e vedrai che 
quello invece è a posto. 
 
 
-- 
Massimiliano Adamo

 niet, non ci sono regole d'oro.
 
Va bene. Come si dice, "Hic Rhodus, hic saltem".
 
# uname -a
Linux patonza 3.11.10-7-default #1 SMP Mon Feb 3 09:41:24 UTC 2014 (750023e)
x86_64 x86_64 x86_64 GNU/Linux
 
# cat /etc/os-release
NAME=openSUSE
VERSION="13.2 Milestone 0 (Harlequin)"
VERSION_ID="13.2milestone0"
PRETTY_NAME="openSUSE 13.2 Milestone 0 (Harlequin) (x86_64)"
ID=opensuse
ANSI_COLOR="0;32"
CPE_NAME="cpe:/o:opensuse:opensuse:13.2"
BUG_REPORT_URL="
https://bugs.opensuse.org
"
HOME_URL="
https://opensuse.org/
"
ID_LIKE="suse"
 
# zypper install varnish
(omissis)
 
# varnishd -V
 
varnishd (varnish-3.0.5 revision 1a89b1f)
Copyright (c) 2006 Verdens Gang AS
Copyright (c) 2006-2011 Varnish Software AS
 
/etc/varnish/vcl.conf:
 
backend member1 {
   .host = "127.0.0.4";
   .port = "80";
}
 
backend member2 {
   .host = "127.0.0.2";
   .port = "80";
}
 
backend member3 {
   .host = "127.0.0.3";
   .port = "80";
}
 
director mydir client {
   {
      .backend = member1;
      .weight = 1;
   }
   {
      .backend = member2;
      .weight = 1;
   }
   {
      .backend = member3;
      .weight = 1;
   }
}
 
sub vcl_recv {
        set client.identity = req.http.X-Real-Ip;
        set req.backend = mydir;
}
 
sub vcl_hash {
        hash_data(req.http.X-Real-Ip);
}
 
Il file "test.php" in ascolto sul loopback:
 
<?php
    // Stampiamo l'indirizzo visto dal server Apache locale
    print "Hello from {$_SERVER['SERVER_ADDR']}\n";
?>
 
A questo punto faccio una bombardata di richieste sempre dallo stesso IP reale
(127.0.0.1), ma mettendo un X-Real-Ip inventato, a rotazione.
 
Comportamento desiderato:
 
	1. esiste un rapporto 1:1 fra l'IP che io trasmetto con X-Real-Ip
	   e l'IP riportato dallo Hello di Apache ("sticky session").
 
	2. il numero di backend coinvolti e' equiripartito (load balancer
	   degno di questo nome).
 
	3. varnish fa effettivamente cache, non e' che mi rifischia tutte
	   le volte un DIRECT_HIT alla strapuppamelo.
 
	4. (requisito *non* funzionale) togliendo client.identity, almeno
           uno dei requisiti li' sopra deve andare a puttane, se no ci fo
	   una figura di palta anche se funzionasse, mi pare chiaro.
 
Script di test per i requisiti 1 e 2:
 
	for j in $( seq 1 10 ); do
		for i in $( seq 1 20 );
			do echo -ne "192.168.0.${i} = "
			curl -H "X-Real-Ip:192.168.0.${i}" \
 
http://192.168.4.200:8088/test.php
 
				2>/dev/null;
		done;
	done \
	| sort | uniq -c
 
Output:
 
    100 192.168.0.1 = Hello from 127.0.0.4
    100 192.168.0.10 = Hello from 127.0.0.4
    100 192.168.0.11 = Hello from 127.0.0.2
    100 192.168.0.12 = Hello from 127.0.0.2
    100 192.168.0.13 = Hello from 127.0.0.3
    100 192.168.0.14 = Hello from 127.0.0.4
    100 192.168.0.15 = Hello from 127.0.0.3
    100 192.168.0.16 = Hello from 127.0.0.4
    100 192.168.0.17 = Hello from 127.0.0.3
    100 192.168.0.18 = Hello from 127.0.0.2
    100 192.168.0.19 = Hello from 127.0.0.2
    100 192.168.0.2 = Hello from 127.0.0.4
    100 192.168.0.20 = Hello from 127.0.0.2
    100 192.168.0.3 = Hello from 127.0.0.4
    100 192.168.0.4 = Hello from 127.0.0.3
    100 192.168.0.5 = Hello from 127.0.0.3
    100 192.168.0.6 = Hello from 127.0.0.4
    100 192.168.0.7 = Hello from 127.0.0.2
    100 192.168.0.8 = Hello from 127.0.0.2
    100 192.168.0.9 = Hello from 127.0.0.3
 
Il requisito numero 1 e' soddisfatto: ogni IP (192.168.0.x) finisce sullo
stesso backend tutte e cento le volte.
 
Il requisito numero 2 e' soddisfatto: ogni backend (127.0.0.x) viene alla
ribalta circa per lo stesso numero di CLIENT (non di richieste):
 
    7 127.0.0.2
    6 127.0.0.3
    7 127.0.0.4
 
Per il requisito numero 3 esaminiamo il campo Age: di varnish:
 
	for j in $( seq 1 100 ); do for i in $( seq 1 20 );
		do echo -ne "192.168.0.${i} = "
		curl -v -H "X-Real-Ip:192.168.0.${i}" \
 
http://192.168.4.200:8088/test.php
 2>&1;
		done;
	done | grep "Age: " | sort | uniq -c
 
     80 < Age: 0
    120 < Age: 1
    140 < Age: 2
    129 < Age: 3
    131 < Age: 4
    140 < Age: 5
    120 < Age: 6
    140 < Age: 7
    140 < Age: 8
    120 < Age: 9
    140 < Age: 10
    137 < Age: 11
    143 < Age: 12
    153 < Age: 13
    147 < Age: 14
     20 < Age: 15
 
...e mi pare che ci siamo. 16 secondi per completare il test.
 
Requisito 4: commento il set client.identity e ripeto il test #1/#2.
 
    100 192.168.0.1 = Hello from 127.0.0.3
    100 192.168.0.10 = Hello from 127.0.0.3
    100 192.168.0.11 = Hello from 127.0.0.3
    100 192.168.0.12 = Hello from 127.0.0.3
    100 192.168.0.13 = Hello from 127.0.0.3
    100 192.168.0.14 = Hello from 127.0.0.3
    100 192.168.0.15 = Hello from 127.0.0.3
    100 192.168.0.16 = Hello from 127.0.0.3
    100 192.168.0.17 = Hello from 127.0.0.3
    100 192.168.0.18 = Hello from 127.0.0.3
    100 192.168.0.19 = Hello from 127.0.0.3
    100 192.168.0.2 = Hello from 127.0.0.3
    100 192.168.0.20 = Hello from 127.0.0.3
    100 192.168.0.3 = Hello from 127.0.0.3
    100 192.168.0.4 = Hello from 127.0.0.3
    100 192.168.0.5 = Hello from 127.0.0.3
    100 192.168.0.6 = Hello from 127.0.0.3
    100 192.168.0.7 = Hello from 127.0.0.3
    100 192.168.0.8 = Hello from 127.0.0.3
    100 192.168.0.9 = Hello from 127.0.0.3
 
...da cui si vede che il requisito #2 e', effettivamente, andato a donnine di
negoziabili costumi.
 
Per controllo, vediamo l'indianino da solo quanto ci avrebbe messo (questa e'
una VM piuttosto umile, eh):
 
     11 < Date: Tue, 10 Jun 2014 19:47:29 GMT
     49 < Date: Tue, 10 Jun 2014 19:47:30 GMT
     49 < Date: Tue, 10 Jun 2014 19:47:31 GMT
[omissis]
     49 < Date: Tue, 10 Jun 2014 19:48:09 GMT
     46 < Date: Tue, 10 Jun 2014 19:48:10 GMT
 
...'nzomma; una accelerazione di un fattore tre, anche se non e' che dovesse
fare tutta 'sta gran cosa. Ma torno a dire che varnish non e' fatto per dare
contenuto dinamico, e prima di dire "qui varnish conviene" bisogna fare test
ammodino.


 NAME=openSUSE
 
Una domanda OT: ho provato la 13.1 qualche settimana fa' (volevo metterla in 
sostituzione della mia Fedora) ma si perdeva il layout di tastiera ad ogni 
riavvio. E` qualcosa di noto oppure sono particolarmente sfigato io?
 
Enrico

riavvio. E` qualcosa di noto oppure sono particolarmente sfigato io?
 
Guarda se tante volte avesse a che fare con questo bug di loadkeys:
 
http://superuser.com/questions/579249/opensuse-12-3-kbd-service-failing-at-boot
 
 
https://bugzilla.novell.com/show_bug.cgi?id=813902
 


Perdonami se non riesco a fare il quoting ma scrivo da android. 
Ho appena bevuto il caffè e appena aperto gli occhi, ma sbaglio o stai operando sulla stessa rete, senza NAT? 
Bene. 
In questo caso, il campo client.ip  non è vuoto e quindi ti funziona, anche se ignora bellamente quel tentativo di client.ip= blahblah 
Dopo ti fa scrivere vcl_hash(blahblah) 
E magari questo funziona. 
Quello che hai fatto tu, devi farlo da PC che provengono da un'altra rete. 
In questo caso non vedrai tre trattini al post dell'IP e non ti funzionerà. 
 
Pensa una sola cosa: qualcuno si è inventato un codice C da inserire nel config di Varnish. 
Perché lo ha fatto? 
 
P.s. va caricato pure un modulo di varnish se non ricordo male. Potrebbe non essere sufficiente il codice C nel config.... Ma questo è un punto che devo verificare.

Ho appena bevuto il caffè e appena aperto gli occhi
 
Mi sa che forse sia meglio riparlarne piu' tardi :-D


 Leonardo
 
 
svelato l'arcano delle 8 di mattina... e devo dire che ho mischiato 2 cose.
 
questo è il mio file di configurazione (il backend è definito altrove): 
 
# Backend server group, with timeouts, health checks etc.
#include "/etc/varnish/backend.vcl";
 
import std;
import misc;
 
C{
#include <netinet/in.h>
#include <string.h>
#include <sys/socket.h>
#include <arpa/inet.h>
}C
 
acl loadbalancer {
   "172.25.135.10"/31;
}
 
sub vcl_recv {
   # Varnish needs to return 200 to Load balancer
   if (client.ip ~ loadbalancer) {
       error 200;
   }
   # Do not allow any query parameter "_wadl" or TRACE
   if (req.url ~ "\b_wadl&?" || req.request == "TRACE") {
       error 403 "X The server understood the request, but is refusing to 
fulfill it.";
   }
   # Do not allow /server-info /server-status /jmx-console /web-console
   if (req.url ~ "^/server-(info|status)" || req.url ~ "^/(web|jmx)-
console") {
       error 403 "The server understood the request, but is refusing to 
fulfill it.";
   }
   # Myproject prod definition
   if (req.http.host ~ "
api-myproject.mycompany.com
" || req.http.host ~ 
"
travelmaps.mycompany.com
") {
      # Paste X-Forwarded-For address into client.ip
      C{
         // This is a hack from Igor Gariev (gariev hotmail com):
         // Copy IP address from "X-Forwarded-For" header
         // into Varnish's client_ip structure.
         // This works with Varnish 3.0.1; test with other versions
         //
         // Trusted "X-Forwarded-For" header is a must!
         //
         struct sockaddr_storage *client_ip_ss = VRT_r_client_ip(sp);
         struct sockaddr_in *client_ip_si = (struct sockaddr_in *) 
client_ip_ss;
         struct in_addr *client_ip_ia = &(client_ip_si->sin_addr);
         char *xff_ip = strtok(VRT_GetHdr(sp, HDR_REQ, "\020X-Forwarded-
For:"), ",");
         if (xff_ip == NULL) xff_ip = VRT_GetHdr(sp, HDR_REQ, "\020X-
Forwarded-For:");
 
         if (xff_ip != NULL) {
            char *firstcomma = strchr( xff_ip, ','); // find the first 
comma in the string
            if (firstcomma) xff_ip[firstcomma-xff_ip]='\0'; // if found, 
terminate the string at first comma position
            // Copy the ip address into the struct’s sin_addr.
            inet_pton(AF_INET, xff_ip, client_ip_ia);
         }
      }C
      set client.identity = client.ip;
      set req.backend = myproject_tomcat;
      # URL POST and PUT Allowed but Private
      if (req.url ~ "^/api/[1-2]/agencies" ||
         req.url ~ "^/api/images" ||
         req.url ~ "^/api/css" ||
         req.url ~ "^/api/lib" ||
         req.url ~ "^/api/index.html$" ||
         req.url ~ "^/api/api-docs" ||
         req.url ~ "^/fe" ) {
         if (misc.inet_pton(false, req.http.X-Forwarded-For, "1.1.1.1") ~ 
mycompany) {
            return (pass);
         }
      }
      # URL POST and PUT Allowed and Public
      if (req.request == "POST" || req.request == "PUT") {
         if (req.url ~ "^/api/2/accounts/login" ||
            req.url ~ "^/api/2/accounts/register" ||
            req.url ~ "^/api/2/accounts/reset" ||
            req.url ~ "^/form/1/download" ||
            req.url ~ "^/api/[1-2]/coupons/(.*)?cityCode=") {
            if (req.http.X-Forwarded-Proto !~ "(?i)https") {
               set req.http.x-Redir-Url = "https://" + req.http.host + 
req.url;
               error 750 req.http.x-Redir-Url;
            } else {
               return (pass);
            }
         }
      }
      if (req.request == "GET" || req.request == "HEAD") {
         # URL GET and HEAD Allowed and Public
         if (req.url ~ "^/api/[1-2]/maps" ||
            req.url ~ "^/api/2/accounts/reset/" ||
            req.url ~ "^/api/versions/apk/(.*)/update" ||
            req.url ~ "^/img" ||
            req.url ~ "^/api/[1-9]*/status?" ||
            req.url ~ "^/api/1/versions" ||
            req.url ~ "^/form/1/download" ||
            req.url ~ "^/form/1/apk" ) {
            if (req.http.X-Forwarded-Proto !~ "(?i)https") {
               set req.http.x-Redir-Url = "https://" + req.http.host + 
req.url;
               error 750 req.http.x-Redir-Url;
            } else {
               return (pass);
            }
         }
         # URL that should return 410
         if (req.url ~ "^/api/0/status" ) {
            error 410;
         }
         # URL GET and HEAD Allowed but Private
         if (req.url ~ "^/api/[1-2]/agencies" ||
            req.url ~ "^/api/images" ||
            req.url ~ "^/api/css" ||
            req.url ~ "^/api/lib" ||
            req.url ~ "^/api/index.html$" ||
            req.url ~ "^/api/api-docs" ||
            req.url ~ "^/fe" ) {
            if (misc.inet_pton(false, req.http.X-Forwarded-For, "1.1.1.1") 
~ mycompany) {
               return (pass);
            }
         }
      error 403 "The server understood the request, but is refusing to 
fulfill it.";
      }
   error 404 "The Mycompany server has not found anything matching the 
Request-URI.";
   }
}
 
sub vcl_error {
   if (obj.status == 750) {
      set obj.http.Location = obj.response;
      set obj.status = 302;
      return (deliver);
   }
}
 
sub vcl_fetch {
   # 503 on POST methods means errors on backends and is very dangerous to 
retry
   if (beresp.status == 503 && req.request == "GET" && req.restarts < 2) {
      return (restart);
   }
   # Set temporary redirect (HTTP/307) cacheable.
   if (beresp.status == 307) {
      set beresp.ttl = 120s;
   }
   set beresp.grace = 30s;
}
 
sub vcl_deliver {
   if (client.ip ~ mycompany) {
      if (obj.hits > 0) {
         set resp.http.X-Cache = "HIT";
         set resp.http.X-Cache-Hits = obj.hits;
      } else {
         set resp.http.X-Cache = "MISS";
      }
   # Do not expose unnecessary information to internet.
   } else {
      unset resp.http.Server;
      unset resp.http.Age;
      unset resp.http.Via;
      unset resp.http.X-Cache-Path;
      unset resp.http.X-Country;
      unset resp.http.X-Powered-By;
      unset resp.http.X-Varnish;
   }
}
# EOF
 
 
 
 
 
-- 
Massimiliano Adamo

 # EOF
 
che vuol dire tutto quel papocchio? 
vuol dire che non posso usare le ACL incongiunzione con l'X-F-F 
Pertanto, se mi servono ACL (e mi servono sempre) sono costretto ad usare 
il client.ip 
A quel punto, avendo sovrascritto il client.ip con il valore di x-f-f, 
tanto vale usare client.ip per il client.identity
 
ti torna questo (che ammetto che è diverso da quel che ho detto ieri)? :)
 
 
 
-- 
Massimiliano Adamo

tanto vale usare client.ip per il client.identity
 
Si', ma... ci siamo messi in una situazione che *non* e' fatta per bene.
 
Qui tu mi dici: se io davanti al varnish metto un front end che non gestisce
le ACL perche' le faccio gestire quando la richiesta *e' gia' entrata*, come
se il client non fosse importante; e poi voglio usare il client perche', pur
non essendo importante, pero' e' importante... ALLORA varnish funziona male.
 
Sicuramente e' cosi', eh: ma diciamo anche che c'e' voluto un certo impegno.
 
Non ha molto senso che io vada a Kabul con la Ferrari Testarossa, saldandoci
sopra lamiere di acciaio per blindatura, e poi mi lamenti che la macchina va
piano, non resiste comunque ai proiettili HEAT, e in piu' consuma un casino.


 Ma anche no. Una ACL significa che quel client tu non lo vuoi. 
 
Ni. Non voglio quell'IP solo in una determinata URL. 
 
Caso A: URL per uso interno
 
Caso B: a una URL particolare corrispondono un servizio e un backend 
diversi. 
 
Dai, tanto è pubblico su internet, quindi ti fo l'esempio:
http://pre-trafficstats.tomtom.com/services/
 (*)
http://pre-trafficstats.tomtom.com/
 
 
(*) non dirmi nulla per la redirect un po' fuori luogo :) Si tratta 
comunque di "caso B". 
Questo è in acceptance, paradossalmente migliore di produzione. 
 
-- 
Massimiliano Adamo

 Ni. Non voglio quell'IP solo in una determinata URL.
 
Kkkkt. Non il caso piu' frequente dell'Universo, diciamolo. Ti potrebbe anche
convenire avere due frontend diversi ("divide et impera"): i client in arrivo
da Internet vengono deviati sulla porta 8881, quelli della intranet invece su
8882. Questo lo puo' fare direttamente (e facilmente) il firewall. *BSD rules
O.K., direi.
 
A questo punto, il frontend sulla porta 8881 - magari, gira pure sulla stessa
macchina dell'altro - applica le ACL URL-based, e puo' farlo molto in fretta.
 
Hai lo svantaggio di un (modesto) incremento di richiesta di risorse... pero'
hai una maggior granularita' e separi i due flussi, e questo puo' venire piu'
che comodo in certe occasioni.


 correttissimo. 
 
No, non mi sono letto tutto il thread, lo ammetto, ma usare, che so, stunnel?
(hi guys, btw)
 

(hi guys, btw)
 
De'. Fatti vivo ogni tanto, e' piu' raro vede' te che Babbo Natale...


 De'. Fatti vivo ogni tanto, e' piu' raro vede' te che Babbo Natale...
 
Eh, vita un po' complicata, negli ultimi anni, ma rileggervi è sempre un piacere. :)