Skip to content

Commit 6454e76

Browse files
committed
Create default.vcl
1 parent 260097a commit 6454e76

File tree

1 file changed

+172
-0
lines changed

1 file changed

+172
-0
lines changed

varnish/default.vcl

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
vcl 4.1;
2+
3+
import std;
4+
5+
backend default {
6+
.host = "webserver";
7+
.port = "90";
8+
.connect_timeout = 2s;
9+
}
10+
11+
# Add hostnames, IP addresses and subnets that are allowed to purge content
12+
acl purge {
13+
"webserver";
14+
"drupal";
15+
"localhost";
16+
"127.0.0.1";
17+
"::1";
18+
}
19+
20+
sub vcl_recv {
21+
# Announce support for Edge Side Includes by setting the Surrogate-Capability header
22+
set req.http.Surrogate-Capability = "Varnish=ESI/1.0";
23+
24+
# Remove empty query string parameters
25+
# e.g.: www.example.com/index.html?
26+
if (req.url ~ "\?$") {
27+
set req.url = regsub(req.url, "\?$", "");
28+
}
29+
30+
# Remove port number from host header
31+
set req.http.Host = regsub(req.http.Host, ":[0-9]+", "");
32+
33+
# Sorts query string parameters alphabetically for cache normalization purposes.
34+
set req.url = std.querysort(req.url);
35+
36+
# Remove the proxy header to mitigate the httpoxy vulnerability
37+
# See https://httpoxy.org/
38+
unset req.http.proxy;
39+
40+
# Add X-Forwarded-Proto header when using https
41+
if (!req.http.X-Forwarded-Proto && (std.port(server.ip) == 443)) {
42+
set req.http.X-Forwarded-Proto = "https";
43+
}
44+
45+
# Ban logic to remove multiple objects from the cache at once. Tailored to Drupal's cache invalidation mechanism
46+
if(req.method == "BAN") {
47+
if(!client.ip ~ purge) {
48+
return(synth(405, "BAN not allowed for this IP address"));
49+
}
50+
51+
if (req.http.Purge-Cache-Tags) {
52+
ban("obj.http.Purge-Cache-Tags ~ " + req.http.Purge-Cache-Tags);
53+
}
54+
else {
55+
ban("obj.http.x-url ~ " + req.url + " && obj.http.x-host == " + req.http.host);
56+
}
57+
58+
return (synth(200, "Ban added."));
59+
}
60+
61+
# Purge logic to remove objects from the cache
62+
if(req.method == "PURGE") {
63+
if(!client.ip ~ purge) {
64+
return(synth(405,"PURGE not allowed for this IP address"));
65+
}
66+
return (purge);
67+
}
68+
69+
# Only handle relevant HTTP request methods
70+
if (
71+
req.method != "GET" &&
72+
req.method != "HEAD" &&
73+
req.method != "PUT" &&
74+
req.method != "POST" &&
75+
req.method != "PATCH" &&
76+
req.method != "TRACE" &&
77+
req.method != "OPTIONS" &&
78+
req.method != "DELETE"
79+
) {
80+
return (pipe);
81+
}
82+
83+
# Remove tracking query string parameters used by analytics tools
84+
if (req.url ~ "(\?|&)(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=") {
85+
set req.url = regsuball(req.url, "&(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "");
86+
set req.url = regsuball(req.url, "\?(utm_source|utm_medium|utm_campaign|utm_content|gclid|cx|ie|cof|siteurl)=([A-z0-9_\-\.%25]+)", "?");
87+
set req.url = regsub(req.url, "\?&", "?");
88+
set req.url = regsub(req.url, "\?$", "");
89+
}
90+
91+
# Only cache GET and HEAD requests
92+
if ((req.method != "GET" && req.method != "HEAD") || req.http.Authorization) {
93+
return(pass);
94+
}
95+
96+
# Mark static files with the X-Static-File header, and remove any cookies
97+
# X-Static-File is also used in vcl_backend_response to identify static files
98+
if (req.url ~ "^[^?]*\.(7z|avi|bmp|bz2|css|csv|doc|docx|eot|flac|flv|gif|gz|ico|jpeg|jpg|js|less|mka|mkv|mov|mp3|mp4|mpeg|mpg|odt|ogg|ogm|opus|otf|pdf|png|ppt|pptx|rar|rtf|svg|svgz|swf|tar|tbz|tgz|ttf|txt|txz|wav|webm|webp|woff|woff2|xls|xlsx|xml|xz|zip)(\?.*)?$") {
99+
set req.http.X-Static-File = "true";
100+
unset req.http.Cookie;
101+
return(hash);
102+
}
103+
104+
# Don't cache the following pages
105+
if (req.url ~ "^/status.php$" ||
106+
req.url ~ "^/update.php$" ||
107+
req.url ~ "^/cron.php$" ||
108+
req.url ~ "^/admin$" ||
109+
req.url ~ "^/admin/.*$" ||
110+
req.url ~ "^/flag/.*$" ||
111+
req.url ~ "^.*/ajax/.*$" ||
112+
req.url ~ "^.*/ahah/.*$" ||
113+
req.url ~ "^/\.well-known/acme-challenge/") {
114+
return (pass);
115+
}
116+
117+
# Remove all cookies except the session & NO_CACHE cookies
118+
if (req.http.Cookie) {
119+
set req.http.Cookie = ";" + req.http.Cookie;
120+
set req.http.Cookie = regsuball(req.http.Cookie, "; +", ";");
121+
set req.http.Cookie = regsuball(req.http.Cookie, ";(S?SESS[a-z0-9]+|NO_CACHE)=", "; \1=");
122+
set req.http.Cookie = regsuball(req.http.Cookie, ";[^ ][^;]*", "");
123+
set req.http.Cookie = regsuball(req.http.Cookie, "^[; ]+|[; ]+$", "");
124+
125+
if (req.http.cookie ~ "^\s*$") {
126+
unset req.http.cookie;
127+
} else {
128+
return(pass);
129+
}
130+
}
131+
return(hash);
132+
}
133+
134+
sub vcl_hash {
135+
# Create cache variations depending on the request protocol
136+
hash_data(req.http.X-Forwarded-Proto);
137+
}
138+
139+
sub vcl_backend_response {
140+
# Inject URL & Host header into the object for asynchronous banning purposes
141+
set beresp.http.x-url = bereq.url;
142+
set beresp.http.x-host = bereq.http.host;
143+
144+
# Serve stale content for 2 minutes after object expiration
145+
# Perform asynchronous revalidation while stale content is served
146+
set beresp.grace = 120s;
147+
148+
# If the file is marked as static we cache it for 1 day
149+
if (bereq.http.X-Static-File == "true") {
150+
unset beresp.http.Set-Cookie;
151+
set beresp.ttl = 1d;
152+
}
153+
154+
# If we dont get a Cache-Control header from the backend
155+
# we default to 1h cache for all objects
156+
if (!beresp.http.Cache-Control) {
157+
set beresp.ttl = 1h;
158+
}
159+
160+
# Parse Edge Side Include tags when the Surrogate-Control header contains ESI/1.0
161+
if (beresp.http.Surrogate-Control ~ "ESI/1.0") {
162+
unset beresp.http.Surrogate-Control;
163+
set beresp.do_esi = true;
164+
}
165+
}
166+
167+
sub vcl_deliver {
168+
# Cleanup of headers
169+
unset resp.http.x-url;
170+
unset resp.http.x-host;
171+
unset req.http.X-Static-File;
172+
}

0 commit comments

Comments
 (0)