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.
Note: From version 5.1 of the controller, multiple routing decisions can be configured as a reject type. As a reject type, the tag ID do not have to be defined.
This tutorial is dependent on: HTTP Routing and assumes that the environment described there is installed and ready.
This is a practical example of setting up CIDR(classless-inter-domain-routing) based routing. More information regarding CIDR can be found here.
# 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 |
+----+---------------+--------------------------------+---------------------+
$ vcli rr update 1 --lookup-order=cidr:1
+----+---------+------+------+-------+---------------+
| ID | Name | DNS | HTTP | Order | Debug Headers |
+----+---------+------+------+-------+---------------+
| 1 | Routing | true | true | cidr:1 | true |
+----+---------+------+------+-------+---------------+
$ 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/5.1.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/
This is a practical example of setting up RegExp (Regular Expression) based routing. More information regarding RegExp can be found here.
# All User-Agent's containing curl should be routed to agents with tag ID 1
$ vcli regexp add test --regexp User-Agent:\".\*curl.\*\":1
+----+------+--------+-----------------------------+-------------+----------------+---------+
| ID | Name | Reject | RegExps | Subdecision | Organization | Creator |
+----+------+--------+-----------------------------+-------------+----------------+---------+
| 1 | test | false | User-Agent:.*curl.*:1(prod) | Healthy | [System Admin] | test(1) |
+----+------+--------+-----------------------------+-------------+----------------+---------+
$ vcli rr update 1 --lookup-order=regexp:1
$ 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/5.1.0
< Date: Tue, 07 Feb 2023 14:55:10 GMT
< Content-Length: 0
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET,HEAD
< Location: http://172.25.255.44:6081/mysite.example.com/
< X-Router-Name: router1
< X-Router-LookupTime: 14.326µs
< X-Router-ClientIP: 17.5.14.1
< X-Router-RouteType: regexp:1
< X-Router-RouteMatch: user-agent:.*curl.*(RegExp)
< X-Router-Endpoint: 0-agent2
< X-Router-Trace: [regexp:1]
< X-Router-Subdecision: Healthy
This is a practical example of setting up reject based routing. More information regarding reject routing can be found here.
# Create a regexp rule that will be used as a reject, to reject all curl users.
# NOTE: Since we configure it as a reject, we don't need a tag ID.
$ vcli regexp add test --reject --regexp User-Agent:\".\*curl.\*\"
+----+------+--------+---------------------+-------------+----------------+---------+
| ID | Name | Reject | RegExps | Subdecision | Organization | Creator |
+----+------+--------+---------------------+-------------+----------------+---------+
| 1 | test | true | User-Agent:.*curl.* | N/A | [System Admin] | test(1) |
+----+------+--------+---------------------+-------------+----------------+---------+
# Here we reference our previously created regexp with its ID (regexp:1)
# Respond with HTTP Status Code 503
$ vcli reject add test --decision regexp:1 --http-resp-code 503
+----+------+-----------------+----------------+----------+----------------+---------+
| ID | Name | Reject All HTTP | Reject All DNS | Decision | Organization | Creator |
+----+------+-----------------+----------------+----------+----------------+---------+
| 1 | test | false | false | RegExp:1 | [System Admin] | test(1) |
+----+------+-----------------+----------------+----------+----------------+---------+
$ vcli rr update 1 --lookup-order=reject:1
$ curl -v http://172.31.0.203:8900 -H "Host: mysite.example.com" -H "X-forwarded-for: 17.5.14.1"
< HTTP/1.1 503 Service Unavailable
< Server: Varnish Request Router/5.1.0
< Date: Tue, 07 Feb 2023 15:07:53 GMT
< Content-Length: 0
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET,HEAD
< X-Router-Name: router1
< X-Router-LookupTime: 12.568µs
< X-Router-ClientIP: 17.5.14.1
< X-Router-RouteType: reject:1
< X-Router-RouteMatch: .*curl.*(RegExp - REJECT)
< X-Router-Trace: [reject:1]
This is a practical example of setting up ASN(Autonomous System Number) based routing. More information regarding ASNs can be found here.
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.
$ docker stop router1
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
# 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 |
+----+---------------+--------------------------------+---------------------+
$ vcli rr update 1 --lookup-order=asn:1
+----+---------+------+------+-------+---------------+
| ID | Name | DNS | HTTP | Order | Debug Headers |
+----+---------+------+------+-------+---------------+
| 1 | Routing | true | true | asn:1 | true |
+----+---------+------+------+-------+---------------+
$ 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/5.1.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 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.
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.
$ docker stop router
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
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.
$ docker stop brainz
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
$ vcli geos suggestions europe
+-------------+-------------+-------------+----------------+------------+------------+
| Suggestions | Type | Subdivision | Country | Continent | Geoname ID |
+-------------+-------------+-------------+----------------+------------+------------+
| Europe | Continent | | | Europe | 6255148 |
+-------------+-------------+-------------+----------------+------------+------------+
# 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 |
+----+--------------------+-------------------------+---------------+
$ vcli rr update 1 --lookup-order=geolocation:1
+----+-------+------+------+---------------+
| ID | Name | DNS | HTTP | Order |
+----+-------+------+------+---------------+
| 1 | video | true | true | geolocation:1 |
+----+-------+------+------+---------------+
$ curl -v http://172.31.0.203:8900 -H "Host: mysite.example.com"
< HTTP/1.1 302 Found
< Server: Varnish Request Router/5.1.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/
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