Search
Varnish Controller

Routing Decisions

Introduction

This tutorial covers examples and a practical look into the controllers routing decisions: ASN, CIDR and Geolocation. More information regarding these routing decisions can be found here.

Environment

This tutorial is dependent on: HTTP Routing and assumes that the environment described there is installed and ready.

CIDR

This is a practical example of setting up CIDR(classless-inter-domain-routing) based routing. More information regarding CIDR can be found here.

Configure the CIDR decision

  1. Create a CIDR route.

    # Every CIDR needs a corresponding Tag ID. The format is `<CIDR>:<TagID>`. Multiple
    # CIDR's can be added with the format of: `<CIDR-1>:<TagID>,<CIDR-2>:<TagID>,..`
    $ vcli cidrroutes add cidrRoute --cidr-to-tag=17.5.0.0/16:1 --subdecision=leastutilized
    +----+---------------+--------------------------------+---------------------+
    | ID |     Name      |          CIDR-To-Tags          |   Subdecision       |
    +----+---------------+--------------------------------+---------------------+
    |  1 | cidrRoute     | 17.5.0.0/16:1(prod)            | LeastUtilized       |
    +----+---------------+--------------------------------+---------------------+
    
  2. Update the routing rule.

    ./cli rr update 1 --lookup-order=cidr:1
    +----+---------+------+------+-------+---------------+
    | ID |  Name   | DNS  | HTTP | Order | Debug Headers |
    +----+---------+------+------+-------+---------------+
    |  1 | Routing | true | true | cidr:1 | true         |
    +----+---------+------+------+-------+---------------+
    
  3. Verify that the request redirects based on CIDR.

    curl -v http://172.31.0.203:8900 -H "Host: mysite.example.com" -H "X-forwarded-for: 17.5.14.1"
    < HTTP/1.1 302 Found
    < Server: Varnish Request Router/1.2.0
    < Access-Control-Allow-Origin: *
    < Access-Control-Allow-Methods: GET
    < X-Router-Name: router1
    < X-Router-LookupTime: 10.578µs
    < X-Router-ClientIP: 17.5.0.0
    < X-Router-RouteType: cidr:1
    < X-Router-RouteMatch: 17.5.0.0/16(CIDR)
    < X-Router-Endpoint: 0-agent2
    < X-Router-Trace: [cidr:1]
    < X-Router-Subdecision: Leastutilized
    < Location: http://172.31.0.202:8081/mysite.example.com/
    

ASN

This is a practical example of setting up ASN(Autonomous System Number) based routing. More information regarding ASNs can be found here.

Requirements

  • MMDB ASN database for lookups. Details can be found here.

MMDB ASN Database

The MMDB ASN database needs to be added to the router container. The path could be either a file path or an URL, which makes it possible to have the MMDB on a remote service. the file can by updated or changed in runtime and will be re-read on configured intervals, see File watcher.

  1. Shutdown the router container.

    $ docker stop router1
    
  2. Start router1 with the path to the MMDB.

    # <path-to-asn-mmdb> Can be either a file path or an URL.
    $ docker-compose run -d -e VARNISH_CONTROLLER_ROUTER_NAME=myASNRouter -e VARNISH_CONTROLLER_MMDB_ASN_FILE="<path-to-asn-mmdb>" router1
    

Configure the ASN decision

  1. Create an ASN route.

    # Every ASN needs a corresponding Tag ID. The format is `<ASN>:<TagID>`.
    # Multiple ASN's can be added with the format of: `<ASN-1>:<TagID>,<ASN-2>:<TagID>,..`
    # This example uses 237 as an ASN, a different ASN might be needed depending on the ISP.
    $ vcli asnroutes add asnRoute --asn-to-tag=237:1 --subdecision=leastutilized
    +----+---------------+--------------------------------+---------------------+
    | ID |     Name      |          ASN-To-Tags           |   Subdecision       |
    +----+---------------+--------------------------------+---------------------+
    |  1 | asnRoute      | 237:1(prod)                    | LeastUtilized       |
    +----+---------------+--------------------------------+---------------------+
    
  2. Update the routing rule.

    ./cli rr update 1 --lookup-order=asn:1
    +----+---------+------+------+-------+---------------+
    | ID |  Name   | DNS  | HTTP | Order | Debug Headers |
    +----+---------+------+------+-------+---------------+
    |  1 | Routing | true | true | asn:1 | true          |
    +----+---------+------+------+-------+---------------+
    
  3. Verify that the request directs based on ASN

    curl -v http://172.31.0.203:8900 -H "Host: mysite.example.com" -H "X-forwarded-for: 35.128.0.0"
    < HTTP/1.1 302 Found
    < Server: Varnish Request Router/1.2.0
    < Access-Control-Allow-Origin: *
    < Access-Control-Allow-Methods: GET
    < X-Router-Name: router1
    < X-Router-LookupTime: 38.808µs
    < X-Router-ClientIP: 35.128.0.0
    < X-Router-RouteType: asn:1
    < X-Router-RouteMatch: 237(ASN)
    < X-Router-Endpoint: 0-agent1
    < X-Router-Trace: [asn:1]
    < X-Router-SubDecisionType: Leastutilized
    < Location: http://172.31.0.202:8081/mysite.example.com/
    

