Juin 252014
 

Voici une mise à jour du template cacti adapté aux nouveaux paramètres de varnishstat (varnish 4.0.1).
Je me suis basé sur ce template prévu pour varnish 3 : https://github.com/glensc/cacti-template-varnish

Le xml : cacti_host_template_varnish_4_0_1.xml
Des graphs supplémentaires ont été ajouté pour les bans, les gzips, les sessions, les threads.

Le script python à ajouter au dossier scripts de cacti : get_varnish_stats.py
Ce script a aussi été modifié pour appeler une clé ssh avec l’option -k ou par défaut « ~/.ssh/id_rsa »

Maj 25/06/2014 : Mise à jour du template 4.0.0 -> 4.0.1 (ajout du graph purges activity)

Avr 102014
 

Nouvelle version majeur de varnish :
https://www.varnish-cache.org/content/varnish-cache-400

Pour l’installer :

curl http://repo.varnish-cache.org/debian/GPG-key.txt | apt-key add -
echo 'deb http://repo.varnish-cache.org/debian/ wheezy varnish-4.0' >> /etc/apt/sources.list.d/varnish.list
apt-get update
apt-get install varnish

Un fichier de configuration pour débuter :

# Varnish 4
vcl 4.0;
# Backend par defaut
backend default {
        .host = "127.0.0.1";
        .port = "81";
        .connect_timeout = 1s;
        .first_byte_timeout = 30s;
        .probe = {
                .url = "/";  # ou .request = "GET / HTTP/1.1" "Host: blog.jeremm.fr" "Connection: close";
                .timeout  = 15s;
                .interval = 15s;
                .window    = 5;
                .threshold = 2;
        }
}
sub vcl_recv {
        # Defini le backend
        set req.backend_hint = default ;
        # Pipe directement au backend pour les requetes non HTTP
        if (req.method != "GET" &&
                req.method != "HEAD" &&
                req.method != "PUT" &&
                req.method != "POST" &&
                req.method != "TRACE" &&
                req.method != "OPTIONS" &&
                req.method != "DELETE") {
                return (pipe);
        }
        # Ne pas cacher pour les requetes HTTP qui ne sont pas des simples demandes GET 
        if (req.method != "GET" && req.method != "HEAD") {
                return (pass);
        }
        # Enleve les cookies sur les medias pour que le hash match tous les clients
        if (req.url ~ "\.(jpeg|jpg|png|gif|ico|swf|js|css|gz|rar|txt|bzip|pdf)(\?.*|)$" && req.url !~ "^/index.php?") {
                unset req.http.Cookie;
                return (hash);
        }
        # Ne pas cacher pour les parties avec authentification
        if (req.http.Authorization) {
                return (pass);
        }
        return (hash);
}
sub vcl_hash {
        hash_data(req.url);
        if (req.http.host) {
                hash_data(req.http.host);
        } else {
                hash_data(server.ip);
        }
        if (req.http.Cookie) {
                hash_data(req.http.Cookie);
        }
        return(lookup);
}
sub vcl_pass {
        set req.http.X-marker = "pass" ;
}
sub vcl_backend_response {
        # Gzip tous les objets
        if ( ! beresp.http.Content-Encoding ~ "gzip" ) {
                set beresp.do_gzip = true;
        }
        # Efface le set-cookie sur les medias
        if (bereq.url ~ "\.(jpeg|jpg|png|gif|ico|swf|js|css|gz|rar|txt|bzip|pdf)(\?.*|)$" && bereq.url !~ "^/index.php?") {
                unset beresp.http.set-cookie;
        }
        # Cache les redirections et ne cache pas les 404
        if (beresp.ttl > 0s ) {
                if (beresp.status >= 300 && beresp.status <= 399) {
                        set beresp.ttl = 10m;
                }
                if (beresp.status >= 399) {
                        set beresp.ttl = 0s;
                }
        }
        # Efface le set-cookie sur les 404 & Cie
        if (beresp.status >= 399) {
                unset beresp.http.set-cookie;
        }
        # Maximum 24h de cache
        if (beresp.ttl > 86400s) {
                set beresp.ttl = 86400s;
        }
        # Marqueur pour l'entete HTTP de la reponse
        if (bereq.http.X-marker == "pass" ) {
                unset bereq.http.X-marker;
                set beresp.http.X-marker = "pass";
                set beresp.ttl = 0s ;
        }
        # Ne pas cacher si il y a encore un set-cookie
        if (beresp.ttl > 0s && beresp.http.set-cookie) {
                set beresp.ttl = 0s ;
        }
}
sub vcl_deliver {
        # Ajout et nettoyage de l'entete HTTP de la reponse
        if (obj.hits > 0){
                set resp.http.X-Varnish-Cache = "HIT";
        } else {
                set resp.http.X-Varnish-Cache = "MISS";
        }
        if (resp.http.X-marker == "pass" ) {
                unset resp.http.X-marker;
                set resp.http.X-Varnish-Cache = "PASS";
        }
        unset resp.http.Via;
        unset resp.http.X-Varnish;
        unset resp.http.Server;
        unset resp.http.X-Powered-By;
}
sub vcl_synth {
        if (resp.status >= 500 && req.restarts < 4) {
                return (restart);
        }
}

