【nodejs代理服务器四】代理服务器增加频繁访问的ip加入黑名单
问题
渗透者在扫站的时候会频繁请求,我们可以做一些策略来封堵这些频繁访问的ip,把ip加入黑名单。
策略
2秒之内访问次数超过100,加入黑名单。
实现思路
- 初次访问把访问Ip作为键,访问ip,时间,次数(初始值为1)封装为一个对象作为value,放入map。
- 开启定时器,定时器每秒执行一次,在定时器里面循环map,2秒之内访问次数超过100的ip加入黑名单数组,同时清除加入黑名单ip对应的map key和value.
- 在代理程序之前,判断请求过来的ip是否在黑名单,如果在,就拒绝访问。
核心代码
/**
www.qingmiaokeji.cn
* ip 频繁访问限制策略
* 2秒之内访问次数超过100,加入黑名单。
* 可能存在并发问题
* @constructor
*/
function IPPolicy () {
this.cache = {};
this.blackIpList=[];
var $this = this;
setInterval (function () {
var nowTime = new Date().getTime();
for(ip in $this.cache){
var item = $this.cache[ip];
var timeDif = nowTime - item.visitTime;
if(timeDif<2000 && item.count>100 ){
$this.blackIpList.push(ip)
delete $this.cache[ip];
}else{
item.count = 0;
}
}
},1000)
}
IPPolicy.prototype.addVisitIp = function (ip) {
if(this.cache[ip]){
this.cache[ip].count = this.cache[ip].count+1;
this.cache[ip].visitTime =new Date().getTime();
}else{
this.cache[ip] ={"ip":ip,"count":1,"visitTime":new Date().getTime()}
}
}
完整代码
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;
}
String.prototype.startWith=function(str){
var reg=new RegExp("^"+str);
return reg.test(this);
}
// 非法字符
var re = /php|exe|cmd|shell|select|union|delete|update|truncate|insert|eval|function/;
/** 这里配置转发
*/
var proxyPassConfig = {
"/test": 'http://127.0.0.1:8080/hello',
"/": "http://www.qingmiaokeji.cn/"
}
/**
* ip 频繁访问限制策略
* 2秒之内访问次数超过100,加入黑名单。
* 可能存在并发问题
* @constructor
*/
function IPPolicy () {
this.cache = {};
this.blackIpList=[];
var $this = this;
setInterval (function () {
var nowTime = new Date().getTime();
for(ip in $this.cache){
var item = $this.cache[ip];
var timeDif = nowTime - item.visitTime;
if(timeDif<2000 && item.count>100 ){
$this.blackIpList.push(ip)
delete $this.cache[ip];
}else{
item.count = 0;
}
}
},1000)
}
IPPolicy.prototype.addVisitIp = function (ip) {
if(this.cache[ip]){
this.cache[ip].count = this.cache[ip].count+1;
this.cache[ip].visitTime =new Date().getTime();
}else{
this.cache[ip] ={"ip":ip,"count":1,"visitTime":new Date().getTime()}
}
}
var iPPolicy = new IPPolicy();
var logRootPath ="d:/httpproxy/";
console.log(welcome.rainbow.bold);
//
// Basic Http Proxy Server
//
var proxy = httpProxy.createProxyServer({});
var server = http.createServer(function (req, res) {
appendLog(req)
var ip = getClientIp(req)
if(iPPolicy.blackIpList.indexOf(ip)>=0){
console.log("ip在黑名单");
backIpHandler(res)
return
}
iPPolicy.addVisitIp(ip);
var postData = "";
req.addListener('end', function(){
//数据接收完毕
console.log(postData);
if(!isValid(postData)){//post请求非法参数
invalidHandler(res)
}
});
req.addListener('data', function(postDataStream){
postData += postDataStream
});
var patternUrl = urlHandler(req.url);
console.log("patternUrl:" + patternUrl);
if (patternUrl) {
var result = isValid(req.url)
//验证http头部是否非法
for(key in req.headers){
result = result&& isValid(req.headers[key])
}
if (result) {
proxy.web(req, res, {target: patternUrl});
} else {
invalidHandler(res)
}
} else {
noPattern(res);
}
});
//代理异常捕获
proxy.on('error', function (err, req, res) {
console.error(err)
try{
res.writeHead(500, {
'Content-Type': 'text/plain'
});
res.end('Something went wrong.');
}catch (e) {
console.error(err)
}
});
/**
* 验证非法参数
* @param value
* @returns {boolean} 非法返回False
*/
function isValid(value) {
return re.test(value.toLowerCase()) ? false : true;
}
/**
* 请求转发
* @param url
* @returns {*}
*/
function urlHandler(url) {
if("/" == url)
return proxyPassConfig["/"];
for(patternUrl in proxyPassConfig ){
if(url.startWith(patternUrl)){
return proxyPassConfig[patternUrl]
}
}
return proxyPassConfig[tempUrl];
}
//非法请求
function invalidHandler(res) {
res.writeHead(400, {'Content-Type': 'text/plain'});
res.write('Bad Request ');
res.end();
}
function backIpHandler(res) {
res.writeHead(500, {'Content-Type': 'text/plain',"charset":"utf-9"});
res.write('ip frequent access ');
res.end();
}
//匹配不到
function noPattern(res) {
res.writeHead(404, {'Content-Type': 'text/plain'});
res.write('not found');
res.end();
}
//获取访问id
function getClientIp(req){
return req.headers['x-forwarded-for'] ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress;
}
//当天日志名称生成
function getCurrentDayFile(){
return logRootPath+"access_"+(new Date()).Format("yyyy-MM-dd")+".log";
}
//访问日志
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);
不足之处
- 对map操作可能不是线程安全?
- 定时器循环map元素需要时间,2秒时间间隔上可能不是很准确。
完善扩展
- 可用redis的过期缓存机制来实现频繁访问的缓存功能。
大概先这么多。。。
【nodejs代理服务器四】代理服务器增加频繁访问的ip加入黑名单的更多相关文章
- linux安全篇:禁止频繁访问的ip访问nginx
实验环境 版本:redhat6.5ip:172.16.1.100,172.16.10软件:nginx 172.16.1.10部署nginx [root@localhost tools]# lsngin ...
- Oracle数据库IP访问限制(IP白名单黑名单)
1.编辑sqlnet.ora 内容为: #允许访问的IP(白名单) TCP.INVITED_NODES=(127.0.0.1,192.168.56.109,ip2,ip3,..,..本地IP..)若使 ...
- shiro之redis频繁访问问题
目前安全框架shiro使用较为广泛,其功能也比较强大.为了分布式session共享,通常的做法是将session存储在redis中,实现多个节点获取同一个session.此实现可以实现session共 ...
- PHP禁止同一IP频繁访问以防止网站被防攻击或采集的代码
PHP禁止同一IP频繁访问以防止网站被防攻击或采集的代码 <?php /* *通过禁止IP频繁访问防止网站被防攻击代码*design by www.scutephp.com*/header('C ...
- .Net频繁访问数据库的优化探究(一)
知识点:DataTable.Linq.lamda表达式.Cache 场景:查询部门的所有员工和管理员,并分配相应的权限 实现过程一般为:查询部门,遍历部门(查询员工.分配权限.查询管理员.分配权限) ...
- 域名访问和ip访问区别
域名访问和ip访问区别 ip访问对应某一台确定的服务器: 域名访问相当于在ip访问的基础上,做了一个反向代理的中间功能.例如:百度,很多人会同时使用,如果使用的是同一台服务器的话,服务器估计会扛不住, ...
- 转载:通过监控Nginx日志来实时屏蔽高频恶意访问的IP
通过监控Nginx日志来实时屏蔽高频恶意访问的IP 目前在我的VPS上主要通过两种方式来限制ip的访问次数. 通过Nginx的limit_req配置来限制同一ip在一分钟内的访问次数 通过Ngin ...
- 获取客户端访问真实 IP
转载自:https://www.qikqiak.com/post/get-client-realip/ 通常,当集群内的客户端连接到服务的时候,是支持服务的 Pod 可以获取到客户端的 IP 地址的, ...
- Nginx禁止ip访问或IP网段访问方法
Nginx禁止ip访问可以防止指定IP访问我们的网站,本例子可以实现是防止单IP访问或IP网段访问了,非常的有用我们一起来看看吧. 常用的linux做法 iptables参考规则 代码如下 复制代码 ...
随机推荐
- Centos7 手动编译 RabbitMQ ,并安装php amqp
RabbitMQ是一个在AMQP基础上完成的,可复用的企业消息系统,底层基于Erlang语言. 一:centos7安装RabbitMQ 这玩意儿安装很扯淡,官方推荐rpm安装,rpm安装本身是最简单的 ...
- 保存wave音频流的方法
保存到文件: void saveToFile(String filename, ByteBuffer buffer) { byte[] bytes = buffer.array(); OutputSt ...
- 安装kubernet(k8s)
简介: 需要学习的都明白,这里就不赘述了. 本文采用CentOS-7-x86_64-DVD-1810.iso 一:安装操作系统 本来是喜欢用fedora的,但是fedora貌似包维护的不好,就又开始用 ...
- 【Leetcode_easy】1160. Find Words That Can Be Formed by Characters
problem 1160. Find Words That Can Be Formed by Characters solution class Solution { public: int coun ...
- jqweui Popup 使用说明
使用步骤说明: 今天遇到一个问题,无论怎么点击一个图标都不会弹出对应的遮罩层,但是把示列代码拷贝过来又可以正常显示:结果是由于在复制的时候把 # 号弄掉了 错误操作展示: <a href=&qu ...
- Swoole练习 websocket
WEBSOCKET 服务端代码 //创建websocket服务器对象,监听0.0.0.0:9502端口 $ws = new swoole_websocket_server("0.0.0.0& ...
- ubuntu 安装 typora
# or run: # sudo apt-key adv --keyserver keyserver.ubuntu.com --recv-keys BA300B7755AFCFAE wget -qO ...
- java学习笔记(6)-多线程(1)
标签(空格分隔): 笔记 一.基本概念 1.1 程序.进程.线程 程序(program):是为完成特定任务.用某种语言编写的一组指令的集合.即指一段静态的代码,静态对象. 进程(process):是程 ...
- redis 主从 哨兵
数据库为什么要读写分离 写代码好多年了,大家先抛弃在代码框架里面各种花哨的设计之外,写的代码到最后无非就是为了增删查改数据库.一般项目数据库刚开始只是但一个库,随着数据量的增大,就开始优化数据库(抛开 ...
- 客户端负载均衡Ribbon之三:AvailabilityFilteringRule的坑(Spring Cloud Finchley.SR2)
我们项目配置了AvailabilityFilteringRule作为所有Ribbon调用的负载均衡规则,它有那些坑呢(理解歧义和注意点)? 首先来看com.netflix.loadbalancer.A ...