226 lines
7.2 KiB
Lua
226 lines
7.2 KiB
Lua
local skynet = require "skynet"
|
|
local oo = require "Class"
|
|
local log = require "Log"
|
|
local sqlUrl = require "SqlUrl"
|
|
local Defense = oo.class()
|
|
|
|
Defense.MaxUser = 1000 --最大记录1000个玩家
|
|
Defense.MsgInterval = 1 --消息间隔时间1秒
|
|
|
|
--系统触发
|
|
Defense.TriggerType_FastMsg = 100 --消息过快
|
|
Defense.TriggerType_ErrorRequest = 101 --错误请求
|
|
Defense.TriggerType_ErrorParam = 102 --错误参数
|
|
|
|
--游戏触发
|
|
Defense.TriggerType_FreeRed = 200 --免费红包
|
|
Defense.TriggerType_AdRed = 201 --付费红包
|
|
Defense.TriggerType_Exp = 202 --经验
|
|
Defense.TriggerType_GainCash = 203 --提现
|
|
Defense.TriggerType_GainDiamond = 204 --获得的钻石
|
|
|
|
Defense.TriggerType_ManualBlackList = 300 --手动添加黑名单
|
|
|
|
Defense.AccountStatus_Normal = 1 --正常玩家
|
|
Defense.AccountStatus_White = 2 --白名单
|
|
Defense.AccountStatus_Gray = 3 --灰名单
|
|
Defense.AccountStatus_Black = 4 --黑名单
|
|
|
|
Defense.ErrorRequestCount = 10 --达到错误请求多少次后IP进入黑名单
|
|
Defense.ErrorParamCount = 10 --达到错误参数多少次后IP进入黑名单
|
|
|
|
--用户触发信息
|
|
local userTrigger =
|
|
{
|
|
userId = 0 , --用户ID
|
|
lastMsgTime = 0 , --上一条消息时间
|
|
count = {}
|
|
}
|
|
|
|
--初始化
|
|
function Defense:Init()
|
|
self.userBlackList = {} --用户黑名单
|
|
self.ipBlackList = {} --黑名单IP列表
|
|
Defense.attackInfo = {}
|
|
end
|
|
|
|
--触发规则
|
|
function Defense:Trigger( userId , type )
|
|
if not Defense.userBlackList[ userId ] then
|
|
return
|
|
end
|
|
|
|
if not Defense.userBlackList[ userId ].count[ type ] then
|
|
--该类型没加入统计就统计
|
|
Defense.userBlackList[ userId ].count[ type ] = 0
|
|
end
|
|
|
|
Defense.userBlackList[ userId ].count[ type ] = Defense.userBlackList[ userId ].count[ type ] + 1
|
|
log.info(string.format("玩家 %d 触发规则 %d %d 次" , userId , type , Defense.userBlackList[ userId ].count[ type ]))
|
|
|
|
local count = Defense.userBlackList[ userId ].count[ type ]
|
|
if Defense.TriggerType_FastMsg == type and count >= 500 then
|
|
elseif Defense.TriggerType_ErrorParam == type and count >= 5 then
|
|
self:ModifyAccountStatus(userId , Defense.AccountStatus_Black , type )
|
|
end
|
|
end
|
|
|
|
--是否为黑名单
|
|
function Defense:IsBlack( userId )
|
|
if self.AccountStatus_Black == Defense.userBlackList[ userId ].accountStatus then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
--修改玩家帐号状态
|
|
function Defense:ModifyAccountStatus( userId , status , type )
|
|
Defense.userBlackList[ userId ].accountStatus = status
|
|
local sql = string.format(sqlUrl.modifyAccountStatusToUser, status , userId )
|
|
local queryData = skynet.server.db:Query(sql)
|
|
|
|
if self.AccountStatus_Black == status then
|
|
local str = string.format("玩家 %d 因触发规则 %d %d 次 被列入黑名单" , userId , type , Defense.userBlackList[ userId ].count[ type ] or 0)
|
|
log.info(str)
|
|
|
|
--踢玩家下线
|
|
local c2sData = {}
|
|
c2sData.userId = userId
|
|
skynet.server.clusterMasterServer:SendAllServerUserOffline(c2sData)
|
|
elseif self.AccountStatus_Normal == status then
|
|
local str = string.format("玩家 %d 成功移除黑名单" , userId)
|
|
log.info(str)
|
|
end
|
|
end
|
|
|
|
--IP是否在黑名单中
|
|
function Defense:IsIPBlackList( addr )
|
|
if not Defense.ipBlackList[addr] then
|
|
return false
|
|
end
|
|
|
|
if Defense.ipBlackList[addr] then
|
|
return true
|
|
end
|
|
|
|
return false
|
|
end
|
|
|
|
--检查攻击相关
|
|
function Defense:CheckAttack( type , addr )
|
|
if not Defense.attackInfo[ addr ] then
|
|
Defense.attackInfo[ addr ] = {}
|
|
Defense.attackInfo[ addr ].count = {}
|
|
end
|
|
|
|
if not Defense.attackInfo[ addr ].count[ type ] then
|
|
Defense.attackInfo[ addr ].count[ type ] = 0
|
|
end
|
|
|
|
Defense.attackInfo[ addr ].count[ type ] = Defense.attackInfo[ addr ].count[ type ] + 1
|
|
local count = Defense.attackInfo[ addr ].count[ type ]
|
|
log.info(string.format("IP %s 攻击类型 %d 数量 %d",addr , type , count))
|
|
if self.TriggerType_ErrorRequest == type and count >= self.ErrorRequestCount then
|
|
--Defense.ipBlackList[addr] = true
|
|
log.info(string.format("IP %s 已经达到上限 攻击类型 %d 数量 %d",addr , type , count))
|
|
elseif self.TriggerType_ErrorParam == type and count >= self.ErrorParamCount then
|
|
--Defense.ipBlackList[addr] = true
|
|
log.info(string.format("IP %s 已经达到上限 攻击类型 %d 数量 %d",addr , type , count))
|
|
end
|
|
end
|
|
|
|
--检查玩家错误的请求
|
|
function Defense:CheckRequest( userId , type , param1 ,param2)
|
|
if not Defense.userBlackList[ userId ] then
|
|
return
|
|
end
|
|
|
|
local isTrigger = false
|
|
if Defense.TriggerType_FastMsg == type then
|
|
--isTrigger = self:CheckFastMsg( userId )
|
|
elseif Defense.TriggerType_ErrorParam == type then
|
|
isTrigger = true
|
|
end
|
|
|
|
if isTrigger then
|
|
--激活触发统计
|
|
self:Trigger( userId , type )
|
|
end
|
|
|
|
Defense.userBlackList[ userId ].lastMsgTime = skynet.GetTime()
|
|
end
|
|
|
|
--检查玩家消息是否过快
|
|
function Defense:CheckFastMsg( userId )
|
|
local user = Defense.userBlackList[ userId ]
|
|
if not user then
|
|
return
|
|
end
|
|
|
|
if skynet.GetTime() - user.lastMsgTime <= Defense.MsgInterval then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
end
|
|
|
|
--检查游戏
|
|
function Defense:CheckGame( player , type )
|
|
local isOK = false
|
|
if Defense.TriggerType_FreeRed == type then
|
|
isOK = self:CheckFreeRed( player )
|
|
elseif Defense.TriggerType_AdRed == type then
|
|
isOK = self:CheckAdRed( player )
|
|
elseif Defense.TriggerType_Exp == type then
|
|
isOK = self:CheckExp( player )
|
|
elseif Defense.TriggerType_GainCash == type then
|
|
isOK = self:CheckGainCash( player )
|
|
elseif Defense.TriggerType_GainDiamond == type then
|
|
isOK = self:CheckGainDiamond( player )
|
|
end
|
|
|
|
if not isOK then
|
|
self:Warning(player.data.id , type)
|
|
end
|
|
return isOK
|
|
end
|
|
|
|
|
|
--检查经验
|
|
function Defense:CheckExp( player )
|
|
local level = player.data.level
|
|
local exp = player.data.todayGain.exp
|
|
|
|
if level < 10 and exp >= 1910 then
|
|
return false
|
|
elseif level >= 10 and level < 16 and exp >= 3410 then
|
|
return false
|
|
elseif level >= 16 and exp >= 4340 then
|
|
return false
|
|
else
|
|
return true
|
|
end
|
|
end
|
|
|
|
--检查获得的现金
|
|
function Defense:CheckGainCash( player )
|
|
if true then
|
|
return true --暂时屏蔽这个功能
|
|
end
|
|
local cash = player.data.todayGain.cash
|
|
if cash > 200 then --超过两无就无法提现
|
|
return false
|
|
end
|
|
return true
|
|
end
|
|
|
|
--警告
|
|
function Defense:Warning( id , type )
|
|
log.info(string.format("警告!玩家 %d 已经触发了游戏中的限制类型 %d ",id ,type))
|
|
local sql = string.format("insert into warning values(%d , %d , %d)",id ,type , skynet.GetTime())
|
|
local queryData = skynet.server.db:Query(sql)
|
|
end
|
|
|
|
skynet.server.defense = Defense
|
|
return Defense |