高安全架构 学习笔记(第 6 部分)
4.2 DDoS 攻击防护
DDoS 攻击类型:
| 攻击类型 | 攻击方式 | 防护措施 |
|---|---|---|
| 流量攻击 | 大量数据包拥塞带宽 | 流量清洗、CDN |
| 协议攻击 | 耗尽服务器连接资源 | 防火墙、负载均衡 |
| 应用层攻击 | 针对应用层漏洞 | WAF、限流、验证码 |
防护实现:
javascript
// DDoS 防护系统
class DDoSProtection {
constructor() {
this.requestCounts = new Map()
this.blockedIPs = new Set()
// 阈值配置
this.thresholds = {
requestsPerSecond: 100,
requestsPerMinute: 1000,
burstSize: 50
}
}
// 请求限流中间件
rateLimiter() {
return (req, res, next) => {
const ip = this.getClientIP(req)
// 检查是否被封锁
if (this.blockedIPs.has(ip)) {
return res.status(429).json({
error: 'Too Many Requests',
message: '您的访问频率过高,已被暂时封锁'
})
}
// 检查请求频率
const checkResult = this.checkRateLimit(ip)
if (!checkResult.allowed) {
// 封锁 IP
this.blockIP(ip, checkResult.reason)
return res.status(429).json({
error: 'Too Many Requests',
message: '请求频率超过限制',
retryAfter: checkResult.retryAfter
})
}
next()
}
}
// 检查请求频率
checkRateLimit(ip) {
const now = Date.now()
const key = this.getRequestKey(ip)
if (!this.requestCounts.has(key)) {
this.requestCounts.set(key, {
count: 1,
firstRequest: now,
lastRequest: now
})
return { allowed: true }
}
const record = this.requestCounts.get(key)
const elapsed = now - record.firstRequest
// 更新计数
record.count++
record.lastRequest = now
// 每秒请求检查
if (elapsed < 1000 && record.count > this.thresholds.requestsPerSecond) {
return {
allowed: false,
reason: '每秒请求超过限制',
retryAfter: 1000 - elapsed
}
}
// 每分钟请求检查
if (elapsed < 60000 && record.count > this.thresholds.requestsPerMinute) {
return {
allowed: false,
reason: '每分钟请求超过限制',
retryAfter: 60000 - elapsed
}
}
// 重置计数器
if (elapsed > 60000) {
this.requestCounts.set(key, {
count: 1,
firstRequest: now,
lastRequest: now
})
}
return { allowed: true }
}
// 封锁 IP
blockIP(ip, reason) {
this.blockedIPs.add(ip)
console.log(`封锁 IP: ${ip}, 原因: ${reason}`)
// 自动解封(10分钟后)
setTimeout(() => {
this.blockedIPs.delete(ip)
console.log(`解封 IP: ${ip}`)
}, 600000)
}
// 验证码验证
captchaVerification() {
return async (req, res, next) => {
const ip = this.getClientIP(req)
// 检查是否需要验证码
if (this.needsCaptcha(ip)) {
const captcha = req.body.captcha
if (!captcha || !(await this.verifyCaptcha(captcha))) {
return res.status(400).json({
error: 'Captcha Required',
message: '需要验证码验证'
})
}
}
next()
}
}
// 判断是否需要验证码
needsCaptcha(ip) {
const record = this.requestCounts.get(this.getRequestKey(ip))
if (!record) return false
// 超过阈值则需要验证码
return record.count > this.thresholds.requestsPerMinute * 0.8
}
// 验证验证码
async verifyCaptcha(captcha) {
// 实际实现:调用验证码服务
return true
}
// 辅助方法
getClientIP(req) {
return req.ip || req.connection.remoteAddress
}
getRequestKey(ip) {
return `rate:${ip}`
}
}
// 使用示例
const express = require('express')
const app = express()
const ddosProtection = new DDoSProtection()
// 应用限流中间件
app.use(ddosProtection.rateLimiter())
// 验证码验证
app.post('/api/sensitive', ddosProtection.captchaVerification(), (req, res) => {
res.json({ message: '操作成功' })
})
app.listen(3000)