【nodejs代理服务器一】nodejs http-proxy 开发反向代理服务器,防火墙,过滤常见的web渗透
事出有因
最近web系统引来了黑客的攻击,经常被扫描,各种漏洞尝试。
分析攻击日志,有几种常见的攻击手段:
- 上传webshell
- 远程执行命令漏洞
- sql注入
- xxs 攻击
- 试探各种开源框架爆出来的漏洞
分析攻击信息的特点
说白了就是采用web渗透技术,利用http请求,黑客想尽办法,在http header ,body,等部分植入非法的命令,非法字符常见的有:exe,cmd,powershell,download,select,union,delete等等。
解决问题思路
- 我们能不能开发个代理服务器,来分析http请求header,body里面的信息,如果有非法字符,就截断,拒绝服务。
- 配置允许请求的白名单,拒绝非法Url.
网络拓扑

http proxy 拦截非法请求,拒绝服务。
技术选型
常见的代理服务器有nginx,apache,不知道这2个代理服务器能不能灵活的配置,过滤,转发,没有深入了解。
因此选用nodejs http-proxy。
nodejs优点
- 轻量级
- 快速部署
- 灵活开发
- 高吞吐,异步io
编码实现逻辑图

绝对干货,分享代码
代码依赖
- http-proxy 1.17.0
https://github.com/nodejitsu/node-http-proxy 代码地址 - "colors": "~0.6.2",
var util = require('util'),
colors = require('colors'),
http = require('http'),
httpProxy = require('./node_modules/http-proxy');
fs = require("fs");
var welcome = [
'# # ##### ##### ##### ##### ##### #### # # # #',
'# # # # # # # # # # # # # # # # ',
'###### # # # # ##### # # # # # # ## # ',
'# # # # ##### ##### ##### # # ## # ',
'# # # # # # # # # # # # # ',
'# # # # # # # # #### # # # '
].join('\n');
Date.prototype.Format = function(fmt) { //author: meizz
var o = {
"M+": this.getMonth() + 1, //月份
"d+": this.getDate(), //日
"h+": this.getHours(), //小时
"m+": this.getMinutes(), //分
"s+": this.getSeconds(), //秒
"S": this.getMilliseconds() //毫秒
};
if (/(y+)/.test(fmt)) fmt = fmt.replace(RegExp.$1, (this.getFullYear() + "").substr(4 - RegExp.$1.length));
for (var k in o)
if (new RegExp("(" + k + ")").test(fmt)) fmt = fmt.replace(RegExp.$1, (RegExp.$1.length == 1) ? (o[k]) : (("00" + o[k]).substr(("" + o[k]).length)));
return fmt;
}
// 非法字符
var re = /php|exe|cmd|shell|select|union|delete|update|insert/;
/** 这里配置转发
*/
var proxyPassConfig = {
"/hello": "http://www.qingmiaokeji.cn ",
"/": "http://127.0.0.1/"
}
var logRootPath ="g:/httpproxy/";
console.log(welcome.rainbow.bold);
function getCurrentDayFile(){
// console.log(logRootPath+"access_"+(new Date()).Format("yyyy-MM-dd")+".log");
return logRootPath+"access_"+(new Date()).Format("yyyy-MM-dd")+".log";
}
//
// Basic Http Proxy Server
//
var proxy = httpProxy.createProxyServer({});
var server = http.createServer(function (req, res) {
appendLog(req)
var postData = "";
req.addListener('end', function(){
//数据接收完毕
console.log(postData);
if(!isValid(postData)){//post请求非法参数
invalidHandler(res)
}
});
req.addListener('data', function(postDataStream){
postData += postDataStream
});
var result = isValid(req.url)
//验证http头部是否非法
for(key in req.headers){
result = result&& isValid(req.headers[key])
}
if (result) {
var patternUrl = urlHandler(req.url);
console.log("patternUrl:" + patternUrl);
if (patternUrl) {
proxy.web(req, res, {target: patternUrl});
} else {
noPattern(res);
}
} else {
invalidHandler(res)
}
});
proxy.on('error', function (err, req, res) {
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong.');
});
/**
* 验证非法参数
* @param value
* @returns {boolean} 非法返回False
*/
function isValid(value) {
return re.test(value) ? false : true;
}
/**
* 请求转发
* @param url
* @returns {*}
*/
function urlHandler(url) {
var tempUrl = url.substring(url.lastIndexOf("/"));
return proxyPassConfig[tempUrl];
}
function invalidHandler(res) {
res.writeHead(400, {'Content-Type': 'text/plain'});
res.write('Bad Request ');
res.end();
}
function noPattern(res) {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('not found');
res.end();
}
function getClientIp(req){
return req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
}
function appendLog(req) {
console.log("request url:" + req.url);
var logData = (new Date()).Format("yyyy-MM-dd hh:mm:ss")+" "+getClientIp(req)+" "+req.method+ " "+req.url+"\n";
fs.exists(logRootPath,function(exists){
if(!exists){
fs.mkdirSync(logRootPath)
}
fs.appendFile(getCurrentDayFile(),logData,'utf8',function(err){
if(err)
{
console.log(err);
}
});
})
}
console.log("listening on port 80".green.bold)
server.listen(80);
思路扩展
- 拦截非法字符后可以发邮件通知管理员
- 可以把日志发送到日志系统,进行大数据分析
- 增加频繁访问,拒绝Ip功能。 可以利用redis 过期缓存实现。
【nodejs代理服务器一】nodejs http-proxy 开发反向代理服务器,防火墙,过滤常见的web渗透的更多相关文章
- 用PHP实现反向代理服务器
什么是反向代理: 百度百科有云: 反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给int ...
- Windows下使用nginx搭建反向代理服务器
反向代理(Reverse Proxy)方式是指以代理服务器来接受internet上的连接请求,然后将请求转发给内部网络上的服务器,并将从服务器上得到的结果返回给internet上请求连接的客户端,此时 ...
- Nginx 一个高性能的HTTP和反向代理服务器
本文只针对Nginx在不加载第三方模块的情况能处理哪些事情,由于第三方模块太多所以也介绍不完,当然本文本身也可能介绍的不完整,毕竟只是我个人使用过和了解过,欢迎留言交流. Nginx能做什么 ——反向 ...
- 高并发解决方案--负载均衡(HTTP,DNS,反向代理服务器)(解决大流量,高并发)
高并发解决方案--负载均衡(HTTP,DNS,反向代理服务器)(解决大流量,高并发) 一.总结 1.什么是负载均衡:当一台服务器的性能达到极限时,我们可以使用服务器集群来提高网站的整体性能.那么,在服 ...
- 如何搭建web服务器 使用Nginx搭建反向代理服务器 .
引言:最近公司有台服务器遭受DDOS攻击,流量在70M以上,由于服务器硬件配置较高所以不需要DDOS硬件防火墙.但我们要知道,IDC机房是肯定不允许这种流量一直处于这么高的,因为没法具体知道后面陆续攻 ...
- apache代理服务器为nodejs服务设置域名
本机以apache为主,其中 在httpd.conf中先设置 <VirtualHost *:80> ServerName nodejs.cc ServerAlias www.nodejs. ...
- nodeJS学习(4)--- webstorm/...开发 NodeJS 项目-节1
前提: 已安装好 IDE ,eg:webstorm/IDEA 2016.3 & 2017.1 nodeJS(含 npm 及 相应的模板等) 要用 webstorm 开发 NodeJS项目(we ...
- 【APT】NodeJS 应用仓库钓鱼,大规模入侵开发人员电脑,批量渗透各大公司内网
APT][社工]NodeJS 应用仓库钓鱼,大规模入侵开发人员电脑,批量渗透各大公司内网 前言 城堡总是从内部攻破的.再强大的系统,也得通过人来控制.如果将入侵直接从人这个环节发起,那么再坚固的防线, ...
- 反向代理服务器(Reverse Proxy)
反向代理服务器(Reverse Proxy) 普通代理服务器是帮助内部网络的计算机访问外部网络.通常,代理服务器同时连接内网和外网.首先内网的计算机需要设置代理服务器地址和端口,然后将HTTP请求 ...
随机推荐
- 手写C++代码实现POST传输数据
char *pHttpPost = "POST %s HTTP/1.1\r\n" "Host: %s:%d\r\n" "Content-Type: a ...
- Docker 持久存储介绍(十三)
目录 一.Docker 数据存储 二.Bind mount 1.详细介绍 2.如何使用 -v or --volume 语法 --mount 语法 两者区别 3.使用场景 4.使用案例 存在目录 bin ...
- Python----数据预处理代码实例
为方便收藏学习,转载自:https://www.jb51.net/article/158168.htm 本文实例为大家分享了Python数据预处理的具体代码,供大家参考,具体内容如下 1.导入标准库 ...
- 八个免费的Vue图标库
1. Vue-awesome 也许大家知道 Font-awesome 之类比较流行的图标库,就像各大组件库都有各自版本一样,它也有Vue的版本 Github地址:https://github.com/ ...
- luogu1972:HH的项链
题目描述 HH 有一串由各种漂亮的贝壳组成的项链.HH 相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH 不断地收集新的贝壳,因此,他的项链变得越来越长. ...
- tomcat修改server.xml的虚拟目录,启动eclipse后清空
修改eclipse中servers的server.xml 参考文章:https://blog.csdn.net/binglong_world/article/details/77604324
- python 字典dict - python基础入门(15)
前面的课程讲解了字符串str/列表list/元组tuple,还有最后一种比较重要的数据类型也需要介绍介绍,那就是python字典,俗称:dict. python中的字典可与字符串/列表/元组不同,因为 ...
- go变量的定义并赋值
变量在定义时没有明确的初始化时会赋值为_零值_. 零值是: 数值类型为 `0`, 布尔类型为 `false`, 字符串为 `""`(空字符串). package main impo ...
- gin mongodb restful api设计: 动态的patch接口
目录 什么是Patch? Patch方法可以用来更新资源的一个组成部分 什么时候使用Patch? 当你仅需更新资源的某一项,即不完全也不幂等 那当我们的模型在数据库中几乎每个字段都可能会遇到改变的时候 ...
- mysql5.7主主(双主)复制
在server1上操作 vi /etc/my.cnf 修改或添加下面这几行: server-id=1 log-bin=mysql-bin # 启用二进制日志 auto-increment-increm ...