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) -
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.
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