From c9b4ad7a838b6ca0ed46a48fab40ead082db11dc Mon Sep 17 00:00:00 2001 From: Razgriz Date: Thu, 16 Jan 2020 02:55:45 -0700 Subject: [PATCH 1/3] IP Reputation Checking --- code/controllers/configuration.dm | 31 ++++++++++++++++++++++++++++--- 1 file changed, 28 insertions(+), 3 deletions(-) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index 4d787f8602..5d7298eabb 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -63,8 +63,8 @@ var/list/gamemode_cache = list() var/allow_random_events = 0 // enables random events mid-round when set to 1 var/enable_game_master = 0 // enables the 'smart' event system. var/allow_ai = 1 // allow ai job - var/allow_ai_shells = TRUE // allow AIs to enter and leave special borg shells at will, and for those shells to be buildable. - var/give_free_ai_shell = TRUE // allows a specific spawner object to instantiate a premade AI Shell + var/allow_ai_shells = FALSE // allow AIs to enter and leave special borg shells at will, and for those shells to be buildable. + var/give_free_ai_shell = FALSE // allows a specific spawner object to instantiate a premade AI Shell var/hostedby = null var/respawn = 1 var/guest_jobban = 1 @@ -104,6 +104,13 @@ var/list/gamemode_cache = list() var/panic_bunker = 0 var/paranoia_logging = 0 + var/ip_reputation = FALSE //Should we query IPs to get scores? Generates HTTP traffic to an API service. + var/ipr_email //Left null because you MUST specify one otherwise you're making the internet worse. + var/ipr_block_bad_ips = FALSE //Should we block anyone who meets the minimum score below? Otherwise we just log it (If paranoia logging is on, visibly in chat). + var/ipr_bad_score = 1 //The API returns a value between 0 and 1 (inclusive), with 1 being 'definitely VPN/Tor/Proxy'. Values equal/above this var are considered bad. + var/ipr_allow_existing = FALSE //Should we allow known players to use VPNs/Proxies? If the player is already banned then obviously they still can't connect. + var/ipr_minimum_age = 5 //How many days before a player is considered 'fine' for the purposes of allowing them to use VPNs. + var/serverurl var/server var/banappeals @@ -806,6 +813,24 @@ var/list/gamemode_cache = list() if ("paranoia_logging") config.paranoia_logging = 1 + if("ip_reputation") + config.ip_reputation = 1 + + if("ipr_email") + config.ipr_email = value + + if("ipr_block_bad_ips") + config.ipr_block_bad_ips = 1 + + if("ipr_bad_score") + config.ipr_bad_score = text2num(value) + + if("ipr_allow_existing") + config.ipr_allow_existing = 1 + + if("ipr_minimum_age") + config.ipr_minimum_age = text2num(value) + if("random_submap_orientation") config.random_submap_orientation = 1 @@ -994,4 +1019,4 @@ var/list/gamemode_cache = list() if(world.system_type == UNIX) config.python_path = "/usr/bin/env python2" else //probably windows, if not this should work anyway - config.python_path = "python" + config.python_path = "python" \ No newline at end of file From 1c2188128cee4d4b43969057e929164047a73481 Mon Sep 17 00:00:00 2001 From: Razgriz Date: Thu, 16 Jan 2020 02:56:35 -0700 Subject: [PATCH 2/3] IP Reputation Checking --- code/modules/client/client defines.dm | 5 +- code/modules/client/client procs.dm | 95 ++++++++++++++++++++++++++- 2 files changed, 97 insertions(+), 3 deletions(-) diff --git a/code/modules/client/client defines.dm b/code/modules/client/client defines.dm index f1978e0eae..f95af88a6a 100644 --- a/code/modules/client/client defines.dm +++ b/code/modules/client/client defines.dm @@ -36,11 +36,12 @@ //SECURITY// //////////// // comment out the line below when debugging locally to enable the options & messages menu - control_freak = CONTROL_FREAK_ALL + //control_freak = 1 var/received_irc_pm = -99999 var/irc_admin //IRC admin that spoke with them last. var/mute_irc = 0 + var/ip_reputation = 0 //Do we think they're using a proxy/vpn? Only if IP Reputation checking is enabled in config. //////////////////////////////////// @@ -55,4 +56,4 @@ preload_rsc = PRELOAD_RSC - var/global/obj/screen/click_catcher/void + var/global/obj/screen/click_catcher/void \ No newline at end of file diff --git a/code/modules/client/client procs.dm b/code/modules/client/client procs.dm index 26b0103ed5..8b1100bc6a 100644 --- a/code/modules/client/client procs.dm +++ b/code/modules/client/client procs.dm @@ -74,7 +74,6 @@ ..() //redirect to hsrc.Topic() - //This stops files larger than UPLOAD_LIMIT being sent from client to server via input(), client.Import() etc. /client/AllowUpload(filename, filelength) if(filelength > UPLOAD_LIMIT) @@ -169,10 +168,19 @@ hook_vr("client_new",list(src)) //VOREStation Code if(config.paranoia_logging) + var/alert = FALSE //VOREStation Edit start. if(isnum(player_age) && player_age == 0) log_and_message_admins("PARANOIA: [key_name(src)] has connected here for the first time.") + alert = TRUE if(isnum(account_age) && account_age <= 2) log_and_message_admins("PARANOIA: [key_name(src)] has a very new BYOND account ([account_age] days).") + alert = TRUE + if(alert) + for(var/client/X in admins) + if(X.is_preference_enabled(/datum/client_preference/holder/play_adminhelp_ping)) + X << 'sound/voice/bcriminal.ogg' + window_flash(X) + //VOREStation Edit end. ////////////// //DISCONNECT// @@ -274,6 +282,31 @@ qdel(src) return 0 + // IP Reputation Check + if(config.ip_reputation) + if(config.ipr_allow_existing && player_age >= config.ipr_minimum_age) + log_admin("Skipping IP reputation check on [key] with [address] because of player age") + else if(update_ip_reputation()) //It is set now + if(ip_reputation >= config.ipr_bad_score) //It's bad + + //Log it + if(config.paranoia_logging) //We don't block, but we want paranoia log messages + log_and_message_admins("[key] at [address] has bad IP reputation: [ip_reputation]. Will be kicked if enabled in config.") + else //We just log it + log_admin("[key] at [address] has bad IP reputation: [ip_reputation]. Will be kicked if enabled in config.") + + //Take action if required + if(config.ipr_block_bad_ips && config.ipr_allow_existing) //We allow players of an age, but you don't meet it + to_chat(src,"Sorry, we only allow VPN/Proxy/Tor usage for players who have spent at least [config.ipr_minimum_age] days on the server. If you are unable to use the internet without your VPN/Proxy/Tor, please contact an admin out-of-game to let them know so we can accomidate this.") + qdel(src) + return 0 + else if(config.ipr_block_bad_ips) //We don't allow players of any particular age + to_chat(src,"Sorry, we do not accept connections from users via VPN/Proxy/Tor connections.") + qdel(src) + return 0 + else + log_admin("Couldn't perform IP check on [key] with [address]") + // VOREStation Edit Start - Department Hours if(config.time_off) var/DBQuery/query_hours = dbcon.NewQuery("SELECT department, hours FROM vr_player_hours WHERE ckey = '[sql_ckey]'") @@ -407,3 +440,63 @@ client/verb/character_setup() if(var_name == NAMEOF(src, holder)) return FALSE return ..() + +//This is for getipintel.net. +//You're welcome to replace this proc with your own that does your own cool stuff. +//Just set the client's ip_reputation var and make sure it makes sense with your config settings (higher numbers are worse results) +/client/proc/update_ip_reputation() + var/request = "http://check.getipintel.net/check.php?ip=[address]&contact=[config.ipr_email]" + var/http[] = world.Export(request) + + /* Debug + world.log << "Requested this: [request]" + for(var/entry in http) + world.log << "[entry] : [http[entry]]" + */ + + if(!http || !islist(http)) //If we couldn't check, the service might be down, fail-safe. + log_admin("Couldn't connect to getipintel.net to check [address] for [key]") + return FALSE + + //429 is rate limit exceeded + if(text2num(http["STATUS"]) == 429) + log_and_message_admins("getipintel.net reports HTTP status 429. IP reputation checking is now disabled. If you see this, let a developer know.") + config.ip_reputation = FALSE + return FALSE + + var/content = file2text(http["CONTENT"]) //world.Export actually returns a file object in CONTENT + var/score = text2num(content) + if(isnull(score)) + return FALSE + + //Error handling + if(score < 0) + var/fatal = TRUE + var/ipr_error = "getipintel.net IP reputation check error while checking [address] for [key]: " + switch(score) + if(-1) + ipr_error += "No input provided" + if(-2) + fatal = FALSE + ipr_error += "Invalid IP provided" + if(-3) + fatal = FALSE + ipr_error += "Unroutable/private IP (spoofing?)" + if(-4) + fatal = FALSE + ipr_error += "Unable to reach database" + if(-5) + ipr_error += "Our IP is banned or otherwise forbidden" + if(-6) + ipr_error += "Missing contact info" + + log_and_message_admins(ipr_error) + if(fatal) + config.ip_reputation = FALSE + log_and_message_admins("With this error, IP reputation checking is disabled for this shift. Let a developer know.") + return FALSE + + //Went fine + else + ip_reputation = score + return TRUE \ No newline at end of file From a7eabb558d5b5555de13450f7e1e8d7640501d26 Mon Sep 17 00:00:00 2001 From: Razgriz Date: Thu, 16 Jan 2020 02:57:03 -0700 Subject: [PATCH 3/3] IP Reputation Tracking --- config/example/config.txt | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/config/example/config.txt b/config/example/config.txt index 06e02d14fc..68b06f8200 100644 --- a/config/example/config.txt +++ b/config/example/config.txt @@ -447,3 +447,39 @@ ENGINE_MAP Supermatter Engine,Edison's Bane ## Uncomment to allow specific solar control computers to set themselves up. ## This requires solar controller computers in the map to be set up to use it, with the auto_start variable. # AUTOSTART_SOLARS + +## Rate of radiation decay (how much it's reduced by) per life tick +RADIATION_DECAY_RATE 1 + +## Lower limit on radiation for actually irradiating things on a turf +RADIATION_LOWER_LIMIT 0.01 + +## Multiplier for radiation resistances when tracing a ray from source to destination to compute radiation on a turf +RADIATION_RESISTANCE_MULTIPLIER 2.1 + +## Divisor for material weights when computing radiation resistance of a material object (walls) +RADIATION_MATERIAL_RESISTANCE_DIVISOR 16 + +## Mode of computing radiation resistance into effective radiation on a turf +## One and only one of the following options must be uncommented +RADIATION_RESISTANCE_CALC_DIVIDE +# RADIATION_RESISTANCE_CALC_SUBTRACT + +## IP Reputation Checking +# Enable/disable IP reputation checking (present/nonpresent) +#IP_REPUTATION + +# Set the e-mail address problems can go to for IPR checks (e-mail address) +IPR_EMAIL whatever@whatever.com + +# Above this value, reputation scores are considered 'bad' (number) +IPR_BAD_SCORE 1 + +# If you want the people disconnected. Otherwise it just logs. (present/nonpresent) +IPR_BLOCK_BAD_IPS + +# If players of a certain length of playtime are allowed anyway (REQUIRES DATABASE) (present/nonpresent) +IPR_ALLOW_EXISTING + +# And what that age is (number) +IPR_MINIMUM_AGE 5