From 92f9ca3efe476ed1bceefebeb4bdfbbec3320952 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Karol=20Wypch=C5=82o?= Date: Thu, 3 Dec 2020 12:59:50 +0100 Subject: [PATCH] improve nginx skylinks cache purging (#553) * purge test * purge test * purge test * purge test * purge test * purge test * purge test * purge test --- docker/nginx/conf.d/client.conf | 19 +++++- docker/nginx/conf.d/scripts/purge-multi.lua | 68 +++++++++++++++++++++ scripts/blocklist-skylink.sh | 18 ++---- 3 files changed, 91 insertions(+), 14 deletions(-) create mode 100644 docker/nginx/conf.d/scripts/purge-multi.lua diff --git a/docker/nginx/conf.d/client.conf b/docker/nginx/conf.d/client.conf index 74781429..b832931c 100644 --- a/docker/nginx/conf.d/client.conf +++ b/docker/nginx/conf.d/client.conf @@ -71,7 +71,7 @@ server { # redirect links with handshake domain on hns subdomain error_page 461 = @hns_domain; - if ($hns_domain != "") { + if ($hns_domain != "") { return 461; } @@ -268,6 +268,12 @@ server { include /etc/nginx/conf.d/include/proxy-buffer; include /etc/nginx/conf.d/include/proxy-cache-downloads; + # redirect purge calls to separate location + error_page 462 = @purge; + if ($request_method = PURGE) { + return 462; + } + limit_conn downloads_by_ip 100; # ddos protection: max 100 downloads at a time add_header Cache-Control "public, max-age=86400"; # allow consumer to cache response @@ -293,6 +299,17 @@ server { proxy_pass http://127.0.0.1/hns/$hns_domain/$request_uri; } + location @purge { + allow 10.0.0.0/8; + allow 127.0.0.1/32; + allow 172.16.0.0/12; + allow 192.168.0.0/16; + deny all; + + set $lua_purge_path "/data/nginx/cache/"; + content_by_lua_file /etc/nginx/conf.d/scripts/purge-multi.lua; + } + location ~ "^/file/([a-zA-Z0-9-_]{46}(/.*)?)$" { include /etc/nginx/conf.d/include/proxy-buffer; diff --git a/docker/nginx/conf.d/scripts/purge-multi.lua b/docker/nginx/conf.d/scripts/purge-multi.lua new file mode 100644 index 00000000..95a5b90f --- /dev/null +++ b/docker/nginx/conf.d/scripts/purge-multi.lua @@ -0,0 +1,68 @@ +-- Tit Petric, Monotek d.o.o., Tue 03 Jan 2017 06:54:56 PM CET +-- +-- Delete nginx cached assets with a PURGE request against an endpoint +-- supports extended regular expression PURGE requests (/upload/.*) +-- +-- https://scene-si.org/2017/01/08/improving-nginx-lua-cache-purge/ +-- + +function file_exists(name) + local f = io.open(name, "r") + if f~=nil then io.close(f) return true else return false end +end + +function explode(d, p) + local t, ll + t={} + ll=0 + if(#p == 1) then return {p} end + while true do + l=string.find(p, d, ll, true) -- find the next d in the string + if l~=nil then -- if "not not" found then.. + table.insert(t, string.sub(p, ll, l-1)) -- Save it in our array. + ll=l+1 -- save just after where we found it for searching next time. + else + table.insert(t, string.sub(p, ll)) -- Save what's left in our array. + break -- Break at end, as it should be, according to the lua manual. + end + end + return t +end + +function purge(filename) + if (file_exists(filename)) then + os.remove(filename) + end +end + +function trim(s) + return (string.gsub(s, "^%s*(.-)%s*$", "%1")) +end + +function exec(cmd) + local handle = io.popen(cmd) + local result = handle:read("*all") + handle:close() + return trim(result) +end + +function list_files(cache_path, purge_pattern) + local result = exec("/usr/bin/find " .. cache_path .. " -type f | /usr/bin/xargs --no-run-if-empty -n1000 /bin/grep -El -m 1 '^KEY: " .. purge_pattern .. "' 2>&1") + if result == "" then + return {} + end + return explode("\n", result) +end + +if ngx ~= nil then + -- list all cached items matching uri + local files = list_files(ngx.var.lua_purge_path, ngx.var.uri) + + ngx.header["Content-type"] = "text/plain; charset=utf-8" + ngx.header["X-Purged-Count"] = table.getn(files) + for k, v in pairs(files) do + purge(v) + end + ngx.say("OK") + ngx.exit(ngx.OK) +end diff --git a/scripts/blocklist-skylink.sh b/scripts/blocklist-skylink.sh index 097cf069..1f7dabfb 100755 --- a/scripts/blocklist-skylink.sh +++ b/scripts/blocklist-skylink.sh @@ -29,25 +29,17 @@ else skylinks=("$1") # just single skylink passed as input argument fi -#################################################### -# iterate through all servers and block the skylinks -#################################################### +######################################################################### +# iterate through all servers, block the skylinks and purge it from cache +######################################################################### for server in "germany.siasky.net" "helsinki.siasky.net" "us-west.siasky.net" "us-va-1.siasky.net" "us-pa-1.siasky.net" "us-pa-2.siasky.net" "siasky.xyz"; do - ############################################################# - # iterate throught all skylinks and add each one to blocklist - ############################################################# for skylink in "${skylinks[@]}"; do echo ".. ⌁ Blocking skylink ${skylink} on ${server}" - ssh -q -t user@${server} 'docker exec sia siac skynet blocklist add '$skylink'' - done - ###################################################### - # purge nginx cache after all the skylinks are blocked - ###################################################### - ssh -q -t user@${server} 'docker exec nginx sh -c "rm -rf /data/nginx/cache/*"' - echo ".... 🗑️ Pruned nginx cache on ${server}" + ssh -q -t user@${server} "docker exec sia siac skynet blocklist add $skylink && docker exec nginx curl -s -i -X PURGE http://localhost/$skylink | egrep \"^(OK|HTTP|X-)\"" + done done echo "✓ All done !"