Performing HTTP redirections in Varnish
Varnish can perform HTTP redirections by returning a synthetic HTTP 301
response containing a Location
header with the redirection endpoint.
Synthetic responses are triggered by a return (synth())
statement called from a client-side VCL subroutine. This also requires extending the vcl_synth
logic and adding the necessary redirection logic.
HTTP to HTTPS redirections
One of the most common types of HTTP redirection is HTTP to HTTPS.
Here’s an example where an HTTP request is redirected to its HTTPS equivalent:
vcl 4.1;
import proxy;
backend default {
.host = "127.0.0.1";
.port = 8080;
}
sub vcl_recv {
if ((req.http.X-Forwarded-Proto && req.http.X-Forwarded-Proto != "https") ||
(req.http.Scheme && req.http.Scheme != "https")) {
return (synth(750));
} elseif (!req.http.X-Forwarded-Proto && !req.http.Scheme && !proxy.is_ssl()) {
return (synth(750));
}
}
sub vcl_synth {
if (resp.status == 750) {
set resp.status = 301;
set resp.http.location = "https://" + req.http.Host + req.url;
set resp.reason = "Moved";
return (deliver);
}
}
If the incoming request has an X-Forwarded-Proto
header with a value other than https
, Varnish will redirect the URL to the HTTPS equivalent. The same applies if the Scheme
header is set to a value other than https
.
X-Forwarded-Proto
header is used by HTTP proxy servers to transport the request protocol to the next hop. X-Forwarded-Proto: https
indicates that the request was made over the HTTPS protocol, whereas any other value would indicate a plain HTTP connection.Scheme
header is set to https
by the HTTP/2 protocol. If you’re using HTTP/2, this header can also be used to determine the request scheme that was used and as a result the requested protocol.If the request doesn’t contain an X-Forwarded-Proto
or a Scheme
header, but the connection was made using the PROXY protocol, Varnish can examine the TLV attributes of the PROXY header and determine whether or not the initial connection was encrypted over TLS.
Thanks to vmod_proxy
we can extract the TLV attributes and use proxy.is_ssl()
to determine whether or not the connection was encrypted using TLS.
Redirecting internally
Usually HTTP redirections are handled by rewrite rules on the origin webserver, but Varnish can perform these redirections as well.
Here’s a VCL example where we redirect requests for /some-page
to /another-page
:
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = 8080;
}
sub vcl_recv {
if (req.url == "/some-page") {
return (synth(301, "/another-page"));
}
}
sub vcl_synth {
if (resp.status == 301) {
set resp.http.location = resp.reason;
set resp.reason = "Moved";
return (deliver);
}
}
Redirecting to another site
Not all redirections are internal. Sometimes it is necessary to redirect content to an external resource. This example redirects requests for /external
to the https://external.example.com/
resource:
vcl 4.1;
backend default {
.host = "127.0.0.1";
.port = 8080;
}
sub vcl_recv {
if (req.url == "/external") {
return (synth(301,"https://external.example.com/"));
}
}
sub vcl_synth {
if (resp.status == 301) {
set resp.http.location = resp.reason;
set resp.reason = "Moved";
return (deliver);
}
}