local skynet = require "skynet" local oo = require "Class" local gameCmd = require "GameCmd" local json =require "json" local log = require "Log" local sqlUrl = require "SqlUrl" local errorInfo = require "ErrorInfo" local serverId = tonumber(skynet.getenv "serverId") local redisKeyUrl = require "RedisKeyUrl" local clusterServer = require "ClusterServer" local MonitorServer = oo.class(clusterServer) MonitorServer.per10Second = 10 --初始化 function MonitorServer:Init() skynet.server.redis:sadd("PlatformType","1") skynet.server.redis:zadd( string.format(redisKeyUrl.BlackListAccount , "1") , 0 , "init member" ) skynet.server.redis:zadd( string.format(redisKeyUrl.BlackListAddr , "1") , 0 , "init member" ) self.statData = {} self.statData.loginAccount = {} --统计登录的帐号 self.statData.loginIp = {} --统计登录的IP end --跨天 function MonitorServer:OnNewDay() end --1秒Timer function MonitorServer:On1SecTimer() end --5秒Timer function MonitorServer:On5SecTimer() self:CheckAttack() self:CheckUnlockIP() end --接收集群数据 function MonitorServer:ClusterRecv(...) local cmd , c2sData = ... local s2cData = {} s2cData.code = errorInfo.Suc if self.Center2All_SyncClusterInfo == cmd then self:RecvSyncClusterInfo( c2sData ) elseif self.Center2All_SyncServerConfig == cmd then --同步服务器配置 self:RecvSyncServerConfig( c2sData ) elseif self.Route2Monitor_VerifyValid == cmd then self:VerifyValid( c2sData , s2cData ) elseif self.All2Moniter_AddAccountToBlack == cmd then self:AddAccountToBlack( c2sData , s2cData ) elseif self.All2Moniter_AddIPToBlack == cmd then self:AddIPToBlack( c2sData , s2cData ) else log.info(string.format("集群服务器 消息接口 %d 不存在", cmd)) s2cData.code = errorInfo.ErrorCode.NoExistInterface end log.info("集群服务器 消息接口", cmd , "返回信息",s2cData.code) return s2cData end --验证有效 function MonitorServer:VerifyValid( c2sData , s2cData ) --检测账号是否为在黑名单中 local key = string.format(redisKeyUrl.BlackListAccount , c2sData.platform ) local isSuc = skynet.server.redis:sismember( key , c2sData.loginAccount ) if isSuc then --帐号在黑名单中 s2cData.code = errorInfo.ErrorCode.BlackListAccount else key = string.format(redisKeyUrl.BlackListAddr , c2sData.platform) local rank = skynet.server.redis:zrank( key , c2sData.addr ) if nil == rank then --IP在在黑名单中 s2cData.code = errorInfo.ErrorCode.BlackListAddr else --成功登录 --统计下帐号登录次数 key = c2sData.platform..":"..c2sData.loginAccount if not self.statData.loginAccount[ key ] then self.statData.loginAccount[ key ] = {} self.statData.loginAccount[ key ].count = 0 self.statData.loginAccount[ key ].refreshTime = skynet.GetTime() end self.statData.loginAccount[ key ].count = self.statData.loginAccount[ key ].count + 1 --统计下IP登录次数 key = c2sData.addr if not self.statData.loginIp[ key ] then self.statData.loginIp[ key ] = {} self.statData.loginIp[ key ].count = 0 self.statData.loginIp[ key ].refreshTime = skynet.GetTime() end self.statData.loginIp[ key ].count = self.statData.loginIp[ key ].count + 1 end end end --添加帐号到黑名音 function MonitorServer:AddAccountToBlack( c2sData , s2cData ) local key = string.format(redisKeyUrl.BlackListAccount , c2sData.platform ) local isSuc = skynet.server.redis:sadd( key , c2sData.loginAccount ) if isSuc then log.info(string.format("监控服 账号加入黑名单 平台 %s 账号 %s 成功" , c2sData.platform , c2sData.loginAccount)) else log.info(string.format("监控服 账号加入黑名单 平台 %s 账号 %s 失败" , c2sData.platform , c2sData.loginAccount)) end end --添加IP到黑名音 function MonitorServer:AddIPToBlack(c2sData , s2cData ) local key = string.format(redisKeyUrl.BlackListAddr , c2sData.platform ) local isSuc = skynet.server.redis:zadd( key , skynet.GetTime() , c2sData.loginAccount ) if isSuc then log.info(string.format("监控服 IP加入黑名单 平台 %s 账号 %s 成功" , c2sData.platform , c2sData.loginAccount)) else log.info(string.format("监控服 IP加入黑名单 平台 %s 账号 %s 失败" , c2sData.platform , c2sData.loginAccount)) end end --检测攻击行为 function MonitorServer:CheckAttack() for k, v in pairs( self.statData.loginAccount ) do --小于10秒并且数量大于阈值就拉黑名单 if skynet.GetTime() <= v.refreshTime + self.per10Second and v.count >= self.serverInfo.LoginMaxCount10Second then local tmp = skynet.server.common:Split( k , ":") local c2sData = {} c2sData.platform = tmp[1] c2sData.loginAccount = tmp[2] self:AddAccountToBlack( c2sData ) elseif skynet.GetTime() > v.refreshTime + self.per10Second then --清空 self.statData.loginAccount[ k ] = nil end end for k, v in pairs( self.statData.loginIp ) do --小于10秒并且数量大于阈值就拉黑名单 if skynet.GetTime() <= v.refreshTime + self.per10Second and v.count >= self.serverInfo.LoginMaxCount10Second then local tmp = skynet.server.common:Split( k , ":") local c2sData = {} c2sData.platform = tmp[1] c2sData.loginAccount = tmp[2] self:AddIPToBlack( c2sData ) elseif skynet.GetTime() > v.refreshTime + self.per10Second then --清空 self.statData.loginIp[ k ] = nil end end end --检测IP是否能解锁 function MonitorServer:CheckUnlockIP() --删除当前时间之前一小时的黑名单IP local key = string.format(redisKeyUrl.BlackListAddr , "Apple" ) local unlockTime = skynet.GetTime() - self.serverInfo.IPUnlockTime skynet.server.redis:zremrangebyscore( key , "-inf" , unlockTime ) end --如果是当前服务器ID,那么就加入进来 if serverId == clusterServer.monitorServerID then skynet.server.monitorServer = MonitorServer end return MonitorServer