mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-24 12:37:26 +01:00
WIP ports XKeyScore from TG
This commit is contained in:
@@ -535,3 +535,17 @@ CREATE TABLE IF NOT EXISTS `discord` (
|
||||
PRIMARY KEY (`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `ipintel`
|
||||
--
|
||||
DROP TABLE IF EXISTS `ipintel`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `ipintel` (
|
||||
`ip` INT UNSIGNED NOT NULL ,
|
||||
`date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL ,
|
||||
`intel` REAL NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY ( `ip` )
|
||||
) ENGINE = INNODB;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
@@ -534,3 +534,17 @@ CREATE TABLE IF NOT EXISTS `SS13_discord` (
|
||||
PRIMARY KEY (`ckey`)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
|
||||
--
|
||||
-- Table structure for table `SS13_ipintel`
|
||||
--
|
||||
DROP TABLE IF EXISTS `SS13_ipintel`;
|
||||
/*!40101 SET @saved_cs_client = @@character_set_client */;
|
||||
/*!40101 SET character_set_client = utf8 */;
|
||||
CREATE TABLE `SS13_ipintel` (
|
||||
`ip` INT UNSIGNED NOT NULL ,
|
||||
`date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL ,
|
||||
`intel` REAL NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY ( `ip` )
|
||||
) ENGINE = INNODB;
|
||||
/*!40101 SET character_set_client = @saved_cs_client */;
|
||||
@@ -0,0 +1,6 @@
|
||||
CREATE TABLE `ipintel` (
|
||||
`ip` INT UNSIGNED NOT NULL ,
|
||||
`date` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP NOT NULL ,
|
||||
`intel` REAL NOT NULL DEFAULT '0',
|
||||
PRIMARY KEY ( `ip` )
|
||||
) ENGINE = INNODB;
|
||||
@@ -123,6 +123,14 @@
|
||||
var/slime_delay = 0
|
||||
var/animal_delay = 0
|
||||
|
||||
//IP Intel vars
|
||||
var/ipintel_email
|
||||
var/ipintel_rating_bad = 1
|
||||
var/ipintel_save_good = 12
|
||||
var/ipintel_save_bad = 1
|
||||
var/ipintel_domain = "check.getipintel.net"
|
||||
var/ipintel_maxplaytime = 0
|
||||
|
||||
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
|
||||
var/use_age_restriction_for_jobs = 0 //Do jobs use account age restrictions? --requires database
|
||||
@@ -213,7 +221,7 @@
|
||||
|
||||
// Automatic localhost admin disable
|
||||
var/disable_localhost_admin = 0
|
||||
|
||||
|
||||
//Start now warning
|
||||
var/start_now_confirmation = 0
|
||||
|
||||
@@ -293,6 +301,20 @@
|
||||
if("shadowling_max_age")
|
||||
config.shadowling_max_age = text2num(value)
|
||||
|
||||
if("ipintel_email")
|
||||
if (value != "ch@nge.me")
|
||||
config.ipintel_email = 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")
|
||||
config.ipintel_save_bad = text2num(value)
|
||||
if("ipintel_maxplaytime")
|
||||
config.ipintel_maxplaytime = text2num(value)
|
||||
|
||||
if("log_ooc")
|
||||
config.log_ooc = 1
|
||||
|
||||
@@ -358,10 +380,10 @@
|
||||
|
||||
if("no_dead_vote")
|
||||
config.vote_no_dead = 1
|
||||
|
||||
|
||||
if("vote_autotransfer_initial")
|
||||
config.vote_autotransfer_initial = text2num(value)
|
||||
|
||||
|
||||
if("vote_autotransfer_interval")
|
||||
config.vote_autotransfer_interval = text2num(value)
|
||||
|
||||
@@ -645,7 +667,7 @@
|
||||
|
||||
if("disable_karma")
|
||||
config.disable_karma = 1
|
||||
|
||||
|
||||
if("start_now_confirmation")
|
||||
config.start_now_confirmation = 1
|
||||
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
SUBSYSTEM_DEF(ipintel)
|
||||
name = "XKeyScore"
|
||||
wait = 1
|
||||
flags = SS_NO_FIRE
|
||||
var/enabled = 0 //disable at round start to avoid checking reconnects
|
||||
var/throttle = 0
|
||||
var/errors = 0
|
||||
|
||||
var/list/cache = list()
|
||||
|
||||
/datum/controller/subsystem/ipintel/Initialize(timeofday, zlevel)
|
||||
enabled = 1
|
||||
. = ..()
|
||||
|
||||
@@ -0,0 +1,138 @@
|
||||
/datum/ipintel
|
||||
var/ip
|
||||
var/intel = 0
|
||||
var/cache = FALSE
|
||||
var/cacheminutesago = 0
|
||||
var/cachedate = ""
|
||||
var/cacherealtime = 0
|
||||
|
||||
/datum/ipintel/New()
|
||||
cachedate = SQLtime()
|
||||
cacherealtime = world.realtime
|
||||
|
||||
/datum/ipintel/proc/is_valid()
|
||||
. = FALSE
|
||||
if (intel < 0)
|
||||
return
|
||||
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
|
||||
. = res
|
||||
if (!ip || !config.ipintel_email || !SSipintel.enabled)
|
||||
return
|
||||
if (!bypasscache)
|
||||
var/datum/ipintel/cachedintel = SSipintel.cache[ip]
|
||||
if (cachedintel && cachedintel.is_valid())
|
||||
cachedintel.cache = TRUE
|
||||
return cachedintel
|
||||
|
||||
if(dbcon.IsConnected())
|
||||
var/rating_bad = config.ipintel_rating_bad
|
||||
var/DBQuery/query_get_ip_intel = dbcon.NewQuery({"
|
||||
SELECT date, intel, TIMESTAMPDIFF(MINUTE,date,NOW())
|
||||
FROM [format_table_name("ipintel")]
|
||||
WHERE
|
||||
ip = INET_ATON('[ip]')
|
||||
AND ((
|
||||
intel < [rating_bad]
|
||||
AND
|
||||
date + INTERVAL [config.ipintel_save_good] HOUR > NOW()
|
||||
) OR (
|
||||
intel >= [rating_bad]
|
||||
AND
|
||||
date + INTERVAL [config.ipintel_save_bad] HOUR > NOW()
|
||||
))
|
||||
"})
|
||||
if(!query_get_ip_intel.Execute())
|
||||
qdel(query_get_ip_intel)
|
||||
return
|
||||
if (query_get_ip_intel.NextRow())
|
||||
res.cache = TRUE
|
||||
res.cachedate = query_get_ip_intel.item[1]
|
||||
res.intel = text2num(query_get_ip_intel.item[2])
|
||||
res.cacheminutesago = text2num(query_get_ip_intel.item[3])
|
||||
res.cacherealtime = world.realtime - (text2num(query_get_ip_intel.item[3])*10*60)
|
||||
SSipintel.cache[ip] = res
|
||||
qdel(query_get_ip_intel)
|
||||
return
|
||||
qdel(query_get_ip_intel)
|
||||
res.intel = ip_intel_query(ip)
|
||||
if (updatecache && res.intel >= 0)
|
||||
SSipintel.cache[ip] = res
|
||||
if(dbcon.IsConnected())
|
||||
var/DBQuery/query_add_ip_intel = 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_add_ip_intel.Execute()
|
||||
qdel(query_add_ip_intel)
|
||||
|
||||
|
||||
/proc/ip_intel_query(ip, var/retryed=0)
|
||||
. = -1 //default
|
||||
if (!ip)
|
||||
return
|
||||
if (SSipintel.throttle > world.timeofday)
|
||||
return
|
||||
if (!SSipintel.enabled)
|
||||
return
|
||||
|
||||
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"])
|
||||
|
||||
if (status == 200)
|
||||
var/response = json_decode(file2text(http["CONTENT"]))
|
||||
if (response)
|
||||
if (response["status"] == "success")
|
||||
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, retryed)
|
||||
if (!retryed)
|
||||
sleep(25)
|
||||
return .(ip, 1)
|
||||
|
||||
else if (status == 429)
|
||||
ipintel_handle_error("Error #429: We have exceeded the rate limit.", ip, 1)
|
||||
return
|
||||
else
|
||||
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, retryed)
|
||||
if (!retryed)
|
||||
sleep(25)
|
||||
return .(ip, 1)
|
||||
|
||||
|
||||
/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 * 120 * SSipintel.errors)
|
||||
else
|
||||
error += " Attempting retry on [ip]."
|
||||
log_ipintel(error)
|
||||
|
||||
/proc/log_ipintel(text)
|
||||
log_game("IPINTEL: [text]")
|
||||
log_debug("IPINTEL: [text]")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -71,6 +71,8 @@
|
||||
|
||||
control_freak = CONTROL_FREAK_ALL | CONTROL_FREAK_SKIN | CONTROL_FREAK_MACROS
|
||||
|
||||
var/ip_intel = "Disabled"
|
||||
|
||||
var/datum/click_intercept/click_intercept = null
|
||||
|
||||
//datum that controls the displaying and hiding of tooltips
|
||||
|
||||
@@ -374,6 +374,7 @@
|
||||
to_chat(src, message)
|
||||
clientmessages.Remove(ckey)
|
||||
|
||||
check_ip_intel()
|
||||
|
||||
send_resources()
|
||||
|
||||
@@ -528,6 +529,19 @@
|
||||
var/DBQuery/query_accesslog = dbcon.NewQuery("INSERT INTO `[format_table_name("connection_log")]`(`id`,`datetime`,`serverip`,`ckey`,`ip`,`computerid`) VALUES(null,Now(),'[serverip]','[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)
|
||||
if(config.ipintel_maxplaytime && config.use_exp_tracking)
|
||||
var/living_hours = get_exp_type_num(EXP_TYPE_LIVING) / 60
|
||||
if(living_hours >= config.ipintel_maxplaytime)
|
||||
message_admins("<span class='adminnotice'>Proxy Detection: [key_name_admin(src)] skips check due to [living_hours] playtime.</span>")
|
||||
return
|
||||
|
||||
var/datum/ipintel/res = get_ip_intel(address)
|
||||
if (res.intel >= config.ipintel_rating_bad)
|
||||
message_admins("<span class='adminnotice'>Proxy Detection: [key_name_admin(src)] IP intel rated [res.intel*100]% likely to be a Proxy/VPN.</span>")
|
||||
ip_intel = res.intel
|
||||
|
||||
#undef TOPIC_SPAM_DELAY
|
||||
#undef UPLOAD_LIMIT
|
||||
|
||||
@@ -176,6 +176,21 @@ GUEST_JOBBAN
|
||||
## Uncomment this to stop people connecting to your server without a registered ckey. (i.e. guest-* are all blocked from connecting)
|
||||
GUEST_BAN
|
||||
|
||||
### IPINTEL:
|
||||
### 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) (Your ip will get banned if you go over 500 a day too many times)
|
||||
#IPINTEL_SAVE_GOOD 72
|
||||
## 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 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
|
||||
## Ignore players with this many hours of playtime. Requires USE_EXP_TRACKING
|
||||
#IPINTEL_MAXPLAYTIME 10
|
||||
|
||||
## Comment to disable checking for the cid randomizer dll. (disabled if database isn't enabled or connected)
|
||||
CHECK_RANDOMIZER
|
||||
|
||||
|
||||
@@ -212,6 +212,7 @@
|
||||
#include "code\controllers\subsystem\fires.dm"
|
||||
#include "code\controllers\subsystem\garbage.dm"
|
||||
#include "code\controllers\subsystem\icon_smooth.dm"
|
||||
#include "code\controllers\subsystem\ipintel.dm"
|
||||
#include "code\controllers\subsystem\jobs.dm"
|
||||
#include "code\controllers\subsystem\machinery.dm"
|
||||
#include "code\controllers\subsystem\mapping.dm"
|
||||
@@ -1128,6 +1129,7 @@
|
||||
#include "code\modules\admin\create_poll.dm"
|
||||
#include "code\modules\admin\create_turf.dm"
|
||||
#include "code\modules\admin\holder2.dm"
|
||||
#include "code\modules\admin\ipintel.dm"
|
||||
#include "code\modules\admin\IsBanned.dm"
|
||||
#include "code\modules\admin\machine_upgrade.dm"
|
||||
#include "code\modules\admin\NewBan.dm"
|
||||
|
||||
Reference in New Issue
Block a user