注意:这篇文章上次更新于1580天前,文章内容可能已经过时。
This article was last updated1580 days ago, the content may be outdated.
起因
4 月 13 号早上八点多,我还在睡梦中,被 Telegram 的一条推送吵醒了。

很奇怪,我一个根本没人访问的 WebServer 小项目竟然会自己就宕机了😕。
上午十点睡醒了,起来看一眼日志吧。
好家伙,有人拿我 抄来 的小项目在练手?
Why It Happened
Around 8 am on April 13th, I was still fast asleep when I was woken up by a push notification on Telegram.

Strange — my little WebServer project, which nobody even visits, had crashed all by itself 😕.
I woke up again around 10 am and took a look at the logs.
Well well, someone is practicing on my copied little project?








等等…很多很多
我也看不到他这些操作是在干什么,但我知道正常在网页上点来点去是不会有这样的请求数据的。这一系列花里胡哨的操作持续了 10 多分钟我就宕机了。
为了应对这种情况,只能再加一个 IP 黑名单模块了。








And so on… a lot of these.
I couldn’t tell what he was doing with all these operations, but I knew that normal clicking around on a web page wouldn’t produce such request data. After this whole series of fancy operations went on for more than 10 minutes, my server crashed.
To deal with this, the only option was to add an IP blacklist module.
基本功能
我的想法是这样的,如果在短时间内同一个 IP 连续多次获得了 404 ,那就把它放在 IP 黑名单里封禁一段时间。
实现逻辑如下:
- IP 黑名单类中需要维护以下数据成员
- 404计数阈值(404次数超过这个阈值,将有可能屏蔽这个IP的连接)
- 已经在黑名单中的 IP 过期时间(对 IP 不进行永久封禁,超过这个时间将被移除黑名单)
- 404计数时间范围(在功能描述中提到,只对短时间内的404进行计数,这个变量规定了这个短时间是多长时间)
- 一个IP到该IP目前状态的映射(也就是说,键是 IP,值包含两部分,第一部分是目前被记录的404次数,第二部分是第一次被记录404的时间点)
- 主要维护以下公有函数
- void set_member(int cnt404,int expire ,int countTime); // 设置成员变量
- bool in_list(u_int32_t IP); // 判断当前 IP 是否在黑名单内
- void add_404(u_int32_t IP); // 增加当前 IP 的 404 计数
由于我们既需要在主线程中使用黑名单对象检查当前 IP 是否在黑名单内,也需要在子线程中使用该对象为 IP 增加 404 计数。所以采用单例模式实现 IP 黑名单类。
Basic Functionality
My idea was this: if the same IP gets 404s multiple times in a short period, put it on the IP blacklist and ban it for a while.
The implementation logic is as follows:
- The IP blacklist class needs to maintain the following data members
- 404 count threshold (if the 404 count exceeds this threshold, the IP’s connection may be blocked)
- Expiration time for IPs already on the blacklist (IPs are not permanently banned; after this time they will be removed from the blacklist)
- 404 counting time window (as mentioned in the description, only 404s within a short period are counted; this variable defines how long that short period is)
- A mapping from an IP to its current state (i.e., the key is the IP, and the value has two parts: the first is the currently recorded 404 count, the second is the time point when the first 404 was recorded)
- Maintains the following public functions
- void set_member(int cnt404,int expire ,int countTime); // 设置成员变量
- bool in_list(u_int32_t IP); // 判断当前 IP 是否在黑名单内
- void add_404(u_int32_t IP); // 增加当前 IP 的 404 计数
Since we need to use the blacklist object in the main thread to check whether the current IP is on the blacklist, and also use it in child threads to increment the 404 count for an IP, the IP blacklist class is implemented as a singleton.
1 | /* |
源文件
Source file
1 | /* |
效果测试
我在两分钟内请求了几次不存在的页面
就直接这样了

并且服务器记录下相关日志

我换了一个新的 IP 可以正常访问服务器。我设置的封禁时间是 3 个小时,应该三小时后就解封了吧。
最后还是欢迎路过的大佬指出错误。
Effect Test
Within two minutes, I made several requests to non-existent pages
And it immediately looked like this

And the server recorded the relevant logs

I switched to a new IP and could access the server normally. I set the ban time to 3 hours, so it should be unbanned after three hours.
Finally, I welcome any expert passing by to point out mistakes.


