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