基于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;

 

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