基於spark實時分析nginx請求日誌,自動封禁IP之一:web功能設計

用過阿里高防的都知道,高防有個很牛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;

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章