SlideShare a Scribd company logo
1 of 57
Download to read offline
Varnish @ Opera
         Varnish Users Group Meeting
               Paris, 22nd March 2012
Cosimo Streppone <cosimo@opera.com>
1st Varnish deployment: My Opera

•   October 2009
•   1 old recycled machine, 2 Gb of disk allocated
•   Started serving static pictures (1M+ req/day)
•   Then more...
•   Even more...
•   ...
•   ~15% of all My Opera requests were «varnished»
•   Around 8M req/day
My Opera – The start

• Still using Debian Etch
  First Varnish instance was running v1.x from Etch.
  several years old, not good


• Experienced VIPs
   – ”Very Interesting Problems”
   – User X getting User Y's session
   – Random users getting admin powers. Nightmare!

• Theory: Varnish was caching response bodies that contained
  Set-Cookie: opera_session=<session_id>
My Opera – The start

if (req.url ~ "^/community/users/avatar.pl/[0-9]+$"
  || req.url ~ "^/.+/avatar.pl$"
  || req.url ~ "^/.+/picture.pl?xscale=100$"
  || req.url ~ "^/desktopteam/xml/atom/blog/?$"
  || req.url ~ "^/desktopteam/xml/rss/blog/?$"
  || req.url ~ "^/community/api/users/friends.pl?user=.+$"
  || req.url ~ "^/community/api/users/groups.pl?user=.+$"
) {
    unset req.http.Cookie;
    unset req.http.Authorization;
    lookup;
}
My Opera – Pass logged in users
    ...
    # Check for cookie only after always-cache URLs
    if (req.http.Cookie ~ "(opera_session|opera_persistent_)") {
      pass;
    }

    # DANGER, Will Robinson! Caching the front-page
    # At this point, lots of Google Analytics cookies will go in.
    # No problem. It's stuff used by Javascript
    if (req.url ~ "^/community/$") {
        lookup;
    }

    pass;
}
My Opera: testing Varnish setup
   ...
   ok 289 - Got response from backend for /community/ (from ...)
   ok 290 - Correct status line
   # Adding header [Cookie] => [language=it]
   # ----------
   # GET http://cache01.my.opera.com:6081/community/
   # Host: my.opera.com
   # ------------
   ok 291 - 2nd request: got response from backend for /community/ (from...)
             X-Varnish: 1211283813 1211283812
   ok 292 - Correct status line
   # X-Varnish: 1211283813 1211283812
             X-Varnish-Status: hit
   # X-Varnish-Status: hit
   # X-Varnish-Cacheable: yes, language cookie
             X-Varnish-Cacheable: yes, language cookie
   # X-Varnish-URL: /community/
             X-Varnish-URL: /community/
   ok 293 - URL '/community/' was handled correctly by varnish
   # cookie_header:
   ok 294 - URL '/community/' has correct cookies (or no cookies)
   1..294

All tests successful.
My Opera – Next steps
My Opera – Next steps

●
    Front page caching
●
    Static assets and UGC
●
    On-the-fly thumbnails
●
    “Shields-up” configuration
Front page caching

 Problem                   Solution

• Very dynamic, i18n   • varnish-accept-language
• Accept-Language        “extension”
  header variation
• Vary: Accept-
  Language sub-optimal
Front page caching - Accept-Language

      SUPPORTED_LANGUAGES = “:de:es:it:ru:”
      DEFAULT_LANGUAGE    = “en”


  Client sends                       Backend receives

Accept-Language:   ru, uk;q=0.9      Accept-Language:   ru
Accept-Language:   es-ES, es;q=0.8   Accept-Language:   es
Accept-Language:   fr, it;q=0.7      Accept-Language:   it
Accept-Language:   fr                Accept-Language:   ben
Front page caching
Static assets and UGC servers

  Problem                   Solution

• One central location    • Decentralized varnish
• SPOF                      servers in multiple DC
• High latency US -> NO   • Talking to 1 backend
                          • Very long TTL
                          • Health probes
                          • Cache invalidation API
                          • Built our GeoDNS
Thumbnail generation and caching

  Problem                 Solution

• Change of Design™      • Switch to on-the-fly
  made our millions of     generation model
  pre-generated          • Used mod_dims (AOL)
  thumbnails useless     • Varnish on :80
                         • 2 backends
                           300k objects
                           95% hit rate avg
                           800 req/s/backend peak
Thumbnail generation and caching

 How it works
 http://localhost/dims/
   crop/472x360/
   contrast/+1/
   quality/90/
   /actual/picture/url.jpg (remote too!)

 Using rewrite rules
 Http://localhost/tn/small/
   /actual/picture/url.jpg
Thumbnail generation and caching


●
    Recognize mobile/non-mobile

●
    Scale thumbnails on the fly

●
    Reduce JPEG quality
    Ex.: /thumb/small/quality/80/some/path/pic.jpg
Shields-up configuration

  Problem                  Solution

• Original setup too     • DDoS
  specific to My Opera   • Varnish in front, rather
• Long tail of non-        than after frontends
  popular content        • Cache most logged out
  “unprotected”            requests with lower TTL
• Can we find some       • Compromise solution,
  more generic setup?      but generic enough
Sitecheck
Sitecheck – Malware, fraud protection

 •   Used by the Opera browser
 •   Must work! Failure not an option
 •   ~8k req/s/backend peak
 •   2 varnish boxes, 16k req/s, 20k peak
 •   85% hit rate
 •   TTL 10'
Opera TV Store
Country-level ban

 • Contract mandates that TV Store shouldn't
   be available in specific countries

 • Country check in the backend means no
   caching is possible

 • Implemented with varnish-geoip
