HomeServer/lualib-src/Server-main/Lib/Defense/Defense.lua

301 lines
9.0 KiB
Lua
Raw Normal View History

2024-11-20 15:41:09 +08:00
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()
Defense.userInfo = {}
Defense.attackInfo = {}
Defense.ipBlackList = {} --黑名单IP列表
end
--玩家进入
function Defense:Enter( userId )
if not Defense.userInfo[ userId ] then
Defense.userInfo[ userId ] = {}
local userInfo ={}
userInfo.userId = userId
userInfo.lastMsgTime = skynet.GetTime()
userInfo.count = {} --各种触发的统计
userInfo.accountStatus = self.AccountStatus_Normal
Defense.userInfo[ userId ] = userInfo
end
end
--玩家退出
function Defense:Exit( userId)
if Defense.userInfo[ userId ] then
Defense.userInfo[ userId ] = nil
end
end
--触发规则
function Defense:Trigger( userId , type )
if not Defense.userInfo[ userId ] then
return
end
if not Defense.userInfo[ userId ].count[ type ] then
--该类型没加入统计就统计
Defense.userInfo[ userId ].count[ type ] = 0
end
Defense.userInfo[ userId ].count[ type ] = Defense.userInfo[ userId ].count[ type ] + 1
log.info(string.format("玩家 %d 触发规则 %d %d 次" , userId , type , Defense.userInfo[ userId ].count[ type ]))
local count = Defense.userInfo[ 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.userInfo[ userId ].accountStatus then
return true
else
return false
end
end
--修改玩家帐号状态
function Defense:ModifyAccountStatus( userId , status , type )
Defense.userInfo[ 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.userInfo[ 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.userInfo[ 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.userInfo[ userId ].lastMsgTime = skynet.GetTime()
end
--检查玩家消息是否过快
function Defense:CheckFastMsg( userId )
local user = Defense.userInfo[ 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:CheckFreeRed( player )
--[[
local unlockCount = 0
for key, value in pairs( player.data.landUnlock ) do
if value then
unlockCount = unlockCount + 1
end
end
if unlockCount < 1 or unlockCount > 3 then
log.info("检查免费红包数量异常",unlockCount)
end
]]
local level = player.data.level
local todayFreeRed = player.data.todayGain.freeRed
if level < 10 and todayFreeRed >= 4900 then
return false
elseif level >= 10 and level < 16 and todayFreeRed >= 9400 then
return false
elseif level >= 16 and todayFreeRed >= 12200 then
return false
else
return true
end
end
--检查付费红包
function Defense:CheckAdRed( player )
local level = player.data.level
local adRed = player.data.todayGain.adRed
if level < 10 and adRed >= 225000 then
return false
elseif level >= 10 and level < 16 and adRed >= 450000 then
return false
elseif level >= 16 and adRed >= 675300 then
return false
else
return true
end
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:CheckGainDiamond( player )
local diamond = player.data.todayGain.buyDiamond
if diamond > 9000 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