# bb-anti-reptile **Repository Path**: RemoteControl/bb-anti-reptile ## Basic Information - **Project Name**: bb-anti-reptile - **Description**: 积木防爬组件,目标是自动化收集用户访问率以达到控制异常访问。 - **Primary Language**: Java - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 4 - **Forks**: 1 - **Created**: 2024-03-21 - **Last Updated**: 2025-10-07 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # bb-anti-reptile ### 介绍 积木防爬组件,一款目标开箱即可用反扒组件,以达到控制异常访问。
包括基于ip、和ua的简单控制,以及添加了ip-plus-rule和user-rule两种规则,基于用户的访问日志(Plumelog-me等)以分析ip和用户的访问规则自动添加访问规则,以限流/验证码/黑名单/告警通知限制访问。 ### 系统要求 - 基于 spring-boot 开发(spring-boot2.x) - 需要 redisson ### 模块说明 #### 1. bb-anti-reptile-core 反扒核心模块,实现了4中规则,以及自带默认方案(最简单方案):比如限流,响应方案、存储方案 - 四种方案: + 基于ua,通过User-Agent字符串 控制用户授权访问,常用几种规则:allowedLinux、allowedMobile、allowedPc、allowedIot、allowedProxy + 基于ip,设置白名单/黑名单ip,以及设置允许ip通过的流量,来控制ip授权访问(难点在于怎么设置ip的限流数值) + 基于ip-plus(仅限非登录), 同样可以设置白名单/黑名单ip,流量限制 基于ip/用户 的访问规则以精准区分流量(好处2个,1、无需设置流量值 2、各个ip将更精准),目前数据分析有2种块(集成Plumelog-me(已完成)、自行分析后自行写入db《bb-anti-reptile-data-db》) + 基于user(仅限登录),同样限流,限制用户的访问规则以精准区分流量,目前数据分析有2块(集成Plumelog-me(已完成)、自行分析后写入db《bb-anti-reptile-data-db》) + 基于平台限流/告警,基于url限流/告警(和以上差异为,一旦限流本规则仅限控制此接口,其他接口不受影响,其他规则则全部限制接口都会受影响) - 4种限流结果: + lock-type=1,只是限流 + lock-type=2,限流且加入可解除的黑名单(黑名单时间建议设置比较短) + lock-type=3,限流且加入不可解除的黑名单(黑名单时间建议设置比较长) + lock-type=9,告警 #### 2. bb-anti-reptile-rateLimiter-redisson 同步限流方案,可以自行实现你需要的限流插件(限流) #### 3. bb-anti-reptile-data-esstat Plumelog-me 日志分析器插件(日志分析-未优化,含bb-anti-reptile-data-db) #### 4. bb-anti-reptile-es es配置插件 #### 5. bb-anti-reptile-data-db db存储(存储方案-mysql) #### 6. bb-anti-reptile-springboot-starter 应用启动器-目前只能在非网关启动,启动 SpringMVC拦截器 对请求进行过滤 #### 7. bb-anti-reptile-captcha 验证码插件,支持验证码限流场景下(仅限验证码限流),用户通过验证码解锁(ip限流解ip,user限流解user) #### 8. bb-anti-reptile-mailalarm 邮件告警,lock-type=9模式下配置邮件属性,以通知管理员,否则只告警无通知,可以根据此定义自己的通知渠道 ### 使用说明 #### 1. 添加maven依赖(目前未添加到公用maven库,请自行打包到私服或者 mvn install 至本地) 引入依赖条件: - mvn install 至本地 - deploy 至私服 - 使用作者的gitee 版本库,pom添加如下 ```yaml jin-gitee-maven https://gitee.com/RemoteControl/maven-repository/raw/master ``` ```xml com.bblocks.common bb-anti-reptile-springboot-starter 1.0.1-SNAPSHOT com.bblocks.common bb-anti-reptile-rateLimiter-redisson 1.0.1-SNAPSHOT com.bblocks.common bb-anti-reptile-data-db 1.0.1-SNAPSHOT ``` #### 2. 配置redisson #### 3. 配置以启动(全部参数如下) ```properties #限流/反爬配置 anti: reptile: #全局开关 enabled: true #启用全局拦截 global-filter-mode: true #非全局拦截下,反扒接口(支持正则表达式匹配(如:^/xx/.*$) include-urls: /abc/1,/abc/2 ua-rule: enabled: false ip-rule: #ip限流(可以用,但不好用,不知道配置数字多少,且ip接口差异太大) enabled: false #时间窗口(ms) expiration-time: 5000 #时间窗口限制量(默认无-不限制) request-max-size: 10 #锁定类型:1=限流 2=验证码(默认 锁定时间结束或者验证码解锁) 3=拉黑(锁定时间结束或者管理平台手工解锁) lock-type: 1 #命中规则后,锁定期限(s)-默认1天,验证码建议30秒 lock-expire: 30 #限制后响应 lock-response: '{"code":0,"msg":"限流!","serviceTips":"限流","sucFlag":false}' ip-plus-rule: enabled: true # hea的token-key(默认Authorization) token-key: Authorization #时间窗口(ms) expiration-time: 5000 #时间窗口限制量(默认值-仅在url无参数的时候生效-不配置不生效) request-max-size: 10 #锁定类型:1=限流 2=验证码(默认 锁定时间结束或者验证码解锁) 3=拉黑(锁定时间结束或者管理平台手工解锁) lock-type: 2 #命中规则后,锁定期限(s)-默认1天,验证码建议10分钟 lock-expire: 600 #最大值系数(url的max*此系数=最终最大值) multiplier: 100.0 #限制后响应 lock-response: '{ "code": 0,"msg": "限流验证码!","serviceTips": "限流验证码!","sucFlag": false }' user-rule: enabled: true # hea的token-key(默认Authorization) token-key: Authorization #时间窗口(ms) expiration-time: 5000 #时间窗口限制量(默认值-仅在url无参数的时候生效-不配置不生效) request-max-size: 10 #锁定类型:1=限流 2=验证码(默认 锁定时间结束或者验证码解锁) 3=拉黑(锁定时间结束或者管理平台手工解锁) lock-type: 3 #最大值系数(url的max*此系数=最终最大值) multiplier: 25.0 #限制后响应 lock-response: '{ "code": 0,"msg": "限流黑名单咯!","serviceTips": "限流黑名单咯!","sucFlag": false }' #bb-anti-reptile-data-esstat 组件需要提取分析日志来源 es: host: 127.0.0.1 port: 9200 username: password: #bb-anti-reptile-data-db 组件需要查询数据(sys_access_sum、sys_access_ip_sum) db: url: jdbc:mysql://127.0.0.1:33060/bb_admin?characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=false&useJDBCCompliantTimezoneShift=true&useLegacyDatetimeCode=false&serverTimezone=GMT%2B8&allowMultiQueries=true&allowPublicKeyRetrieval=true driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 #bb-anti-reptile-data-db 同步数据用,db-》redis sync: #启动同步一次限流规则(建议不要启动-测试阶段可以) sync-on-start: false #每天同步时间(2点) sync-time: 2 #统一的响应策略参数(ip-plus-rule/user-rule 特殊的响应策略,时间单位:s,1=限流,2=验证码限流,3=黑名单限流) rule-result-params: - lock-type: 1 lock-expire: 30 lock-response: '{"code":0,"msg":"限流!","serviceTips":"限流","sucFlag":false}' - lock-type: 2 lock-expire: 600 lock-response: '{ "code": 0,"msg": "限流验证码!","serviceTips": "限流验证码!","sucFlag": false }' - lock-type: 3 lock-expire: 86400 lock-response: '{ "code": 0,"msg": "限流黑名单咯!","serviceTips": "限流黑名单咯!","sucFlag": false }' ``` #### 4. bb-anti-reptile-data-db 需要连接db,请初始化 doc/bb-anti-reptile-plugin.sql 脚本至配置数据库 - db配置中的 rate_ip_limit_type、rate_user_limit_type、rate_plate_limit_type 比此规则中的lock-type优先级高 #### 5. 自行分析你的访问日志,提取:用户最大访问qps、平均qps,ip最大qps(非登录qps/ip/用户),ip平均qps(非登录qps/ip/用户),以及ip的用户数量,写入db以供 user-rule和ip-plus-rule使用 #### 6. 或者直接使用启用组件:bb-anti-reptile-data-esstat,集成Plumelog-me日志分析并写入db(每天启动时:sync.sync-time-1 启动),配置以及使用条件: 1. 配置: ```xml com.bblocks.common bb-anti-reptile-data-esstat 1.0.1-SNAPSHOT ``` ```properties #限流/反爬配置 日志分析 anti: reptile: esstat: #es分组,分隔字符串 spitter-str: "&&&" ##分析数据超过7天,才最后产生限流规则(7天内只分析数据),默认:0(不启动) stat-limit-day: 2 ``` 2. 使用条件(具体查询dsl见:bb-anti-reptile-plugin\bb-anti-reptile-data-esstat\src\main\resources\static\),目前为了查询接口上的用户信息查询都是走的应用服务器日志,未查询网关日志 - 含字段:USER_ID(以分析用户行为) - 含字段:FROM(以区分服务内部调用-微服务用,目前分析的数据是来自网关的调用) - 含字段:IP(以分析ip行为) - 含字段:COST(以区分日志请求还是响应-目前都是分析请求) - 含字段:URL(以分析请求qps) - 具体dsl: + ip_day_users.json 分页统计ip的用户数量 + ip_nologin_access.json 分页统计url-ip(未登录)请求 + ip_nologin_access_qps.json 统计url-ip(未登录)请求,最大qps-单ip(以计算url ip平均qps) + user_access.json 分页统计url-userid请求 + user_access_qps.json 统计url-userid请求最大qps-单人(以计算url人平均qps) - Plumelog-me添加日志字段: ```java MDC.put("USER_ID","用户ID。。。(可能无)"); MDC.put("FROM","来源。。。"); MDC.put("IP","ip、、、"); MDC.put("COST","耗时。。。"); MDC.put("URL","url..."); logger.info("扩展字段"); ``` 3. 如需定制es查询dsl(原则上是肯定需要修改的),请/doc/static/下 dsl修改后 static文件夹放入项目resource下即可 #### 7. 接口使用反扒三个方案: 1. 使用配置文件,启动全局过滤 ```properties anti.reptile.global-filter-mode: true ``` 2. 使用配置文件,只开启具体接口过滤 ```properties anti.reptile.global-filter-mode: false anti.reptile.include-urls: /xxx ``` 3. 使用注解以启动 ```properties anti.reptile.global-filter-mode: false ``` ```java @AntiReptile @GetMapping("/xxx") public R hello() { return R.ok("Hello,World!"); } ``` #### 8. 验证码限流后解锁 1. 添加依赖 ```xml com.bblocks.common bb-anti-reptile-captcha 1.0.1 ``` 2. 提取验证码(当前段收到 验证码限流响应码时 调用此接口弹出验证窗口):post /antireptile/captcha/one,响应格式如下: ```json { "msg": "成功", "data": { "verKey": "fef703da-2528-4c51-882f-35af5850698a", "image": "data:image/png;base64,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" }, "code": 1 } ``` 3. 验证验证码:post /antireptile/captcha/verify?verKey=xxx&verCode=xxx,验证通过即可解除 验证码限流提示 4. 其他属性配置: ```properties #定义响应对象(可以不配置,以下的均为默认值) anti.reptile.captcha.code-name: code anti.reptile.captcha.msg-name: msg anti.reptile.captcha.data-name: data #定义成功的code值(一般0/1) anti.reptile.captcha.code-suc: 1 #验证码有效期(分钟) anti.reptile.captcha.timeout: 10 ``` 5. 其他需求参考模块:bb-anti-reptile-captcha,其他解锁如:黑名单解锁也参考:RuleActuator.reset(HttpServletRequest request, String realRequestUri, RuleResultEnum resetTypeLimit) 6. 固定配置的ip黑名单目前直接返回 黑名单限流同时不能解除 ### 缺陷/待改进 1. 基于用户的拦截,目前拦截的是token,后续提供用户token转换user_id接口,以达到直接拦截user_id(已实现2024-04-02) 2. 后续再定制验证码方案,目前只是返回了错误码,需要开发定制验证码业务(已实现2024-04-17) 3. 基于Plumelog-me日志统计分析未完成,所以需要自行统计分析写入DB,bb-anti-reptile-data-db负责读取数据源(已实现2024-04-12) 4. 限流属于同步操作,会影响并发后期考虑使用异步限流,以提高性能(火焰分析主要耗时:黑名单验证、限流(大头)) 5. 目前的starter 未实现gateway,但是还是感觉限流在gw上更合适,需要实现gw上starter 6. 支持特定策略,sys_access_sum.rate_limit_type 可以配置特定的响应策略(已实现2024-04-12) 7. 支持拦截回调,以记录用户黑名单信息,实现见:NoticeServiceImplDefault(已实现2024-04-16) ### 特技 1. 集成Plumelog-me,可以做到开箱使用,无需配置限流参数值,集成其他平台可以参考实现。 2. 基于统计分析,可以知道每个用户对每个接口的使用需求,按照此系数自动设定每个用户的qps,支持冗余(1、n秒 * qps以平滑,2、qps支持一定的放大系数 3、支持验证码限流,在超过值后允许用户解开验证码再次使用) 3. 基于统计分析,可以统计ip用户数量,以及以及带来的非登录访问qps,以此计算出一个用户会有多少非登录qps,最终得出每个ip限流量,支持冗余(1、n秒 * qps以平滑,2、qps支持一定的放大系数 3、支持验证码限流,再超过值后允许用户解开验证码再次使用) 4. 简单做了性能测试qps能达到:6000(组件添加前:28000)-10线程无业务(amd R5 24G内存),具体测试文件见doc/limit_after.png ### 参与贡献 1. 参考了kk-anti-reptile