Country-level ban
 sub country_ban_list_check {

     # Allow testing of country ban
     if (req.http.Cookie ~ "x_geo_ip_forceds*=s*country:..") {
       set req.http.X-Geo-IP = regsuball(
          req.http.Cookie,
          "^.*x_geo_ip_forceds*=s*(country:..).*$", "1"
       );
       log "Forced X-Geo-IP to '" req.http.X-Geo-IP "'";
     }

     # Block access to tvstore in these countries
     if (req.http.X-Geo-IP &&
         req.http.X-Geo-IP ~ "^country:(C1|C2|C3|...)$") {
         log "Country ban";
         error 750 "tvstore is not available in your country";
     }
 }

 sub vcl_recv {
     C{ vcl_geoip_country_set_header_xff(sp); }C
     call country_ban_list_check;
 }
Brand + device TV detection


• Analyze User-Agent header

• Regex the hell out of it

• Send X-Brand, X-Device header to backend

• Fallback Device detection in the backend
  (for development, test setups, ...)
VCL library
accept-encoding.vcl
# STD: Deal with different Accept-Encoding formats
sub accept_encoding_normalize {
    if (req.http.Accept-Encoding) {

        if (req.http.Accept-Encoding ~ "gzip") {
            set req.http.Accept-Encoding = "gzip";
        }
        elsif (req.http.Accept-Encoding ~ "deflate") {
            set req.http.Accept-Encoding = "deflate";
        }
        else {
            unset req.http.Accept-Encoding;
        }
    }
}
accept-language.vcl
C{

/*
 * Accept-language header normalization
 *
 * - Parses client Accept-Language HTTP header
 * - Tries to find the best match with the supported languages
 * - Writes the best match as req.http.X-Varnish-Accept-Language
 *
 * http://github.com/cosimo/varnish-accept-language
 */

#include   <ctype.h> /* isupper */
#include   <stdio.h>
#include   <stdlib.h> /* qsort */
#include   <string.h>

#define DEFAULT_LANGUAGE "en"
#define SUPPORTED_LANGUAGES ":de:en:es-la:fr:fy:hu:ja:no:pl:pt-
br:ru:sk:sq:sr:tr:uk:vn:xx-lol:zh-tw:"

…
maintenance.vcl + {up,down}.sh
include "/etc/varnish/accept-encoding.vcl";

backend oopsy {
    .host = "10.20.21.22”;
    .port = "80";
}

sub vcl_recv {

    set req.backend = oopsy;

    # Serve page from within Varnish. See vcl_error()
    if (req.url == "/ping.html") {
        error 700;
    }

    call accept_encoding_normalize;

    # Collapse URLs, so that we have just one cached object
    set req.url = "/maintenance-down";

    remove req.http.Cookie;
    remove req.http.Authorization;
    return (lookup);
}
purge.vcl
acl purge { … }

sub vcl_recv {

    if (req.request == "PURGE") {
        If (! (client.ip ~ purge)) {
            error 405 "Not allowed.";
        }
        purge("req.url == " req.url);
        error 200 "Purged.";
    }

    else if (req.request == "PURGE_SUFFIX") {
        set req.http.X-URL =
          regsuball(req.url, "[|]|[^.$|()*+?{}]", "0") "$";
        purge_url(req.http.X-URL);
        unset req.http.X-URL;
        error 200 "Purged suffix.";
    }


                                                              Ugly!
    else if (req.request == "PURGE_PREFIX") {
        …
    }

}
X-forwarded-for.vcl
# See http://www.varnish-cache.org/trac/ticket/540
sub inject_forwarded_for {

    # Rename the incoming XFF header to work around a Varnish bug
    if (req.http.X-Forwarded-For) {
        # Append the client IP
        set req.http.X-Real-Forwarded-For =
            req.http.X-Forwarded-For ", "
            regsub(client.ip, ":.*", "");
    }
    else {
        # Simply use the client IP
        set req.http.X-Real-Forwarded-For = regsub(client.ip,
":.*", "");
    }
}

                                                      Wat!?
Testing VCLs – http-cuke
http-cuke – csrf.test

Feature: TVStore uses cookies to protect against CSRF attacks
 In order to protect the users from CSRF attacks
 As a TV Store developer
 I want to verify that some pages send out a CSRF cookie token to
   the browser or device

Scenario: Accessing the Backgammon application URL
 Given a "Opera/9.80 (Linux … Opera TV Store)" user agent
 When I go to "https://tvstore.server/store/app/backgammon"
 Then the final HTTP status code should be "200"
 Then the page should contain "A board game for one player"
  Then the page should not be cached by varnish
 Then the server should send a CSRF token
http-cuke – prove-like output




    $ http-cuke --test ./csrf.test

    $ http-cuke --test-dir ./some-dir
http-cuke – a sample test run
# ============================================================
# FEATURE: TV Store uses cookies to protect against CSRF attacks
# ============================================================
# ------------------------------------------------------------
#   SCENARIO: Accessing the Backgammon application URL
# ------------------------------------------------------------
ok 1 - Given a "Opera/9.80 (Linux...)" user agent
ok 2 - When I go to "https://tvstore.server/app/backgammon"
ok 3 -   Status code is 200 (expected 200)
ok 4 - Then the final HTTP status code should be "200"
ok 5 -   String 'A board game for one player' was found in the page
ok 6 - Then the page should contain "A board game for one player"
ok 7 -   X-Varnish header contains only current XID (523289525)
ok 8 -   Age of cached resource is zero
ok 9 - Then the page should not be cached by varnish
ok 10 -   CSRF token was found (49a0da1b2758bf62a028072e4f7f36dc)
ok 11 - Then the server should send a CSRF token
Puppet module
varnish/manifests/init.pp
 class varnish {

     package { "varnish": ensure => "installed" }
     file { "/etc/init.d/varnish": … }
     file { "/etc/sysctl.conf": … }
         exec { "update-sysctl": … }
     file { "/usr/share/varnish/purge-cache": … }

     service { "varnish": ensure => "running", … }
     munin::plugin::custom { "varnish_": }
     munin::plugin { [
         "varnish_backend_traffic",
         "varnish_expunge",
         …
     }
 }
Custom init script
  # Lower stack limit demand for every Varnish thread
  # http://projects.linpro.no/pipermail/varnish-misc/2009-August/002977.html
  # Still relevant for Varnish 3 ??
  ulimit -s 256


  # Startup with custom cc_command fails
  # Filed Debian bug #659005
  if bash -c "start-stop-daemon 
    --start --quiet --pidfile ${PIDFILE} 
    --exec ${DAEMON} -- -P ${PIDFILE} 
    ${DAEMON_OPTS} > ${output} 2>&1"; then
       log_end_msg 0
  else
    …
Custom sysctl settings
 # From http://varnish.projects.linpro.no/wiki/Performance
 # + our own tweaking and tuning

 net.ipv4.ip_local_port_range = 1024 65536
 net.core.rmem_max = 16777216
 net.core.wmem_max = 16777216
 net.ipv4.tcp_rmem = 4096 87380 16777216
 net.ipv4.tcp_wmem = 4096 65536 16777216
 net.ipv4.tcp_fin_timeout = 30
 net.core.netdev_max_backlog = 30000
 net.ipv4.tcp_no_metrics_save = 1
 net.core.somaxconn = 262144
 net.ipv4.tcp_syncookies = 1
 net.ipv4.tcp_max_orphans = 262144
 net.ipv4.tcp_max_syn_backlog = 262144
 net.ipv4.tcp_synack_retries = 2
 net.ipv4.tcp_syn_retries = 2
Purge cache script


 Modeled after Debian vcl-reload script

 $ purge-cache -a
 $ purge-cache -u http://some.url
 $ purge-cache -r '^/(home|user)/'
varnish/manifests/init.pp – 2
 define varnish::config (
     $vcl_conf="default.vcl",   $listen_address="",
     $listen_port=6081,         $thread_min=400,
     $thread_max=5000,          $thread_timeout=30,
     $storage_type="malloc",    $storage_size="12G",
     $ttl=60,                   $thread_pools=$processorcount,
     $sess_workspace=131072,    $cc_command="",
     $sess_timeout=3 ) {
     file { "/etc/default/varnish":
         ensure => "present",
         owner   => "root",
         group   => "root",
         mode    => 644,
         content => template("varnish/debian-defaults.erb"),
         require => Package["varnish"],
         notify => Service["varnish"],
     }

 }
Example of varnish::config
 varnish::config { "cache-varnish-config":
     vcl_conf       => "cache.vcl",
     storage_type   => "malloc",
     storage_size   => "20G",
     listen_port    => 80,
     sess_workspace => 131072,
     ttl            => 86400,
     thread_pools   => 8,
     thread_min     => 800,
     thread_max     => 10000,
     # Necessary for GeoIP
     cc_command     =>
          'exec cc -fpic -shared -Wl,-x 
          -L/usr/include/GeoIP.h -lGeoIP -o %o %s',
 }
varnish/manifests/init.pp – 3

 define varnish::vcl ($source) {

     file { "/etc/varnish/${name}.vcl":
         ensure => "present",
         owner   => "root",
         group   => "root",
         mode    => 644,
         source => $source,
         require => Package["varnish"],
         notify => Service["varnish"],
     }

 }
Migration to Varnish 3
Following Debian stable
   Not there yet. Still anchored to 2.1
Migration 2.0 → 2.1 was relatively painless
Embedded C code?
Migrate accept-language and geoip
      extensions to VMODs
2.1 → 3.0 syntax changes?
       Test our VCLs
Customizations
Are they still relevant for 3.0?
       (ulimit -s 256, etc...)
I'd like to see in varnish...
Easier VMODs
Ideally, as easy as embedded C!
varnishtop -t10s
  Collect traffic for 10s and then report


    Bonus feature: tags, AKA group-by

varnishtop -i RxURL -g RxHeader.Referer -t 60s
Use headers as vars less than ideal
  Introduce variables or registers to avoid

    set req.http.X-Var = regsuball(
        req.http.Some-Header, '…', '1'
    );
Better Cookies inspection
Avoid regsuball() mess on req.http.Cookie

set req.http.Cookie.SomeName = “xxx”;
set req.http.X-Var1 = req.http.Cookie.sessionid;

                    and...

set var.SessionID = req.http.Cookie.sessionid;
file storage?
malloc works fine for us, but we always had
        problems with file storage
Better SSL handling
Not really. nginx works fine.
Questions!
opera.com/jobs

More Related Content

What's hot

Puppet and the HashiStack
Puppet and the HashiStackPuppet and the HashiStack
Puppet and the HashiStackBram Vogelaar
 
Testing your infrastructure with litmus
Testing your infrastructure with litmusTesting your infrastructure with litmus
Testing your infrastructure with litmusBram Vogelaar
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnAppWalter Heck
 
Ansible : what's ansible & use case by REX
Ansible :  what's ansible & use case by REXAnsible :  what's ansible & use case by REX
Ansible : what's ansible & use case by REXSaewoong Lee
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stackBram Vogelaar
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slidesharetomcopeland
 
More tips n tricks
More tips n tricksMore tips n tricks
More tips n tricksbcoca
 
rake puppetexpert:create - Puppet Camp Silicon Valley 2014
rake puppetexpert:create - Puppet Camp Silicon Valley 2014rake puppetexpert:create - Puppet Camp Silicon Valley 2014
rake puppetexpert:create - Puppet Camp Silicon Valley 2014nvpuppet
 
Creating Reusable Puppet Profiles
Creating Reusable Puppet ProfilesCreating Reusable Puppet Profiles
Creating Reusable Puppet ProfilesBram Vogelaar
 
Configuration Surgery with Augeas
Configuration Surgery with AugeasConfiguration Surgery with Augeas
Configuration Surgery with AugeasPuppet
 
Autoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomadAutoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomadBram Vogelaar
 
Hacking ansible
Hacking ansibleHacking ansible
Hacking ansiblebcoca
 
PuppetCamp SEA 1 - Version Control with Puppet
PuppetCamp SEA 1 - Version Control with PuppetPuppetCamp SEA 1 - Version Control with Puppet
PuppetCamp SEA 1 - Version Control with PuppetWalter Heck
 
Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteBram Vogelaar
 
Observability with Consul Connect
Observability with Consul ConnectObservability with Consul Connect
Observability with Consul ConnectBram Vogelaar
 
Ansible for beginners
Ansible for beginnersAnsible for beginners
Ansible for beginnersKuo-Le Mei
 
Securing Prometheus exporters using HashiCorp Vault
Securing Prometheus exporters using HashiCorp VaultSecuring Prometheus exporters using HashiCorp Vault
Securing Prometheus exporters using HashiCorp VaultBram Vogelaar
 
HTTP caching with Varnish
HTTP caching with VarnishHTTP caching with Varnish
HTTP caching with VarnishDavid de Boer
 
DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)Soshi Nemoto
 

What's hot (20)

Puppet and the HashiStack
Puppet and the HashiStackPuppet and the HashiStack
Puppet and the HashiStack
 
Testing your infrastructure with litmus
Testing your infrastructure with litmusTesting your infrastructure with litmus
Testing your infrastructure with litmus
 
PuppetCamp SEA 1 - Puppet Deployment at OnApp
PuppetCamp SEA 1 - Puppet Deployment  at OnAppPuppetCamp SEA 1 - Puppet Deployment  at OnApp
PuppetCamp SEA 1 - Puppet Deployment at OnApp
 
Ansible : what's ansible & use case by REX
Ansible :  what's ansible & use case by REXAnsible :  what's ansible & use case by REX
Ansible : what's ansible & use case by REX
 
Bootstrapping multidc observability stack
Bootstrapping multidc observability stackBootstrapping multidc observability stack
Bootstrapping multidc observability stack
 
Railsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshareRailsconf2011 deployment tips_for_slideshare
Railsconf2011 deployment tips_for_slideshare
 
More tips n tricks
More tips n tricksMore tips n tricks
More tips n tricks
 
rake puppetexpert:create - Puppet Camp Silicon Valley 2014
rake puppetexpert:create - Puppet Camp Silicon Valley 2014rake puppetexpert:create - Puppet Camp Silicon Valley 2014
rake puppetexpert:create - Puppet Camp Silicon Valley 2014
 
Creating Reusable Puppet Profiles
Creating Reusable Puppet ProfilesCreating Reusable Puppet Profiles
Creating Reusable Puppet Profiles
 
Configuration Surgery with Augeas
Configuration Surgery with AugeasConfiguration Surgery with Augeas
Configuration Surgery with Augeas
 
Autoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomadAutoscaling with hashi_corp_nomad
Autoscaling with hashi_corp_nomad
 
Hacking ansible
Hacking ansibleHacking ansible
Hacking ansible
 
PuppetCamp SEA 1 - Version Control with Puppet
PuppetCamp SEA 1 - Version Control with PuppetPuppetCamp SEA 1 - Version Control with Puppet
PuppetCamp SEA 1 - Version Control with Puppet
 
Integrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suiteIntegrating icinga2 and the HashiCorp suite
Integrating icinga2 and the HashiCorp suite
 
FreeBSD: Dev to Prod
FreeBSD: Dev to ProdFreeBSD: Dev to Prod
FreeBSD: Dev to Prod
 
Observability with Consul Connect
Observability with Consul ConnectObservability with Consul Connect
Observability with Consul Connect
 
Ansible for beginners
Ansible for beginnersAnsible for beginners
Ansible for beginners
 
Securing Prometheus exporters using HashiCorp Vault
Securing Prometheus exporters using HashiCorp VaultSecuring Prometheus exporters using HashiCorp Vault
Securing Prometheus exporters using HashiCorp Vault
 
HTTP caching with Varnish
HTTP caching with VarnishHTTP caching with Varnish
HTTP caching with Varnish
 
DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)DevOps(3) : Ansible - (MOSG)
DevOps(3) : Ansible - (MOSG)
 

