IOCP连接中如何防止恶意连接:相同IP间隔5秒内请求达到100次
下面是示例代码片段,只展示核心思路。(例如每次接收完一个请求或统计一次「请求事件」时调用)。 1. 统计与屏蔽逻辑(成员变量示例)
- #include <unordered_map>
- #include <string>
- #include <vector>
- struct IpRequestStat
- {
- int count = 0;
- DWORD windowStart = 0; // 窗口起始时间(GetTickCount)
- bool blocked = false; // 已经被判定为恶意
- };
- class IocpServer
- {
- // ...
- std::unordered_map<std::string, IpRequestStat> m_ipStats;
- std::vector<std::string> m_blockedIpLog; // 记录触发的 IP
- DWORD m_requestWindowMs = 5000; // 5 秒窗口
- int m_requestLimit = 100; // 100 次
- CRITICAL_SECTION m_ipStatLock; // 如需线程安全
- // ...
- public:
- // 在构造函数中初始化临界区,析构时删除
- // InitializeCriticalSection(&m_ipStatLock);
- // DeleteCriticalSection(&m_ipStatLock);
- bool OnRequestFromIp(const std::string& ip);
- const std::vector<std::string>& GetBlockedIpLog() const { return m_blockedIpLog; }
- };
复制代码
2. 每次请求时调用的函数:超过阈值则记入列表并拒绝
- bool IocpServer::OnRequestFromIp(const std::string& ip)
- {
- DWORD now = ::GetTickCount();
- EnterCriticalSection(&m_ipStatLock);
- IpRequestStat& st = m_ipStats[ip];
- if (st.windowStart == 0) {
- st.windowStart = now;
- st.count = 1;
- st.blocked = false;
- } else {
- // 窗口是否过期:超过 5 秒就重置
- DWORD elapsed = now - st.windowStart;
- if (elapsed > m_requestWindowMs) {
- st.windowStart = now;
- st.count = 1;
- st.blocked = false;
- } else {
- ++st.count;
- }
- }
- // 已经标记过的 IP,直接忽略连接
- if (st.blocked) {
- LeaveCriticalSection(&m_ipStatLock);
- return false; // 表示此 IP 连接要被忽略/断开
- }
- // 在 5 秒窗口内请求次数超过 100:记录并屏蔽
- if (st.count >= m_requestLimit) {
- st.blocked = true;
- m_blockedIpLog.push_back(ip);
- LeaveCriticalSection(&m_ipStatLock);
- return false; // 超限:忽略这个 IP 的本次及后续连接
- }
- LeaveCriticalSection(&m_ipStatLock);
- return true; // 允许继续处理该请求
- }
复制代码 3. 使用示例(伪代码)处理新连接或新请求的地方,取得对端 IP(例如 "192.168.1.100"),调用: - // 假设 ipStr 是当前连接的字符串形式 IP 地址
- if (!OnRequestFromIp(ipStr)) {
- // 超限:记录后忽略此 IP 的连接
- // 可以在这里直接关闭 socket
- // closesocket(clientSocket);
- return; // 不再继续处理
- }
复制代码这样就满足: - 同一 IP 在 5 秒内请求次数达到 100 次时:
- 立即把这个 IP 加入 m_blockedIpLog(std::vector<std::string>std::string)。
- OnRequestFromIp 返回 false,调用处可以关闭/忽略连接。
- 线程安全通过 CRITICAL_SECTION 简单保护;如果你已有其它同步方式,可以去掉或替换。
|