varnish throttle
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,3 +4,4 @@ instance/
|
|||||||
venv/
|
venv/
|
||||||
.env
|
.env
|
||||||
version.txt
|
version.txt
|
||||||
|
deploy/varnish/default.vcl
|
@@ -1,56 +0,0 @@
|
|||||||
vcl 4.1;
|
|
||||||
|
|
||||||
backend app {
|
|
||||||
.host = "app";
|
|
||||||
.port = "8080";
|
|
||||||
}
|
|
||||||
|
|
||||||
acl purge { "127.0.0.1"; }
|
|
||||||
|
|
||||||
sub vcl_recv {
|
|
||||||
# PURGE tylko lokalnie
|
|
||||||
if (req.method == "PURGE") {
|
|
||||||
if (!client.ip ~ purge) {
|
|
||||||
return (synth(405, "Not allowed"));
|
|
||||||
}
|
|
||||||
return (purge);
|
|
||||||
}
|
|
||||||
|
|
||||||
# omijamy cache dla healthchecków / wewn. nagłówka
|
|
||||||
if (req.url == "/healthcheck" || req.http.X-Internal-Check) {
|
|
||||||
return (pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
# metody inne niż GET/HEAD bez cache
|
|
||||||
if (req.method != "GET" && req.method != "HEAD") {
|
|
||||||
return (pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
# static – agresywnie cache’ujemy
|
|
||||||
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
|
|
||||||
return (hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
return (hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub vcl_backend_response {
|
|
||||||
if (bereq.url ~ "^/static/" || bereq.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
|
|
||||||
set beresp.ttl = 24h;
|
|
||||||
} else {
|
|
||||||
if (beresp.http.Cache-Control ~ "no-cache|no-store|private") {
|
|
||||||
set beresp.uncacheable = true;
|
|
||||||
set beresp.ttl = 0s;
|
|
||||||
} else {
|
|
||||||
set beresp.ttl = 60s; # domyślny TTL dla HTML/API
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub vcl_deliver {
|
|
||||||
if (obj.hits > 0) {
|
|
||||||
set resp.http.X-Cache = "HIT";
|
|
||||||
} else {
|
|
||||||
set resp.http.X-Cache = "MISS";
|
|
||||||
}
|
|
||||||
}
|
|
@@ -1,32 +1,33 @@
|
|||||||
vcl 4.1;
|
vcl 4.1;
|
||||||
|
|
||||||
|
import vsthrottle;
|
||||||
|
|
||||||
backend app {
|
backend app {
|
||||||
.host = "app";
|
.host = "app";
|
||||||
.port = "${APP_PORT}";
|
.port = "${APP_PORT}";
|
||||||
}
|
}
|
||||||
|
|
||||||
acl purge { "127.0.0.1"; }
|
acl purge { "localhost"; "127.0.0.1"; }
|
||||||
|
|
||||||
sub vcl_recv {
|
sub vcl_recv {
|
||||||
|
# RATE LIMIT: 10 żądań / 10s, po przekroczeniu blokada na 30s
|
||||||
|
if (vsthrottle.is_denied(client.identity, 10, 10s, 30s)) {
|
||||||
|
return (synth(429, "Too Many Requests"));
|
||||||
|
}
|
||||||
|
|
||||||
# PURGE tylko lokalnie
|
# PURGE tylko lokalnie
|
||||||
if (req.method == "PURGE") {
|
if (req.method == "PURGE") {
|
||||||
if (!client.ip ~ purge) {
|
if (!client.ip ~ purge) { return (synth(405, "Not allowed")); }
|
||||||
return (synth(405, "Not allowed"));
|
|
||||||
}
|
|
||||||
return (purge);
|
return (purge);
|
||||||
}
|
}
|
||||||
|
|
||||||
# omijamy cache dla healthchecków / wewn. nagłówka
|
# omijamy cache dla healthchecków / wewn. nagłówka
|
||||||
if (req.url == "/healthcheck" || req.http.X-Internal-Check) {
|
if (req.url == "/healthcheck" || req.http.X-Internal-Check) { return (pass); }
|
||||||
return (pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
# metody inne niż GET/HEAD bez cache
|
# metody inne niż GET/HEAD bez cache
|
||||||
if (req.method != "GET" && req.method != "HEAD") {
|
if (req.method != "GET" && req.method != "HEAD") { return (pass); }
|
||||||
return (pass);
|
|
||||||
}
|
|
||||||
|
|
||||||
# static – agresywnie cache’ujemy
|
# statyczne – agresywny cache
|
||||||
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
|
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
|
||||||
return (hash);
|
return (hash);
|
||||||
}
|
}
|
||||||
@@ -42,15 +43,27 @@ sub vcl_backend_response {
|
|||||||
set beresp.uncacheable = true;
|
set beresp.uncacheable = true;
|
||||||
set beresp.ttl = 0s;
|
set beresp.ttl = 0s;
|
||||||
} else {
|
} else {
|
||||||
set beresp.ttl = 60s; # domyślny TTL dla HTML/API
|
set beresp.ttl = 60s; # domyślny TTL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
sub vcl_deliver {
|
sub vcl_deliver {
|
||||||
|
|
||||||
if (obj.hits > 0) {
|
if (obj.hits > 0) {
|
||||||
set resp.http.X-Cache = "HIT";
|
set resp.http.X-Cache = "HIT";
|
||||||
} else {
|
} else {
|
||||||
set resp.http.X-Cache = "MISS";
|
set resp.http.X-Cache = "MISS";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Nagłówki rate limit – MUSZĄ używać tej samej czwórki parametrów co is_denied()
|
||||||
|
set resp.http.X-RateLimit-Limit = "10";
|
||||||
|
set resp.http.X-RateLimit-Window = "10s";
|
||||||
|
set resp.http.X-RateLimit-Remaining = vsthrottle.remaining(client.identity, 10, 10s, 30s);
|
||||||
|
set resp.http.Retry-After = vsthrottle.blocked(client.identity, 10, 10s, 30s);
|
||||||
|
|
||||||
|
unset resp.http.Via;
|
||||||
|
unset resp.http.X-Varnish;
|
||||||
|
#unset resp.http.Age;
|
||||||
|
unset resp.http.Server;
|
||||||
}
|
}
|
||||||
|
@@ -1,58 +0,0 @@
|
|||||||
vcl 4.1;
|
|
||||||
|
|
||||||
import vsthrottle;
|
|
||||||
|
|
||||||
backend app {
|
|
||||||
.host = "app";
|
|
||||||
.port = "8080";
|
|
||||||
}
|
|
||||||
|
|
||||||
acl purge { "localhost"; "127.0.0.1"; }
|
|
||||||
|
|
||||||
sub vcl_recv {
|
|
||||||
# RATE LIMIT
|
|
||||||
if (!vsthrottle.is_allowed(client.ip, 10, 10s)) {
|
|
||||||
return (synth(429, "Too Many Requests"));
|
|
||||||
}
|
|
||||||
|
|
||||||
# PURGE tylko lokalnie
|
|
||||||
if (req.method == "PURGE") {
|
|
||||||
if (!client.ip ~ purge) { return (synth(405, "Not allowed")); }
|
|
||||||
return (purge);
|
|
||||||
}
|
|
||||||
|
|
||||||
# omijamy cache dla healthchecków / wewn. nagłówka
|
|
||||||
if (req.url == "/healthcheck" || req.http.X-Internal-Check) { return (pass); }
|
|
||||||
|
|
||||||
# metody inne niż GET/HEAD bez cache
|
|
||||||
if (req.method != "GET" && req.method != "HEAD") { return (pass); }
|
|
||||||
|
|
||||||
# static – agresywnie cache’ujemy
|
|
||||||
if (req.url ~ "^/static/" || req.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") { return (hash); }
|
|
||||||
|
|
||||||
return (hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
sub vcl_backend_response {
|
|
||||||
if (bereq.url ~ "^/static/" || bereq.url ~ "\.(css|js|png|jpg|svg|ico|woff2?)$") {
|
|
||||||
set beresp.ttl = 24h;
|
|
||||||
} else {
|
|
||||||
if (beresp.http.Cache-Control ~ "no-cache|no-store|private") {
|
|
||||||
set beresp.uncacheable = true;
|
|
||||||
set beresp.ttl = 0s;
|
|
||||||
} else {
|
|
||||||
set beresp.ttl = 60s; # domyślny TTL dla HTML/API
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
sub vcl_deliver {
|
|
||||||
if (obj.hits > 0) {
|
|
||||||
set resp.http.X-Cache = "HIT";
|
|
||||||
} else {
|
|
||||||
set resp.http.X-Cache = "MISS";
|
|
||||||
}
|
|
||||||
|
|
||||||
set resp.http.X-RateLimit-Limit = "10";
|
|
||||||
set resp.http.X-RateLimit-Window = "10s";
|
|
||||||
}
|
|
Reference in New Issue
Block a user