Introduction

Fastly is a popular CDN based on the open-source Varnish. Since it supports VCL, a lot of custom “logic” to handle incoming requests can be added, right at the edge. This improves the user experience as well as frees up the overhead on origin servers.

We’ll implement a simple service which will return details about users accessing it. Details like public IP, user-agent, location etc. It can be extended to put out more information as needed.

Solution

The service will rely entirely on Fastly’s VCL and will not depend on the origin at all! This is possible, thanks to synthetic responses that can be served from Fastly.

The request flow will be like this (no requests are sent to the origin) - fastly-meta-service

VCL Snippets

To make this work, we just need 2 VCL snippets - recv and error.

Add the following code in recv snippet -

 1unset req.http.Cookie;
 2
 3if (req.url ~ "^/$" ){
 4  set req.http.synthetic_resp = "Public IP: " + req.http.Fastly-Client-IP;
 5  error 620;
 6}
 7
 8if (req.url ~ "^/more$" ){
 9  set req.http.synthetic_resp = "Public IP: " + req.http.Fastly-Client-IP + " | City: " + std.toupper(client.geo.city) + " | Country: " + client.geo.country_code + " | User-Agent: " + req.http.user-agent + " | FServer: " + server.hostname + " | FDC: " + server.datacenter;
10  error 620;
11}
12
13if (req.url ~ "^/ip$" ){
14  set req.http.synthetic_resp = req.http.Fastly-Client-IP;
15  error 620;
16}
17
18set req.http.synthetic_resp = "Not Found!";
19error 644;

Add the following code in error snippet -

 1if (obj.status == 620) {
 2    set obj.status = 200;
 3    set obj.response = "OK";
 4    set obj.http.Content-Type = "text/html";
 5    set obj.http.cache-control = "private, no-store, no-cache, max-age=0";
 6    synthetic req.http.synthetic_resp;
 7    return (deliver);
 8}
 9
10if (obj.status == 644) {
11    set obj.status = 404;
12    set obj.response = "Not Found";
13    set obj.http.Content-Type = "text/html";
14    set obj.http.cache-control = "private, no-store, no-cache, max-age=0";
15    synthetic req.http.synthetic_resp;
16    return (deliver);
17}

Both snippets and other service configurations are available here

Deployment

The service, configurations and vcls can be quickly deployed to Fastly using Terraform. The required code is here

Tests

Once the service is ready, verify the responses either via curl or browser.

fastly-meta-service-test

Curl responses (masked some bits)

 1$ curl http://meta.dane-example.com.global.prod.fastly.net
 2Public IP: 192.168.1.1
 3
 4$ curl http://meta.dane-example.com.global.prod.fastly.net/more
 5Public IP: 192.168.1.1 | City: CITY | Country: GB | User-Agent: curl/7.73.0 | FServer: cache-lhr7341 | FDC: LHR
 6
 7$ curl http://meta.dane-example.com.global.prod.fastly.net/ip
 8192.168.1.1
 9
10$ curl http://meta.dane-example.com.global.prod.fastly.net/random
11Not Found!

Conclusion

This service can be nice value add, and also help non-technical folks gather all the information needed for whitelisting or debugging issues. It removes any reliance on 3rd party services which may or may not be hosted in secure environments. It is possible to further enhance this service to put out even more information, as needed.

Note:  Code mentioned above is here 

References (1)

  1. About Vcl Snippets