mirror of
https://gitgud.io/fatchan/haproxy-protection.git
synced 2025-05-09 02:05:37 +00:00
feat: added captcha serving service to haproxy
This commit is contained in:
19
README.MD
Normal file
19
README.MD
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
## HaProxy DDoS protection system PoC
|
||||||
|
|
||||||
|
If there is an unusual HTTP requests flow to a specific domain, the system detects it and triggers DDoS protection mode.
|
||||||
|
Each new client will be first forced to complete hCaptcha, before proceeding to the website.
|
||||||
|
|
||||||
|
|
||||||
|
##### How to test
|
||||||
|
|
||||||
|
- export hcaptcha sitekey and secret:
|
||||||
|
```bash
|
||||||
|
export HCAPTCHA_SITEKEY=xxxXXxxx
|
||||||
|
export HCAPTCHA_SECRET=xxxXXxxx
|
||||||
|
```
|
||||||
|
- run docker compose:
|
||||||
|
```bash
|
||||||
|
docker compose up
|
||||||
|
```
|
||||||
|
|
||||||
|
- visit *http://127.0.0.1/captcha*
|
@@ -9,6 +9,9 @@ services:
|
|||||||
volumes:
|
volumes:
|
||||||
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
|
- ./haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg
|
||||||
- ./scripts/:/usr/local/etc/haproxy/scripts/
|
- ./scripts/:/usr/local/etc/haproxy/scripts/
|
||||||
|
environment:
|
||||||
|
- HCAPTCHA_SECRET=${HCAPTCHA_SECRET}
|
||||||
|
- HCAPTCHA_SITEKEY=${HCAPTCHA_SITEKEY}
|
||||||
|
|
||||||
nginx:
|
nginx:
|
||||||
image: "nginx:latest"
|
image: "nginx:latest"
|
||||||
|
@@ -95,8 +95,26 @@ STOPSIGNAL SIGUSR1
|
|||||||
|
|
||||||
ADD haproxy/docker-entrypoint.sh /usr/local/bin/
|
ADD haproxy/docker-entrypoint.sh /usr/local/bin/
|
||||||
RUN ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat
|
RUN ln -s usr/local/bin/docker-entrypoint.sh / # backwards compat
|
||||||
RUN apt-get update && apt-get install luarocks -y
|
|
||||||
RUN luarocks install luasocket
|
# This is terrible mess but we need it for simple testing purposes of our POC
|
||||||
|
RUN apt-get update && apt-get install libssl-dev make nano wget gcc libreadline-dev unzip git -y
|
||||||
|
RUN wget http://www.lua.org/ftp/lua-5.3.5.tar.gz &&\
|
||||||
|
tar -zxf lua-5.3.5.tar.gz &&\
|
||||||
|
cd lua-5.3.5 &&\
|
||||||
|
make linux test &&\
|
||||||
|
make install
|
||||||
|
|
||||||
|
RUN wget "https://luarocks.org/releases/luarocks-3.3.1.tar.gz" &&\
|
||||||
|
tar zxpf luarocks-3.3.1.tar.gz &&\
|
||||||
|
cd luarocks-3.3.1 &&\
|
||||||
|
./configure --with-lua-include=/usr/local/include --lua-version=5.3 --lua-suffix=5.3 &&\
|
||||||
|
make &&\
|
||||||
|
make install
|
||||||
|
|
||||||
|
RUN /usr/local/bin/luarocks install luasocket &&\
|
||||||
|
/usr/local/bin/luarocks install luasec &&\
|
||||||
|
/usr/local/bin/luarocks install net-url
|
||||||
|
|
||||||
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
|
ENTRYPOINT ["/usr/local/bin/docker-entrypoint.sh"]
|
||||||
|
|
||||||
# no USER for backwards compatibility (to try to avoid breaking existing users)
|
# no USER for backwards compatibility (to try to avoid breaking existing users)
|
||||||
|
@@ -15,6 +15,7 @@ frontend http-in
|
|||||||
default_backend servers
|
default_backend servers
|
||||||
# http-request lua.test-payload
|
# http-request lua.test-payload
|
||||||
http-request use-service lua.hello-world if { path /hello_world }
|
http-request use-service lua.hello-world if { path /hello_world }
|
||||||
|
http-request use-service lua.hcaptcha-view if { path /captcha }
|
||||||
|
|
||||||
backend servers
|
backend servers
|
||||||
server server1 nginx:80 maxconn 32
|
server server1 nginx:80 maxconn 32
|
||||||
|
1559
scripts/JSON.lua
Normal file
1559
scripts/JSON.lua
Normal file
File diff suppressed because it is too large
Load Diff
51
scripts/hcaptcha.lua
Normal file
51
scripts/hcaptcha.lua
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
hcaptcha = {}
|
||||||
|
|
||||||
|
local url = require("net.url")
|
||||||
|
local https = require("ssl.https")
|
||||||
|
local json = require("json")
|
||||||
|
|
||||||
|
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 =
|
||||||
|
[[
|
||||||
|
<form method="POST">
|
||||||
|
<div class="h-captcha" data-sitekey="%s"></div>
|
||||||
|
<script src="https://hcaptcha.com/1/api.js" async defer></script>
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
|
]]
|
||||||
|
response = string.format(response, hcaptcha_sitekey)
|
||||||
|
elseif applet.method == "POST" then
|
||||||
|
local parsed_body = url.parseQuery(applet.receive(applet))
|
||||||
|
|
||||||
|
if parsed_body["h-captcha-response"] then
|
||||||
|
local url =
|
||||||
|
string.format(
|
||||||
|
"https://hcaptcha.com/siteverify?secret=%s&response=%s",
|
||||||
|
hcaptcha_secret,
|
||||||
|
parsed_body["h-captcha-response"]
|
||||||
|
)
|
||||||
|
local body, code, headers, status = https.request(url)
|
||||||
|
local api_response = json:decode(body)
|
||||||
|
|
||||||
|
if api_response.success == true then
|
||||||
|
print("HCAPTCHA SUCCESSFULLY PASSED")
|
||||||
|
print("... success captcha flow goes here ...")
|
||||||
|
else
|
||||||
|
print("HCAPTCHA FAILED", body)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
response = "Thank you for submitting"
|
||||||
|
end
|
||||||
|
|
||||||
|
applet:set_status(200)
|
||||||
|
applet:add_header("content-type", "text/html")
|
||||||
|
applet:add_header("content-length", string.len(response))
|
||||||
|
applet:start_response()
|
||||||
|
applet:send(response)
|
||||||
|
end
|
@@ -1,5 +1,7 @@
|
|||||||
package.path = package.path .. "./?.lua;/usr/local/etc/haproxy/scripts/?.lua"
|
package.path = package.path .. "./?.lua;/usr/local/etc/haproxy/scripts/?.lua"
|
||||||
|
|
||||||
require("guard")
|
require("guard")
|
||||||
|
require("hcaptcha")
|
||||||
|
|
||||||
core.register_service("hello-world", "http", guard.hello_world);
|
core.register_service("hello-world", "http", guard.hello_world)
|
||||||
|
core.register_service("hcaptcha-view", "http", hcaptcha.view)
|
Reference in New Issue
Block a user