Viewers also liked

IPW2008 - my.opera.com scalability
IPW2008 - my.opera.com scalabilityIPW2008 - my.opera.com scalability
IPW2008 - my.opera.com scalabilityCosimo Streppone
 
NPW2009 - my.opera.com scalability v2.0
NPW2009 - my.opera.com scalability v2.0NPW2009 - my.opera.com scalability v2.0
NPW2009 - my.opera.com scalability v2.0Cosimo Streppone
 
YAPC::EU::2009 - How Opera Software uses Perl
YAPC::EU::2009 - How Opera Software uses PerlYAPC::EU::2009 - How Opera Software uses Perl
YAPC::EU::2009 - How Opera Software uses PerlCosimo Streppone
 
Velocity 2011 - Our first DDoS attack
Velocity 2011 - Our first DDoS attackVelocity 2011 - Our first DDoS attack
Velocity 2011 - Our first DDoS attackCosimo Streppone
 
Velocity 2012 - Learning WebOps the Hard Way
Velocity 2012 - Learning WebOps the Hard WayVelocity 2012 - Learning WebOps the Hard Way
Velocity 2012 - Learning WebOps the Hard WayCosimo Streppone
 

Viewers also liked (6)

IPW2008 - my.opera.com scalability
IPW2008 - my.opera.com scalabilityIPW2008 - my.opera.com scalability
IPW2008 - my.opera.com scalability
 