Téléchargeable ici : http://blog.jeremm.fr/default.4.0.vcl

Maj 25/06/2014 : Ajout de commentaires dans la conf
Maj 22/02/2014 : Retrait des règles X-Forwarded-For natif en version 4

Déc 192013
 

Si varnish écoute sur un port différent du port 80, il faut ajouter une ligne au début de votre configuration vcl_recv sinon le backend risque de ne pas retrouver le bon vhost demandé :

sub vcl_recv {
     set req.http.host = regsuball(req.http.host, ":[0-9]+$", "");
Oct 182013
 

Pour limiter le nombre de requêtes par IP, vous pouvez installer le vmod throttle.
Voici le fichier compilé pour varnish 3.0.4 à placer sous debian dans /usr/lib/varnish/vmods :
libvmod_throttle.so.3.0.4.tar
MAJ : Voici le fichier compilé pour varnish 3.0.5 à placer sous debian dans /usr/lib/varnish/vmods :
libvmod_throttle.so.3.0.5.tar
MAJ : Voici le fichier compilé pour varnish 3.0.3 à placer sous debian dans /usr/lib/varnish/vmods :
libvmod_throttle.so.3.0.3.tar
Il faut ensuite ajouter dans la configuration en premier lieu:

import throttle;

puis dans le vcl_recv :

if(throttle.is_allowed("ip:" + client.ip, "20req/s") > 0s) {
        error 429 "Calm down";
}

Vous pouvez préciser plusieurs ratios entre les guillemets :

20req/s, 200req/30s, 1000req/5m, 2000req/h

Les unités de temps possibles sont : s,m,h,d

Vous pouvez exclure des IPs en utilisant une acl :

acl allowIP {
        "127.0.0.1";
}
 
sub vcl_recv {
        if (!client.ip ~ allowIP) {
                if(throttle.is_allowed("ip:" + client.ip, "20req/s") > 0s) {
                        error 429 "Calm down";
                }
        }
}

Vous pouvez aussi changer comment il applique le ratio, par exemple par user-agent :

if(throttle.is_allowed(req.http.user-agent, "20req/s") > 0s) {

On peut aussi appliquer le ratio que sur les miss par ip par exemple :

sub vcl_miss {
    if(req.url !~ "\.(jpg|jpeg|png|gif|ico|swf|css|js|html|htm)$") {
         if(throttle.is_allowed("miss:" + client.ip, "20req/s") > 0s) {
               error 429 "Calm down";
         }
    }
}

Lien : https://github.com/nand2/libvmod-throttle