Fail2Topic

This commit is contained in:
kevinz000
2020-01-07 04:48:39 -08:00
parent c39862711a
commit ab2292dfd5
9 changed files with 171 additions and 22 deletions
+107
View File
@@ -0,0 +1,107 @@
SUBSYSTEM_DEF(fail2topic)
name = "Fail2Topic"
init_order = SS_INIT_MISC_FIRST
flags = SS_FIRE_IN_LOBBY | SS_BACKGROUND
var/list/rate_limiting = list()
var/list/fail_counts = list()
var/list/active_bans = list()
var/rate_limit
var/max_fails
var/rule_name
var/enabled = FALSE
/datum/controller/subsystem/fail2topic/Initialize(timeofday)
rate_limit = CONFIG_GET(number/fail2topic_rate_limit)
max_fails = CONFIG_GET(number/fail2topic_max_fails)
rule_name = CONFIG_GET(string/fail2topic_rule_name)
enabled = CONFIG_GET(flag/fail2topic_enabled)
DropFirewallRule() // Clear the old bans if any still remain
if (world.system_type == UNIX && enabled)
enabled = FALSE
subsystem_log("DISABLED - UNIX systems are not supported.")
if(!enabled)
flags |= SS_NO_FIRE
can_fire = FALSE
return ..()
/datum/controller/subsystem/fail2topic/fire()
while (rate_limiting.len)
var/ip = rate_limiting[1]
var/last_attempt = rate_limiting[ip]
if (world.time - last_attempt > rate_limit)
rate_limiting -= ip
fail_counts -= ip
if (MC_TICK_CHECK)
return
/datum/controller/subsystem/fail2topic/Shutdown()
DropFirewallRule()
/datum/controller/subsystem/fail2topic/proc/IsRateLimited(ip)
var/last_attempt = rate_limiting[ip]
if (config?.api_rate_limit_whitelist[ip])
return FALSE
if (active_bans[ip])
return TRUE
rate_limiting[ip] = world.time
if (isnull(last_attempt))
return FALSE
if (world.time - last_attempt > rate_limit)
fail_counts -= ip
return FALSE
else
var/failures = fail_counts[ip]
if (isnull(failures))
fail_counts[ip] = 1
return FALSE
else if (failures > max_fails)
BanFromFirewall(ip)
return TRUE
else
fail_counts[ip] = failures + 1
return TRUE
/datum/controller/subsystem/fail2topic/proc/BanFromFirewall(ip)
if (!enabled)
return
active_bans[ip] = world.time
fail_counts -= ip
rate_limiting -= ip
. = shell("netsh advfirewall firewall add rule name=\"[rule_name]\" dir=in interface=any action=block remoteip=[ip]")
if (.)
subsystem_log("Failed to ban [ip]. Exit code: [.].")
else if (isnull(.))
subsystem_log("Failed to invoke shell to ban [ip].")
else
subsystem_log("Banned [ip].")
/datum/controller/subsystem/fail2topic/proc/DropFirewallRule()
if (!enabled)
return
active_bans = list()
. = shell("netsh advfirewall firewall delete rule name=\"[rule_name]\"")
if (.)
subsystem_log("Failed to drop firewall rule. Exit code: [.].")
else if (isnull(.))
subsystem_log("Failed to invoke shell for firewall rule drop.")
else
subsystem_log("Firewall rule dropped.")