Fail2Topic
This commit is contained in:
@@ -0,0 +1,15 @@
|
||||
/datum/config_entry/number/fail2topic_rate_limit
|
||||
config_entry_value = 10 //deciseconds
|
||||
|
||||
/datum/config_entry/number/fail2topic_max_fails
|
||||
config_entry_value = 5
|
||||
|
||||
/datum/config_entry/string/fail2topic_rule_name
|
||||
config_entry_value = "_dd_fail2topic"
|
||||
protection = CONFIG_ENTRY_LOCKED //affects physical server configuration, no touchies!!
|
||||
|
||||
/datum/config_entry/flag/fail2topic_enabled
|
||||
config_entry_value = TRUE
|
||||
|
||||
/datum/config_entry/number/topic_max_size
|
||||
config_entry_value = 8192
|
||||
@@ -54,7 +54,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
var/static/restart_clear = 0
|
||||
var/static/restart_timeout = 0
|
||||
var/static/restart_count = 0
|
||||
|
||||
|
||||
var/static/random_seed
|
||||
|
||||
//current tick limit, assigned before running a subsystem.
|
||||
@@ -69,7 +69,7 @@ GLOBAL_REAL(Master, /datum/controller/master) = new
|
||||
if(!random_seed)
|
||||
random_seed = (TEST_RUN_PARAMETER in world.params) ? 29051994 : rand(1, 1e9)
|
||||
rand_seed(random_seed)
|
||||
|
||||
|
||||
var/list/_subsystems = list()
|
||||
subsystems = _subsystems
|
||||
if (Master != src)
|
||||
|
||||
@@ -155,6 +155,8 @@
|
||||
if(SS_SLEEPING)
|
||||
state = SS_PAUSING
|
||||
|
||||
/datum/controller/subsystem/proc/subsystem_log(msg)
|
||||
return log_subsystem(name, msg)
|
||||
|
||||
//used to initialize the subsystem AFTER the map has loaded
|
||||
/datum/controller/subsystem/Initialize(start_timeofday)
|
||||
@@ -162,7 +164,7 @@
|
||||
var/time = (REALTIMEOFDAY - start_timeofday) / 10
|
||||
var/msg = "Initialized [name] subsystem within [time] second[time == 1 ? "" : "s"]!"
|
||||
to_chat(world, "<span class='boldannounce'>[msg]</span>")
|
||||
log_world(msg)
|
||||
log_subsystem("INIT", msg)
|
||||
return time
|
||||
|
||||
//hook for printing stats to the "MC" statuspanel for admins to see performance and related stats etc.
|
||||
|
||||
@@ -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.")
|
||||
Reference in New Issue
Block a user