【nodejs代理服务器四】代理服务器增加频繁访问的ip加入黑名单

简介: 【nodejs代理服务器四】代理服务器增加频繁访问的ip加入黑名单

问题

渗透者在扫站的时候会频繁请求,我们可以做一些策略来封堵这些频繁访问的ip,把ip加入黑名单。


策略

2秒之内访问次数超过100,加入黑名单。


实现思路

  1. 初次访问把访问Ip作为键,访问ip,时间,次数(初始值为1)封装为一个对象作为value,放入map。
  2. 开启定时器,定时器每秒执行一次,在定时器里面循环map,2秒之内访问次数超过100的ip加入名单数组,同时清除加入黑名单ip对应的map key和value.
  3. 在代理程序之前,判断请求过来的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的过期缓存机制来实现频繁访问的缓存功能。

大概先这么多。。。

相关文章
|
8天前
|
JavaScript
NodeJs——无法使用内网IP访问
NodeJs——无法使用内网IP访问
9 1
|
16天前
|
自然语言处理 JavaScript 数据挖掘
Node.js服务器如何搭建?
【8月更文挑战第4天】Node.js服务器如何搭建?
24 2
|
16天前
|
缓存 负载均衡 JavaScript
Node.js 服务器性能优化
【8月更文挑战第4天】 Node.js 服务器性能优化
19 1
|
21天前
|
弹性计算 运维 数据安全/隐私保护
云服务器 ECS产品使用问题之如何更改服务器的IP地址或端口号
云服务器ECS(Elastic Compute Service)是各大云服务商阿里云提供的一种基础云计算服务,它允许用户租用云端计算资源来部署和运行各种应用程序。以下是一个关于如何使用ECS产品的综合指南。
|
1月前
|
前端开发 JavaScript
【node写接口】 通过node 快速搭建一个服务器、get请求、post请求 小白入门
【node写接口】 通过node 快速搭建一个服务器、get请求、post请求 小白入门
52 4
|
22天前
|
XML 存储 网络协议
/etc/netplan/network-manager-all.yaml 配置服务器ip
/etc/netplan/network-manager-all.yaml 配置服务器ip
40 0
若依修改,若依部署在本地运行时的注意事项,后端连接了服务器,本地的vue.config.js要先改成localhost:端口号与后端匹配,部署的时候再改公网IP:端口号
若依修改,若依部署在本地运行时的注意事项,后端连接了服务器,本地的vue.config.js要先改成localhost:端口号与后端匹配,部署的时候再改公网IP:端口号
|
4天前
|
机器学习/深度学习 编解码 人工智能
阿里云gpu云服务器租用价格:最新收费标准与活动价格及热门实例解析
随着人工智能、大数据和深度学习等领域的快速发展,GPU服务器的需求日益增长。阿里云的GPU服务器凭借强大的计算能力和灵活的资源配置,成为众多用户的首选。很多用户比较关心gpu云服务器的收费标准与活动价格情况,目前计算型gn6v实例云服务器一周价格为2138.27元/1周起,月付价格为3830.00元/1个月起;计算型gn7i实例云服务器一周价格为1793.30元/1周起,月付价格为3213.99元/1个月起;计算型 gn6i实例云服务器一周价格为942.11元/1周起,月付价格为1694.00元/1个月起。本文为大家整理汇总了gpu云服务器的最新收费标准与活动价格情况,以供参考。
阿里云gpu云服务器租用价格:最新收费标准与活动价格及热门实例解析
|
7天前
|
云安全 弹性计算 安全
阿里云服务器基础安全防护简介,云服务器基础安全防护及常见安全产品简介
在使用云服务器的过程中,云服务器的安全问题是很多用户非常关心的问题,阿里云服务器不仅提供了一些基础防护,我们也可以选择其他的云安全类产品来确保我们云服务器的安全。本文为大家介绍一下阿里云服务器的基础安全防护有哪些,以及阿里云的一些安全防护类云产品。
阿里云服务器基础安全防护简介,云服务器基础安全防护及常见安全产品简介
|
6天前
|
机器学习/深度学习 弹性计算 人工智能
阿里云第八代云服务器ECSg8i实例深度解析:性能及适用场景参考
目前企业对云服务器的性能、安全性和AI能力的要求日益提高。阿里云推出的第八代云服务器ECS g8i实例,以其卓越的性能、增强的AI能力和全面的安全防护,除了适用于通用互联网应用和在线音视频应用等场景之外,也广泛应用于AI相关应用。本文将深入解析ECS g8i实例的技术特性、产品优势、适用场景及与同类产品的对比,以供参考。
阿里云第八代云服务器ECSg8i实例深度解析:性能及适用场景参考