feat: added action to validate ddos protection cookie

This commit is contained in:
Eugene Prodan
2021-06-08 20:17:16 +03:00
parent 0f7bd9951b
commit 888a11da83
4 changed files with 109 additions and 7 deletions

View File

@ -13,9 +13,13 @@ defaults
frontend http-in
bind *:80
default_backend servers
# http-request lua.test-payload
http-request use-service lua.hello-world if { path /hello_world }
http-request use-service lua.hcaptcha-view if { path /captcha }
http-request lua.hcaptcha-redirect if !{ path -m beg /captcha }
http-request use-service lua.hello-world if { path /hello_world }
http-request use-service lua.hcaptcha-view if { path /captcha/ }
acl captcha_passed var(txn.captcha_passed) -m bool
acl on_captcha_url path -m beg /captcha
redirect prefix /captcha code 301 if !captcha_passed !on_captcha_url
backend servers
server server1 nginx:80 maxconn 32

82
scripts/cookie.lua Normal file
View File

@ -0,0 +1,82 @@
-- Copyright (C) 2013-2016 Jiale Zhi (calio), CloudFlare Inc.
-- See RFC6265 http://tools.ietf.org/search/rfc6265
-- require "luacov"
local type = type
local byte = string.byte
local sub = string.sub
local EQUAL = byte("=")
local SEMICOLON = byte(";")
local SPACE = byte(" ")
local HTAB = byte("\t")
local _M = {}
_M._VERSION = '0.01'
function _M.get_cookie_table(text_cookie)
if type(text_cookie) ~= "string" then
return {}
end
local EXPECT_KEY = 1
local EXPECT_VALUE = 2
local EXPECT_SP = 3
local n = 0
local len = #text_cookie
for i=1, len do
if byte(text_cookie, i) == SEMICOLON then
n = n + 1
end
end
local cookie_table = {}
local state = EXPECT_SP
local i = 1
local j = 1
local key, value
while j <= len do
if state == EXPECT_KEY then
if byte(text_cookie, j) == EQUAL then
key = sub(text_cookie, i, j - 1)
state = EXPECT_VALUE
i = j + 1
end
elseif state == EXPECT_VALUE then
if byte(text_cookie, j) == SEMICOLON
or byte(text_cookie, j) == SPACE
or byte(text_cookie, j) == HTAB
then
value = sub(text_cookie, i, j - 1)
cookie_table[key] = value
key, value = nil, nil
state = EXPECT_SP
i = j + 1
end
elseif state == EXPECT_SP then
if byte(text_cookie, j) ~= SPACE
and byte(text_cookie, j) ~= HTAB
then
state = EXPECT_KEY
i = j
j = j - 1
end
end
j = j + 1
end
if key ~= nil and value == nil then
cookie_table[key] = sub(text_cookie, i)
end
return cookie_table
end
return _M

View File

@ -4,13 +4,12 @@ local url = require("net.url")
local https = require("ssl.https")
local json = require("json")
local utils = require("utils")
local cookie = require("cookie")
local floating_hash = utils.get_floating_hash()
function hcaptcha.view(applet)
local hcaptcha_secret = os.getenv("HCAPTCHA_SECRET")
local hcaptcha_sitekey = os.getenv("HCAPTCHA_SITEKEY")
local response
if applet.method == "GET" then
response =
@ -37,7 +36,7 @@ function hcaptcha.view(applet)
if api_response.success == true then
print("HCAPTCHA SUCCESSFULLY PASSED")
applet:add_header("set-cookie", string.format("z_ddos_protection=%s; Max-Age=14400", floating_hash))
applet:add_header("set-cookie", string.format("z_ddos_protection=%s; Max-Age=14400; Path=/", floating_hash))
else
print("HCAPTCHA FAILED", body)
end
@ -52,3 +51,19 @@ function hcaptcha.view(applet)
applet:start_response()
applet:send(response)
end
function hcaptcha.check_captcha_status(txn)
print("CAPTCHA STATUS CHECK START")
local raw_request_cookies = txn.sf:hdr("Cookie")
local parsed_request_cookies = cookie.get_cookie_table(raw_request_cookies)
print("RECEIVED SECRET COOKIE: ", parsed_request_cookies["z_ddos_protection"])
print("OUR SECRET COOKIE: ", floating_hash)
if parsed_request_cookies["z_ddos_protection"] == floating_hash then
print("CAPTCHA STATUS CHECK SUCCESS")
return txn:set_var("txn.captcha_passed", true);
end
print("CAPTCHA STATUS CHECK FINISH")
end

View File

@ -5,3 +5,4 @@ require("hcaptcha")
core.register_service("hello-world", "http", guard.hello_world)
core.register_service("hcaptcha-view", "http", hcaptcha.view)
core.register_action("hcaptcha-redirect", { 'http-req', }, hcaptcha.check_captcha_status)