# Reference: https://docs.varnish-software.com/tutorials/securing-multi-tier-varnish-environments/ varnishtest "HMAC signatures in a multi tier environment" # Origin server server s1 { rxreq txresp expect req.http.X-Signature == expect req.http.X-Timestamp == } -start # Origin protect tier varnish v2 -vcl { import std; import digest; backend b1 { .host = "${s1_addr}"; .port = "${s1_port}"; } sub verify_signature { if (!req.http.X-Signature) { std.log("Signature is missing in the request"); return(synth(403)); } if (!req.http.X-Timestamp) { std.log("Timestamp is missing in the request"); return(synth(403)); } # Allow up to 30 seconds clock skew between the tiers. if (std.time(req.http.X-Timestamp, now + 1d) > now + 30s) { std.log("Timestamp is in the future"); return(synth(403)); } if (std.time(req.http.X-Timestamp, now - 1d) < now - 30s) { std.log("Timestamp is in the past"); return(synth(403)); } # Verify HMAC on all incoming requests if (req.http.X-Signature != digest.hmac_sha256("changeme", req.http.host + req.url + req.http.X-Timestamp)) { std.log("Signature not valid"); return(synth(403)); } # Clean up to avoid passing these headers to the next tier. unset req.http.X-Timestamp; unset req.http.X-Signature; } sub vcl_recv { # Call this early call verify_signature; } } -start # Edge tier varnish v1 -vcl { import digest; backend b1 { .host = "${v2_addr}"; .port = "${v2_port}"; } sub generate_signature { unset bereq.http.X-Timestamp; unset bereq.http.X-Signature; set bereq.http.X-Timestamp = now; set bereq.http.X-Signature = digest.hmac_sha256("changeme", bereq.http.host + bereq.url + bereq.http.X-Timestamp); } sub vcl_backend_fetch { # Call this late, but before any return statements. call generate_signature; } } -start # Clients are allowed to access the edge tier client c1 -connect ${v1_sock} { txreq -url "/" -hdr "host: example.com" rxresp expect resp.status == 200 } -run # Clients are not allowed to access the origin protect tier client c2 -connect ${v2_sock} { txreq -url "/" -hdr "host: example.com" rxresp expect resp.status == 403 } -run