Geolocation

Geolocation routing makes it possible to configure routing based on clients geolocation. Each geolocation configured is connected to a tag and the client will be routed to one of the endpoints within the tag. More information regarding the Geolocation decision can be found here.

Requirements

  • MMDB GeoIP City database for geolocation lookups. Details can be found here.
  • CSV GeoIP City database for location reference. Details can be found here.

MMDB Database

The MMDB database needs to be added to the router container. The path could be either a file path or an URL, which makes it possible to have the mmdb on a remote service. The file can by updated or changed in runtime and will be re-read at configured intervals, see File watcher.

  1. Start by adding mmdb to the environment.

    $ docker stop router
    
  2. Start router with the mmdb file.

    # <path-to-mmdb> Can be either a file path or an URL.
    $ docker-compose run -d -e VARNISH_CONTROLLER_ROUTER_NAME=myASNRouter -e VARNISH_CONTROLLER_MMDB_FILE="<path-to-mmdb>" brainz
    

CSV Database

For ensuring correctness when adding Geolocation routing the brainz instances needs a corresponding CSV version of the MMDB database, this ensures also that geolocations with non-unique naming such as London, which exists in multiple locations will be routed correctly, because it matches on Geoname ID.

The CSV GeoIP database needs to be added to the brainz container. The path could be either a file path or URL, which makes it possible to have the CSV on a remote service. The file can be updated or changed in runtime and will be re-read at configured intervals. See File CSV watcher.

  1. Add the CSV to the environment.

    $ docker stop brainz
    
  2. Start brainz with the CSV version.

    # <path-to-mmdb-csv> Can be either a file path or an URL.
    $ docker-compose run -d -e VARNISH_CONTROLLER_BRAINZ_NAME=myBrainz -e VARNISH_CONTROLLER_MMDB_FILE_CSV="<path-to-mmdb-csv>" brainz
    

Configure the Geolocation decision

  1. Lookup which geolocations that exists(This depends on the CSV file loaded into the controller).

    ./cli geos suggestions europe
    +-------------+-------------+-------------+----------------+------------+------------+
    | Suggestions |    Type     | Subdivision |    Country     | Continent  | Geoname ID |
    +-------------+-------------+-------------+----------------+------------+------------+
    | Europe      | Continent   |             |                | Europe     |    6255148 |
    +-------------+-------------+-------------+----------------+------------+------------+
    
  2. Create a Geolocation route.

    # This assumes that the client IP resolves to Europe from the MMDB. Use a location
    # that will match the requests going through the router in your environment.
    
    $ vcli geolocationroutes add geolocationRoute --geolocation-to-tag="Europe:1" --subdecision=leastutilized
    +----+--------------------+-------------------------+---------------+
    | ID |        Name        |   Geolocation-To-Tags   |  Subdecision  |
    +----+--------------------+-------------------------+---------------+
    |  1 | geolocationRoute   | Europe(6255148):1(prod) | LeastUtilized |
    +----+--------------------+-------------------------+---------------+
    
  3. Update the routing rule.

    $ vcli rr update 1 --lookup-order=geolocation:1
    +----+-------+------+------+---------------+
    | ID | Name  | DNS  | HTTP |     Order     |
    +----+-------+------+------+---------------+
    |  1 | video | true | true | geolocation:1 |
    +----+-------+------+------+---------------+
    
  4. Verify that the request directs based on Geolocation

    curl -v http://172.31.0.203:8900 -H "Host: mysite.example.com"
    < HTTP/1.1 302 Found
    < Server: Varnish Request Router/1.2.0
    < Access-Control-Allow-Origin: *
    < Access-Control-Allow-Methods: GET
    < X-Router-Name: router1
    < X-Router-LookupTime: 38.456µs
    < X-Router-ClientIP: 2.125.160.216
    < X-Router-RouteType: geolocation:1
    < X-Router-RouteMatch: Europe(Continent)
    < X-Router-Endpoint: 0-agent1
    < X-Router-Trace: [geolocation:1]
    < X-Router-SubDecisionType: Leastutilized
    < Location: http://172.31.0.201:8081/mysite.example.com/
    

Cleanup

The docker-compose will create volumes for storing database and other configuration data. These can be cleaned up if you want to start from scratch.

# Stop environment
docker-compose down
# Remove volumes
docker volume rm router_example_dbdata router_example_varnish router_example_vcontroller