Files
haproxy-protection/haproxy/haproxy.cfg
Thomas Lynch bbec69b89b Remove redundant and fix forwarded IP in varnish config
Skip unnecessary methods in haproxy instead of giving extra work to varnish (kept the check in vcl)
2024-11-29 15:19:11 +11:00

173 lines
8.9 KiB
INI

global
daemon
ca-base /etc/ssl/certs
crt-base /etc/ssl/private
master-worker
maxconn "${HAPROXY_MAXCONN}"
log stdout format raw local0 debug
lua-load /etc/haproxy/scripts/register-servers.lua
lua-load-per-thread /etc/haproxy/scripts/register-bot-check.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 dontlognull
option httplog
timeout connect 5000ms
timeout client 50000ms
timeout server 50000ms
timeout tarpit 5000ms
http-error status 400 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errors/400.http
http-error status 403 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errors/403.http
http-error status 408 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errors/408.http
http-error status 429 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errors/429.http
http-error status 500 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errors/500.http
http-error status 502 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errors/502.http
http-error status 503 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errors/503.http
http-error status 504 content-type "text/html; charset=utf-8" lf-file /etc/haproxy/errors/504.http
program api
command dataplaneapi -f /etc/haproxy/dataplaneapi.yml --update-map-files
no option start-on-reload
frontend stats-frontend
bind 127.0.0.1:2000
option tcplog
mode tcp
acl white_list src 127.0.0.1
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
# bind *:443 ssl crt /etc/haproxy/certs/haproxy.pem alpn h3,h2,http/1.1
# bind quic4@*:443 ssl crt /etc/haproxy/certs/haproxy.pem
# http-response set-header alt-svc "h3=\":443\";ma=900;"
# Or instead, for Tor, to use circuit IDs as "IP":
#bind 127.0.0.1:80 accept-proxy
option forwardfor
# optional geoip handling (maps required) and alt-svc header addition
http-request set-var(req.xcc) src,map_ip(/etc/haproxy/map/geoip.map)
http-request set-var(req.asn) src,map_ip(/etc/haproxy/map/iptoasn.map)
http-request set-var(txn.xcn) var(req.xcc),map(/etc/haproxy/map/cctocn.map)
http-request set-header X-Country-Code %[var(req.xcc)]
http-request set-header X-Continent-Code %[var(txn.xcn)]
http-request set-header X-ASN %[var(req.asn)]
# drop requests with invalid host header
acl is_existing_vhost hdr(host),lower,map_str(/etc/haproxy/map/hosts.map) -m found
acl has_query query -m found
acl on_bot_check path /.basedflare/bot-check
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/template/trace.txt if { path /.basedflare/cgi/trace }
http-request track-sc1 query table count_qs_throttle if has_query !on_bot_check
# acl for blocked IPs/subnets/ASN/country
http-request lua.set-lang-json
acl found_in_blockedip_map src,map_ip(/etc/haproxy/map/blockedip.map) -m found
acl found_in_blockedasn_map var(req.asn),map(/etc/haproxy/map/blockedasn.map) -m found
acl found_in_blockedcc_map var(req.xcc),map(/etc/haproxy/map/blockedcc.map) -m found
acl found_in_blockedcn_map var(txn.xcn),map(/etc/haproxy/map/blockedcn.map) -m found
acl blocked_bool var(txn.blocked_bool) -m bool
http-request lua.set-ip-var blockedip txn.blocked_bool ip if found_in_blockedip_map
http-request lua.set-ip-var blockedasn txn.blocked_bool asn if found_in_blockedasn_map
http-request lua.set-ip-var blockedcc txn.blocked_bool cc if found_in_blockedcc_map
http-request lua.set-ip-var blockedcn txn.blocked_bool cn if found_in_blockedcn_map
http-request deny deny_status 403 if blocked_bool
# 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 on_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 found_in_whitelist_map src,map_ip(/etc/haproxy/map/whitelist.map) -m found
acl is_excluded var(txn.whitelist_ip_or_subnet) -m bool
http-request lua.set-ip-var whitelist txn.whitelist_ip_or_subnet ip if found_in_whitelist_map
acl is_excluded src -f /etc/haproxy/map/crawler-whitelist.map
acl is_excluded path /favicon.ico /.basedflare/pow-icon #add more
# acl ORs for when ddos_mode_enabled
acl ddos_mode_enabled_override str("true"),map(/etc/haproxy/map/ddos_global.map) -m found
acl ddos_mode_enabled hdr(host),lower,map(/etc/haproxy/map/ddos.map) -m found
acl ddos_mode_enabled base,map(/etc/haproxy/map/ddos.map) -m found
acl large_unique_query_count table_cnt(count_qs_throttle) -m int gt 1000
acl ddos_mode_enabled_override acl(large_unique_query_count,has_query,!on_bot_check)
# serve challenge page scripts directly from haproxy
http-request return file /etc/haproxy/js/auto.min.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/auto.min.js }
http-request return file /etc/haproxy/js/argon2.min.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/argon2.min.js }
http-request return file /etc/haproxy/js/challenge.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/challenge.min.js }
http-request return file /etc/haproxy/js/worker.min.js status 200 content-type "application/javascript; charset=utf-8" hdr "Cache-Control" "public, max-age=86400" if { path /.basedflare/js/worker.min.js }
# rewrite specific domain+path to domain or domain+path
http-request redirect location https://%[base,map(/etc/haproxy/map/rewrite.map)] code 302 if { base,map(/etc/haproxy/map/rewrite.map) -i -m found }
# redirect domain to domain or domain+path
http-request redirect location https://%[hdr(host),map(/etc/haproxy/map/redirect.map)] code 302 if { hdr(host),map(/etc/haproxy/map/redirect.map) -i -m found }
# 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
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
# 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/map/maintenance.map) -m found
#http-request lua.set-lang-json
#http-request return lf-file /etc/haproxy/template/maintenance.html status 200 content-type "text/html; charset=utf-8" hdr "Cache-Control" "private, max-age=30" if maintenance_mode
# optional alt-svc header (done after cache so not set in cached responses
acl match_server_continent var(txn.xcn) -m str "${HAPROXY_CONTINENT}"
http-response set-header X-Server-CN "${HAPROXY_CONTINENT}"
http-response set-header X-User-CN %[var(txn.xcn)]
http-response set-header Alt-Svc %[var(txn.xcn),map(/etc/haproxy/map/alt-svc.map)] if !match_server_continent
# varnish caching if available
acl varnish_available nbsrv(haproxy-to-varnish-cache) gt 0
acl is_varnish_methods method GET HEAD PURGE BAN
use_backend haproxy-to-varnish-cache if varnish_available is_varnish_methods
default_backend servers
frontend varnish-to-haproxy-internal
bind unix@/shared-sockets/varnish-to-haproxy-internal.sock user root mode 666
default_backend servers
backend haproxy-to-varnish-cache
server varnish unix@/shared-sockets/haproxy-to-varnish-cache.sock check observe layer7 inter 1s
backend servers
balance leastconn
use-server %[lua.get_server_names] if TRUE
backend bot_check_post_throttle
stick-table type ipv6 size 100k expire 60s store http_req_rate(60s)
backend count_qs_throttle
stick-table type string size 100k expire 60s store http_req_rate(60s)