From e36add4ee77bf79ed046399e021d977e1c3e71a4 Mon Sep 17 00:00:00 2001 From: Thomas Lynch Date: Sat, 9 Sep 2023 21:39:45 +1000 Subject: [PATCH] Add asn blocking --- haproxy/haproxy.cfg | 19 ++++++++++++------- haproxy/map/blockedasn.map | 1 + haproxy/map/{blocked.map => blockedip.map} | 0 haproxy/map/domtoacc.map | 3 ++- haproxy/map/hosts.map | 2 +- haproxy/map/iptoasn.map | 1 + haproxy/map/whitelist.map | 1 + src/lua/scripts/bot-check.lua | 21 +++++++++++++++------ src/lua/scripts/register-bot-check.lua | 2 +- 9 files changed, 34 insertions(+), 16 deletions(-) create mode 100644 haproxy/map/blockedasn.map rename haproxy/map/{blocked.map => blockedip.map} (100%) create mode 100644 haproxy/map/iptoasn.map diff --git a/haproxy/haproxy.cfg b/haproxy/haproxy.cfg index de7d14d..2e2ab4f 100644 --- a/haproxy/haproxy.cfg +++ b/haproxy/haproxy.cfg @@ -57,9 +57,11 @@ frontend http-in # 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 @@ -68,11 +70,14 @@ frontend http-in # 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 } - # acl for blocked IPs/subnets - acl found_in_blocked_map src,map_ip(/etc/haproxy/map/blocked.map) -m found - acl blocked_ip_or_subnet var(txn.blocked_ip_or_subnet) -m bool - http-request lua.set-ip-var "blocked" "txn.blocked_ip_or_subnet" if found_in_blocked_map - http-request deny deny_status 403 if blocked_ip_or_subnet + # acl for blocked IPs/subnets/ASN + 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 blocked_ip_or_subnet_or_asn var(txn.blocked_ip_or_subnet_or_asn) -m bool + http-request lua.set-ip-var blockedip txn.blocked_ip_or_subnet_or_asn ip if found_in_blockedip_map + http-request lua.set-ip-var blockedasn txn.blocked_ip_or_subnet_or_asn asn if found_in_blockedasn_map + http-request deny deny_status 403 if blocked_ip_or_subnet_or_asn # 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 } @@ -82,7 +87,7 @@ frontend http-in # 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" if found_in_whitelist_map + 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 @@ -99,7 +104,7 @@ frontend http-in # 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 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 # rewrite specific domain+path to domain or domain+path diff --git a/haproxy/map/blockedasn.map b/haproxy/map/blockedasn.map new file mode 100644 index 0000000..b136f39 --- /dev/null +++ b/haproxy/map/blockedasn.map @@ -0,0 +1 @@ +12345 admin:asdf diff --git a/haproxy/map/blocked.map b/haproxy/map/blockedip.map similarity index 100% rename from haproxy/map/blocked.map rename to haproxy/map/blockedip.map diff --git a/haproxy/map/domtoacc.map b/haproxy/map/domtoacc.map index c0e8168..89160f1 100644 --- a/haproxy/map/domtoacc.map +++ b/haproxy/map/domtoacc.map @@ -1 +1,2 @@ -localhost-test.com admin +example.com asdf +localhost admin diff --git a/haproxy/map/hosts.map b/haproxy/map/hosts.map index 85380b7..ce38125 100644 --- a/haproxy/map/hosts.map +++ b/haproxy/map/hosts.map @@ -1 +1 @@ -localhost-test 127.0.0.1:3000 +localhost 127.0.0.1:81 diff --git a/haproxy/map/iptoasn.map b/haproxy/map/iptoasn.map new file mode 100644 index 0000000..e40e1f3 --- /dev/null +++ b/haproxy/map/iptoasn.map @@ -0,0 +1 @@ +0.0.0.0/0 12345 diff --git a/haproxy/map/whitelist.map b/haproxy/map/whitelist.map index e69de29..3a5c176 100644 --- a/haproxy/map/whitelist.map +++ b/haproxy/map/whitelist.map @@ -0,0 +1 @@ +0.0.0.0/0 admin diff --git a/src/lua/scripts/bot-check.lua b/src/lua/scripts/bot-check.lua index 8c1ec26..8edf9f7 100644 --- a/src/lua/scripts/bot-check.lua +++ b/src/lua/scripts/bot-check.lua @@ -411,23 +411,32 @@ function _M.set_lang_json(txn) end -- set a variable if ip or subnet in blocked/whitelist map and list of usernames matches the one for the current domain -local blocked_map = Map.new("/etc/haproxy/map/blocked.map", Map._ip); +local blockedip_map = Map.new("/etc/haproxy/map/blockedip.map", Map._ip); +local blockedasn_map = Map.new("/etc/haproxy/map/blockedasn.map", Map._str); local whitelist_map = Map.new("/etc/haproxy/map/whitelist.map", Map._ip); local accounts_map = Map.new("/etc/haproxy/map/domtoacc.map", Map._str); local maps_map = { - ["blocked"] = blocked_map, + ["blockedip"] = blockedip_map, + ["blockedasn"] = blockedasn_map, ["whitelist"] = whitelist_map, } -function _M.set_ip_var(txn, map_name, set_variable) +function _M.set_ip_var(txn, map_name, set_variable, lookup_var) -- get the host header and user ip local host = txn.sf:hdr("Host") - local ip = txn.sf:src() - if ip == nil or host == nil then + -- choose lookup key + local lookup_key = nil + if lookup_var == "ip" then -- 1=ip + lookup_key = txn.sf:src() + elseif lookup_var == "asn" then -- 2=asn + lookup_key = txn:get_var("req.asn") + end + -- if none return + if lookup_key == nil or host == nil then return end -- get the name of current domain user, and the list -- of names that have blocked this ip (in case multiple) - local names_list = maps_map[map_name]:lookup(ip) + local names_list = maps_map[map_name]:lookup(lookup_key) local current_name = accounts_map:lookup(string.lower(host)) if names_list == nil or current_name == nil then return diff --git a/src/lua/scripts/register-bot-check.lua b/src/lua/scripts/register-bot-check.lua index 5581c76..84bb2ca 100644 --- a/src/lua/scripts/register-bot-check.lua +++ b/src/lua/scripts/register-bot-check.lua @@ -20,4 +20,4 @@ core.register_action("pow-check", { 'http-req', }, bot_check.check_pow_status) core.register_action("decide-checks-necessary", { 'http-req', }, bot_check.decide_checks_necessary) core.register_action("kill-tor-circuit", { 'http-req', }, bot_check.kill_tor_circuit) core.register_action("set-lang-json", { 'http-req', }, bot_check.set_lang_json) -core.register_action("set-ip-var", { 'http-req', }, bot_check.set_ip_var, 2) +core.register_action("set-ip-var", { 'http-req', }, bot_check.set_ip_var, 3)