Skip to content

Commit 710654f

Browse files
authored
Update anti_ddos_challenge.lua
Fixed both guest and logged in user cache Fixed POST request caching Change default value to false in-case other scripts are present on the Nginx server to be executed after this script. Improved content cache key so it works with other request types like POST etc
1 parent 651f655 commit 710654f

File tree

1 file changed

+67
-41
lines changed

1 file changed

+67
-41
lines changed

lua/anti_ddos_challenge.lua

Lines changed: 67 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
--[[
33
Introduction and details :
4-
Script Version: 1.1
4+
Script Version: 1.2
55
66
Copyright Conor McKnight
77
@@ -318,11 +318,11 @@ local content_cache = {
318318
{"GET",}, --request method to cache
319319
{ --bypass cache on cookie
320320
{
321-
"logged_in", --cookie name
322-
"1", --cookie value
321+
"logged_in", --cookie name regex ".*" for any cookie
322+
"1", --cookie value ".*" for any value
323323
0, --0 guest user cache only 1 both guest and logged in user cache useful if logged_in cookie is present then cache key will include cookies
324324
},
325-
--{"name1","value1",},
325+
--{"name1","value1",0,},
326326
}, --bypass cache on cookie
327327
{"/login.html","/administrator","/admin*.$",}, --bypass cache urls
328328
1, --Send cache status header X-Cache-Status: HIT, X-Cache-Status: MISS
@@ -351,24 +351,24 @@ local content_cache = {
351351
},
352352
"", --1e+6, --Maximum content size to cache in bytes 1e+6 = 1MB content larger than this wont be cached empty string "" to skip
353353
"", --Minimum content size to cache in bytes content smaller than this wont be cached empty string "" to skip
354-
{"content-type","content-range","content-length","etag","last-modified","set-cookie",}, --headers
354+
{"content-type","content-range","content-length","etag","last-modified","set-cookie",}, --headers you can use this to specify what headers you want to keep on your cache HIT/UPDATING output
355355
},
356356
{
357357
".*", --regex match any site / path
358358
"video/mp4", --content-type valid types are text/css text/javascript
359-
--lua_shared_dict html_cache 10m; #HTML pages cache
360-
ngx.shared.mp4_cache, --shared cache zone to use or empty string to not use "" lua_shared_dict mp4_cache 10m; #video mp4 cache
359+
--lua_shared_dict mp4_cache 300m; #video mp4 cache
360+
ngx.shared.mp4_cache, --shared cache zone to use or empty string to not use "" lua_shared_dict mp4_cache 300m; #video mp4 cache
361361
60, --ttl for cache or ""
362362
1, --enable logging 1 to enable 0 to disable
363363
{200,206,}, --response status codes to cache
364364
{"GET",}, --request method to cache
365365
{ --bypass cache on cookie
366366
{
367-
"logged_in", --cookie name
368-
"1", --cookie value
367+
"logged_in", --cookie name ".*" for any cookie
368+
"1", --cookie value ".*" for any value
369369
0, --0 guest user cache only 1 both guest and logged in user cache useful if logged_in cookie is present then cache key will include cookies
370370
},
371-
--{"name1","value1",},
371+
--{"name1","value1",0,},
372372
}, --bypass cache on cookie
373373
{"/login.html","/administrator","/admin*.$",}, --bypass cache urls
374374
1, --Send cache status header X-Cache-Status: HIT, X-Cache-Status: MISS
@@ -378,7 +378,7 @@ local content_cache = {
378378
"", --content modified not needed for this format
379379
4e+7, --Maximum content size to cache in bytes 1e+6 = 1MB, 1e+7 = 10MB, 1e+8 = 100MB, 1e+9 = 1GB content larger than this wont be cached empty string "" to skip
380380
200000, --200kb --Minimum content size to cache in bytes content smaller than this wont be cached empty string "" to skip
381-
{"content-type","content-range","content-length","etag","last-modified","set-cookie",}, --headers
381+
{"content-type","content-range","content-length","etag","last-modified","set-cookie",}, --headers you can use this to specify what headers you want to keep on your cache HIT/UPDATING output
382382
},
383383
]]
384384
}
@@ -1680,7 +1680,7 @@ useful for developers who do not want to trigger a exit status and do more thing
16801680
true = ngx_exit(ngx_OK) --Go to content
16811681
false = nothing the script will run down to the end of the file and nginx will continue normally going to the next script on the server
16821682
]]
1683-
local exit_status = true --true or false
1683+
local exit_status = false --true or false
16841684

