Varnish is caching logged in users pages and serving those pages

cachevarnish

I set logged_in cookie when user login. If logged_in cookie exists then varnish will not cache the request.

This is my vcl_recv

sub vcl_recv
{
    if (req.backend.healthy) {
        set req.grace = 30s;
    } else {
        set req.grace = 1h;
    }

    # Handle compression correctly. Different browsers send different
    # "Accept-Encoding" headers, even though they mostly support the same
    # compression mechanisms. By consolidating compression headers into
    # a consistent format, we reduce the cache size and get more hits.
    # @see: http:// varnish.projects.linpro.no/wiki/FAQ/Compression
    if (req.http.Accept-Encoding) {
            if (req.http.Accept-Encoding ~ "gzip") {
            # If the browser supports it, we'll use gzip.
            set req.http.Accept-Encoding = "gzip";
        }
        else if (req.http.Accept-Encoding ~ "deflate") {
            # Next, try deflate if it is supported.
            set req.http.Accept-Encoding = "deflate";
        }
        else {
            # Unknown algorithm. Remove it and send unencoded.
            unset req.http.Accept-Encoding;
        }
    }

    # Set client IP
    if (req.http.x-forwarded-for) {
        set req.http.X-Forwarded-For =
        req.http.X-Forwarded-For + ", " + client.ip;
    } else {
        set req.http.X-Forwarded-For = client.ip;
    }

    if (req.http.Authorization || req.http.Authenticate)
    {
      return (pass);
    }

    if (req.url ~ "^/registration" ||
        req.url ~ "^/blog/viewnoti/" ||
        req.url ~ "^/action/insert_user" ||
        req.url ~ "^/loginmanager.*$") {
        return (pass);
    }

    if (req.request != "GET" &&
      req.request != "HEAD" &&
      req.request != "PUT" &&
      req.request != "POST" &&
      req.request != "TRACE" &&
      req.request != "OPTIONS" &&
      req.request != "DELETE") {
          # /* Non-RFC2616 or CONNECT which is weird. */
        return (pipe);
    }

    if (req.request != "GET" && req.request != "HEAD") {
        # /* We only deal with GET and HEAD by default */
        return (pass);
    }

    if (!req.backend.healthy) {
        unset req.http.Cookie;
    }

    if (req.http.cookie ~ "logged_in") {
        return (pass);
    }

    if (req.http.Cache-Control ~ "(no-cache|no-store|private)") {
        return (pass);
    }

    if (req.http.cookie) {
        # removes all cookies named __utm? (utma, utmb...) - tracking thing
        set req.http.cookie = regsuball(req.http.cookie, "(^|; ) *__utm.=[^;]+;? *", "\1");

        if (req.http.cookie == "") {
            unset req.http.cookie;
        }
    }

    return (lookup);
}

This is my vcl_fetch

sub vcl_fetch
{
    if (req.url ~ "^/" ||
        req.url ~ "^/live" ||
        req.url ~ "^/selected" )
    {
        set beresp.ttl = 5m;
    } else {
      set beresp.ttl = 30m;
    }

    if (req.http.cookie ~ "logged_in") {
        set beresp.ttl = 0s;
    }

    if (req.http.Cache-Control ~ "(no-cache|no-store|private)") {
        set beresp.ttl = 0s;
    }

    # Set Grace Time to one hour
    set beresp.grace = 2h;
}

Varnish is cacheing logged in user request and serveing those page to visitors and other loggedin users. I can not figure out why t is doing it.

Best Answer

did you try moving cookie check before if (!req.backend.healthy) { block (which might unset cookies)? Or you may want (at least for test) making cache per-cookie (so it will not serve wrong content for logged in users):

sub vcl_hash {
    hash_data(req.http.cookie);
}

see docs for more granular approach. It might be worth checking vcl_hash if you have something specific already there...