Italian, do you speak it?
Italian, do you speak it?Italian, do you speak it?
Italian, do you speak it?
 
NPW2009 - my.opera.com scalability v2.0
NPW2009 - my.opera.com scalability v2.0NPW2009 - my.opera.com scalability v2.0
NPW2009 - my.opera.com scalability v2.0
 
YAPC::EU::2009 - How Opera Software uses Perl
YAPC::EU::2009 - How Opera Software uses PerlYAPC::EU::2009 - How Opera Software uses Perl
YAPC::EU::2009 - How Opera Software uses Perl
 
Velocity 2011 - Our first DDoS attack
Velocity 2011 - Our first DDoS attackVelocity 2011 - Our first DDoS attack
Velocity 2011 - Our first DDoS attack
 
Velocity 2012 - Learning WebOps the Hard Way
Velocity 2012 - Learning WebOps the Hard WayVelocity 2012 - Learning WebOps the Hard Way
Velocity 2012 - Learning WebOps the Hard Way
 

Similar to VUG5: Varnish at Opera Software

HTTP Caching and PHP
HTTP Caching and PHPHTTP Caching and PHP
HTTP Caching and PHPDavid de Boer
 
Caching with Varnish
Caching with VarnishCaching with Varnish
Caching with Varnishschoefmax
 
