Explicitly Approving (Whitelisting) Cookies in Varnish With Libvmod-Cookie

Mattias Geniar, Sunday, December 21, 2014

In all my previous Varnish 3.x configs, I've always used blacklisting as the way of handling Cookies. You explicitly tell which cookies you want to remove in vcl_recv, all others remain. But just as security measures, whitelisting is always better than blacklisting.

Even if you fully manage your site and all code, you may not have full control over 3rd party (client-side) advertisers that use tracking cookies. And those cookies may, even if you don't approve of the method, be placed under your domain. So the next request to your site suddenly includes (random) tracking cookies, unique for each visitor, and it destroys the caching in vcl_hash.

Please note this guide is focused on Varnish 3.x. Varnish 4.x will have the Cookie VMOD available by default, no custom compiles required!

Blacklisting / Removing cookies in Varnish

This is the common method of removing cookies in vcl_recv.

set req.http.Cookie = regsuball(req.http.Cookie, "has_js=[^;]+(; )?", "");

And you would repeat that line 1, 10 or 100 times, depending on what cookies you want to remove.

Implementing a whitelist of allowed cookies

In order to use a whitelisting approach, you can use the libvmod-cookie VMOD for Varnish 3.x. It allows more fine-grained control over what cookies are preserved and which ones get removed.

In order to use the VMOD, you need to compile it from source. And to compile the VMOD from source, you also need the Varnish source files somewhere on your system. You can still keep the RPM packages from Varnish installed, but the source is needed to compile the VMOD against it.

Preparing the Varnish source

In this guide, I'll use Varnish 3.0.6 as the base-version to compile against. Download the source and run make to build the binary files, but no not make install as you want to keep the packages from the upstream Varnish repo intact.

$ cd /usr/local/src
$ wget "https://repo.varnish-cache.org/source/varnish-3.0.6.tar.gz"
$ tar xzvf varnish-3.0.6.tar.gz
$ cd varnish-3.0.6
$ ./configure
$ make

Now you have the Varnish source and a built binary available in /usr/local/src/varnish-3.0.6. We'll use this to compile the VMOD against.

Download and install the libvmod-cookie varnish module

Next, download and compile the libvmod-cookie module.

$ cd /usr/local/src
$ wget "https://github.com/lkarsten/libvmod-cookie/tarball/3.0"
$ tar xzvf 3.0
$ cd lkarsten-libvmod-cookie-fe38614
$ ./configure VARNISHSRC=/usr/local/src/varnish-3.0.6 VMODDIR=/usr/lib64/varnish/vmods/
$ make && make install

The result is a vmod module installed in /usr/lib64/varnish/vmods/.

$ ls -alh /usr/lib64/varnish/vmods/
-rwxr-xr-x 1 root root  955 Dec 21 21:28 libvmod_cookie.la
-rwxr-xr-x 1 root root  42K Dec 21 21:28 libvmod_cookie.so
-rwxr-xr-x 1 root root  16K Oct 16 16:30 libvmod_std.so

The libvmod_std is the standard library included by Varnish. The libvmod_cookie is the new binary module, and you can include the vmod in your VCL code now.

import cookie;

vcl_recv {
  ...
}

Whitelisting cookies using filter_except() in libvmod-cookie

And now that the VMOD module is installed and ready for use, you can use the powerful filter_except() function call to pass a comma-separated list of cookies to allow, all others will be removed.

vcl_recv {
  # Let the module parse the "Cookie:" header from the client
  cookie.parse(req.http.cookie);

  # Filter all except these cookies from it
  cookie.filter_except("cookie1,cookie2");

  # Set the "Cookie:" header to the parsed/filtered value, removing all unnecessary cookies
  set req.http.cookie = cookie.get_string();
}

Any other cookie besides cookie1 and cookie2 will be removed from the Cookie: header now.

To debug this and to test what cookies are removed and which ones remain, look at my post about seeing which cookies get stripped in the VCL.

Next up: figuring out how to pass regex's along. ;-)

Caveats

A few things to keep in mind;

  1. VMODs are compiled, so it's better to make packages out of them
  2. Since VMODs are compiled against a specific version, they need to match the Varnish version. (so varnish 3.0.5 from RPM/Yum repos and VMODs compiled with 3.0.6 source can mean troubles)
  3. For automating this at scale, you need the VMODs in your own repository
  4. The filter_except() call accepts strings, not regex's -- to match against regex's, you would need to loop all values

To be continued!



Hi! My name is Mattias Geniar. I'm a Support Manager at Nucleus Hosting in Belgium, a general web geek, public speaker and podcaster. Currently working on DNS Spy. Follow me on Twitter as @mattiasgeniar.

I respect your privacy and you won't get spam. Ever.
Just a weekly newsletter about Linux and open source.

SysCast podcast

In the SysCast podcast I talk about Linux & open source projects, interview sysadmins or developers and discuss web-related technologies. A show by and for geeks!

cron.weekly newsletter

A weekly newsletter - delivered every Sunday - for Linux sysadmins and open source users. It helps keeps you informed about open source projects, Linux guides & tutorials and the latest news.

Share this post

Did you like this post? Will you help me share it on social media? Thanks!

Comments

Ljubisa Monday, March 28, 2016 at 13:27 (permalink)

Vmod would be great but it seems that it doesn’t work in vcl_backend_response fn.

Reply


Leave a Reply

Your email address will not be published. Required fields are marked *