From d220416ed3fcbcdc122a31309c90e9257bd5b6a1 Mon Sep 17 00:00:00 2001 From: MrStonedOne Date: Fri, 17 Jun 2016 03:54:42 -0700 Subject: [PATCH] Makes ipintel only warn, fixes some cache things. --- code/controllers/configuration.dm | 11 +++-- code/controllers/subsystem/ipintel.dm | 5 ++- code/modules/admin/IsBanned.dm | 16 ------- code/modules/admin/ipintel.dm | 62 +++++++++++++++++++-------- code/modules/client/client_defines.dm | 1 + code/modules/client/client_procs.dm | 11 +++++ config/config.txt | 15 ++++--- 7 files changed, 73 insertions(+), 48 deletions(-) diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm index f141715dbbd..f8aec416e19 100644 --- a/code/controllers/configuration.dm +++ b/code/controllers/configuration.dm @@ -72,9 +72,10 @@ //IP Intel vars var/ipintel_email - var/ipintel_rating_max = 1 - var/ipintel_save_good = 3 + var/ipintel_rating_bad = 1 + var/ipintel_save_good = 12 var/ipintel_save_bad = 1 + var/ipintel_domain = "check.getipintel.net" var/admin_legacy_system = 0 //Defines whether the server uses the legacy admin system with admins.txt or the SQL system. Config option in config.txt var/ban_legacy_system = 0 //Defines whether the server uses the legacy banning system with the files in /data or the SQL system. Config option in config.txt @@ -398,8 +399,10 @@ if("ipintel_email") if (value != "ch@nge.me") config.ipintel_email = value - if("ipintel_rating_max") - config.ipintel_rating_max = text2num(value) + if("ipintel_rating_bad") + config.ipintel_rating_bad = text2num(value) + if("ipintel_domain") + config.ipintel_domain = value if("ipintel_save_good") config.ipintel_save_good = text2num(value) if("ipintel_save_bad") diff --git a/code/controllers/subsystem/ipintel.dm b/code/controllers/subsystem/ipintel.dm index ecfb6c928f5..b1b99d59392 100644 --- a/code/controllers/subsystem/ipintel.dm +++ b/code/controllers/subsystem/ipintel.dm @@ -1,8 +1,9 @@ var/datum/subsystem/ipintel/SSipintel /datum/subsystem/ipintel - name = "IP Intel" - priority = -3 + name = "XKeyScore" + init_order = -10 + flags = SS_NO_FIRE var/enabled = 0 //disable at round start to avoid checking reconnects var/throttle = 0 var/errors = 0 diff --git a/code/modules/admin/IsBanned.dm b/code/modules/admin/IsBanned.dm index 6b7f75a81df..75eaeab65fb 100644 --- a/code/modules/admin/IsBanned.dm +++ b/code/modules/admin/IsBanned.dm @@ -99,22 +99,6 @@ log_access("Failed Login: [key] [computer_id] [address] - Banned [.["reason"]]") return . - if (config.ipintel_email && SSipintel.enabled) - var/datum/ipintel/res = get_ip_intel(address) - if (res.intel > config.ipintel_rating_max) - if (admin) - log_admin("The admin [key] has been allowed to bypass an IP intel ban. [address] was rated [res.intel*100]% likely to be a bad ip.") - message_admins("The admin [key] has been allowed to bypass an IP intel ban. [address] was rated [res.intel*100]% likely to be a bad ip.") - addclientmessage(ckey,"You have been allowed to bypass an IP intel ban. Your IP [address] was rated [res.intel*100]% likely to be a bad ip.") - else - if (!res.cache) - log_admin("Failed Login: [key] [computer_id] [address] - IP intel rated [res.intel*100]% likely to be a bad ip.") - message_admins("Failed Login: [key] [computer_id] [address] - IP intel rated [res.intel*100]% likely to be a bad ip.") - - . = list("reason"="IP_INTEL", "desc"="\nYour IP [address] was rated [res.intel*100]% likely to be a bad IP (spammer/proxy). The highest allowed to connect is [config.ipintel_rating_max*100]%.\nThis rating was retrieved [res.cacheminutesago] minutes ago on [res.cachedate] and refreshes in [(config.ipintel_save_bad*60)-res.cacheminutesago] minutes.") - log_access("Failed Login: [key] [computer_id] [address] - IP intel rated [res.intel*100]% likely to be a bad ip.") - return - . = ..() //default pager ban stuff if (.) //byond will not trigger isbanned() for "global" host bans, diff --git a/code/modules/admin/ipintel.dm b/code/modules/admin/ipintel.dm index 8b6a1566866..d176de32bb5 100644 --- a/code/modules/admin/ipintel.dm +++ b/code/modules/admin/ipintel.dm @@ -14,14 +14,13 @@ . = FALSE if (intel < 0) return - if (intel <= config.ipintel_rating_max) + if (intel <= config.ipintel_rating_bad) if (world.realtime < cacherealtime+(config.ipintel_save_good*60*60*10)) return TRUE else if (world.realtime < cacherealtime+(config.ipintel_save_bad*60*60*10)) return TRUE - /proc/get_ip_intel(ip, bypasscache = FALSE, updatecache = TRUE) var/datum/ipintel/res = new() res.ip = ip @@ -35,33 +34,50 @@ return cachedintel if (establish_db_connection()) - var/DBQuery/query = dbcon.NewQuery("SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW()), UNIX_TIMESTAMP(date) FROM [format_table_name("ipintel")] WHERE ip = INET_ATON('[ip]') AND ((intel <= [config.ipintel_rating_max] AND date + INTERVAL [config.ipintel_save_good] HOUR > NOW()) OR (intel > [config.ipintel_rating_max] AND date + INTERVAL [config.ipintel_save_bad] HOUR > NOW()))") + var/DBQuery/query = dbcon.NewQuery({" + SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW()) + FROM [format_table_name("ipintel")] + WHERE + ip = INET_ATON('[ip]') + AND (( + intel < [config.ipintel_rating_bad] + AND + date + INTERVAL [config.ipintel_save_good] HOUR > NOW() + ) OR ( + intel >= [config.ipintel_rating_bad] + AND + date + INTERVAL [config.ipintel_save_bad] HOUR > NOW() + )) + "}) query.Execute() if (query.NextRow()) res.cache = TRUE res.cachedate = query.item[1] res.intel = query.item[2] res.cacheminutesago = query.item[3] - res.cacherealtime = query.item[4]*10 + res.cacherealtime = world.realtime - (query.item[3]*10*60) SSipintel.cache[ip] = res return res.intel = ip_intel_query(ip) - if (updatecache && res.intel >= 0 && establish_db_connection()) + if (updatecache && res.intel >= 0) SSipintel.cache[ip] = res - var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NULL") - query.Execute() + if (establish_db_connection()) + var/DBQuery/query = dbcon.NewQuery("INSERT INTO [format_table_name("ipintel")] (ip, intel) VALUES (INET_ATON('[ip]'), [res.intel]) ON DUPLICATE KEY UPDATE intel = VALUES(intel), date = NOW()") + query.Execute() return -/proc/ip_intel_query(ip, var/retry=0) +/proc/ip_intel_query(ip, var/retryed=0) . = -1 //default if (!ip) return if (SSipintel.throttle > world.timeofday) return + if (!SSipintel.enabled) + return - var/http[] = world.Export("http://check.getipintel.net/check.php?ip=[ip]&contact=[config.ipintel_email]&format=json") + var/list/http[] = world.Export("http://[config.ipintel_domain]/check.php?ip=[ip]&contact=[config.ipintel_email]&format=json&flags=f") if (http) var/status = text2num(http["STATUS"]) @@ -70,10 +86,17 @@ var/response = json_decode(file2text(http["CONTENT"])) if (response) if (response["status"] == "success") - return text2num(response["result"]) + var/intelnum = text2num(response["result"]) + if (isnum(intelnum)) + return text2num(response["result"]) + else + ipintel_handle_error("Bad intel from server: [response["result"]].", ip, retryed) + if (!retryed) + sleep(25) + return .(ip, 1) else - ipintel_handle_error("Bad response from server: [response["status"]].", ip, retry) - if (!retry) + ipintel_handle_error("Bad response from server: [response["status"]].", ip, retryed) + if (!retryed) sleep(25) return .(ip, 1) @@ -81,28 +104,29 @@ ipintel_handle_error("Error #429: We have exceeded the rate limit.", ip, 1) return else - ipintel_handle_error("Unknown status code: [status].", ip, retry) - if (!retry) + ipintel_handle_error("Unknown status code: [status].", ip, retryed) + if (!retryed) sleep(25) return .(ip, 1) else - ipintel_handle_error("Unable to connect to API.", ip, retry) - if (!retry) + ipintel_handle_error("Unable to connect to API.", ip, retryed) + if (!retryed) sleep(25) return .(ip, 1) -/proc/ipintel_handle_error(error, ip, retry) - if (retry) +/proc/ipintel_handle_error(error, ip, retryed) + if (retryed) SSipintel.errors++ error += " Could not check [ip]. Disabling IPINTEL for [SSipintel.errors] minute[( SSipintel.errors == 1 ? "" : "s" )]" - SSipintel.throttle = world.timeofday + (10 * 60 * SSipintel.errors) + SSipintel.throttle = world.timeofday + (10 * 120 * SSipintel.errors) else error += " Attempting retry on [ip]." log_ipintel(error) /proc/log_ipintel(text) log_game("IPINTEL: [text]") + debug_admins("IPINTEL: [text]") diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 78b19cb7198..7443a4a17ed 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -45,6 +45,7 @@ // Used by html_interface module. var/hi_last_pos + var/ip_intel = "Disabled" //datum that controls the displaying and hiding of tooltips var/datum/tooltip/tooltips diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index a888c025b7e..c9fa33716bf 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -210,6 +210,8 @@ var/next_external_rsc = 0 sync_client_with_db() + check_ip_intel() + send_resources() if(!void) @@ -322,6 +324,15 @@ var/next_external_rsc = 0 var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]` (`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[sql_ckey]','[sql_ip]','[sql_computerid]');") query_accesslog.Execute() +/client/proc/check_ip_intel() + set waitfor = 0 //we sleep when getting the intel, no need to hold up the client connection while we sleep + if (config.ipintel_email) + var/datum/ipintel/res = get_ip_intel(address) + if (res.intel >= config.ipintel_rating_bad) + message_admins("Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.") + ip_intel = res.intel + + /client/proc/add_verbs_from_config() if(config.see_own_notes) verbs += /client/proc/self_notes diff --git a/config/config.txt b/config/config.txt index f371a024b59..d04cd64cd3d 100644 --- a/config/config.txt +++ b/config/config.txt @@ -112,16 +112,17 @@ HOSTEDBY Yournamehere GUEST_BAN ### IPINTEL: -### This allows you to block likely proxies by checking ips against getipintel.net -## Maximum rating: (0.90 is good, 1 is 100% likely to be a spammer/proxy, 0.8 is 80%, etc) anything higher then this number is rejected -#IPINTEL_RATING_MAX 0.90 +### This allows you to detect likely proxies by checking ips against getipintel.net +## Rating to warn at: (0.90 is good, 1 is 100% likely to be a spammer/proxy, 0.8 is 80%, etc) anything equal to or higher then this number triggers an admin warning +#IPINTEL_RATING_BAD 0.90 ## Contact email, (required to use the service, leaving blank or default disables IPINTEL) #IPINTEL_EMAIL ch@nge.me -## How long to save good matches (ipintel rate limits to 15 per minute and 500 per day. so this shouldn't be too low, getipintel.net suggests 6 hours, time is in hours) -#IPINTEL_SAVE_GOOD 6 +## How long to save good matches (ipintel rate limits to 15 per minute and 500 per day. so this shouldn't be too low, getipintel.net suggests 6 hours, time is in hours) (Your ip will get banned if you go over 500 a day too many times) +#IPINTEL_SAVE_GOOD 12 ## How long to save bad matches (these numbers can change as ips change hands, best not to save these for too long in case somebody gets a new ip used by a spammer/proxy before.) -#IPINTEL_SAVE_BAD 1 - +#IPINTEL_SAVE_BAD 3 +## Domain name to query (leave commented out for the default, only needed if you pay getipintel.net for more querys) +#IPINTEL_DOMAIN check.getipintel.net ## Uncomment to allow web client connections #ALLOW_WEBCLIENT