├── .gitignore ├── ISSUE_TEMPLATE.zh-CN.md ├── LICENSE ├── PULL_REQUEST_TEMPLATE.zh-CN.md ├── README.md ├── falcon ├── History.md ├── LICENSE ├── Readme.md ├── ddos │ ├── agent.js │ ├── controller.js │ └── listener.js ├── index.js ├── lib │ ├── config.js │ ├── env.js │ └── logger.js ├── nmap │ ├── nmap-engine.js │ ├── nmap-manager.js │ └── nmap.js ├── package.json ├── public │ ├── css │ │ ├── bootstrap.min.css │ │ ├── font-awesome.min.css │ │ ├── metisMenu.min.css │ │ ├── sb-admin-2.css │ │ ├── site.css │ │ └── zui.min.css │ ├── fonts │ │ ├── fontawesome-webfont.woff2 │ │ ├── glyphicons-halflings-regular.eot │ │ ├── glyphicons-halflings-regular.svg │ │ ├── glyphicons-halflings-regular.ttf │ │ ├── glyphicons-halflings-regular.woff │ │ ├── glyphicons-halflings-regular.woff2 │ │ └── zenicon.woff │ ├── image │ │ ├── 1.jpg │ │ ├── 3.jpg │ │ ├── background.png │ │ ├── cornor.png │ │ ├── ddos.jpg │ │ ├── nmap.jpg │ │ └── ssl.png │ └── js │ │ ├── bootstrap.min.js │ │ ├── flot │ │ ├── excanvas.min.js │ │ ├── jquery.flot.js │ │ ├── jquery.flot.pie.js │ │ ├── jquery.flot.resize.js │ │ ├── jquery.flot.symbol.js │ │ └── jquery.flot.time.js │ │ ├── jquery.min.js │ │ ├── login.js │ │ ├── metisMenu.min.js │ │ ├── sb-admin-2.js │ │ └── zui.min.js ├── routes │ ├── common.js │ ├── ddos.js │ ├── error.js │ ├── index.js │ ├── login.js │ ├── logout.js │ ├── nmap.js │ └── ssl.js ├── ssl │ ├── cert.js │ ├── certdata.txt │ ├── parse.js │ ├── trust_ca.txt │ └── trust_ca_dump.js ├── system │ ├── falcon.conf │ ├── falcon.init │ ├── falcon.pam │ ├── falcon.service │ └── genkey.sh ├── test │ ├── ddos │ │ ├── agent.js │ │ ├── controller.js │ │ └── listener.js │ ├── nmap │ │ ├── db.json │ │ ├── manager.js │ │ └── scan.js │ └── ssl.js └── views │ ├── ddos.ejs │ ├── ddos_js.ejs │ ├── error.ejs │ ├── foot.ejs │ ├── head.ejs │ ├── index.ejs │ ├── loading.ejs │ ├── login.ejs │ ├── nav.ejs │ ├── nmap_exec.ejs │ ├── nmap_exec_js.ejs │ ├── nmap_history.ejs │ ├── nmap_history_js.ejs │ ├── nmap_setup.ejs │ ├── ssl-path.ejs │ ├── ssl_cert_class_js.ejs │ ├── ssl_exec.ejs │ └── ssl_exec_js.ejs ├── screen-shot-1.png ├── screen-shot-2.png ├── screen-shot-3.png ├── screen-shot-4.png └── tfn2k ├── Makefile ├── README ├── aes.c ├── aes.h ├── agreed ├── base64.c ├── cast.c ├── config.h ├── disc.c ├── flood.c ├── ip.c ├── ip.h ├── mkpass.c ├── process.c ├── td.c ├── tfn.c ├── tribe.c └── tribe.h /.gitignore: -------------------------------------------------------------------------------- 1 | falcon/.tags 2 | falcon/node_modules 3 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.zh-CN.md: -------------------------------------------------------------------------------- 1 | ## 该问题是怎么引起的? 2 | 3 | 4 | 5 | ## 重现步骤 6 | 7 | 8 | 9 | ## 报错信息 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /PULL_REQUEST_TEMPLATE.zh-CN.md: -------------------------------------------------------------------------------- 1 | ## 该Pull Request关联的Issue 2 | 3 | 4 | ## 修改描述 5 | 6 | 7 | 8 | ## 测试用例 9 | 10 | 11 | 12 | ## 修复效果的截屏 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 关于猎鹰网络安全工具 2 | 以下情形,猎鹰可能适合您: 3 | 4 | * 您需要知道某台主机到底开放了哪些端口,是否有后门 5 | * 您需要知道对某些设备在疯狂的网络DOS攻击到底有何表现 6 | * 您想要学习以下nodejs的开发,需要一些例子 7 | * 您想了解以下测试驱动,需要一些例子 8 | * 您也不知道要什么,随便看看 9 | 10 | 11 | ## 功能特点 12 | ### DOS攻击测试 13 | * 支持icmp/tcp/udp DOS攻击 14 | * 支持多傀儡主机并发攻击 15 | * 实时DOS攻击流量统计 16 | * DOS攻击状态可视化 17 | ### 端口扫描 18 | * 全面TCP端口扫描 (速度待完善) 19 | * 智能判断端口合法性 (待完善) 20 | * 判断规则自行定义 (待完善) 21 | * 支持扫描历史查询 22 | 23 | ## 如何使用 24 | 你可以在如下系统中使用猎鹰 25 | 26 | * CentOS (7.2已测) 27 | * Ubuntu (12.04+已测) 28 | * MacOS (Sierra已测) 29 | * 树莓派 (Raspberry PI 3 model B部分测试) 30 | * 其它(若可用,可告诉我) 31 | 32 | 具体安装使用见 [帮助文档](/falcon/Readme.md) ,您可以与我邮件联系,也可以加入QQ群 156704037 实时讨论。 33 | 34 | ## 界面截图 35 |  36 | 37 |  38 | 39 |  40 | 41 |  42 | -------------------------------------------------------------------------------- /falcon/History.md: -------------------------------------------------------------------------------- 1 | 1.4.0 / 2019-10-12 2 | ================== 3 | * 增强端口扫描功能,支持指定端口范围精准扫描,提高扫描灵活性 4 | 5 | 1.2.0 / 2017-04-28 6 | ================== 7 | * 增加SSL证书安全性检测功能,包含 8 | * 证书颁发来源检测 9 | * 证书颁发时间有效性检测 10 | * 证书主体身份吻合性检测 11 | * 证书加密强度符合性检测 12 | 13 | 1.1.0 / 2017-03-28 14 | ================== 15 | * 支持https,由配置文件falcon.conf定义,使用详见帮助文件 16 | 17 | 1.0.1 / 2017-03-11 18 | ================== 19 | * 增加dns不可用时的容错处理以及相关处理 20 | * 增加对所有端口扫描的支持(只在Linux平台下可用) 21 | * 修正对于nmap xml结果文件解析非标准端口service节点不存在导致扫描结果端口不完整的问题 22 | 23 | 1.0.0 / 2017-02-17 24 | ================== 25 | * 支持DOS测试功能,支持多台傀儡主机控制,支持实时流量统计,支持二维流量曲线 26 | * 支持端口扫描功能,当前支持1000个常用端口扫描,支持扫描历史记录检索 27 | * 支持Ubuntu 12.04平台 28 | * 支持MacOS Sierra平台 29 | * 支持CentOS 7.2平台 30 | 31 | 0.9.0 / 2017-01 32 | ================== 33 | * 初始版本,可基本工作 34 | -------------------------------------------------------------------------------- /falcon/Readme.md: -------------------------------------------------------------------------------- 1 | 使用须知 2 | ======= 3 | * 强烈建议用户以非root用户运行猎鹰程序,符合系统安全规定 4 | * 本帮助假定以运行猎鹰的用户账号为admin,先在系统中创建账号 5 | 6 | ```sh 7 | useradd -d /home/admin -m -c "security user" admin #CentOS下创建用户 8 | passwd admin #设置密码admin 9 | ``` 10 | 11 | * 猎鹰支持CentOS、Ubuntu、MacOS、树莓派 12 | 13 | 安装 14 | ==================== 15 | 请按顺序执行以下步骤(以centos 7.2为例) 16 | 1. 以admin账号,获取源码包 17 | 18 | ```sh 19 | cd /home/admin 20 | git clone https://git.oschina.net/cxueqin/falcon.git 21 | ``` 22 | 23 | 24 | 2. 编译ddos工具,并安装 25 | 26 | ```sh 27 | cd /home/admin/falcon 28 | cd tfn2k 29 | make #中间若有输入密码,则输入8个字母或数字,回车即可 30 | sudo cp td tfn /usr/local/sbin 31 | ``` 32 | 33 | 34 | 3. 安装nodejs、nmap工具,推荐使用nodejs 6.9或更高版本 35 | 36 | ```sh 37 | sudo yum install nodejs npm nmap 38 | ``` 39 | 40 | 41 | 4. 安装依赖库 42 | 43 | ```sh 44 | sudo yum install pam-devel gcc-c++ #若遗漏此步,安装authenticate-pam时会报头文件缺少错误 45 | ``` 46 | 47 | 5. 安装猎鹰主程序包 48 | 49 | ```sh 50 | cd /home/admin/falcon 51 | cd falcon #注意本项目下还有一个falcon目录 52 | npm install 53 | ``` 54 | 55 | 其它平台注意 56 | =========== 57 | 1. 对于Ubuntu 12.04而言,默认系统是gcc-4.7,需要升级到gcc-4.8以及g++-4.8环境, 否者nodejs环境使用了c++11的特性,会出现编译错误. 升级方法见 58 | http://askubuntu.com/questions/271388/how-to-install-gcc-4-8 59 | 60 | 2. 对于Ubuntu环境,需要安装pam开发包,否则npm install编译authenticate-pam时会出现错误,安装命令 61 | 62 | ```sh 63 | sudo apt-get install libpam0g-dev 64 | ``` 65 | 66 | 67 | 3. 对于CentOS 6平台,需要注意安装nodejs 6.9更高版本,需要将gcc编译器升级至支持c++11的版本,升级方法可参考此文 68 | http://hiltmon.com/blog/2015/08/09/c-plus-plus-11-on-centos-6-dot-6/ 69 | 升级之后,需要确保启用高版本gcc,再用npm install安装相关的模块,否则会报告如下编译错误 70 | 71 | ``` 72 | npm ERR! authenticate-pam@1.0.2 install: `node-gyp build` 73 | npm ERR! Exit status 1 74 | ``` 75 | 76 | 运行前准备 77 | ========= 78 | 请顺序执行以下步骤,使得猎鹰运行环境就绪 79 | 1. 先启动dos守护程序 80 | 81 | ```sh 82 | sudo /usr/local/sbin/td & 83 | ``` 84 | 85 | 86 | 2. 安装配置文件 87 | 88 | ```sh 89 | cd /home/admin/falcon 90 | cd falcon 91 | sudo cp system/falcon.conf /etc/falcon.conf #猎鹰遵守*Nix配置标准 92 | ``` 93 | 94 | 95 | 3. 执行测试,看核心模块是否工作正常(记住:测试驱动的思想) 96 | 97 | ```sh 98 | cd /home/admin/falcon 99 | cd falcon 100 | npm test #大部分测试应该是通过的 101 | ``` 102 | 103 | 104 | 4. 创建猎鹰数据目录 105 | 106 | ```sh 107 | sudo mkdir -p /var/lib/falcon/nmap 108 | sudo chown -R admin:admin /var/lib/falcon #设置目录权限为admin可读写 109 | ``` 110 | 111 | 运行 112 | ====== 113 | 测试通过之后,我们就可在admin用户下把主程序运行起来了 114 | 115 | ```sh 116 | cd /home/admin/falcon 117 | cd falcon 118 | node index.js 119 | ``` 120 | 121 | 然后打开浏览器,访问 http://localhost:8000 就出现登陆页,输入你操作系统中存在的真实用户账号与密码,即可进入. 现在,开始你的网络安全之旅吧:) 122 | 123 | 启用https 124 | ========== 125 | 猎鹰的WEB控制台默认使用http,若要开启https模式,请按照如下步骤 126 | 127 | 1. 利用openssl工具制作服务器私钥和证书,system目录中有一个genkey.sh脚本可生成自签名证书,当然您也可自行生成 128 | 129 | ```sh 130 | cd system 131 | ./genkey.sh output localhost 12345678 # output为证书文件生成目录,localhost为证书主机,12345678为CA私钥密码 132 | 133 | #运行之后会在生成output目录,里面有cert目录,其中有ca,client,server,tmp目录,服务器证书就在server目录 134 | ``` 135 | 136 | 137 | 2. 将上步生成的服务器证书拷贝到/etc目录 138 | 139 | ```sh 140 | sudo cp output/cert/server/server.key /etc/falcon.keys 141 | sudo cp output/cert/server/server.crt /etc/falcon.crt 142 | ``` 143 | 144 | 145 | 3. 编辑配置文件,启用https 146 | 147 | ```sh 148 | sudo vim /etc/falcon.conf 149 | [daemon] 150 | port_ssl = 8001 151 | key = /etc/falcon.key 152 | cert = /etc/falcon.crt 153 | # https端口将侦听在8001端口,也可更改为其它端口 154 | ``` 155 | 156 | 157 | 4. 启动主程序 158 | 159 | ```sh 160 | node index.js 161 | ``` 162 | 帮助 163 | ======= 164 | 在码云上提交问题或者邮件给我 7219530@qq.com 165 | 166 | -------------------------------------------------------------------------------- /falcon/ddos/agent.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * DOS测试代理类 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | var exec = require('child_process').exec; 9 | var sprintf = require('sprintf-js').sprintf; 10 | var TFN_PATH = '/usr/local/sbin/tfn'; 11 | var logger = require('../lib/logger'); 12 | var EventEmitter = require('events').EventEmitter; 13 | FloodAgent = function(ip) { 14 | this.type = ""; 15 | this.host = ip; 16 | this.state = 'idle'; 17 | 18 | //ddos attack option 19 | this.option = {}; 20 | this.emitter = new EventEmitter(); 21 | this.stat = { packetSent: 0, byteSent: 0} ; 22 | } 23 | 24 | FloodAgent.prototype = { 25 | constructor: FloodAgent, 26 | 27 | start: function (target, option) { 28 | if (!target) { 29 | throw new Error('target should be specificed'); 30 | } 31 | 32 | if (this.state != 'idle') { 33 | throw new Error(sprintf('invalid %s state', this.state)); 34 | } 35 | this.target = target; 36 | this.state = 'starting'; 37 | this._start(option); 38 | }, 39 | 40 | stop: function () { 41 | this._stop(); 42 | }, 43 | 44 | onStart: function (listener) { 45 | this.emitter.on('started', listener); 46 | }, 47 | 48 | onStop: function (listener) { 49 | this.emitter.on('stopped', listener); 50 | }, 51 | 52 | processTraffic: function (data) { 53 | if (!data ) { 54 | throw new TypeError('should have data param with packet and byte property'); 55 | } 56 | //TODO packet and type should be number 57 | this.stat.packetSent += data.packet; 58 | this.stat.byteSent += data.byte; 59 | }, 60 | 61 | getTraffic: function () { 62 | return this.stat; 63 | }, 64 | 65 | resetTraffic: function () { 66 | this.stat.packetSent = 0; 67 | this.stat.byteSent = 0; 68 | }, 69 | 70 | _start: function (option) { 71 | var cmd; 72 | switch (option.type) { 73 | case 'udp': 74 | cmd = sprintf("%s -h %s -i %s -c 4", TFN_PATH, this.host, this.target ); 75 | break; 76 | case 'tcp': 77 | cmd = sprintf("%s -h %s -i %s -c 5 -p %s", TFN_PATH, this.host, this.target, option.port ); 78 | break; 79 | default: 80 | cmd = sprintf("%s -h %s -i %s -c 6 ", TFN_PATH, this.host, this.target, option.port ); 81 | } 82 | var child = exec(cmd); 83 | logger.debug('tfn command %s', cmd); 84 | this.resetTraffic(); 85 | var thiz = this; 86 | this.option = option; 87 | child.stdout.on('data', function (data) { 88 | logger.debug('tfn output:' + data); 89 | }); 90 | child.on('exit', function (code) { 91 | if (code == 0) { 92 | thiz.state = 'started'; 93 | logger.debug('%s ddos from %s to %s started', option.type, thiz.host, thiz.target); 94 | thiz.emitter.emit('started'); 95 | } else { 96 | logger.err('ddos started fail %d ', code) 97 | } 98 | }); 99 | }, 100 | 101 | _stop: function () { 102 | if (this.state != 'started') { 103 | logger.info('stop fail cause wrong state %s ', this.state); 104 | return; 105 | } 106 | var cmd = sprintf("%s -h %s -c 0", TFN_PATH, this.host); 107 | var last = exec(cmd); 108 | var thiz = this; 109 | last.stdout.on('data', function (data) { 110 | logger.debug('tfn command output:' + data); 111 | }); 112 | last.on('exit', function (code) { 113 | if (code == 0) { 114 | thiz.state = 'idle'; 115 | logger.info('ddos from %s to %s already stopped', thiz.host, thiz.option.target); 116 | thiz.emitter.emit('stopped'); 117 | } else { 118 | logger.err('ddos stop fail %d ', code) 119 | } 120 | }); 121 | } 122 | } 123 | 124 | module.exports = FloodAgent; 125 | -------------------------------------------------------------------------------- /falcon/ddos/controller.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * DOS测试控制类 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | var exec = require('child_process').exec; 9 | var sprintf = require('sprintf-js').sprintf; 10 | var logger = require('../lib/logger'); 11 | var _ = require('lodash'); 12 | 13 | FloodController = function() { 14 | this.type = ''; 15 | this.state = 'idle'; 16 | this.target = ''; 17 | } 18 | 19 | FloodController.prototype = { 20 | constructor: FloodController, 21 | init: function () { 22 | this.agents = new Array(); 23 | }, 24 | 25 | getState: function () { 26 | return { 27 | state: this.state, 28 | type: this.type 29 | }; 30 | }, 31 | 32 | addAgent: function (agent) { 33 | this.agents.push(agent); 34 | }, 35 | 36 | getAgents: function () { 37 | return _.clone(this.agents); 38 | }, 39 | 40 | removeAgent: function (agent) { 41 | var removedAgent = _.remove(this.agents, function (item){ 42 | return agent.host == item.host; 43 | }); 44 | if (removedAgent.length == 1) { 45 | return 0; 46 | } else { 47 | return -1; 48 | } 49 | }, 50 | 51 | findAgent: function (selector) { 52 | return _.find(this.agents, selector); 53 | }, 54 | 55 | startFlood: function (target, option) { 56 | if (this.state != 'idle') { 57 | throw new Error(`invalid state ${this.state}`); 58 | } 59 | _.forEach(this.agents, function (agent) { 60 | agent.start(target, option); 61 | }); 62 | this.state = 'started'; 63 | }, 64 | 65 | stopFlood: function () { 66 | if (this.state != 'started') { 67 | throw new Error(`invalid state ${this.state}`); 68 | } 69 | 70 | _.forEach(this.agents, function (agent) { 71 | agent.stop(); 72 | }); 73 | this.state = 'idle'; 74 | }, 75 | 76 | getTrafficStat: function () { 77 | var packetSent = 0; 78 | var byteSent = 0; 79 | 80 | _.forEach(this.agents, function (agent){ 81 | var stat = agent.getTraffic(); 82 | 83 | packetSent += stat.packetSent; 84 | byteSent += stat.byteSent; 85 | logger.debug("agent %s packetSent %d byteSent %d", agent.host, 86 | stat.packetSent, stat.byteSent); 87 | }); 88 | logger.debug("packetSent = %d byteSent = %d", packetSent, byteSent); 89 | return { 90 | packetSent: packetSent, 91 | byteSent: byteSent 92 | }; 93 | }, 94 | } 95 | 96 | module.exports = new FloodController(); 97 | -------------------------------------------------------------------------------- /falcon/ddos/listener.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * DOS测试事件监听类 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | var exec = require('child_process').exec; 9 | var sprintf = require('sprintf-js').sprintf; 10 | var logger = require('../lib/logger'); 11 | var dgram = require('dgram'); 12 | var qs = require('querystring'); 13 | 14 | FloodListener = function(port, controller) { 15 | if ( !port ) { 16 | throw new Error('missing port or controller parameter'); 17 | } 18 | this.port = port; 19 | this.controller = controller; 20 | this.stat = { packetSent: 0, byteSent: 0}; 21 | } 22 | 23 | FloodListener.prototype = { 24 | constructor: FloodListener, 25 | 26 | start: function () { 27 | var controller = this.controller; 28 | if (this.socket) { 29 | return; 30 | } 31 | var thiz = this; 32 | this.socket = dgram.createSocket('udp4'); 33 | this.socket.bind(this.port, function () { 34 | logger.debug(`bind port ${thiz.port} success`); 35 | }); 36 | 37 | this.socket.on('message', function(msg, rinfo) { 38 | logger.debug(`got: ${msg} from ${rinfo.address}:${rinfo.port}`); 39 | var str = msg.toString('utf8', 0, msg.length); 40 | if (!/^packets=\d+&bytes=\d+$/.test(str)) { 41 | logger.warn('invalid incoming data (%s)', str); 42 | return; 43 | } 44 | 45 | var trafficData = qs.parse(str); 46 | var nPacket = parseInt(trafficData.packets); 47 | var nByte = parseInt(trafficData.bytes); 48 | thiz.stat.packetSent += nPacket; 49 | thiz.stat.byteSent += nByte; 50 | if (!controller) { 51 | logger.warn('no controller to handle '); 52 | return; 53 | } 54 | var agent = controller.findAgent({host: rinfo.address}); 55 | if (!agent ) { 56 | logger.warn('unknown udp packet from %s', rinfo.address); 57 | return; 58 | } 59 | agent.processTraffic({packet:nPacket, byte:nByte}); 60 | }); 61 | 62 | }, 63 | 64 | stop: function () { 65 | if (!this.socket) { 66 | return; 67 | } 68 | var thiz = this; 69 | this.socket.close(()=> { 70 | thiz.socket = null; 71 | }); 72 | }, 73 | 74 | getState: function () { 75 | if (!this.socket) { 76 | return 'idle'; 77 | } else { 78 | return 'started'; 79 | } 80 | }, 81 | 82 | getTraffic: function () { 83 | return this.stat; 84 | } 85 | } 86 | 87 | module.exports = FloodListener; 88 | -------------------------------------------------------------------------------- /falcon/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * 猎鹰网络安全评估系统主程序 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | 9 | var express = require('express'); 10 | var bodyParser = require('body-parser'); 11 | var session = require('express-session'); 12 | var paginate = require('express-paginate'); 13 | 14 | var logger = require('./lib/logger'); 15 | var ConfigManager = require('./lib/config'); 16 | var env = require('./lib/env'); 17 | // 检查运行环境是否满足要求 18 | env.validate(); 19 | 20 | var app = module.exports = express(); 21 | 22 | const PAGE_LIMIT = 10; 23 | const PAGE_MAX_LIMIT = 50; 24 | app.use(paginate.middleware(PAGE_LIMIT, PAGE_MAX_LIMIT)); 25 | 26 | // config static resource 27 | app.use(express.static(__dirname+'/public')); 28 | 29 | app.set('view engine', 'ejs'); 30 | app.set('views', __dirname + '/views'); 31 | 32 | // middleware 33 | app.use(bodyParser.json()); 34 | app.use(bodyParser.urlencoded({ extended: false })); 35 | // follow http://expressjs.com/en/advanced/best-practice-security.html 36 | app.disable('x-powered-by'); 37 | app.use(session({ 38 | resave: false, // don't save session if unmodified 39 | saveUninitialized: false, // don't create session until something stored 40 | secret: 'shhhh, very secret', 41 | name: 'fsid' 42 | })); 43 | 44 | // Session-persisted message middleware 45 | 46 | app.use(function(req, res, next){ 47 | var sess = req.session; 48 | /* session test,just counter */ 49 | if (sess.views) { 50 | sess.views++; 51 | }else { 52 | sess.views = 1; 53 | } 54 | next(); 55 | }); 56 | 57 | 58 | var index = require('./routes/index'); 59 | var login = require('./routes/login'); 60 | var logout = require('./routes/logout'); 61 | var nmap = require('./routes/nmap'); 62 | var ddos = require('./routes/ddos'); 63 | var ssl = require('./routes/ssl'); 64 | var error = require('./routes/error'); 65 | 66 | app.use(index); 67 | app.use(login); 68 | app.use(logout); 69 | app.use(nmap); 70 | app.use(ddos); 71 | app.use(ssl); 72 | app.use(error); 73 | 74 | /* istanbul ignore next */ 75 | if (!module.parent) { 76 | var port = ConfigManager.getPort(); 77 | app.listen(port); 78 | logger.info('Falcon service started on http port %s', port); 79 | 80 | try { 81 | var options = ConfigManager.getSSL(); 82 | var https = require('https'); 83 | 84 | https.createServer(options, app).listen(options.port, () => { 85 | logger.info('Falcon service started on https port %s', options.port); 86 | }); 87 | 88 | } catch (e) { 89 | logger.debug('Falcon https disabled (%s)', e.message); 90 | } finally { 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /falcon/lib/config.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * 系统配置辅助类 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | 'use strict'; 9 | 10 | var CONFIG_FILE = '/etc/falcon.conf'; 11 | var IniConfigParser = require('ini-config-parser'); 12 | var fs = require('fs'); 13 | var DEFAULT_PORT = 8000; 14 | var _ = require('lodash'); 15 | 16 | function ConfigManager(path) { 17 | //参数必须赋值,否则抛出异常 18 | if (!path || !fs.existsSync(path)) { 19 | throw new Error(`lack of falcon config file ${path}`) 20 | } 21 | 22 | var data = fs.readFileSync(path).toString(); 23 | this.config = IniConfigParser.parse(data); 24 | 25 | } 26 | 27 | // Encapsulation in JavaScript 封装,继承,多态CRUD就属于多态一种 28 | // The one disadvantage of overwriting the prototype is that 29 | // the constructor property no longer points to the prototype, 30 | // so we have to set it manually. 31 | ConfigManager.prototype = { 32 | constructor: ConfigManager, 33 | 34 | getNmapStorageDir: function () { 35 | return this.config.daemon.datadir+"/nmap"; 36 | }, 37 | 38 | getSSL: function () { 39 | var port = this.config.daemon.port_ssl; 40 | 41 | if ( !port ) { 42 | throw new Error(`missing port_ssl config`); 43 | } 44 | var portInt = parseInt(port, 10); 45 | if (isNaN(portInt)) { 46 | throw new Error(`port_ssl ${port} invalid`); 47 | } 48 | 49 | if (portInt < 1024 || portInt > 65535) { 50 | throw new Error(`port_ssl ${port} range invalid`); 51 | } 52 | 53 | var key = this.config.daemon.key; 54 | var cert = this.config.daemon.cert; 55 | if (!key || !fs.existsSync(key)) { 56 | throw new Error(`missing private key file ${key}`); 57 | } 58 | 59 | if (!cert || !fs.existsSync(cert)) { 60 | throw new Error(`missing cerificate key file ${cert}`); 61 | } 62 | 63 | return { 64 | port: port, 65 | key: fs.readFileSync(key), 66 | cert: fs.readFileSync(cert) 67 | }; 68 | }, 69 | 70 | getPort: function () { 71 | var port = this.config.daemon.port; 72 | 73 | if ( !port ) 74 | return DEFAULT_PORT; 75 | var portInt = parseInt(port, 10); 76 | if (isNaN(portInt)) 77 | return DEFAULT_PORT; 78 | if (portInt < 1024 || portInt > 65535) 79 | return DEFAULT_PORT; 80 | return portInt; 81 | }, 82 | 83 | getLoglevel: function () { 84 | var map = { 85 | emerg: 'LOG_EMERG', 86 | alert: 'LOG_ALERT', 87 | crit: 'LOG_CRIT', 88 | err: 'LOG_ERR', 89 | warning: 'LOG_WARNING', 90 | notice: 'LOG_NOTICE', 91 | info: 'LOG_INFO', 92 | debug: 'LOG_DEBUG' 93 | }; 94 | var level = this.config.daemon.loglevel; 95 | if ( !level ) 96 | return 'LOG_INFO'; 97 | if ( map[level] ) { 98 | return map[level]; 99 | } else { 100 | return 'LOG_INFO'; 101 | } 102 | }, 103 | 104 | ifLogConsole: function () { 105 | var flag = this.config.daemon.log_console; 106 | var trueArray = ["true", "yes", "1"]; 107 | 108 | if ( typeof flag === 'undefined' ) { 109 | return false; 110 | } 111 | var flagStr = new String(flag); 112 | var flagLC = flagStr.toLowerCase(); 113 | for (var i =0; i< trueArray.length; i++) { 114 | if (flagLC == trueArray[i]) { 115 | return true; 116 | } 117 | } 118 | return false; 119 | }, 120 | 121 | getDdosAgents: function () { 122 | var strAgents = this.config.ddos.agents; 123 | 124 | return _.split(strAgents, ','); 125 | } 126 | }; 127 | 128 | exports = module.exports = new ConfigManager(CONFIG_FILE); 129 | -------------------------------------------------------------------------------- /falcon/lib/env.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * 运行环境检查模块,目前限定linux和darwin平台 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | 9 | function validate() { 10 | const os = require('os'); 11 | 12 | var platform = os.platform(); 13 | 14 | if (platform != 'linux' && platform != 'darwin') { 15 | throw new Error(`sorry, no support for ${platform} platform`) 16 | } 17 | 18 | if (process.geteuid) { 19 | var euid = process.geteuid() 20 | if (euid == '0') { 21 | throw new Error(`sorry, falcon should not run under root`) 22 | } 23 | } 24 | 25 | //TODO: 检查nodejs的版本,太低则拒绝运行 26 | //TODO: 检查nmap是否可用,dos测试命令是否可用,用程序做到必要检查,让用户可自行发现问题 27 | } 28 | 29 | exports.validate = validate; 30 | -------------------------------------------------------------------------------- /falcon/lib/logger.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * 系统日志类 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | var syslog = require('modern-syslog'); 12 | var ConfigManager = require('./config'); 13 | 14 | function Logger() { 15 | var ident = "falcon"; 16 | var option = syslog.LOG_PID | syslog.LOG_ODELAY ; 17 | if (ConfigManager.ifLogConsole()) { 18 | option |= syslog.LOG_PERROR 19 | } 20 | var facility = syslog.LOG_LOCAL0; 21 | 22 | syslog.open(ident, option, facility); 23 | syslog.upto(ConfigManager.getLoglevel()); 24 | this.init(); 25 | } 26 | 27 | // Encapsulation in JavaScript 封装,继承,多态CRUD就属于多态一种 28 | // The one disadvantage of overwriting the prototype is that 29 | // the constructor property no longer points to the prototype, 30 | // so we have to set it manually. 31 | Logger.prototype = { 32 | constructor: Logger, 33 | 34 | //这样的现代写法真是绝妙 35 | wrap: function (name) { 36 | 37 | this[name] = syslog[name]; 38 | 39 | }, 40 | 41 | init: function () { 42 | this.wrap('emerg'); 43 | this.wrap('alert'); 44 | this.wrap('emerg'); 45 | this.wrap('crit'); 46 | this.wrap('err'); 47 | this.wrap('warn'); 48 | this.wrap('warning'); 49 | this.wrap('note'); 50 | this.wrap('notice'); 51 | this.wrap('info'); 52 | this.wrap('debug'); 53 | //这是直观的方法 54 | //this.emerg = syslog.emerg; 55 | //this.notice = syslog.notice; 56 | } 57 | }; 58 | 59 | exports = module.exports = new Logger(); 60 | -------------------------------------------------------------------------------- /falcon/nmap/nmap-engine.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * 网络扫描引擎类 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | /** 12 | * Expose `createApplication()`. 13 | */ 14 | 15 | exports = module.exports = createApplication; 16 | 17 | function createEngine() { 18 | var engine = {}; 19 | 20 | return engine; 21 | } 22 | -------------------------------------------------------------------------------- /falcon/nmap/nmap-manager.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * 扫描管理类 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | exports.setHome = setHome; 12 | exports.getManager = getManager; 13 | 14 | var low = require('lowdb'); 15 | var fs = require('fs'); 16 | var _ = require('lodash'); 17 | var sprintf = require('sprintf-js').sprintf; 18 | var dataHome = '.'; 19 | var manager; 20 | 21 | function setHome(path) { 22 | if (!path || !fs.existsSync(path)) { 23 | throw new TypeError(`${path} does not exist`) 24 | } 25 | dataHome = path; 26 | } 27 | 28 | function getManager() { 29 | if (manager) 30 | return manager; 31 | 32 | manager = new NmapManager(dataHome); 33 | return manager; 34 | } 35 | 36 | function NmapManager(home) { 37 | //参数必须赋值,否则抛出异常 38 | if (!home || !fs.existsSync(home)) { 39 | throw new TypeError('arg home must be real filesytem path') 40 | } 41 | 42 | this.db = low(home+'/db.json'); 43 | this.db._.mixin(require('underscore-db')) 44 | //初始化时,先要初始化数据为合法方式,否则insert插入不了 45 | //this.db.setState({'results': []}); 46 | //初始化后,就可以调用insert接口,数据将自动存储 47 | this.db.defaults( {results: []} ).write() 48 | //this.db.get('results').push({a:"aaa"}) 49 | } 50 | 51 | // Encapsulation in JavaScript 封装,继承,多态CRUD就属于多态一种 52 | // The one disadvantage of overwriting the prototype is that 53 | // the constructor property no longer points to the prototype, 54 | // so we have to set it manually. 55 | NmapManager.prototype = { 56 | constructor: NmapManager, 57 | addResult : function (scan, xml) { 58 | var item 59 | 60 | if (scan) { 61 | var row = { host: scan.range[0], time: _.now(), status: 'running'} 62 | item = this.db.get('results').insert(row).value() 63 | this.db.write() 64 | } 65 | return item; 66 | }, 67 | 68 | updateResult : function (result, data) { 69 | var item = this.db.get('results').find( {id: result.id}) 70 | 71 | var clone = item.value(); 72 | clone.data = data; 73 | clone.status = 'done'; 74 | item.assign(clone) 75 | this.db.write() 76 | return clone; 77 | }, 78 | 79 | delResult : function (rid) { 80 | //必须加value()方可触发写入,切记 81 | var item = this.db.get('results').removeById(rid).value() 82 | if (item) { 83 | this.db.write(); 84 | return 0; 85 | } else { 86 | return -1 87 | } 88 | }, 89 | 90 | getResultWithDetail : function (rid) { 91 | var result = this.db.get('results').getById(rid).value(); 92 | 93 | if (result ) 94 | this._addTimeString(result); 95 | return result; 96 | }, 97 | 98 | getResults : function () { 99 | var results = this.db.get('results').sortBy('time').reverse().value(); 100 | _.forEach(results, this._addTimeString); 101 | return results; 102 | }, 103 | 104 | _addTimeString : function(o) { 105 | var date = new Date(); 106 | 107 | if (!o.time) 108 | return o; 109 | 110 | date.setTime(o.time); 111 | o.timeString = sprintf("%d/%02d/%02d %02d:%02d", 112 | date.getFullYear(), 113 | date.getMonth()+1, 114 | date.getDate(), 115 | date.getHours(), 116 | date.getMinutes()) 117 | return o; 118 | } 119 | }; 120 | -------------------------------------------------------------------------------- /falcon/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "falcon", 3 | "description": "falcon network security toolkit", 4 | "version": "1.1.0", 5 | "author": { 6 | "name": "chen xueqin", 7 | "email": "7219530@qq.com" 8 | }, 9 | "contributors": [ 10 | { 11 | "name": "Lin Xiao", 12 | "email": "814265730@qq.com" 13 | } 14 | ], 15 | "license": "LGPL-2.1", 16 | "repository": { 17 | "type": "git", 18 | "url": "https://git.oschina.net/cxueqin/falcon.git" 19 | }, 20 | "homepage": "http://git.oschina.net/cxueqin/falcon", 21 | "keywords": [ 22 | "ddos", 23 | "nmap", 24 | "TDD", 25 | "network security" 26 | ], 27 | "dependencies": { 28 | "authenticate-pam": "1.0.2", 29 | "body-parser": "^1.17.1", 30 | "cookie-parser": "^1.4.3", 31 | "debug": "^2.6.3", 32 | "ejs": "^2.5.6", 33 | "express": "^4.15.2", 34 | "express-paginate": "^0.2.2", 35 | "express-session": "^1.15.2", 36 | "ini-config-parser": "^1.0.3", 37 | "lodash": "^4.17.4", 38 | "lowdb": "^0.15.5", 39 | "modern-syslog": "^1.1.4", 40 | "queued-up": "^2.0.2", 41 | "should": "^11.2.1", 42 | "sprintf-js": "1.0.3", 43 | "underscore-db": "0.12.2", 44 | "xml2js": "^0.4.15" 45 | }, 46 | "devDependencies": { 47 | "mocha": "^3.2.0", 48 | "morgan": "^1.7.0", 49 | "should": "~11.2.0", 50 | "sleep": "5.1.0", 51 | "chai": "3.5.0" 52 | }, 53 | "engines": { 54 | "node": ">= 0.10.0" 55 | }, 56 | "files": [ 57 | "LICENSE", 58 | "History.md", 59 | "Readme.md", 60 | "index.js", 61 | "public", 62 | "lib", 63 | "system", 64 | "views", 65 | "test", 66 | "routes", 67 | "nmap", 68 | "ddos" 69 | ], 70 | "scripts": { 71 | "test": "mocha --reporter spec --bail --check-leaks test/ddos test/nmap/ test/" 72 | }, 73 | "gitHead": "", 74 | "bugs": { 75 | "url": "http://git.oschina.net/cxueqin/falcon/issues" 76 | }, 77 | "_id": "falcon@1.0.0", 78 | "_shasum": "c1ee3f42cdc891fb3dc650a8922d51ec847d0d66", 79 | "_from": "express@latest", 80 | "_npmVersion": "3.10.8", 81 | "_npmUser": { 82 | "name": "chen xueqin", 83 | "email": "chenxq@star-net.cn" 84 | }, 85 | "maintainers": [ 86 | { 87 | "name": "chen xueqin", 88 | "email": "7210530@qq.com" 89 | } 90 | ] 91 | } 92 | -------------------------------------------------------------------------------- /falcon/public/css/metisMenu.min.css: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v1.1.3 3 | * Easy menu jQuery plugin for Twitter Bootstrap 3 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumus 7 | * Under MIT License 8 | */ 9 | 10 | .arrow{float:right;line-height:1.42857}.glyphicon.arrow:before{content:"\e079"}.active>a>.glyphicon.arrow:before{content:"\e114"}.fa.arrow:before{content:"\f104"}.active>a>.fa.arrow:before{content:"\f107"}.plus-times{float:right}.fa.plus-times:before{content:"\f067"}.active>a>.fa.plus-times{filter:progid:DXImageTransform.Microsoft.BasicImage(rotation=1);-webkit-transform:rotate(45deg);-moz-transform:rotate(45deg);-ms-transform:rotate(45deg);-o-transform:rotate(45deg);transform:rotate(45deg)}.plus-minus{float:right}.fa.plus-minus:before{content:"\f067"}.active>a>.fa.plus-minus:before{content:"\f068"} -------------------------------------------------------------------------------- /falcon/public/css/site.css: -------------------------------------------------------------------------------- 1 | 2 | .row11 3 | { 4 | 5 | min-height: 100%; /* Fallback for browsers do NOT support vh unit */ 6 | min-height: 100vh; /* These two lines are counted as one :-) */ 7 | 8 | display: flex; 9 | align-items: center; 10 | 11 | } 12 | 13 | .navbar-cornor { 14 | float: left; 15 | padding: 7.5px 7.5px; 16 | } 17 | 18 | .pagination { 19 | margin-top: 0px; 20 | margin-right: 0px; 21 | margin-bottom: 0px; 22 | margin-left: 0px; 23 | } 24 | 25 | .col-lg-6 .panel .panel-body .col-sm-4 { 26 | padding-right: 3px; 27 | padding-left: 3px; 28 | } 29 | 30 | .col-lg-6 .panel .panel-body .col-sm-6 { 31 | padding-right: 3px; 32 | padding-left: 3px; 33 | } 34 | 35 | 36 | .col-lg-6 .panel .panel-body .row { 37 | margin-right: 0px; 38 | margin-left: 0px; 39 | } 40 | 41 | .panel-heading h3.panel-title { 42 | font-size: 12px; 43 | } 44 | 45 | .ddos-stat { 46 | padding-top: 2px; 47 | padding-bottom: 2px; 48 | } 49 | 50 | .feature-item { 51 | padding-top: 10px; 52 | padding-bottom: 0px; 53 | font-size: 18px; 54 | } 55 | 56 | .feature-heading { 57 | font-size: 24px; 58 | text-align: center; 59 | } 60 | 61 | .form-group { 62 | /*margin-bottom: 0px;*/ 63 | } 64 | 65 | .level1 { 66 | text-indent: 0em; 67 | } 68 | 69 | .level2 { 70 | text-indent: 1em; 71 | } 72 | 73 | .level3 { 74 | text-indent: 2em; 75 | } 76 | 77 | .level4 { 78 | text-indent: 3em; 79 | } 80 | 81 | #ssl-result .glyphicon-ok { 82 | color: green; 83 | } 84 | 85 | #ssl-result .glyphicon-remove { 86 | color: red; 87 | } 88 | 89 | #page-wrapper .feature { 90 | margin-top: 15px; 91 | } 92 | -------------------------------------------------------------------------------- /falcon/public/fonts/fontawesome-webfont.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/fonts/fontawesome-webfont.woff2 -------------------------------------------------------------------------------- /falcon/public/fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /falcon/public/fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /falcon/public/fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /falcon/public/fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /falcon/public/fonts/zenicon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/fonts/zenicon.woff -------------------------------------------------------------------------------- /falcon/public/image/1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/image/1.jpg -------------------------------------------------------------------------------- /falcon/public/image/3.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/image/3.jpg -------------------------------------------------------------------------------- /falcon/public/image/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/image/background.png -------------------------------------------------------------------------------- /falcon/public/image/cornor.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/image/cornor.png -------------------------------------------------------------------------------- /falcon/public/image/ddos.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/image/ddos.jpg -------------------------------------------------------------------------------- /falcon/public/image/nmap.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/image/nmap.jpg -------------------------------------------------------------------------------- /falcon/public/image/ssl.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/cxueqin/falcon/6f341ac862def78992826038629601bfe422166d/falcon/public/image/ssl.png -------------------------------------------------------------------------------- /falcon/public/js/flot/jquery.flot.resize.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin for automatically redrawing plots as the placeholder resizes. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | It works by listening for changes on the placeholder div (through the jQuery 7 | resize event plugin) - if the size changes, it will redraw the plot. 8 | 9 | There are no options. If you need to disable the plugin for some plots, you 10 | can just fix the size of their placeholders. 11 | 12 | */ 13 | 14 | /* Inline dependency: 15 | * jQuery resize event - v1.1 - 3/14/2010 16 | * http://benalman.com/projects/jquery-resize-plugin/ 17 | * 18 | * Copyright (c) 2010 "Cowboy" Ben Alman 19 | * Dual licensed under the MIT and GPL licenses. 20 | * http://benalman.com/about/license/ 21 | */ 22 | (function($,e,t){"$:nomunge";var i=[],n=$.resize=$.extend($.resize,{}),a,r=false,s="setTimeout",u="resize",m=u+"-special-event",o="pendingDelay",l="activeDelay",f="throttleWindow";n[o]=200;n[l]=20;n[f]=true;$.event.special[u]={setup:function(){if(!n[f]&&this[s]){return false}var e=$(this);i.push(this);e.data(m,{w:e.width(),h:e.height()});if(i.length===1){a=t;h()}},teardown:function(){if(!n[f]&&this[s]){return false}var e=$(this);for(var t=i.length-1;t>=0;t--){if(i[t]==this){i.splice(t,1);break}}e.removeData(m);if(!i.length){if(r){cancelAnimationFrame(a)}else{clearTimeout(a)}a=null}},add:function(e){if(!n[f]&&this[s]){return false}var i;function a(e,n,a){var r=$(this),s=r.data(m)||{};s.w=n!==t?n:r.width();s.h=a!==t?a:r.height();i.apply(this,arguments)}if($.isFunction(e)){i=e;return a}else{i=e.handler;e.handler=a}}};function h(t){if(r===true){r=t||1}for(var s=i.length-1;s>=0;s--){var l=$(i[s]);if(l[0]==e||l.is(":visible")){var f=l.width(),c=l.height(),d=l.data(m);if(d&&(f!==d.w||c!==d.h)){l.trigger(u,[d.w=f,d.h=c]);r=t||true}}else{d=l.data(m);d.w=0;d.h=0}}if(a!==null){if(r&&(t==null||t-r<1e3)){a=e.requestAnimationFrame(h)}else{a=setTimeout(h,n[o]);r=false}}}if(!e.requestAnimationFrame){e.requestAnimationFrame=function(){return e.webkitRequestAnimationFrame||e.mozRequestAnimationFrame||e.oRequestAnimationFrame||e.msRequestAnimationFrame||function(t,i){return e.setTimeout(function(){t((new Date).getTime())},n[l])}}()}if(!e.cancelAnimationFrame){e.cancelAnimationFrame=function(){return e.webkitCancelRequestAnimationFrame||e.mozCancelRequestAnimationFrame||e.oCancelRequestAnimationFrame||e.msCancelRequestAnimationFrame||clearTimeout}()}})(jQuery,this); 23 | 24 | (function ($) { 25 | var options = { }; // no options 26 | 27 | function init(plot) { 28 | function onResize() { 29 | var placeholder = plot.getPlaceholder(); 30 | 31 | // somebody might have hidden us and we can't plot 32 | // when we don't have the dimensions 33 | if (placeholder.width() == 0 || placeholder.height() == 0) 34 | return; 35 | 36 | plot.resize(); 37 | plot.setupGrid(); 38 | plot.draw(); 39 | } 40 | 41 | function bindEvents(plot, eventHolder) { 42 | plot.getPlaceholder().resize(onResize); 43 | } 44 | 45 | function shutdown(plot, eventHolder) { 46 | plot.getPlaceholder().unbind("resize", onResize); 47 | } 48 | 49 | plot.hooks.bindEvents.push(bindEvents); 50 | plot.hooks.shutdown.push(shutdown); 51 | } 52 | 53 | $.plot.plugins.push({ 54 | init: init, 55 | options: options, 56 | name: 'resize', 57 | version: '1.0' 58 | }); 59 | })(jQuery); 60 | -------------------------------------------------------------------------------- /falcon/public/js/flot/jquery.flot.symbol.js: -------------------------------------------------------------------------------- 1 | /* Flot plugin that adds some extra symbols for plotting points. 2 | 3 | Copyright (c) 2007-2014 IOLA and Ole Laursen. 4 | Licensed under the MIT license. 5 | 6 | The symbols are accessed as strings through the standard symbol options: 7 | 8 | series: { 9 | points: { 10 | symbol: "square" // or "diamond", "triangle", "cross" 11 | } 12 | } 13 | 14 | */ 15 | 16 | (function ($) { 17 | function processRawData(plot, series, datapoints) { 18 | // we normalize the area of each symbol so it is approximately the 19 | // same as a circle of the given radius 20 | 21 | var handlers = { 22 | square: function (ctx, x, y, radius, shadow) { 23 | // pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2 24 | var size = radius * Math.sqrt(Math.PI) / 2; 25 | ctx.rect(x - size, y - size, size + size, size + size); 26 | }, 27 | diamond: function (ctx, x, y, radius, shadow) { 28 | // pi * r^2 = 2s^2 => s = r * sqrt(pi/2) 29 | var size = radius * Math.sqrt(Math.PI / 2); 30 | ctx.moveTo(x - size, y); 31 | ctx.lineTo(x, y - size); 32 | ctx.lineTo(x + size, y); 33 | ctx.lineTo(x, y + size); 34 | ctx.lineTo(x - size, y); 35 | }, 36 | triangle: function (ctx, x, y, radius, shadow) { 37 | // pi * r^2 = 1/2 * s^2 * sin (pi / 3) => s = r * sqrt(2 * pi / sin(pi / 3)) 38 | var size = radius * Math.sqrt(2 * Math.PI / Math.sin(Math.PI / 3)); 39 | var height = size * Math.sin(Math.PI / 3); 40 | ctx.moveTo(x - size/2, y + height/2); 41 | ctx.lineTo(x + size/2, y + height/2); 42 | if (!shadow) { 43 | ctx.lineTo(x, y - height/2); 44 | ctx.lineTo(x - size/2, y + height/2); 45 | } 46 | }, 47 | cross: function (ctx, x, y, radius, shadow) { 48 | // pi * r^2 = (2s)^2 => s = r * sqrt(pi)/2 49 | var size = radius * Math.sqrt(Math.PI) / 2; 50 | ctx.moveTo(x - size, y - size); 51 | ctx.lineTo(x + size, y + size); 52 | ctx.moveTo(x - size, y + size); 53 | ctx.lineTo(x + size, y - size); 54 | } 55 | }; 56 | 57 | var s = series.points.symbol; 58 | if (handlers[s]) 59 | series.points.symbol = handlers[s]; 60 | } 61 | 62 | function init(plot) { 63 | plot.hooks.processDatapoints.push(processRawData); 64 | } 65 | 66 | $.plot.plugins.push({ 67 | init: init, 68 | name: 'symbols', 69 | version: '1.0' 70 | }); 71 | })(jQuery); 72 | -------------------------------------------------------------------------------- /falcon/public/js/login.js: -------------------------------------------------------------------------------- 1 | $(document).ready(function(){ 2 | $("#login_btn").click(function(){ 3 | var xmlhttp; 4 | var login = $("[name='login']").val(); 5 | var passwd = $("[name='password']").val(); 6 | if(window.XMLHttpRequest) 7 | { 8 | xmlhttp = new XMLHttpRequest(); 9 | 10 | }else{ 11 | xmlhttp = new ActiveXObject("Microsoft.XMLHTTP"); 12 | } 13 | xmlhttp.onreadystatechange = function(){ 14 | if(xmlhttp.readyState == 4 && xmlhttp.status == 200){ 15 | var obj = JSON.parse(xmlhttp.responseText); 16 | if(obj.status === "success"){ 17 | checkCookie(login); 18 | $("#loginForm").submit(); 19 | }else{ 20 | alert("账号或密码错误"); 21 | } 22 | } 23 | } 24 | xmlhttp.open("GET","/login.asp?login="+login+"&password="+passwd+"",true); 25 | xmlhttp.send(); 26 | }); 27 | document.onkeydown = function(event) { 28 | var target, code, tag; 29 | if (!event) { 30 | event = window.event; //针对ie浏览器 31 | target = event.srcElement; 32 | code = event.keyCode; 33 | if (code == 13) { 34 | tag = target.tagName; 35 | if (tag == "TEXTAREA") { return true; } 36 | else { return false; } 37 | } 38 | } 39 | else { 40 | target = event.target; //针对遵循w3c标准的浏览器,如Firefox 41 | code = event.keyCode; 42 | if (code == 13) { 43 | tag = target.tagName; 44 | if (tag == "INPUT") { return false; } 45 | else { return true; } 46 | } 47 | } 48 | }; 49 | }); 50 | 51 | function getCookie(c_name) 52 | { 53 | if(document.cookie.length>0) 54 | { 55 | c_start=document.cookie.indexOf(c_name+"="); 56 | if(c_start!=-1) 57 | { 58 | c_start=c_start+c_name.length+1; 59 | c_end=document.cookie.indexOf(";",c_start); 60 | if(c_end==-1) 61 | c_end=document.cookie.length; 62 | return unescape(document.cookie.substring(c_start,c_end)); 63 | } 64 | } 65 | return ""; 66 | } 67 | 68 | function setCookie(c_name,value,expiredays) 69 | { 70 | var exdate = new Date(); 71 | exdate.setDate(exdate.getDate()+expiredays); 72 | 73 | document.cookie=c_name+"="+escape(value)+((expiredays==null)? "":";expires="+exdate.toGMTString()); 74 | 75 | } 76 | 77 | function clearCookie(name) { 78 | setCookie(name, "", null); 79 | } 80 | 81 | function checkCookie(c_name){ 82 | userName = getCookie('userName'); 83 | if(userName != null && userName != ""){ 84 | alert('welcome again' + userName +"1"); 85 | }else{ 86 | setCookie('userName' , c_name, null); 87 | } 88 | } -------------------------------------------------------------------------------- /falcon/public/js/metisMenu.min.js: -------------------------------------------------------------------------------- 1 | /* 2 | * metismenu - v1.1.3 3 | * Easy menu jQuery plugin for Twitter Bootstrap 3 4 | * https://github.com/onokumus/metisMenu 5 | * 6 | * Made by Osman Nuri Okumus 7 | * Under MIT License 8 | */ 9 | !function(a,b,c){function d(b,c){this.element=a(b),this.settings=a.extend({},f,c),this._defaults=f,this._name=e,this.init()}var e="metisMenu",f={toggle:!0,doubleTapToGo:!1};d.prototype={init:function(){var b=this.element,d=this.settings.toggle,f=this;this.isIE()<=9?(b.find("li.active").has("ul").children("ul").collapse("show"),b.find("li").not(".active").has("ul").children("ul").collapse("hide")):(b.find("li.active").has("ul").children("ul").addClass("collapse in"),b.find("li").not(".active").has("ul").children("ul").addClass("collapse")),f.settings.doubleTapToGo&&b.find("li.active").has("ul").children("a").addClass("doubleTapToGo"),b.find("li").has("ul").children("a").on("click."+e,function(b){return b.preventDefault(),f.settings.doubleTapToGo&&f.doubleTapToGo(a(this))&&"#"!==a(this).attr("href")&&""!==a(this).attr("href")?(b.stopPropagation(),void(c.location=a(this).attr("href"))):(a(this).parent("li").toggleClass("active").children("ul").collapse("toggle"),void(d&&a(this).parent("li").siblings().removeClass("active").children("ul.in").collapse("hide")))})},isIE:function(){for(var a,b=3,d=c.createElement("div"),e=d.getElementsByTagName("i");d.innerHTML="",e[0];)return b>4?b:a},doubleTapToGo:function(a){var b=this.element;return a.hasClass("doubleTapToGo")?(a.removeClass("doubleTapToGo"),!0):a.parent().children("ul").length?(b.find(".doubleTapToGo").removeClass("doubleTapToGo"),a.addClass("doubleTapToGo"),!1):void 0},remove:function(){this.element.off("."+e),this.element.removeData(e)}},a.fn[e]=function(b){return this.each(function(){var c=a(this);c.data(e)&&c.data(e).remove(),c.data(e,new d(this,b))}),this}}(jQuery,window,document); -------------------------------------------------------------------------------- /falcon/public/js/sb-admin-2.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Start Bootstrap - SB Admin 2 v3.3.7+1 (http://startbootstrap.com/template-overviews/sb-admin-2) 3 | * Copyright 2013-2016 Start Bootstrap 4 | * Licensed under MIT (https://github.com/BlackrockDigital/startbootstrap/blob/gh-pages/LICENSE) 5 | */ 6 | $(function() { 7 | $('#side-menu').metisMenu(); 8 | }); 9 | 10 | //Loads the correct sidebar on window load, 11 | //collapses the sidebar on window resize. 12 | // Sets the min-height of #page-wrapper to window size 13 | $(function() { 14 | $(window).bind("load resize", function() { 15 | var topOffset = 50; 16 | var width = (this.window.innerWidth > 0) ? this.window.innerWidth : this.screen.width; 17 | if (width < 768) { 18 | $('div.navbar-collapse').addClass('collapse'); 19 | topOffset = 100; // 2-row-menu 20 | } else { 21 | $('div.navbar-collapse').removeClass('collapse'); 22 | } 23 | 24 | var height = ((this.window.innerHeight > 0) ? this.window.innerHeight : this.screen.height) - 1; 25 | height = height - topOffset; 26 | if (height < 1) height = 1; 27 | if (height > topOffset) { 28 | $("#page-wrapper").css("min-height", (height) + "px"); 29 | } 30 | }); 31 | 32 | var url = window.location; 33 | // var element = $('ul.nav a').filter(function() { 34 | // return this.href == url; 35 | // }).addClass('active').parent().parent().addClass('in').parent(); 36 | var element = $('ul.nav a').filter(function() { 37 | return this.href == url; 38 | }).addClass('active').parent(); 39 | 40 | while (true) { 41 | if (element.is('li')) { 42 | element = element.parent().addClass('in').parent(); 43 | } else { 44 | break; 45 | } 46 | } 47 | }); 48 | 49 | $(document).ready(function() { 50 | $("#bookmarkme").click(function() { 51 | if (window.sidebar) { // Mozilla Firefox Bookmark 52 | window.sidebar.addPanel(location.href,document.title,""); 53 | } else if (window.external && ('AddFavorite' in window.external)) { // IE Favorite 54 | window.external.AddFavorite(location.href,document.title); } 55 | else if(window.opera && window.print) { // Opera Hotlist 56 | this.title=document.title; 57 | return true; 58 | } else { // webkit - safari/chrome 59 | alert('请按 ' + (navigator.userAgent.toLowerCase().indexOf('mac') != -1 ? 'Command/Cmd' : 'CTRL') + ' + D 快捷键盘收藏.'); 60 | } 61 | }); 62 | }); 63 | -------------------------------------------------------------------------------- /falcon/routes/common.js: -------------------------------------------------------------------------------- 1 | //定义公共变量,以便各个模版使用 2 | indexOptions = {title:"猎鹰网络分析系统" }; 3 | loginOptions = {title:"猎鹰网络分析系统", login:true }; 4 | -------------------------------------------------------------------------------- /falcon/routes/ddos.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * DOS WEB UI层处理定义文件 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | var express = require('express'); 9 | var router = express.Router(); 10 | require('./common'); 11 | var ddosOptions = {title:"DDOS测试" }; 12 | var ConfigManager = require('../lib/config'); 13 | var _ = require('lodash'); 14 | var logger = require('../lib/logger'); 15 | const util = require('util'); 16 | var controller = require('../ddos/controller'); 17 | var FloodAgent = require('../ddos/agent'); 18 | var FloodListener = require('../ddos/listener'); 19 | 20 | controller.init(); 21 | var listener = new FloodListener( ConfigManager.getPort(), controller); 22 | listener.start(); 23 | 24 | var agents = ConfigManager.getDdosAgents(); 25 | _.forEach(agents, function (agent) { 26 | controller.addAgent(new FloodAgent(agent)); 27 | }); 28 | 29 | router.get('/ui/ddos', function(req, res){ 30 | res.render('ddos', ddosOptions); 31 | }); 32 | 33 | router.post('/api/ddos', function(req, res){ 34 | //TODO:处理参数异常情况,target为非法地址 35 | var hcode = 200; 36 | logger.debug("ddos type %s target %s", req.body.type, req.body.target); 37 | var result; 38 | try { 39 | controller.startFlood(req.body.target, {type: req.body.type}); 40 | result = {}; 41 | } catch (e) { 42 | result = e; 43 | hcode = 500; 44 | } finally { 45 | res.status(hcode).json(result); 46 | } 47 | }); 48 | 49 | router.delete('/api/ddos', function(req, res){ 50 | //TODO:处理参数异常情况,target为非法地址 51 | var hcode = 200; 52 | logger.debug("stop flood"); 53 | var result; 54 | try { 55 | controller.stopFlood(); 56 | result = {}; 57 | } catch (e) { 58 | result = e; 59 | hcode = 500; 60 | } finally { 61 | res.status(hcode).json(result); 62 | } 63 | }); 64 | 65 | router.get('/api/ddos', function(req, res){ 66 | var result = controller.getState(); 67 | res.status(200).json(result); 68 | }); 69 | 70 | router.get('/api/ddos/traffic', function(req, res){ 71 | var result = controller.getTrafficStat(); 72 | res.status(200).json(result); 73 | }); 74 | 75 | 76 | module.exports = router; 77 | -------------------------------------------------------------------------------- /falcon/routes/error.js: -------------------------------------------------------------------------------- 1 | var express = require('express'); 2 | 3 | module.exports = function(req, res, next){ 4 | // we may use properties of the error object 5 | // here and next(err) appropriately, or if 6 | // we possibly recovered from the error, simply next(). 7 | res.status(404); 8 | res.render('error', { error: req.originalUrl, title:"not found" }); 9 | }; 10 | -------------------------------------------------------------------------------- /falcon/routes/index.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * WEB 首页UI层处理定义文件 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | var express = require('express'); 9 | var router = express.Router(); 10 | require('./common'); 11 | 12 | function restrict(req, res, next) { 13 | if (req.session.user) { 14 | next(); 15 | } else { 16 | req.session.error = 'Access denied!'; 17 | res.render('login', loginOptions); 18 | } 19 | } 20 | 21 | function restrictAPI(req, res, next) { 22 | if (req.session.user) { 23 | next(); 24 | } else { 25 | res.status(500).end(); 26 | } 27 | } 28 | 29 | /* GET home page. */ 30 | // TODO: post 请求没做检查会存在漏洞隐患 31 | router.get('*', restrict); 32 | router.all('/api/*', restrictAPI); 33 | 34 | router.get('/', function(req, res){ 35 | res.render('index', indexOptions); 36 | }); 37 | 38 | router.get('/restricted', restrict, function(req, res){ 39 | res.send('Wahoo! restricted area, click to logout'); 40 | }); 41 | 42 | module.exports = router; 43 | -------------------------------------------------------------------------------- /falcon/routes/login.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * WEB 登陆认证处理定义文件 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | var express = require('express'); 9 | var router = express.Router(); 10 | var pam = require('authenticate-pam'); 11 | var logger = require('../lib/logger'); 12 | require('./common'); 13 | // Authenticate using our plain-object database of doom! 14 | 15 | function authenticate(name, pass, fn) { 16 | pam.authenticate(name, pass, function(err){ 17 | if (err){ 18 | fn(new Error('invalid password or username')); 19 | }else{ 20 | fn(null, {'name': name}); 21 | } 22 | }),{serviceName:'login' , remoteHost:'localhost'}; 23 | } 24 | 25 | router.get('/login', function(req, res){ 26 | res.render('login', loginOptions); 27 | }); 28 | 29 | router.post('/login', function(req, res){ 30 | authenticate(req.body.username, req.body.password, function(err, user){ 31 | if (user) { 32 | // Regenerate session when signing in 33 | // to prevent fixation 34 | req.session.regenerate(function(){ 35 | // Store the user's primary key 36 | // in the session store to be retrieved, 37 | // or in this case the entire user object 38 | logger.notice("auth %s ok from %s", req.body.username, req.ip); 39 | req.session.user = user; 40 | req.session.success = 'Authenticated as ' + user.name 41 | + ' click to logout. ' 42 | + ' You may now access /restricted.'; 43 | res.redirect('/'); 44 | }); 45 | } else { 46 | req.session.error = 'Authentication failed, please check your ' 47 | + ' username and password.' 48 | + ' (use "tj" and "foobar")'; 49 | logger.notice("auth %s failed from %s", req.body.username, req.ip); 50 | res.redirect('/login'); 51 | } 52 | }); 53 | }); 54 | 55 | module.exports = router; 56 | -------------------------------------------------------------------------------- /falcon/routes/logout.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * WEB UI层登出处理定义文件 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | var express = require('express'); 9 | var router = express.Router(); 10 | 11 | router.get('/logout', function(req, res){ 12 | // destroy the user's session to log them out 13 | // will be re-created next request 14 | req.session.destroy(function(){ 15 | res.redirect('/'); 16 | }); 17 | }); 18 | 19 | module.exports = router; 20 | -------------------------------------------------------------------------------- /falcon/routes/nmap.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * WEB UI层端口扫描处理定义文件 3 | * 4 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 5 | * 6 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 7 | */ 8 | const debug = require('debug')('routes_nmap'); 9 | var express = require('express'); 10 | var router = express.Router(); 11 | require('./common'); 12 | var execOptions = {title:"端口扫描" }; 13 | var setupOptions = {title:"端口规格配置" }; 14 | var NmapManagerFactory = require('../nmap/nmap-manager'); 15 | var Nmap = require('../nmap/nmap').nodenmap; 16 | var ConfigManager = require('../lib/config'); 17 | var manager; 18 | var _ = require('lodash'); 19 | var logger = require('../lib/logger'); 20 | const util = require('util'); 21 | 22 | NmapManagerFactory.setHome(ConfigManager.getNmapStorageDir()); 23 | manager = NmapManagerFactory.getManager(); 24 | 25 | router.get('/ui/nmap/exec', function(req, res){ 26 | res.render('nmap_exec', execOptions); 27 | }); 28 | 29 | router.post('/api/nmap', function(req, res){ 30 | debug('req.body=%j',req.body) 31 | let scan 32 | if (req.body.spec){ 33 | debug('req.body.spec=%j', req.body.spec) 34 | scan = new Nmap.NmapScan(req.body.target, req.body.spec) 35 | } else { 36 | scan = new Nmap.NmapScan(req.body.target) 37 | } 38 | 39 | //TODO:处理参数异常情况 40 | 41 | var result = manager.addResult(scan); 42 | scan.startScan(); 43 | scan.on('complete', function (data) { 44 | manager.updateResult( result, data) 45 | }); 46 | //nmap调用可能失败,故在调用方必须增加容错处理 47 | scan.on('error', function (data) { 48 | //manager.updateResult( result, data) 49 | }); 50 | //必须手工设定,否则返回304 Not Modified 51 | res.status(200).json(result); 52 | logger.debug("result %s", util.inspect(result, {depth: null})); 53 | }); 54 | 55 | router.get('/api/nmap', function(req, res){ 56 | logger.debug("query id %s", req.query.id); 57 | var result = manager.getResultWithDetail(req.query.id); 58 | res.status(200).json(result); 59 | }); 60 | 61 | router.get('/ui/nmap/setup', function(req, res){ 62 | res.render('nmap_setup', setupOptions); 63 | }); 64 | 65 | router.get('/ui/nmap/history', function(req, res){ 66 | var page = req.query.page; 67 | var limit = req.query.limit; 68 | var results = manager.getResults(); 69 | var itemCounts = results.length; 70 | var paginate = res.locals.paginate; 71 | 72 | pageCount = _.ceil(itemCounts / limit); 73 | 74 | var i = 1; 75 | // add index number to each result 76 | _.forEach(results, function(item) { 77 | item.index = i; 78 | i++; 79 | }); 80 | //注意:page是从1开始计数的, paginate模块自动算好skip 81 | results = _.slice(results, req.offset, page*limit ); 82 | var pages = paginate.getArrayPages(10, pageCount, page); 83 | logger.debug("page: %d pageCount: %d pages: %s", 84 | page, pageCount, util.inspect(pages, { depth: null })); 85 | var historyOptions = { 86 | title:"端口扫描历史", 87 | results: results, 88 | pages: pages, 89 | pageCount: pageCount, 90 | paginate: paginate 91 | }; 92 | res.render('nmap_history', historyOptions); 93 | }); 94 | 95 | module.exports = router; 96 | -------------------------------------------------------------------------------- /falcon/routes/ssl.js: -------------------------------------------------------------------------------- 1 | 'use strict' 2 | 3 | /*! 4 | * WEB UI层端口扫描处理定义文件 5 | * 6 | * 版权所有 2017 陈学芹 联系方式: 7219530@qq.com 7 | * 8 | * 本软件在GNU LGPL-V2.1协议下发布,欢迎使用. 9 | */ 10 | var express = require('express'); 11 | var router = express.Router(); 12 | require('./common'); 13 | var execOptions = {title:"SSL检测" }; 14 | var logger = require('../lib/logger'); 15 | const util = require('util'); 16 | var sslCertficate = require('../ssl/cert'); 17 | const assert = require('assert'); 18 | /*TODO: support multi session concurrent*/ 19 | var ssl_state = undefined; 20 | var ssl_error = 0; 21 | var ssl_cert = undefined; 22 | 23 | router.get('/ui/ssl/exec', function(req, res){ 24 | res.render('ssl_exec', execOptions); 25 | }); 26 | 27 | /* Note current only support one ssl detect session */ 28 | router.post('/api/ssl', function(req, res){ 29 | //TODO:处理参数异常情况 30 | if (ssl_state == 'running') { 31 | logger.err("ssl detect already running"); 32 | res.status(500).end(); 33 | return; 34 | } 35 | var host = req.body.host; 36 | var port = req.body.port || 443; 37 | if (!host) { 38 | logger.err("Lack of host parameter"); 39 | res.status(500).end(); 40 | return; 41 | } 42 | ssl_state = 'running'; 43 | logger.debug("start to check ssl certificate %s:%s", host, port); 44 | /*USE callback api */ 45 | sslCertficate.connect(host, port, (err, cert) => { 46 | if (err) { 47 | ssl_error = 400; 48 | ssl_state = 'done'; 49 | logger.warn('ssl connect to %s:%s error(%s)', host, port, err.message); 50 | }else { 51 | ssl_state = 'done'; 52 | ssl_cert = cert; 53 | ssl_error = 0; 54 | logger.debug("ssl connect to %s:%s done", host, port); 55 | } 56 | }); 57 | /* 58 | FIXME: ssl promise API has some circular bug in result 59 | */ 60 | /* 61 | sslCertficate.get(host, port).then((cert)=> { 62 | ssl_state = 'done'; 63 | ssl_cert = cert; 64 | ssl_error = 0; 65 | logger.debug("ssl done"); 66 | }) 67 | .catch((e)=>{ 68 | ssl_error = 400; 69 | ssl_state = 'done'; 70 | }) 71 | */ 72 | res.status(200).end(); 73 | }); 74 | 75 | router.get('/api/ssl', function(req, res){ 76 | if (typeof ssl_state === 'undefined') { 77 | /* ssl never been started */ 78 | res.status(500).end(); 79 | return; 80 | } 81 | 82 | if (ssl_state == 'running') { 83 | res.status(100).end(); 84 | return; 85 | } 86 | assert(ssl_state == 'done'); 87 | var result = {}; 88 | result.errcode = ssl_error; 89 | if (ssl_cert) { 90 | result.cert = ssl_cert; 91 | } 92 | console.dir(ssl_cert); 93 | res.status(200).json(result); 94 | }); 95 | 96 | router.get('/ui/ssl/history', function(req, res){ 97 | //TODO: add history 98 | res.status(500).end(); 99 | }); 100 | 101 | module.exports = router; 102 | -------------------------------------------------------------------------------- /falcon/ssl/cert.js: -------------------------------------------------------------------------------- 1 | var tls = require('tls'); 2 | 3 | /* 修正测试结果中的环形指针,避免无限循环 */ 4 | function fixCyclic (obj) { 5 | var seenObjects = []; 6 | 7 | function detect (obj) { 8 | if (obj && typeof obj === 'object') { 9 | if (seenObjects.indexOf(obj) !== -1) { 10 | return true; 11 | } 12 | seenObjects.push(obj); 13 | for (var key in obj) { 14 | if (obj.hasOwnProperty(key) && detect(obj[key])) { 15 | return true; 16 | } 17 | } 18 | } 19 | return false; 20 | } 21 | 22 | seenObjects.push(obj); 23 | for (var key in obj) { 24 | if (obj.hasOwnProperty(key) && detect(obj[key])) { 25 | /* 26 | key属性指向已有的一个值, 判断发生短路, 需要断开此环路 27 | 注意使用delete,而非将属性设为 undefined 28 | */ 29 | delete obj[key]; 30 | } 31 | } 32 | } 33 | 34 | 35 | function isEmpty(object) { 36 | for(var prop in object) { 37 | if(object.hasOwnProperty(prop)) 38 | return false; 39 | } 40 | 41 | return true; 42 | } 43 | 44 | function get(host, port) { 45 | if (!host || typeof host !== 'string') { 46 | throw Error("A valid host is required"); 47 | } 48 | var myport = 443; 49 | if (port) { 50 | myport = port; 51 | } 52 | 53 | var options = { 54 | host: host, 55 | port: myport, 56 | rejectUnauthorized: false, 57 | ciphers: "ALL", 58 | }; 59 | 60 | return new Promise(function (resolve, reject) { 61 | var socket = tls.connect(options, () => { 62 | var certificate = socket.getPeerCertificate(true); 63 | if (isEmpty(certificate) || certificate === null) { 64 | reject(new Error('The server did not provide a certificate')); 65 | } else { 66 | certificate.cipher = socket.getCipher(); 67 | fixCyclic(certificate); 68 | resolve(certificate); 69 | } 70 | /* 立即关闭socket */ 71 | socket.end(); 72 | }); 73 | 74 | socket.on('error', function(e) { 75 | reject(e); 76 | socket.end(); 77 | }); 78 | }); 79 | } 80 | 81 | /* 证书检查回调版本 */ 82 | function connect(host, port, callback) { 83 | if (!host || typeof host !== 'string') { 84 | throw Error("A valid host is required"); 85 | } 86 | 87 | var myport = 443; 88 | if (port) { 89 | myport = port; 90 | } 91 | 92 | if (typeof callback !== 'function') { 93 | throw Error("Callback functioin is required"); 94 | } 95 | 96 | var options = { 97 | host: host, 98 | port: myport, 99 | rejectUnauthorized: false, 100 | ciphers: "ALL", 101 | }; 102 | 103 | var socket = tls.connect(options, () => { 104 | var certificate = socket.getPeerCertificate(true); 105 | if (isEmpty(certificate) || certificate === null) { 106 | callback(new Error('The server did not provide a certificate')); 107 | } else { 108 | /*mixin Cipher property into certificate*/ 109 | certificate.cipher = socket.getCipher(); 110 | fixCyclic(certificate); 111 | callback(null, certificate); 112 | } 113 | /* 立即关闭socket */ 114 | socket.end(); 115 | }); 116 | 117 | socket.on('error', function(e) { 118 | callback(e); 119 | socket.end(); 120 | }); 121 | 122 | } 123 | 124 | module.exports = { 125 | get: get, 126 | connect: connect 127 | }; 128 | -------------------------------------------------------------------------------- /falcon/ssl/parse.js: -------------------------------------------------------------------------------- 1 | var cmd_args = process.argv.splice(2); 2 | 3 | const x509 = require('x509'); 4 | var cert = x509.parseCert(cmd_args[0]); 5 | console.dir(cert); 6 | -------------------------------------------------------------------------------- /falcon/ssl/trust_ca_dump.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var fs = require('fs'); 4 | 5 | var ca_list = new Array(); 6 | 7 | function readLines(input, func) { 8 | var remaining = ''; 9 | 10 | input.on('data', function(data) { 11 | remaining += data; 12 | var index = remaining.indexOf('\n'); 13 | while (index > -1) { 14 | var line = remaining.substring(0, index); 15 | remaining = remaining.substring(index + 1); 16 | func(line); 17 | index = remaining.indexOf('\n'); 18 | } 19 | }); 20 | 21 | input.on('end', function() { 22 | if (remaining.length > 0) { 23 | func(remaining); 24 | } 25 | ca_list.sort(); 26 | 27 | console.log(JSON.stringify(ca_list,null, '\t')); 28 | }); 29 | } 30 | 31 | function func(data) { 32 | 33 | var rePattern = new RegExp(/^# Issuer: CN=([^,]*),(.*)$/); 34 | 35 | //var arrMatches = data.match(/^# Issuer: CN=(.*)OU=(.*)C=(.*)$/); 36 | var arrMatches = data.match(rePattern); 37 | if (arrMatches) { 38 | //console.log('ALL:' + arrMatches[0]); 39 | //console.log('CN:' + arrMatches[1]); 40 | 41 | ca_list.push(arrMatches[1]); 42 | } 43 | //console.log('Line :', data); 44 | 45 | } 46 | 47 | var input = fs.createReadStream('trust_ca.txt'); 48 | readLines(input, func); 49 | -------------------------------------------------------------------------------- /falcon/system/falcon.conf: -------------------------------------------------------------------------------- 1 | [daemon] 2 | port = 8000 3 | loglevel = debug 4 | datadir = /var/lib/falcon 5 | log_console = yes 6 | ;port_ssl = 8001 7 | ;key = /etc/falcon.key 8 | ;cert = /etc/falcon.crt 9 | 10 | [ddos] 11 | ;support multi server like 12 | ;agents = 127.0.0.1,192.168.177.51 13 | agents = 127.0.0.1 14 | 15 | [nmap] 16 | 17 | [hydra] 18 | -------------------------------------------------------------------------------- /falcon/system/falcon.init: -------------------------------------------------------------------------------- 1 | 2 | #!/bin/bash 3 | 4 | SERVER="/mnt/hgfs/linux_share/newnodejs/web-controler.js"; 5 | PROCESS=`ps -ef|grep $SERVER|grep -v grep|grep -v PPID|awk '{ print $2}'`; 6 | 7 | start(){ 8 | if [ $PROCESS ];then 9 | echo "process is running" 10 | else 11 | node $SERVER & 12 | fi 13 | } 14 | 15 | stop(){ 16 | if [ $PROCESS ];then 17 | sudo kill -9 $PROCESS 18 | else 19 | echo "process is not running" 20 | fi 21 | } 22 | 23 | case "$1" in 24 | "start") 25 | start;; 26 | "stop") 27 | stop;; 28 | *) 29 | echo "Usage: $0 {start|stop|restart|status|info}" ; 30 | exit 1 ; 31 | esac 32 | exit 0 ; 33 | -------------------------------------------------------------------------------- /falcon/system/falcon.pam: -------------------------------------------------------------------------------- 1 | #%PAM-1.0 2 | #auth include system-auth 3 | auth sufficient pam_unix.so nullok try_first_pass 4 | -------------------------------------------------------------------------------- /falcon/system/falcon.service: -------------------------------------------------------------------------------- 1 | [Unit] 2 | Description=falcon server daemon 3 | Documentation=man:falcon(8) 4 | After=network.target 5 | ;Wants= 6 | 7 | [Service] 8 | Type=simple 9 | User=admin 10 | Group=admin 11 | EnvironmentFile=/etc/sysconfig/sshd 12 | ExecStart=/usr/bin/node /home/robbie/falcon_project/nepartakak/falcon $OPTIONS 13 | ;ExecReload=/bin/kill -HUP $MAINPID 14 | KillMode=process 15 | Restart=on-failure 16 | RestartSec=42s 17 | 18 | [Install] 19 | WantedBy=multi-user.target 20 | -------------------------------------------------------------------------------- /falcon/system/genkey.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | if test $# -ne 3 3 | then 4 | echo "Wrong number of arguments" 5 | exit 1 6 | fi 7 | 8 | ROOTPATH="$1" 9 | FQDN=$2 10 | PASSWORD=$3 11 | RSABITS=4096 12 | 13 | # make directories to work from 14 | mkdir -p $ROOTPATH/certs/{server,client,ca,tmp} 15 | 16 | PATH_CA=$ROOTPATH/certs/ca 17 | PATH_SERVER=$ROOTPATH/certs/server 18 | PATH_CLIENT=$ROOTPATH/certs/client 19 | PATH_TMP=$ROOTPATH/certs/tmp 20 | 21 | ###### 22 | # CA # 23 | ###### 24 | 25 | openssl genrsa -des3 -passout pass:$PASSWORD -out $PATH_TMP/ca.key $RSABITS 26 | 27 | # Create Authority Certificate 28 | openssl req -new -x509 -days 365 -key $PATH_TMP/ca.key \ 29 | -out $PATH_CA/ca.crt -passin pass:$PASSWORD \ 30 | -subj "/C=FR/ST=./L=./O=ACME Signing Authority Inc/CN=." 31 | 32 | ########## 33 | # SERVER # 34 | ########## 35 | 36 | # Generate server key 37 | openssl genrsa -out $PATH_SERVER/server.key $RSABITS 38 | 39 | # Generate server cert 40 | openssl req -new -key $PATH_SERVER/server.key \ 41 | -out $PATH_TMP/server.csr -passout pass:$PASSWORD \ 42 | -subj "/C=FR/ST=./L=./O=ACME Signing Authority Inc/CN=$FQDN" 43 | 44 | # Sign server cert with self-signed cert 45 | openssl x509 -req -days 365 -passin pass:$PASSWORD \ 46 | -in $PATH_TMP/server.csr -CA $PATH_CA/ca.crt \ 47 | -CAkey $PATH_TMP/ca.key -set_serial 01 \ 48 | -out $PATH_SERVER/server.crt 49 | 50 | ########## 51 | # CLIENT # 52 | ########## 53 | 54 | openssl genrsa -out $PATH_CLIENT/client.key $RSABITS 55 | 56 | openssl req -new -key $PATH_CLIENT/client.key \ 57 | -out $PATH_TMP/client.csr -passout pass:$PASSWORD \ 58 | -subj "/C=FR/ST=./L=./O=ACME Signing Authority Inc/CN=CLIENT" 59 | 60 | openssl x509 -req -days 365 -passin pass:$PASSWORD \ 61 | -in $PATH_TMP/client.csr -CA $PATH_CA/ca.crt \ 62 | -CAkey $PATH_TMP/ca.key -set_serial 01 \ 63 | -out $PATH_CLIENT/client.crt 64 | 65 | exit 0 66 | -------------------------------------------------------------------------------- /falcon/test/ddos/agent.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var FloodAgent = require('../../ddos/agent'); 3 | const AGENT_IP = "127.0.0.1"; 4 | const TARGET_IP = "127.0.0.1"; 5 | 6 | describe('FloodAgent Interface Static Test', function() { 7 | var agent; 8 | 9 | before(function() { 10 | // runs before all tests in this block 11 | agent = new FloodAgent(AGENT_IP); 12 | }); 13 | 14 | after(function() { 15 | // runs after all tests in this block 16 | }); 17 | 18 | it('agent instance property should be valid after successfully created', function() { 19 | assert.equal( AGENT_IP, agent.host ); 20 | assert.equal( "idle", agent.state ); 21 | }); 22 | 23 | it('agent should start flood when call start api', function(done) { 24 | agent.onStart(done); 25 | assert.doesNotThrow(function () { agent.start(TARGET_IP, {type: 'icmp'}); }); 26 | }); 27 | 28 | it('agent static data should be correct when call processTraffic api', function() { 29 | agent.processTraffic({packet: 10, byte: 1000}); 30 | var stat = agent.getTraffic(); 31 | assert.equal(stat.packetSent, 10); 32 | assert.equal(stat.byteSent, 1000); 33 | }); 34 | 35 | it('agent static data should be correct when twice processTraffic api call', function() { 36 | agent.processTraffic({packet: 1, byte: 100}); 37 | var stat = agent.getTraffic(); 38 | assert.equal(stat.packetSent, 11); 39 | assert.equal(stat.byteSent, 1100); 40 | }); 41 | 42 | it('agent should stop flood when call stop api', function(done) { 43 | agent.onStop(done); 44 | assert.doesNotThrow(function () { agent.stop(); }); 45 | }); 46 | 47 | it('agent static data should reset when call resetTraffic api', function() { 48 | agent.resetTraffic(); 49 | var stat = agent.getTraffic(); 50 | assert.equal(stat.packetSent, 0); 51 | assert.equal(stat.byteSent, 0); 52 | }); 53 | 54 | }); 55 | -------------------------------------------------------------------------------- /falcon/test/ddos/controller.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var floodController = require('../../ddos/controller'); 3 | var FloodAgent = require('../../ddos/agent'); 4 | var FloodListener = require('../../ddos/listener'); 5 | var sleep = require('sleep').sleep; 6 | 7 | const AGENT_IP = "127.0.0.1"; 8 | const TARGET_IP = "127.0.0.1"; 9 | 10 | describe('FloodController Interface Static Test', function() { 11 | var controller; 12 | 13 | before(function() { 14 | // runs before all tests in this block 15 | assert.ok(floodController); 16 | assert.ok(floodController.init); 17 | assert.ok(floodController.addAgent); 18 | assert.ok(floodController.removeAgent); 19 | assert.ok(floodController.getAgents); 20 | assert.ok(floodController.findAgent); 21 | assert.ok(floodController.startFlood); 22 | assert.ok(floodController.stopFlood); 23 | assert.ok(floodController.getState); 24 | assert.ok(floodController.getTrafficStat); 25 | }); 26 | 27 | after(function() { 28 | // runs after all tests in this block 29 | }); 30 | 31 | it('controller should set correct internal data after init ', function() { 32 | floodController.init(); 33 | var listener = new FloodListener( 8000, floodController); 34 | listener.start(); 35 | 36 | var state = floodController.getState(); 37 | assert.equal('idle', state.state); 38 | var agents = floodController.getAgents(); 39 | assert.equal(0, agents.length); 40 | 41 | var data = floodController.getState(); 42 | 43 | }); 44 | 45 | it(' agent list should have more elements when addAgent invoked', function() { 46 | floodController.addAgent(new FloodAgent(AGENT_IP)); 47 | var agents = floodController.getAgents(); 48 | assert.equal(1, agents.length); 49 | }); 50 | 51 | it(' controller should find agent when given ip', function() { 52 | var selector = { host: AGENT_IP}; 53 | var agent = floodController.findAgent(selector); 54 | assert.ok(agent); 55 | }); 56 | 57 | 58 | it(' agent should be in started state when startFlood ', function() { 59 | assert.doesNotThrow( 60 | () => { 61 | floodController.startFlood(TARGET_IP, {type: 'icmp'}) 62 | } 63 | ); 64 | var state = floodController.getState(); 65 | assert.equal( 'started', state.state); 66 | }); 67 | 68 | it(' controller should reject state when already startFlood ', function() { 69 | assert.throws( 70 | () => { 71 | floodController.startFlood(TARGET_IP, {type: 'icmp'}); 72 | } 73 | ); 74 | }); 75 | 76 | it(' traffic stat should change when get every 2 secnonds ', function(done) { 77 | setTimeout( () => { 78 | var trafficInfo = floodController.getTrafficStat(); 79 | console.log("trafficInfo %o", trafficInfo); 80 | assert.ok(trafficInfo.packetSent>1000); 81 | assert.ok(trafficInfo.byteSent>1000); 82 | done(); 83 | }, 1000); 84 | }); 85 | 86 | it(' agent should be in idle state when stopFood', function() { 87 | assert.doesNotThrow( 88 | () => { 89 | floodController.stopFlood(); 90 | } 91 | ); 92 | }); 93 | 94 | it(' controller should reject stopFlood when flood not started ', function() { 95 | assert.throws( 96 | () => { 97 | floodController.stopFlood(); 98 | } 99 | ); 100 | }); 101 | 102 | it(' agent list should remove specific element when removeAgent invoked', function() { 103 | var cond = { host: AGENT_IP}; 104 | var agent = floodController.findAgent(cond); 105 | assert.ok(agent); 106 | var ret = floodController.removeAgent(agent); 107 | assert.equal(0, ret); 108 | }); 109 | }); 110 | -------------------------------------------------------------------------------- /falcon/test/ddos/listener.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var FloodListener = require('../../ddos/listener'); 3 | const LISTEN_PORT = 3333; 4 | 5 | describe('FloodListener Interface Static Test', function() { 6 | before(function() { 7 | // runs before all tests in this block 8 | 9 | }); 10 | 11 | after(function() { 12 | // runs after all tests in this block 13 | }); 14 | 15 | it('constructor should has port parameter', function() { 16 | var listener = undefined; 17 | 18 | listener = new FloodListener(LISTEN_PORT); 19 | assert.ok(listener); 20 | }); 21 | 22 | it('constructor no port parameter should throw exception', function() { 23 | 24 | assert.throws( function () { new FloodListener();}, Error); 25 | 26 | }); 27 | 28 | it('constructor may have second controller parameter', function() { 29 | var listener = undefined; 30 | var controller = null; 31 | 32 | listener = new FloodListener(LISTEN_PORT, controller); 33 | assert.ok(listener); 34 | }); 35 | 36 | }); 37 | 38 | describe('FloodListener Interface Dynamic Test', function() { 39 | var listener; 40 | var sleep = require('sleep').sleep; 41 | 42 | before(function() { 43 | // runs before all tests in this block 44 | listener = new FloodListener(LISTEN_PORT); 45 | listener.start(); 46 | }); 47 | 48 | after(function() { 49 | // runs after all tests in this block 50 | listener.stop(); 51 | }); 52 | 53 | it('state should be started after 3 seconds', function(done) { 54 | sleep(1); 55 | //assert.equal( "started", listener.getState()); 56 | done(); 57 | }); 58 | 59 | it('should handle packet correctly when receive valid report packet', function(done) { 60 | var dgram = require('dgram'); 61 | var message = Buffer.from("packets=2&bytes=200"); 62 | var client = dgram.createSocket("udp4"); 63 | 64 | 65 | client.send(message, LISTEN_PORT, 'localhost', function(err) { 66 | //console.log(' message has been sent.'); 67 | client.close(); 68 | }); 69 | // 注意,利用定时器,不阻塞执行线程,让服务端回调接口得以正确处理 70 | setTimeout(() => { 71 | var report = listener.getTraffic(); 72 | //console.log('getTraffic '+JSON.stringify(report)); 73 | assert.equal(report.packetSent, 2); 74 | assert.equal(report.byteSent, 200); 75 | done(); 76 | }, 1000); 77 | }); 78 | 79 | it('should handle packet correctly when receive invalid report packet', function(done) { 80 | var dgram = require('dgram'); 81 | var message = new Buffer("Something Wrong"); 82 | var client = dgram.createSocket("udp4"); 83 | 84 | client.send(message, 0, message.length, LISTEN_PORT, "localhost", function(err) { 85 | client.close(); 86 | }); 87 | setTimeout(() => { 88 | var stat = listener.getTraffic(); 89 | assert.equal(stat.packetSent, 2); 90 | assert.equal(stat.byteSent, 200); 91 | done(); 92 | }, 1000); 93 | }); 94 | 95 | }); 96 | -------------------------------------------------------------------------------- /falcon/test/nmap/db.json: -------------------------------------------------------------------------------- 1 | { 2 | "results": [] 3 | } -------------------------------------------------------------------------------- /falcon/test/nmap/manager.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var NmapManagerFactory = require('../../nmap/nmap-manager'); 3 | NmapManagerFactory.setHome(__dirname); 4 | 5 | describe('Nmap Manager Result Matter', function() { 6 | var manager = undefined; 7 | var resultid = undefined; 8 | var result = undefined; 9 | 10 | before(function() { 11 | // runs before all tests in this block 12 | //清空数据 13 | var _ = require('lodash'); 14 | var _db = require('underscore-db'); 15 | _.mixin(_db); 16 | _.save({ results: [] }, __dirname+'/db.json') 17 | manager = NmapManagerFactory.getManager(); 18 | }); 19 | 20 | after(function() { 21 | // runs after all tests in this block 22 | }); 23 | 24 | it('addResult should successfully when scan and xml string all ok', function() { 25 | var scan, xml; 26 | var ret; 27 | scan = { range: ["192.168.40.1"] }; 28 | ret = manager.addResult(scan, xml) 29 | assert.ok(ret); 30 | assert.ok(ret.id); 31 | assert.equal(ret.status, 'running') 32 | resultid = ret.id; 33 | result = ret; 34 | }); 35 | 36 | it('addResult should fail when scan or xml string invalid ', function() { 37 | var scan, xml; 38 | var ret; 39 | 40 | ret = manager.addResult(scan, xml); 41 | assert(!ret); 42 | }); 43 | 44 | it('getResultWithDetail should success when resultid valid ', function() { 45 | assert.ok(manager.getResultWithDetail(resultid)); 46 | }); 47 | 48 | it('getResultWithDetail should fail when resultid invalid ', function() { 49 | assert.ok(!manager.getResultWithDetail('111111')); 50 | }); 51 | 52 | it('updateResult should ok when valid result and data ', function() { 53 | var ret = manager.updateResult(result, [{port:'22', status:'open'}]) 54 | assert.ok(ret); 55 | assert.equal(ret.status, 'done'); 56 | }); 57 | 58 | it('getResults should return all result ', function() { 59 | assert(manager.getResults()); 60 | assert.equal(manager.getResults().length, 1); 61 | }); 62 | 63 | it('delResult should success when resultid valid ', function() { 64 | assert.equal( manager.delResult(resultid), 0 ); 65 | }); 66 | 67 | it('delResult should fail when resultid invalid ', function() { 68 | assert.equal( manager.delResult('111111'), -1); 69 | }); 70 | }); 71 | 72 | describe('Nmap Manager Spec Matter', function() { 73 | var manager; 74 | var resultid; 75 | 76 | before(function() { 77 | // runs before all tests in this block 78 | manager = NmapManagerFactory.getManager(); 79 | }); 80 | 81 | after(function() { 82 | // runs after all tests in this block 83 | }); 84 | 85 | it('addSpec should successfully when spec object valid', function() { 86 | }); 87 | 88 | it('addSpec should fail when spec object invalid ', function() { 89 | assert.equal(-1, [1,2,3].indexOf(4)); 90 | }); 91 | 92 | it('delSpec should success when spec id valid ', function() { 93 | assert.equal(-1, [1,2,3].indexOf(4)); 94 | }); 95 | 96 | it('delSpec should fail when spec id invalid ', function() { 97 | assert.equal(-1, [1,2,3].indexOf(4)); 98 | }); 99 | 100 | it('getSpecs should return all spec ', function() { 101 | assert.equal(-1, [1,2,3].indexOf(4)); 102 | }); 103 | 104 | it('updateSpec should success when valid spec object ', function() { 105 | assert.equal(-1, [1,2,3].indexOf(4)); 106 | }); 107 | 108 | it('updateSpec should fail when invalid spec object ', function() { 109 | assert.equal(-1, [1,2,3].indexOf(4)); 110 | }); 111 | 112 | it('delSpec should success when valid spec id', function() { 113 | assert.equal(-1, [1,2,3].indexOf(4)); 114 | }); 115 | 116 | it('delSpec should fail when invalid spec id', function() { 117 | assert.equal(-1, [1,2,3].indexOf(4)); 118 | }); 119 | }); 120 | -------------------------------------------------------------------------------- /falcon/test/ssl.js: -------------------------------------------------------------------------------- 1 | var assert = require('assert'); 2 | var sslCertficate = require('../ssl/cert'); 3 | 4 | describe('SSL Certficate Interface Test', function() { 5 | 6 | before(function() { 7 | // runs before all tests in this block 8 | }); 9 | 10 | after(function() { 11 | // runs after all tests in this block 12 | }); 13 | 14 | it('Should get certificate when host is a real ssl server ', function(done) { 15 | var promise = sslCertficate.get('baidu.com'); 16 | promise.then((cert) => { 17 | assert.equal(cert.subject.C, "CN"); 18 | assert.equal(cert.subject.ST, "beijing") 19 | assert.equal(cert.subject.O, "BeiJing Baidu Netcom Science Technology Co., Ltd") 20 | done(); 21 | }) 22 | }); 23 | 24 | 25 | it('Should get certificate when ssl port specificed', function(done) { 26 | var promise = sslCertficate.get('baidu.com', 443); 27 | promise.then((cert) => { 28 | assert.equal(cert.subject.C, "CN"); 29 | assert.equal(cert.subject.ST, "beijing") 30 | assert.equal(cert.subject.O, "BeiJing Baidu Netcom Science Technology Co., Ltd") 31 | assert.equal(cert.cipher.name, "ECDHE-RSA-AES128-GCM-SHA256") 32 | done(); 33 | }) 34 | }); 35 | 36 | it('Aliyun SSL test', function(done) { 37 | this.timeout(10000); 38 | sslCertficate.connect('www.aliyun.com', 443, (err, cert) => { 39 | assert.ok(!err); 40 | assert.equal(cert.subject.C, "CN"); 41 | assert.equal(cert.subject.ST, "ZheJiang") 42 | assert.equal(cert.subject.L, "HangZhou") 43 | assert.equal(cert.subject.O, "Alibaba (China) Technology Co., Ltd.") 44 | assert.equal(cert.cipher.name, "ECDHE-ECDSA-AES128-GCM-SHA256"); 45 | //console.dir(cert); 46 | done(); 47 | }); 48 | 49 | }); 50 | 51 | it('Fail to get certificate with wrong ssl port', function() { 52 | var promise = sslCertficate.get('www.baidu.com', 8443); 53 | 54 | promise.catch((e) => { 55 | assert.ok(e); 56 | done(); 57 | }) 58 | }); 59 | 60 | it('Fail to get certificate with ssh port', function() { 61 | var promise = sslCertficate.get('example.com', 22); 62 | 63 | promise.catch((e) => { 64 | assert.ok(e); 65 | done(); 66 | }) 67 | }); 68 | 69 | it('Fail to get certificate when host does not support ssl', function(done) { 70 | var promise = sslCertficate.get('127.0.0.1'); 71 | 72 | promise.catch((e) => { 73 | assert.ok(e); 74 | done(); 75 | }) 76 | }); 77 | 78 | }); 79 | -------------------------------------------------------------------------------- /falcon/views/ddos.ejs: -------------------------------------------------------------------------------- 1 | 2 | <% include head %> 3 | 4 | <% include nav %> 5 | 6 |