16851685
--[[
16861686
End Configuration
@@ -5233,6 +5233,7 @@ local function minification(content_type_list)
52335233

52345234
local request_method_match = 0
52355235
local cookie_match = 0
5236+
local guest_or_logged_in = 0
52365237
local request_uri_match = 0
52375238
if content_type_list[i][7] ~= "" then
52385239
for a=1, #content_type_list[i][7] do
@@ -5242,32 +5243,38 @@ local function minification(content_type_list)
52425243
end
52435244
end
52445245
if request_method_match == 0 then
5245-
if content_type_list[i][5] == 1 then
5246-
ngx_log(ngx_LOG_TYPE, "request method not matched")
5247-
end
5246+
--if content_type_list[i][5] == 1 then
5247+
--ngx_log(ngx_LOG_TYPE, "request method not matched")
5248+
--end
52485249
--goto end_for_loop
52495250
end
52505251
end
52515252
if content_type_list[i][8] ~= "" then
5252-
local guest_or_logged_in = 0
52535253
for a=1, #content_type_list[i][8] do
52545254
local cookie_name = content_type_list[i][8][a][1]
52555255
local cookie_value = content_type_list[i][8][a][2]
5256-
guest_or_logged_in = content_type_list[i][8][a][3]
52575256
local cookie_exist = ngx_var["cookie_" .. cookie_name] or ""
52585257
if cookie_exist then
52595258
if string_match(cookie_exist, cookie_value ) then
52605259
cookie_match = 1
5260+
if content_type_list[i][8][a][3] == 1 then
5261+
guest_or_logged_in = 1
5262+
end
52615263
break
52625264
end
52635265
end
52645266
end
52655267
if cookie_match == 1 then
5266-
if content_type_list[i][5] == 1 then
5267-
ngx_log(ngx_LOG_TYPE, "cookie matched so bypass")
5268-
end
52695268
if guest_or_logged_in == 0 then --if guest user cache only then bypass cache for logged in users
52705269
--goto end_for_loop
5270+
--if content_type_list[i][5] == 1 then
5271+
--ngx_log(ngx_LOG_TYPE, " GUEST ONLY cache " .. guest_or_logged_in )
5272+
--end
5273+
else
5274+
--if content_type_list[i][5] == 1 then
5275+
--ngx_log(ngx_LOG_TYPE, " BOTH GUEST and LOGGED_IN in cache " .. guest_or_logged_in )
5276+
--end
5277+
cookie_match = 0 --set to 0
52715278
end
52725279
end
52735280
end
@@ -5279,9 +5286,9 @@ local function minification(content_type_list)
52795286
end
52805287
end
52815288
if request_uri_match == 1 then
5282-
if content_type_list[i][5] == 1 then
5283-
ngx_log(ngx_LOG_TYPE, "request uri matched so bypass")
5284-
end
5289+
--if content_type_list[i][5] == 1 then
5290+
--ngx_log(ngx_LOG_TYPE, "request uri matched so bypass")
5291+
--end
52855292
--goto end_for_loop
52865293
end
52875294
end
@@ -5422,6 +5429,14 @@ local function minification(content_type_list)
54225429
TRACE = ngx.HTTP_TRACE,
54235430
--CONNECT = ngx.HTTP_CONNECT, --does not exist but put here never know in the future
54245431
}
5432+
5433+
--[[
5434+
For debugging tests i have checked these and they work fine i am leaving this here for future refrence
5435+
curl post request test - curl.exe "http://localhost/" -H "User-Agent: testagent" -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" -H "Accept-Language: en-GB,en;q=0.5" -H "Accept-Encoding: gzip, deflate, br, zstd" -H "DNT: 1" -H "Connection: keep-alive" -H "Cookie: name1=1; name2=2; logged_in=1" -H "Upgrade-Insecure-Requests: 1" -H "Sec-Fetch-Dest: document" -H "Sec-Fetch-Mode: navigate" -H "Sec-Fetch-Site: none" -H "Sec-Fetch-User: ?1" -H "Priority: u=0, i" -H "Pragma: no-cache" -H "Cache-Control: no-cache" --request POST --data '{"username":"xyz","password":"xyz"}' -H "Content-Type: application/json"
5436+
curl post no data test - curl.exe "http://localhost/" -H "User-Agent: testagent" -H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8" -H "Accept-Language: en-GB,en;q=0.5" -H "Accept-Encoding: gzip, deflate, br, zstd" -H "DNT: 1" -H "Connection: keep-alive" -H "Cookie: name1=1; name2=2; logged_in=1" -H "Upgrade-Insecure-Requests: 1" -H "Sec-Fetch-Dest: document" -H "Sec-Fetch-Mode: navigate" -H "Sec-Fetch-Site: none" -H "Sec-Fetch-User: ?1" -H "Priority: u=0, i" -H "Pragma: no-cache" -H "Cache-Control: no-cache" --request POST -H "Content-Type: application/json"
5437+
5438+
client_body_in_file_only on; #nginx config to test / debug on post data being stored in file incase of large post data sizes the nginx memory buffer was not big enough i turned this on to check this works as it should.
5439+
]]
54255440
ngx.req.read_body()
54265441
local request_body = ngx.req.get_body_data()
54275442
local request_body_file = ""
@@ -5430,6 +5445,8 @@ local function minification(content_type_list)
54305445
if file then
54315446
request_body_file = file
54325447
end
5448+
--client_body_in_file_only on; #nginx config to test / debug
5449+
--ngx_log(ngx_LOG_TYPE, " request_body_file is " .. request_body_file )
54335450
end
54345451
if request_body_file ~= "" then
54355452
local fh, err = io.open(request_body_file, "rb")
@@ -5442,13 +5459,17 @@ local function minification(content_type_list)
54425459
request_body = fh:read("*all")
54435460
fh:close()
54445461
end
5462+
if request_body == nil then
5463+
request_body = "" --set to empty string
5464+
end
5465+
54455466
local req_headers = ngx_req_get_headers() --get all request headers
54465467

54475468
local cached = content_type_list[i][3] or ""
54485469
if cached ~= "" then
54495470
local ttl = content_type_list[i][4] or ""
54505471
local cookie_string = ""
5451-
if cookie_match == 1 then
5472+
if guest_or_logged_in == 1 then
54525473
local cookies = req_headers["cookie"] or "" --for dynamic pages
54535474
if type(cookies) ~= "table" then
54545475
--ngx_log(ngx_LOG_TYPE, " cookies are string ")
@@ -5459,9 +5480,14 @@ local function minification(content_type_list)
54595480
cookie_string = cookie_string .. cookies[t]
54605481
end
54615482
end
5483+
else
5484+
req_headers["cookie"] = "" --avoid cache poisoning by removing REQUEST header cookies to ensure user is logged out when the expected logged_in cookie is missing
54625485
end
54635486
--ngx_log(ngx_LOG_TYPE, " cookies are " .. cookie_string)
5464-
local key = scheme .. "://" .. host .. content_type_list[i][12] .. cookie_string
5487+
5488+
--TODO: convert cache key to a smaller storage format to use less memory for storage perhaps hex or binary etc
5489+
local key = ngx_var.request_method .. scheme .. "://" .. host .. content_type_list[i][12] .. cookie_string .. request_body --fastcgi_cache_key / proxy_cache_key - GET - https - :// - host - request_uri - request_header["cookie"] - request_body
5490+
--ngx_log(ngx_LOG_TYPE, " full cache key is " .. key)
54655491

54665492
local content_type_cache = cached:get("content-type"..key) or nil
54675493

@@ -5531,9 +5557,6 @@ local function minification(content_type_list)
55315557
if content_type_list[i][10] == 1 then
55325558
ngx_header["X-Cache-Status"] = "UPDATING"
55335559
end
5534-
if content_type_list[i][11] == 1 and cookie_match == 0 then
5535-
ngx_header["Set-Cookie"] = nil
5536-
end
55375560
cached:set(key, output_minified, ttl)
55385561
cached:set("s"..key, res.status, ttl)
55395562
if res.headers ~= nil and type(res.headers) == "table" then
@@ -5550,6 +5573,9 @@ local function minification(content_type_list)
55505573
ngx_header[headerName] = header
55515574
end
55525575
end
5576+
if content_type_list[i][11] == 1 and guest_or_logged_in == 0 then
5577+
ngx_header["Set-Cookie"] = nil
5578+
end
55535579
ngx_header["Content-Length"] = #output_minified
55545580
--ngx_status = res.status
55555581
ngx_status = response_status_match(res.status)
@@ -5624,9 +5650,6 @@ local function minification(content_type_list)
56245650
if content_type_list[i][10] == 1 then
56255651
ngx_header["X-Cache-Status"] = "UPDATING"
56265652
end
5627-
if content_type_list[i][11] == 1 and cookie_match == 0 then
5628-
ngx_header["Set-Cookie"] = nil
5629-
end
56305653
cached:set(key, output_minified, ttl)
56315654
cached:set("s"..key, res.status, ttl)
56325655
if res.header ~= nil and type(res.header) == "table" then
@@ -5643,6 +5666,9 @@ local function minification(content_type_list)
56435666
ngx_header[headerName] = header
56445667
end
56455668
end
5669+
if content_type_list[i][11] == 1 and guest_or_logged_in == 0 then
5670+
ngx_header["Set-Cookie"] = nil
5671+
end
56465672
ngx_header["Content-Length"] = #output_minified
56475673
--ngx_status = res.status
56485674
ngx_status = response_status_match(res.status)
@@ -5669,13 +5695,10 @@ local function minification(content_type_list)
56695695
local output_minified = cached:get(key)
56705696
local res_status = cached:get("s"..key)
56715697

5672-
ngx_header.content_type = content_type_list[i][2]
5698+
--ngx_header.content_type = content_type_list[i][2]
56735699
if content_type_list[i][10] == 1 then
56745700
ngx_header["X-Cache-Status"] = "HIT"
56755701
end
5676-
if content_type_list[i][11] == 1 and cookie_match == 0 then
5677-
ngx_header["Set-Cookie"] = nil
5678-
end
56795702
if content_type_list[i][17] ~= "" or #content_type_list[i][17] > 0 then
56805703
for a=1, #content_type_list[i][17] do
56815704
local header_name = string_lower(content_type_list[i][17][a])
@@ -5686,6 +5709,9 @@ local function minification(content_type_list)
56865709
end
56875710
end
56885711
end
5712+
if content_type_list[i][11] == 1 and guest_or_logged_in == 0 or guest_or_logged_in == 1 then
5713+
ngx_header["Set-Cookie"] = nil
5714+
end
56895715
ngx_header["Content-Length"] = #output_minified
56905716
--ngx_status = res_status
56915717
ngx_status = response_status_match(res_status)
@@ -5755,15 +5781,15 @@ local function minification(content_type_list)
57555781
end --end foreach regex check
57565782
end
57575783

5758-
if content_type_list[i][11] == 1 and cookie_match == 0 then
5759-
ngx_header["Set-Cookie"] = nil
5760-
end
57615784
if res.headers ~= nil and type(res.headers) == "table" then
57625785
for headerName, header in next, res.headers do
57635786
--ngx_log(ngx_LOG_TYPE, " header name" .. headerName .. " value " .. header )
57645787
ngx_header[headerName] = header
57655788
end
57665789
end
5790+
--if content_type_list[i][11] == 1 and guest_or_logged_in == 0 then
5791+
--ngx_header["Set-Cookie"] = nil
5792+
--end
57675793
ngx_header["Content-Length"] = #output_minified
57685794
--ngx_status = res.status
57695795
ngx_status = response_status_match(res.status)
@@ -5832,15 +5858,15 @@ local function minification(content_type_list)
58325858
end --end foreach regex check
58335859
end
58345860

5835-
if content_type_list[i][11] == 1 and cookie_match == 0 then
5836-
ngx_header["Set-Cookie"] = nil
5837-
end
58385861
if res.header ~= nil and type(res.header) == "table" then
58395862
for headerName, header in next, res.header do
58405863
--ngx_log(ngx_LOG_TYPE, " header name" .. headerName .. " value " .. header )
58415864
ngx_header[headerName] = header
58425865
end
58435866
end
5867+
--if content_type_list[i][11] == 1 and guest_or_logged_in == 0 then
5868+
--ngx_header["Set-Cookie"] = nil
5869+
--end
58445870
ngx_header["Content-Length"] = #output_minified
58455871
--ngx_status = res.status
58465872
ngx_status = response_status_match(res.status)

0 commit comments

Comments
 (0)