Supercharging Content Delivery with Varnish
Supercharging Content Delivery with VarnishSupercharging Content Delivery with Varnish
Supercharging Content Delivery with VarnishSamantha Quiñones
 
PHP London Dec 2013 - Varnish - The 9 circles of hell
PHP London Dec 2013 - Varnish - The 9 circles of hellPHP London Dec 2013 - Varnish - The 9 circles of hell
PHP London Dec 2013 - Varnish - The 9 circles of hellluis-ferro
 
Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Asher Martin
 
Varnish: Making eZ Publish sites fly
Varnish: Making eZ Publish sites flyVarnish: Making eZ Publish sites fly
Varnish: Making eZ Publish sites flyPeter Keung
 
Boost your website by running PHP on Nginx
Boost your website by running PHP on NginxBoost your website by running PHP on Nginx
Boost your website by running PHP on NginxHarald Zeitlhofer
 
June8 presentation
June8 presentationJune8 presentation
June8 presentationnicobn
 
Apache and PHP: Why httpd.conf is your new BFF!
Apache and PHP: Why httpd.conf is your new BFF!Apache and PHP: Why httpd.conf is your new BFF!
Apache and PHP: Why httpd.conf is your new BFF!Jeff Jones
 
Running Docker in Development & Production (#ndcoslo 2015)
Running Docker in Development & Production (#ndcoslo 2015)Running Docker in Development & Production (#ndcoslo 2015)
Running Docker in Development & Production (#ndcoslo 2015)Ben Hall
 
php & performance
 php & performance php & performance
php & performancesimon8410
 
Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부Hyun-Mook Choi
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.jsorkaplan
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applicationsTom Croucher
 
Fisl - Deployment
Fisl - DeploymentFisl - Deployment
Fisl - DeploymentFabio Akita
 
Toster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsToster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsFabio Akita
 
Understanding the Rails web model and scalability options
Understanding the Rails web model and scalability optionsUnderstanding the Rails web model and scalability options
Understanding the Rails web model and scalability options.toster
 

Similar to VUG5: Varnish at Opera Software (20)

HTTP Caching and PHP
HTTP Caching and PHPHTTP Caching and PHP
HTTP Caching and PHP
 
Caching with Varnish
Caching with VarnishCaching with Varnish
Caching with Varnish
 
Supercharging Content Delivery with Varnish
Supercharging Content Delivery with VarnishSupercharging Content Delivery with Varnish
Supercharging Content Delivery with Varnish
 
PHP London Dec 2013 - Varnish - The 9 circles of hell
PHP London Dec 2013 - Varnish - The 9 circles of hellPHP London Dec 2013 - Varnish - The 9 circles of hell
PHP London Dec 2013 - Varnish - The 9 circles of hell
 
Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2Cape Cod Web Technology Meetup - 2
Cape Cod Web Technology Meetup - 2
 
Varnish: Making eZ Publish sites fly
Varnish: Making eZ Publish sites flyVarnish: Making eZ Publish sites fly
Varnish: Making eZ Publish sites fly
 
Boost your website by running PHP on Nginx
Boost your website by running PHP on NginxBoost your website by running PHP on Nginx
Boost your website by running PHP on Nginx
 
June8 presentation
June8 presentationJune8 presentation
June8 presentation
 
Pecl Picks
Pecl PicksPecl Picks
Pecl Picks
 
Apache and PHP: Why httpd.conf is your new BFF!
Apache and PHP: Why httpd.conf is your new BFF!Apache and PHP: Why httpd.conf is your new BFF!
Apache and PHP: Why httpd.conf is your new BFF!
 
Nodejs - A quick tour (v6)
Nodejs - A quick tour (v6)Nodejs - A quick tour (v6)
Nodejs - A quick tour (v6)
 
Rack
RackRack
Rack
 
Running Docker in Development & Production (#ndcoslo 2015)
Running Docker in Development & Production (#ndcoslo 2015)Running Docker in Development & Production (#ndcoslo 2015)
Running Docker in Development & Production (#ndcoslo 2015)
 
php & performance
 php & performance php & performance
php & performance
 
Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부Fargate 를 이용한 ECS with VPC 1부
Fargate 를 이용한 ECS with VPC 1부
 
introduction to node.js
introduction to node.jsintroduction to node.js
introduction to node.js
 
Writing robust Node.js applications
Writing robust Node.js applicationsWriting robust Node.js applications
Writing robust Node.js applications
 
Fisl - Deployment
Fisl - DeploymentFisl - Deployment
Fisl - Deployment
 
Toster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability OptionsToster - Understanding the Rails Web Model and Scalability Options
Toster - Understanding the Rails Web Model and Scalability Options
 
Understanding the Rails web model and scalability options
Understanding the Rails web model and scalability optionsUnderstanding the Rails web model and scalability options
Understanding the Rails web model and scalability options
 

Recently uploaded

Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebUiPathCommunity
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Mark Simos
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenHervé Boutemy
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfAddepto
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...AliaaTarek5
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfAlex Barbosa Coqueiro
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfLoriGlavin3
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024Lonnie McRorey
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 3652toLead Limited
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr BaganFwdays
 

Recently uploaded (20)

Dev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio WebDev Dives: Streamline document processing with UiPath Studio Web
Dev Dives: Streamline document processing with UiPath Studio Web
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
Tampa BSides - Chef's Tour of Microsoft Security Adoption Framework (SAF)
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
DevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache MavenDevoxxFR 2024 Reproducible Builds with Apache Maven
DevoxxFR 2024 Reproducible Builds with Apache Maven
 
Gen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdfGen AI in Business - Global Trends Report 2024.pdf
Gen AI in Business - Global Trends Report 2024.pdf
 
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
(How to Program) Paul Deitel, Harvey Deitel-Java How to Program, Early Object...
 
Unraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdfUnraveling Multimodality with Large Language Models.pdf
Unraveling Multimodality with Large Language Models.pdf
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
Moving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdfMoving Beyond Passwords: FIDO Paris Seminar.pdf
Moving Beyond Passwords: FIDO Paris Seminar.pdf
 
TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024TeamStation AI System Report LATAM IT Salaries 2024
TeamStation AI System Report LATAM IT Salaries 2024
 
Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365Ensuring Technical Readiness For Copilot in Microsoft 365
Ensuring Technical Readiness For Copilot in Microsoft 365
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan"ML in Production",Oleksandr Bagan
"ML in Production",Oleksandr Bagan
 

VUG5: Varnish at Opera Software

  • 1. Varnish @ Opera Varnish Users Group Meeting Paris, 22nd March 2012 Cosimo Streppone <cosimo@opera.com>
  • 2. 1st Varnish deployment: My Opera • October 2009 • 1 old recycled machine, 2 Gb of disk allocated • Started serving static pictures (1M+ req/day) • Then more... • Even more... • ... • ~15% of all My Opera requests were «varnished» • Around 8M req/day
  • 3. My Opera – The start • Still using Debian Etch First Varnish instance was running v1.x from Etch. several years old, not good • Experienced VIPs – ”Very Interesting Problems” – User X getting User Y's session – Random users getting admin powers. Nightmare! • Theory: Varnish was caching response bodies that contained Set-Cookie: opera_session=<session_id>
  • 4. My Opera – The start if (req.url ~ "^/community/users/avatar.pl/[0-9]+$" || req.url ~ "^/.+/avatar.pl$" || req.url ~ "^/.+/picture.pl?xscale=100$" || req.url ~ "^/desktopteam/xml/atom/blog/?$" || req.url ~ "^/desktopteam/xml/rss/blog/?$" || req.url ~ "^/community/api/users/friends.pl?user=.+$" || req.url ~ "^/community/api/users/groups.pl?user=.+$" ) { unset req.http.Cookie; unset req.http.Authorization; lookup; }
  • 5. My Opera – Pass logged in users ... # Check for cookie only after always-cache URLs if (req.http.Cookie ~ "(opera_session|opera_persistent_)") { pass; } # DANGER, Will Robinson! Caching the front-page # At this point, lots of Google Analytics cookies will go in. # No problem. It's stuff used by Javascript if (req.url ~ "^/community/$") { lookup; } pass; }
  • 6. My Opera: testing Varnish setup ... ok 289 - Got response from backend for /community/ (from ...) ok 290 - Correct status line # Adding header [Cookie] => [language=it] # ---------- # GET http://cache01.my.opera.com:6081/community/ # Host: my.opera.com # ------------ ok 291 - 2nd request: got response from backend for /community/ (from...) X-Varnish: 1211283813 1211283812 ok 292 - Correct status line # X-Varnish: 1211283813 1211283812 X-Varnish-Status: hit # X-Varnish-Status: hit # X-Varnish-Cacheable: yes, language cookie X-Varnish-Cacheable: yes, language cookie # X-Varnish-URL: /community/ X-Varnish-URL: /community/ ok 293 - URL '/community/' was handled correctly by varnish # cookie_header: ok 294 - URL '/community/' has correct cookies (or no cookies) 1..294 All tests successful.
  • 7. My Opera – Next steps
  • 8. My Opera – Next steps ● Front page caching ● Static assets and UGC ● On-the-fly thumbnails ● “Shields-up” configuration
  • 9. Front page caching Problem Solution • Very dynamic, i18n • varnish-accept-language • Accept-Language “extension” header variation • Vary: Accept- Language sub-optimal
  • 10. Front page caching - Accept-Language SUPPORTED_LANGUAGES = “:de:es:it:ru:” DEFAULT_LANGUAGE = “en” Client sends Backend receives Accept-Language: ru, uk;q=0.9 Accept-Language: ru Accept-Language: es-ES, es;q=0.8 Accept-Language: es Accept-Language: fr, it;q=0.7 Accept-Language: it Accept-Language: fr Accept-Language: ben
  • 12. Static assets and UGC servers Problem Solution • One central location • Decentralized varnish • SPOF servers in multiple DC • High latency US -> NO • Talking to 1 backend • Very long TTL • Health probes • Cache invalidation API • Built our GeoDNS
  • 13. Thumbnail generation and caching Problem Solution • Change of Design™ • Switch to on-the-fly made our millions of generation model pre-generated • Used mod_dims (AOL) thumbnails useless • Varnish on :80 • 2 backends 300k objects 95% hit rate avg 800 req/s/backend peak
  • 14. Thumbnail generation and caching How it works http://localhost/dims/ crop/472x360/ contrast/+1/ quality/90/ /actual/picture/url.jpg (remote too!) Using rewrite rules Http://localhost/tn/small/ /actual/picture/url.jpg
  • 15. Thumbnail generation and caching ● Recognize mobile/non-mobile ● Scale thumbnails on the fly ● Reduce JPEG quality Ex.: /thumb/small/quality/80/some/path/pic.jpg
  • 16. Shields-up configuration Problem Solution • Original setup too • DDoS specific to My Opera • Varnish in front, rather • Long tail of non- than after frontends popular content • Cache most logged out “unprotected” requests with lower TTL • Can we find some • Compromise solution, more generic setup? but generic enough
  • 18. Sitecheck – Malware, fraud protection • Used by the Opera browser • Must work! Failure not an option • ~8k req/s/backend peak • 2 varnish boxes, 16k req/s, 20k peak • 85% hit rate • TTL 10'
  • 20. Country-level ban • Contract mandates that TV Store shouldn't be available in specific countries • Country check in the backend means no caching is possible • Implemented with varnish-geoip
  • 21.
  • 22. Country-level ban sub country_ban_list_check { # Allow testing of country ban if (req.http.Cookie ~ "x_geo_ip_forceds*=s*country:..") { set req.http.X-Geo-IP = regsuball( req.http.Cookie, "^.*x_geo_ip_forceds*=s*(country:..).*$", "1" ); log "Forced X-Geo-IP to '" req.http.X-Geo-IP "'"; } # Block access to tvstore in these countries if (req.http.X-Geo-IP && req.http.X-Geo-IP ~ "^country:(C1|C2|C3|...)$") { log "Country ban"; error 750 "tvstore is not available in your country"; } } sub vcl_recv { C{ vcl_geoip_country_set_header_xff(sp); }C call country_ban_list_check; }
  • 23. Brand + device TV detection • Analyze User-Agent header • Regex the hell out of it • Send X-Brand, X-Device header to backend • Fallback Device detection in the backend (for development, test setups, ...)
  • 25. accept-encoding.vcl # STD: Deal with different Accept-Encoding formats sub accept_encoding_normalize { if (req.http.Accept-Encoding) { if (req.http.Accept-Encoding ~ "gzip") { set req.http.Accept-Encoding = "gzip"; } elsif (req.http.Accept-Encoding ~ "deflate") { set req.http.Accept-Encoding = "deflate"; } else { unset req.http.Accept-Encoding; } } }
  • 26. accept-language.vcl C{ /* * Accept-language header normalization * * - Parses client Accept-Language HTTP header * - Tries to find the best match with the supported languages * - Writes the best match as req.http.X-Varnish-Accept-Language * * http://github.com/cosimo/varnish-accept-language */ #include <ctype.h> /* isupper */ #include <stdio.h> #include <stdlib.h> /* qsort */ #include <string.h> #define DEFAULT_LANGUAGE "en" #define SUPPORTED_LANGUAGES ":de:en:es-la:fr:fy:hu:ja:no:pl:pt- br:ru:sk:sq:sr:tr:uk:vn:xx-lol:zh-tw:" …
  • 27. maintenance.vcl + {up,down}.sh include "/etc/varnish/accept-encoding.vcl"; backend oopsy { .host = "10.20.21.22”; .port = "80"; } sub vcl_recv { set req.backend = oopsy; # Serve page from within Varnish. See vcl_error() if (req.url == "/ping.html") { error 700; } call accept_encoding_normalize; # Collapse URLs, so that we have just one cached object set req.url = "/maintenance-down"; remove req.http.Cookie; remove req.http.Authorization; return (lookup); }
  • 28. purge.vcl acl purge { … } sub vcl_recv { if (req.request == "PURGE") { If (! (client.ip ~ purge)) { error 405 "Not allowed."; } purge("req.url == " req.url); error 200 "Purged."; } else if (req.request == "PURGE_SUFFIX") { set req.http.X-URL = regsuball(req.url, "[|]|[^.$|()*+?{}]", "0") "$"; purge_url(req.http.X-URL); unset req.http.X-URL; error 200 "Purged suffix."; } Ugly! else if (req.request == "PURGE_PREFIX") { … } }
  • 29. X-forwarded-for.vcl # See http://www.varnish-cache.org/trac/ticket/540 sub inject_forwarded_for { # Rename the incoming XFF header to work around a Varnish bug if (req.http.X-Forwarded-For) { # Append the client IP set req.http.X-Real-Forwarded-For = req.http.X-Forwarded-For ", " regsub(client.ip, ":.*", ""); } else { # Simply use the client IP set req.http.X-Real-Forwarded-For = regsub(client.ip, ":.*", ""); } } Wat!?
  • 30. Testing VCLs – http-cuke
  • 31. http-cuke – csrf.test Feature: TVStore uses cookies to protect against CSRF attacks In order to protect the users from CSRF attacks As a TV Store developer I want to verify that some pages send out a CSRF cookie token to the browser or device Scenario: Accessing the Backgammon application URL Given a "Opera/9.80 (Linux … Opera TV Store)" user agent When I go to "https://tvstore.server/store/app/backgammon" Then the final HTTP status code should be "200" Then the page should contain "A board game for one player" Then the page should not be cached by varnish Then the server should send a CSRF token
  • 32. http-cuke – prove-like output $ http-cuke --test ./csrf.test $ http-cuke --test-dir ./some-dir
  • 33. http-cuke – a sample test run # ============================================================ # FEATURE: TV Store uses cookies to protect against CSRF attacks # ============================================================ # ------------------------------------------------------------ # SCENARIO: Accessing the Backgammon application URL # ------------------------------------------------------------ ok 1 - Given a "Opera/9.80 (Linux...)" user agent ok 2 - When I go to "https://tvstore.server/app/backgammon" ok 3 - Status code is 200 (expected 200) ok 4 - Then the final HTTP status code should be "200" ok 5 - String 'A board game for one player' was found in the page ok 6 - Then the page should contain "A board game for one player" ok 7 - X-Varnish header contains only current XID (523289525) ok 8 - Age of cached resource is zero ok 9 - Then the page should not be cached by varnish ok 10 - CSRF token was found (49a0da1b2758bf62a028072e4f7f36dc) ok 11 - Then the server should send a CSRF token
  • 34.
  • 36. varnish/manifests/init.pp class varnish { package { "varnish": ensure => "installed" } file { "/etc/init.d/varnish": … } file { "/etc/sysctl.conf": … } exec { "update-sysctl": … } file { "/usr/share/varnish/purge-cache": … } service { "varnish": ensure => "running", … } munin::plugin::custom { "varnish_": } munin::plugin { [ "varnish_backend_traffic", "varnish_expunge", … } }
  • 37. Custom init script # Lower stack limit demand for every Varnish thread # http://projects.linpro.no/pipermail/varnish-misc/2009-August/002977.html # Still relevant for Varnish 3 ?? ulimit -s 256 # Startup with custom cc_command fails # Filed Debian bug #659005 if bash -c "start-stop-daemon --start --quiet --pidfile ${PIDFILE} --exec ${DAEMON} -- -P ${PIDFILE} ${DAEMON_OPTS} > ${output} 2>&1"; then log_end_msg 0 else …
  • 38. Custom sysctl settings # From http://varnish.projects.linpro.no/wiki/Performance # + our own tweaking and tuning net.ipv4.ip_local_port_range = 1024 65536 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 net.ipv4.tcp_rmem = 4096 87380 16777216 net.ipv4.tcp_wmem = 4096 65536 16777216 net.ipv4.tcp_fin_timeout = 30 net.core.netdev_max_backlog = 30000 net.ipv4.tcp_no_metrics_save = 1 net.core.somaxconn = 262144 net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_orphans = 262144 net.ipv4.tcp_max_syn_backlog = 262144 net.ipv4.tcp_synack_retries = 2 net.ipv4.tcp_syn_retries = 2
  • 39. Purge cache script Modeled after Debian vcl-reload script $ purge-cache -a $ purge-cache -u http://some.url $ purge-cache -r '^/(home|user)/'
  • 40. varnish/manifests/init.pp – 2 define varnish::config ( $vcl_conf="default.vcl", $listen_address="", $listen_port=6081, $thread_min=400, $thread_max=5000, $thread_timeout=30, $storage_type="malloc", $storage_size="12G", $ttl=60, $thread_pools=$processorcount, $sess_workspace=131072, $cc_command="", $sess_timeout=3 ) { file { "/etc/default/varnish": ensure => "present", owner => "root", group => "root", mode => 644, content => template("varnish/debian-defaults.erb"), require => Package["varnish"], notify => Service["varnish"], } }
  • 41. Example of varnish::config varnish::config { "cache-varnish-config": vcl_conf => "cache.vcl", storage_type => "malloc", storage_size => "20G", listen_port => 80, sess_workspace => 131072, ttl => 86400, thread_pools => 8, thread_min => 800, thread_max => 10000, # Necessary for GeoIP cc_command => 'exec cc -fpic -shared -Wl,-x -L/usr/include/GeoIP.h -lGeoIP -o %o %s', }
  • 42. varnish/manifests/init.pp – 3 define varnish::vcl ($source) { file { "/etc/varnish/${name}.vcl": ensure => "present", owner => "root", group => "root", mode => 644, source => $source, require => Package["varnish"], notify => Service["varnish"], } }
  • 43.
  • 45. Following Debian stable Not there yet. Still anchored to 2.1 Migration 2.0 → 2.1 was relatively painless
  • 46. Embedded C code? Migrate accept-language and geoip extensions to VMODs
  • 47. 2.1 → 3.0 syntax changes? Test our VCLs
  • 48. Customizations Are they still relevant for 3.0? (ulimit -s 256, etc...)
  • 49. I'd like to see in varnish...
  • 50. Easier VMODs Ideally, as easy as embedded C!
  • 51. varnishtop -t10s Collect traffic for 10s and then report Bonus feature: tags, AKA group-by varnishtop -i RxURL -g RxHeader.Referer -t 60s
  • 52. Use headers as vars less than ideal Introduce variables or registers to avoid set req.http.X-Var = regsuball( req.http.Some-Header, '…', '1' );
  • 53. Better Cookies inspection Avoid regsuball() mess on req.http.Cookie set req.http.Cookie.SomeName = “xxx”; set req.http.X-Var1 = req.http.Cookie.sessionid; and... set var.SessionID = req.http.Cookie.sessionid;
  • 54. file storage? malloc works fine for us, but we always had problems with file storage
  • 55. Better SSL handling Not really. nginx works fine.