Files
haproxy-protection/haproxy/haproxy.cfg
Thomas Lynch 45bc67fae4 Move everything under paths like /.basedflare/ instead of putting stuff in paths where it might conflict
Move templates to own file instead of in main lua script
Rename some stuff from "hcatpcha" to more correct "captcha" and "bot-check" because we no longer only have hcaptcha
Clean some code and add a few comments
2023-02-11 14:16:51 +11:00

126 lines
5.4 KiB
INI

global
daemon
maxconn 256
log stdout format raw local0 debug
lua-load-per-thread /etc/haproxy/scripts/register.lua
stats socket /var/run/haproxy.sock mode 666 level admin
stats socket 127.0.0.1:1999 level admin
httpclient.ssl.verify none
# Allow larger buffer size for return-file of argon scripts
tune.bufsize 51200
defaults
log global
mode http
option httplog
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
timeout tarpit 5000ms
#frontend stats-frontend
# bind *:2000
# option tcplog
# mode tcp
# acl white_list src xxx.xxx.xxx.xxx
# tcp-request connection reject unless white_list
# default_backend stats-backend
#backend stats-backend
# mode tcp
# server stats-localhost 127.0.0.1:1999
frontend http-in
# Clearnet http (you'll have to figure out https yourself)
bind *:80
# Or instead, for Tor, to use circuit IDs as "IP":
#bind 127.0.0.1:80 accept-proxy
#option forwardfor
# drop requests with invalid host header
acl is_existing_vhost hdr(host),lower,map_str(/etc/haproxy/hosts.map) -m found
http-request silent-drop unless is_existing_vhost
# debug information at /.basedflare/cgi/trace
http-request return status 200 content-type "text/plain; charset=utf-8" lf-file /etc/haproxy/trace.txt if { path /.basedflare/cgi/trace }
# acl for blocked IPs/subnets
acl blocked_ip_or_subnet src,map_ip(/etc/haproxy/blocked.map) -m found
http-request deny deny_status 403 if blocked_ip_or_subnet
# ratelimit (and for tor, kill circuit) on POST bot-check. legitimate users shouldn't hit this.
http-request track-sc0 src table bot_check_post_throttle if { path /.basedflare/bot-check } { method POST }
http-request lua.kill-tor-circuit if { sc_http_req_rate(0) gt 1 }
http-request tarpit if { sc_http_req_rate(0) gt 1 }
# acl for lua check whitelisted IPs/subnets and some excluded paths
acl is_excluded src,map_ip(/etc/haproxy/whitelist.map) -m found
acl is_excluded path /favicon.ico #add more
# acl ORs for when ddos_mode_enabled
acl ddos_mode_enabled_override hdr_cnt(xr3la1rfFc) eq 0
acl ddos_mode_enabled hdr(host),lower,map(/etc/haproxy/ddos.map) -m bool
acl ddos_mode_enabled base,map(/etc/haproxy/ddos.map) -m bool
# serve challenge page scripts directly from haproxy
http-request return file /var/www/js/argon2.js status 200 content-type "application/javascript; charset=utf-8" hdr "cache-control" "public, max-age=300" if { path /.basedflare/js/argon2.js }
http-request return file /var/www/js/challenge.js status 200 content-type "application/javascript; charset=utf-8" hdr "cache-control" "public, max-age=300" if { path /.basedflare/js/challenge.js }
http-request return file /var/www/js/worker.js status 200 content-type "application/javascript; charset=utf-8" hdr "cache-control" "public, max-age=300" if { path /.basedflare/js/worker.js }
# acl for domains in maintenance mode to return maintenance page (after challenge page htp-request return rules, for the footerlogo)
acl maintenance_mode hdr(host),lower,map_str(/etc/haproxy/maintenance.map) -m found
http-request return lf-file /var/www/html/maintenance.html status 200 content-type "text/html; charset=utf-8" hdr "cache-control" "private, max-age=30" if maintenance_mode
# create acl for bools updated by lua
acl captcha_passed var(txn.captcha_passed) -m bool
acl pow_passed var(txn.pow_passed) -m bool
acl validate_captcha var(txn.validate_captcha) -m bool
acl validate_pow var(txn.validate_pow) -m bool
# check pow/captcha and show page if necessary
acl on_bot_check path /.basedflare/bot-check
http-request use-service lua.bot-check if on_bot_check !is_excluded
# challenge decisions, checking, and redirecting to /bot-check
http-request lua.decide-checks-necessary if !is_excluded !on_bot_check ddos_mode_enabled
http-request lua.captcha-check if !is_excluded !on_bot_check validate_captcha
http-request lua.pow-check if !is_excluded !on_bot_check validate_pow OR !is_excluded !on_bot_check ddos_mode_enabled_override
http-request redirect location /.basedflare/bot-check?%[capture.req.uri] code 302 if validate_captcha !captcha_passed !on_bot_check ddos_mode_enabled !is_excluded OR validate_pow !pow_passed !on_bot_check ddos_mode_enabled !is_excluded OR !pow_passed ddos_mode_enabled_override !on_bot_check !is_excluded
# X-Cache-Status header (may be sent in some non-cache responses because NOSRV can happen for other reasons, but should always be present in responses served by cache-use)
http-response set-header X-Cache-Status HIT if !{ srv_id -m found }
http-response set-header X-Cache-Status MISS if { srv_id -m found }
default_backend servers
cache basic_cache
total-max-size 2500
max-object-size 31457280
max-age 86400
backend servers
# simple example cache for files
http-request set-var(txn.path) path
acl can_cache var(txn.path) -i -m end .png .jpg .jpeg .jpe .ico .webmanifest .xml .apng .bmp .webp .pjpeg .jfif .gif .mp4 .webm .mov .mkv .svg .m4a .aac .flac .mp3 .ogg .wav .opus .txt .pdf .sid
http-request cache-use basic_cache if can_cache
http-response cache-store basic_cache if can_cache
# placeholder servers, activated by LUA or the control panel
server-template websrv 1-100 0.0.0.0:80 check disabled
# use server based on hostname
use-server %[req.hdr(host),lower,map(/etc/haproxy/backends.map)] if TRUE
backend bot_check_post_throttle
stick-table type ipv6 size 100k expire 60s store http_req_rate(60s)
backend hcaptcha
mode http
server hcaptcha hcaptcha.com:443
backend recaptcha
mode http
server recaptcha www.google.com:443