用過阿里高防的都知道,高防有個很牛X的防CC功能配置:基於域名,基於某URL(精確匹配或後模糊匹配),限制某個時間跨度的請求頻率,超過該頻率會拉黑n分鐘。廢話少說,直接上圖:
然而:
高防不是所有公司都用得起的(月費用1萬以上),
高防配置的域名數量越來越苛刻(一級域名和二級域名數都有嚴格限制了),
高防也有抽風的時候,有很多時候發現該功能沒起效果,
所以我們搞了個自己的防CC功能。
改方案暫取名lbwaf,主要功能包括手動拉黑(就是手動填IP黑名單),自動拉黑(重點功能,配置規則),自動拉黑支持白名單配置,支持查看規則觸發的日誌明細。
實時分析基於spark structure streaming,下一章介紹;本章介紹web功能和數據庫設計。
1. WEB功能
貼2個主要頁面
a)、黑名單列表
來源類型:api\spark\手動(目前未實現api)
來源:spark對應具體的規則id;手動對應具體的用戶名
b)、規則管理
規則包括:域名、URL、匹配類型(精確、後模糊)、時間範圍、請求閾值、封禁時間
2. 數據庫設計
主要表和JOB
存儲過程:根據spark輸出的數據,生成IP黑名單結果
CREATE PROCEDURE `proc_spark_ipblacklist`()
BEGIN
declare v_auto_ip_quota int default 1000; -- 支持最大自動拉黑IP數
declare v_id_last bigint; -- 上次處理到的id(含)
declare v_id_curr bigint; -- 當前id
declare v_ip_blacklist_cnt int; -- 現有的拉黑IP數
declare v_to_add bigint; -- 當前新增拉黑IP數
select id_deal_until into v_id_last from job_process where id=1;
select max(id) into v_id_curr from match_record;
select count(*) into v_ip_blacklist_cnt from ip_blacklist where source_type='spark';
start transaction;
-- 當前有新增IP
if (v_id_curr > v_id_last) then
-- 當前新增需要處理的IP數
select count(distinct rule_id,ip_addr) into v_to_add
from match_record t
where id > v_id_last
and id <= v_id_curr
and ip_addr not in (select ip_addr from ip_blacklist);
-- 新增數量大於配額,直接清空所有存量IP黑名單
if (v_to_add >= v_auto_ip_quota) then
delete from ip_blacklist where source_type='spark';
-- 新增數量與存量IP黑名單之和大於配額,刪除存量IP黑名單中老的IP
elseif (v_to_add + v_ip_blacklist_cnt > v_auto_ip_quota) then
select v_to_add + v_ip_blacklist_cnt - v_auto_ip_quota into @v_to_delete;
prepare s1 from "delete from ip_blacklist where source_type='spark' order by create_time limit ?";
execute s1 using @v_to_delete;
end if;
-- 插入新增IP
insert into ip_blacklist(source,ip_addr,effective_time,status,source_type)
select distinct concat('rule',rule_id),ip_addr,
(select block_duration from rule where id=t.rule_id), 0,'spark'
from match_record t
where id > v_id_last
and id <= v_id_curr
and ip_addr not in (select ip_addr from ip_blacklist)
limit 1000;
update job_process set id_deal_until = v_id_curr where id = 1;
end if;
commit;
end;
存儲過程:IP黑名單封禁到期後,修改狀態,刪除過期數據
CREATE PROCEDURE `proc_ip_blacklist_status_update`()
begin
update ip_blacklist
set status=1
where date_add(modify_time,INTERVAL effective_time minute) < now();
commit;
delete from ip_blacklist
where status = 1
and source_type='spark';
commit;
delete from ip_blacklist
where status = 1
and source_type='手動'
and modify_time < DATE_SUB(now(),INTERVAL 1 day);
commit;
end;