问题背景Web 上,凡是有价值的接口页面、接口,在利益的驱动下,总有被犯罪分子刷的可能;
对方少数几个 IP 还好说,直接封 IP 了事,要是人家有肉鸡,有几千几万的 PC 资源,源源不断,封 IP 即便是自动检测自动封 IP 仍然是显的乏力,被欺负心里很不爽。
解决办法其实很简单,在处理每个请求前,先检测下这个 IP 是否是恶意攻击的 IP,如果是直接返回个不知所云的页面给对方就好了。
要判断是否是恶意攻击的 IP,我们需要记录每个 IP 每一次请求的时间,如果在 xx 秒内,访问量超过 yy 值,则判定为恶意攻击的 IP。
这里要几个问题:
- 由于每个接口请求,都要记录下 IP 和 请求时间,这个记录动作必须非常快,不能卡住,否则会影响整个服务。
- 这些记录的 Log 数据量非常大,但真正对我们有效的也就是最近 xx 秒内的数据,所以要有个机制自动删除无用的记录以节省空间。
- 判断是否是恶意攻击的 IP 这个逻辑要求有比较高的效率。
采用 Redis 来解决问题- 对于每个请求,IP + timestamp 为 Key,在 Redis 里面建立一个计数器;相同 IP 相同时间每访问一次,该计数器加 1
- 给 Key 设置个有效期,如 5 分钟,5 分钟后,Redis 自动删除过期数据释放空间。
- 如我们设定,5秒内超过20次,即判定为恶意 IP。对于每个请求,通过 IP + timestamp 取最近的 5 秒所对应 Key 的计数器的值,然后累加,看是否看过限额即可;如果超过限额,则将以该 IP 为 Key,存入 Redis 中,超时设置为 5 分钟,这样就形成了最近被封的 IP 列表。每次请求,都判断当前 IP 是否在这个列表,如果在这个列表,直接封掉。
- 效率问题,Redis 保证,这个不用担心。