NodeJS后端,用express实现的Web服务器,通过记录访问频率和行为模式,识别潜在的恶意活动,从而实现Web服务器防扫描功能。
代码:
const express = require('express');
const app = express();
// 用于存储IP地址及其请求历史
const ipHistory = {};
// 防目录扫描中间件
function preventDirectoryScanning(req, res, next) {
const ip = req.ip || req.connection.remoteAddress;
// 初始化该IP的历史记录
if (!ipHistory[ip]) {
ipHistory[ip] = {
requests: [],
lastRequestTime: Date.now(),
blockedUntil: 0,
};
}
const history = ipHistory[ip];
// 如果当前时间还在封禁时间内,则直接返回403
if (Date.now() < history.blockedUntil) {
console.log(`Blocked request from ${ip}: ${req.url}`);
return res.status(403).send('Forbidden');
}
// 清除过期的请求记录
history.requests = history.requests.filter(request => Date.now() - request.time < 60 * 1000); // 保留最近一分钟内的请求
// 添加新的请求记录
history.requests.push({
time: Date.now(),
url: req.url,
});
// 检查是否有大量对不存在资源的请求
const recentRequestsCount = history.requests.length;
const uniqueUrls = new Set(history.requests.map(r => r.url));
const uniqueUrlCount = uniqueUrls.size;
// 如果在短时间内有大量不同的URL请求,则可能是扫描行为
if (recentRequestsCount > 20 && uniqueUrlCount / recentRequestsCount > 0.8) {
// 封禁该IP一段时间
history.blockedUntil = Date.now() + 5 * 60 * 1000; // 5分钟
console.log(`Detected suspicious scanning activity from ${ip}. Blocking for 5 minutes.`);
return res.status(403).send('Forbidden');
}
next(); // 继续处理请求
}
// 使用中间件
app.use(preventDirectoryScanning);
// 定义路由
app.get('/', (req, res) => {
res.send('Hello World!');
});
// 启动Web服务器
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on http://localhost:${PORT}`);
});
代码说明:
ipHistory用于存储每个IP地址的请求历史。
中间件preventDirectoryScanning会检查来自特定IP的所有请求,并记录它们。
如果某个IP在短时间内尝试访问多个不同的URL(这里定义为超过20个不同URL),并且这些URL大多是不存在的资源(假设大部分请求都是404错误),那么这个IP将被暂时封禁5分钟。
这样就实现了Web服务器防扫描功能。