HttpGuard是基于openresty, 以lua脚本语言开发的防cc攻击软件。而openresty是集成了高性能web服务器Nginx,以及一系列的Nginx模块,这其中最重要的,也是 我们主要用到的nginx lua模块。HttpGuard基于nginx lua开发,继承了nginx高并发,高性能的特点,可以以非常小的性能损耗来防范大规模的cc攻击。
下面介绍HttpGuard防cc的一些特性。
限制访客在一定时间内的请求次数
向访客发送302转向响应头来识别恶意用户,并阻止其再次访问
向访客发送带有跳转功能的js代码来识别恶意用户,并阻止其再次访问
向访客发送cookie来识别恶意用户,并阻止其再次访问
支持向访客发送带有验证码的页面,来进一步识别,以免误伤
支持直接断开恶意访客的连接
支持结合iptables来阻止恶意访客再次连接
支持白名单功能
支持根据统计特定端口的连接数来自动开启或关闭防cc模式
被动防御
1. 统计单位时间内单个 IP 的访问次数
2. 统计单位时间内单个 UA 的访问次数(针对火车头)
主动防御
1.302 跳转
2.js 跳转
3.cookie 验证
前两个没啥好说的,很简单的,着重说一下后面三个的实现方式
302跳转
302 跳转主要是对访问的ip随机的进行一次302跳转,而跳转的时候在原始url后面加上几个参数,一般抓取程序或者cc攻击不会去识别header,设定一 个阀值,当一个IP多次不跳转的时候就可以干掉他了。而如果成功进行了跳转的话,一般就可以认为是正常的用户,那么我们可以设置一个cookie值以及时 效,当然cookie的值是经过ip和一些特殊参数计算出来的,不能让别人给破解了,然后在这个时效内不会再对用户进行探测
js跳转
其实js跳转也跟上面类似,不过跳转的方式是通过js来进行的。当一个请求来的时候可以吐出一个简单的js跳转,然后再原始的url后面加上一些参数,接下来的一些验证什么的就跟上面302跳转一样了
cookie验证
cookie验证是当用户第一次访问的时候就给他种下cookie,并记录访问次数,如果第二次来访问没cookie的话可以再次尝试种cookie,当cookie回传失败次数大于某个阀值就可以干掉这个IP了。
github项目地址:https://github.com/centos-bz/HttpGuard
联系作者: admin#centos.bz
赞助作者持续开发: 查看支付宝条码
306972903开始部署HttpGuard
一、安装openresty或者nginx lua
在安装HttpGuard之前,需要先安装openresty或者nginx lua,有三种方法:
使用ezhttp一键安装https://www.lxconfig.com/thread-52-1-1.html
按照openresty官网手动安装http://openresty.com/
安装Nginx并安装nginx_lua模块
二、安装HttpGuard
假设我们把HttpGuard安装到/data/www/waf/,当然你可以选择安装在任意目录。
cd /data/www
wget --no-check-certificate https://github.com/centos-bz/HttpGuard/archive/master.zip
unzip master.zip
mv HttpGuard-master waf
三、生成验证码图片为了支持验证码识别用户,我们需要先生成验证码图片。生成验证码图片需要系统安装有php,以及php-gd模块。
1、编辑/data/www/waf/captcha/getImg.php文件,找到
$font = '/data/www/waf/captcha/t1.ttf';
复制代码
把font的路径正确指向t1.tff文件。
2、以命令行执行getImg.php文件
cd /data/www/waf/captcha/
/usr/local/php/bin/php getImg.php
大概要生成一万个图片,可能需要花几分钟的时间。
四、修改nginx.conf配置文件
向http区块输入如下代码:
lua_package_path "/data/www/waf/?.lua";
lua_shared_dict guard_dict 100m;
lua_shared_dict dict_captcha 70m;
init_by_lua_file '/data/www/waf/init.lua';
access_by_lua_file '/data/www/waf/runtime.lua';
lua_max_running_timers 1;
记得要修改相关的路径。
五、配置HttpGuard
HttpGuard全部的配置项都在config.lua文件中,请根据以下文章修改配置文件。
https://www.lxconfig.com/thread-121-1-1.html
1、设置ASP HTML 等其他页面的保护,如要支持任何后缀类型包含默认首页打开的无后缀的情况
在url-protect/相应的文件中添加一行 $ 即可
2、limitReqModules = { state = "On" , maxReqs = 50 , amongTime = 10, urlProtect = baseDir.."url-protect/limit.txt" },
其中maxReqs的值不宜过小,太小了容易导致即使认证了有些图片也显示不了
3、当设置成保护所有页面时
访问 www.xxx.com/ 输入验证码后,跳到www.xxx.com/favicon.ico
解决方法:保护除 .ico结尾的页面
^(?!\.ico)*.$
Nginx与Lua
Posted on 2012-08-31
火云邪神语录:天下武功,无坚不破,唯快不破!Nginx的看家本领就是速度,Lua的拿手好戏亦是速度,这两者的结合在速度上无疑有基因上的优势。
最先将Nginx,Lua组合到一起的是OpenResty,它有一个ngx_lua模块,将Lua嵌入到了Nginx里面;随后Tengine也包含了ngx_lua模块。至于二者的区别:OpenResty是Nginx的Bundle;而Tengine则是Nginx的Fork。值得一提的是,OpenResty和Tengine均是国人自己创建的项目,前者主要由春哥和晓哲开发,后者主要由淘宝打理。
至于OpenResty和Tengine孰优孰劣,留给大家自己判断,如下资料可供参考:
ngx_openresty: an Nginx ecosystem glued by Lua
淘宝网Nginx应用、定制与开发实战
推荐看看春哥在Tech-Club上关于『由Lua粘合的Nginx生态环境』的演讲实录,有料!
安装
需要最新版的Nginx,LuaJIT,ngx_devel_kit,ngx_lua等安装文件。
安装Lua或者LuaJIT都是可以的,但是出于效率的考虑,推荐安装LuaJIT。
shell> wget http://luajit.org/download/LuaJIT-<VERSION>.tar.gz shell> tar zxvf LuaJIT-<VERSION>.tar.gz shell> cd LuaJIT-<VERSION> shell> make shell> make install
因为安装在缺省路径,所以LuaJIT对应的lib,include均在/usr/local目录里。
shell> export LUAJIT_LIB=/usr/local/lib shell> export LUAJIT_INC=/usr/local/include/luajit-<VERSION>
下面就可以编译Nginx了:
shell> wget http://nginx.org/download/nginx-<VERSION>.tar.gz shell> tar zxvf nginx-<VERSION>.tar.gz shell> cd nginx-<VERSION> shell> ./configure --add-module=/path/to/ngx_lua \ --add-module=/path/to/ngx_devel_kit shell> make shell> make install
试着启动一下Nginx看看,如果你运气不好的话,可能会遇到如下错误:
cannot open shared object file: No such file or directory
这是神马情况?可以用ldd命令来看看:
shell> ldd /path/to/nginx libluajit-<VERSION>.so => not found
此类问题通常使用ldconfig命令就能解决:
shell> echo "/usr/local/lib" > /etc/ld.so.conf.d/usr_local_lib.conf shell> ldconfig
再试着启动Nginx看看,应该就OK了。
应用
我们先用一个简单的程序来暖暖场:把下面的代码加入到Nginx的配置文件nginx.conf,并重启Nginx,然后浏览,就能看到效果了。
location /lua { set $test "hello, world."; content_by_lua ' ngx.header.content_type = "text/plain"; ngx.say(ngx.var.test); '; }
在深入学习ngx_lua之前,建议大家仔细阅读一遍春哥写的Nginx教程。
这 里我就说关键的:Nginx配置文件所使用的语言本质上是『声明性的』,而非『过程性的』。Nginx处理请求的时候,指令的执行并不是由定义指令时的物 理顺序来决定的,而是取决于指令所属的阶段,Nginx常用的阶段按先后顺序有:rewrite阶段,access阶段,content阶段等等。演示代 码中的set指令属于rewrite阶段,content_by_lua指令属于content阶段,如果试着把两条指令的顺序交换一下,会发现程序依然 能够正常运行。
下面我们尝试结合Redis写个更实战一点的例子。
首先,我们需要创建一个Redis配置文件config.json,内容如下:
{ "host": "<HOST>", "port": "<PORT>" }
然后,我们创建一个解析配置文件的脚本init.lua,其中用到了Lua CJSON模块:
local cjson = require "cjson"; local config = ngx.shared.config; local file = io.open("config.json", "r"); local content = cjson.decode(file:read("*all")); file:close(); for name, value in pairs(content) do config:set(name, value); end
说明:代码里用到了共享内存,这样就不必每次请求都解析一遍配置文件了。
接着,我们创建一个渲染内容的脚本content.lua,用到了Resty Redis模块:
ngx.header.content_type = "text/plain"; local redis = require "resty.redis"; local config = ngx.shared.config; local instance = redis:new(); local host = config:get("host"); local port = config:get("port"); local ok, err = instance:connect(host, port); if not ok then ngx.log(ngx.ERR, err); ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE); end instance:set("name", "laowang"); local name = instance:get("name") instance:close(); ngx.say("name: ", name);
说明:建议把Resty Redis模块放到vendor目录下,稍后在Nginx中统一设置。
最后,我们需要在Nginx配置文件里设置一下:
lua_shared_dict config 1m; lua_package_path "/path/to/vendor/?.lua;;"; init_by_lua_file /path/to/init.lua; server { lua_code_cache off; location /lua { content_by_lua_file /path/to/content.lua; } ... }
说明:为了方便调试,我关闭了lua_code_cache,如果是生产环境,应该开启它。
另外,安装CJSON的时候,需要注意Makefile文件里头文件的路径,缺省是:
PREFIX = /usr/local LUA_INCLUDE_DIR = $(PREFIX)/include
如果安装的是LuaJIT的话,最好把头文件拷贝到相应目录:
cp /usr/local/include/luajit-<VERSION>/* /usr/local/include/
…
我最近参与的一个项目,提供了一些用于Web轮询的接口,都是用Nginx+Lua实现的,虽然总共只有十几台服务器,但是每天可以提供几十亿次的请求量,贼拉拉的强。
最后,让我引用某位�潘康挠锫甲鼋崾�语吧:Lua,未婚男性程序员的最爱。