0x01 前言

verynginx是一款基于lua_nginx_module开发的一款开源的nginx拓展。它可以实现防火墙、统计、等功能,最重要的是它提供了非常简单的操作界面。

我一直使用naxsi(安装naxsi为nginx提供WAF服务)作为nginx的waf,在最近一个月测试verynginx后发现,它也可以实现naxsi的功能,而且使用起来更为方便。但目前我还没有使用verynginx替代naxsi的计划。

0x02 安装

因为verynginx是基于lua开发的,所以我建议使用OpenResty(编译安装基于 Nginx 与 Lua 的高性能 Web 平台-OpenResty)替代原始的nginx版本。在这里我不在叙述编译安装OpenResty的过程,如有需要,请点击上面的链接。

如果你不需要自定义OpenResty,也可以使用verynginx中的安装脚本进行安装。

首先到该项目的GitHub页中下载源代码:

#先建立一个临时文件夹
[root@web-t1 ~]# mkdir codex/verynginx/

#进入该文件夹
[root@web-t1 ~]# cd codex/verynginx/

#从GitHub中下载文件
[root@web-t1 verynginx]# wget https://github.com/alexazhou/VeryNginx/archive/master.zip

#解压
[root@web-t1 verynginx]# unzip master.zip

在解压出来的目录中有以下文件:

#进入解压出来的文件夹
[root@web-t1 verynginx]# cd VeryNginx-master/

#包含的文件如下
[root@web-t1 VeryNginx-master]# ll
total 40
drwxr-xr-x 2 root root   23 Mar 13 23:13 Docker
-rw-r--r-- 1 root root 4669 Mar 13 23:13 install.py
-rw-r--r-- 1 root root 7651 Mar 13 23:13 LICENSE.txt
-rw-r--r-- 1 root root 1169 Mar 13 23:13 nginx.conf
-rw-r--r-- 1 root root 7941 Mar 13 23:13 readme.md
-rw-r--r-- 1 root root 8321 Mar 13 23:13 readme_zh.md
drwxr-xr-x 3 root root   77 Mar 13 23:13 test
drwxr-xr-x 7 root root   84 Mar 13 23:13 verynginx

我们使用install.py这个python文件进行安装:

[root@web-t1 VeryNginx-master]# python install.py 
usage: install.py <cmd> <args> ... 

install cmds and args:
    install
        all        :  install verynginx and openresty(default)
        openresty  :  install openresty
        verynginx  :  install verynginx
    update
        verynginx  :  update the installed verynginx

如果你想使用自行编译的nginx或OpenResty,那么只需要install verynginx;如果想一键安装,则输入install all;还有一个选项是只安装OpenResty:install openresty。

因为我需要使用自行编译的OpenResty,所以安装命令如下:

[root@web-t1 VeryNginx-master]# python install.py install verynginx
### copy VeryNginx files ...
cp -r -f ./verynginx /opt/verynginx
openresty not fount, so not copy nginx.conf
chmod -R 777 /opt/verynginx/verynginx/configs
*** All work finished successfully, enjoy it~

从上面的输出可以看到,只安装verynginx的话,只是做一些复制与权限修改的操作。

0x03 配置

verynginx有以下三个配置文件需要include到相应的位置中:

#添加到http区块外
include /opt/verynginx/verynginx/nginx_conf/in_external.conf;

#添加到http区块内
include /opt/verynginx/verynginx/nginx_conf/in_http_block.conf;

#添加到server区块内
include /opt/verynginx/verynginx/nginx_conf/in_server_block.conf;

简单的配置文件如下:

worker_processes  1;

events {
    worker_connections  1024;
}

include /opt/verynginx/verynginx/nginx_conf/in_external.conf;

http {
    include /opt/verynginx/verynginx/nginx_conf/in_http_block.conf;

    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        include /opt/verynginx/verynginx/nginx_conf/in_server_block.conf;
        
        listen       80;
        server_name  localhost;

        location / {
            root   html;
            index  index.html index.htm;
        }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }

    }

}

请注意上方的高亮行,然后重新加载nginx:

#测试nginx配置文件
[root@web-t1 verynginx]# nginx -t
nginx: the configuration file /usr/local/nginx/nginx.conf syntax is ok
nginx: configuration file /usr/local/nginx/nginx.conf test is successful

#重新加载
[root@web-t1 verynginx]# nginx -s reload

0x04 使用 1 Block URL

在浏览器中输入:

http://[your domain or ip]/verynginx/index.html

即可看到登陆界面,然后使用默认的用户名和密码:verynginx即可登入:

下面来测试block一个路径:

以上是一个不存在的路径,我想服务器返回403,设置如下:

在config标签中选择Matcher,在Add Rule对话框中输入匹配规则名称,然后点选New Conditions添加规则,要注意的是,规则支持正则表达式:

修改了配置请不要忘记保存!

然后在Custom Action中的Filter标签中定义动作:

添加后也需要手动点击save保存!保存后并不需要重新加载nginx,这一切都是动态完成加载的。现在再次测试刚才的404连接,返还的结果为设定的403:

0x05 使用 2 BLOCK UA

我首先使用anache ab进行测试:

MacBook-Air-wifi:~ terence$ ab -c 200 -n 100 -t 99 http://10.1.1.111/

相关图标如下:

nginx日志如下:

10.1.1.66 - - [19/Mar/2017:13:32:11 +0800] "GET / HTTP/1.0" 200 10 "-" "ApacheBench/2.3"

现在我想屏蔽ApacheBench这个UA,那么Matcher的配置为:

然后在Filter中将这个匹配规则的响应设为403或其他即可,在这里我尝试设置为502:

再使用apache ab测试:

MacBook-Air-wifi:~ terence$ ab -c 200 -n 100 -t 99 http://10.1.1.111/

Server Software:        openresty/1.11.2.2
Server Hostname:        10.1.1.111
Server Port:            80

Document Path:          /
Document Length:        179 bytes

Concurrency Level:      200
Time taken for tests:   6.420 seconds
Complete requests:      8411
Failed requests:        0
Non-2xx responses:      8411
Total transferred:      2834507 bytes
HTML transferred:       1505569 bytes
Requests per second:    1310.04 [#/sec] (mean)
Time per request:       152.667 [ms] (mean)
Time per request:       0.763 [ms] (mean, across all concurrent requests)
Transfer rate:          431.14 [Kbytes/sec] received

请注意第14行,全部响应已经是非200。再看看nginx日志:

10.1.2.66 - - [19/Mar/2017:13:37:21 +0800] "GET / HTTP/1.0" 502 179 "-" "ApacheBench/2.3"

所有响应都变成了502,证明配置有效,完全达到应有的目的。下面再试试curl:

#通过curl获取页面
MacBook-Air-wifi:~ terence$ curl http://10.1.1.111

#响应内容
<html>
<head><title>502 Bad Gateway</title></head>
<body bgcolor="white">
<center><h1>502 Bad Gateway</h1></center>
<hr><center>openresty/1.11.2.2</center>
</body>
</html>

curl同样返还502,也达到屏蔽的目的。

0x06 使用 3 防御CC

CC攻击一般是使用工具或脚本不断访问动态页面,诸如搜索或用户验证等页面。但这类工具一般有一个共同点:不跟随302或307跳转、不跟随js跳转、无法验证Cookie等。

如果是正常的浏览器,肯定会有以上动作,当然verynginx也会相应的检测功能:

以下为添加的Cookie验证:

再次通过浏览器访问http://10.1.1.111/,使用控制台检查跳转情况发现有一个302跳转,而且Set-Cookie中存在verynginx_sign_cookie的数值。由此可见,上方的设置是有效的:

我先关闭先前添加的curl UA block,然后使用curl检查,返还302。但curl并不会跟随跳转,所以停留在了302的状态。

MacBook-Air-wifi:~ terence$ curl http://10.1.1.111
<html>
<head><title>302 Found</title></head>
<body bgcolor="white">
<center><h1>302 Found</h1></center>
<hr><center>openresty/1.11.2.2</center>
</body>
</html>

用apache ab检查:

MacBook-Air-wifi:~ terence$ ab -c 200 -n 100 -t 99 http://10.1.1.111/

Server Software:        openresty/1.11.2.2
Server Hostname:        10.1.1.111
Server Port:            80

Document Path:          /
Document Length:        167 bytes

Concurrency Level:      200
Time taken for tests:   6.372 seconds
Complete requests:      10451
Failed requests:        0
Non-2xx responses:      10451
Total transferred:      4567087 bytes
HTML transferred:       1745317 bytes
Requests per second:    1640.27 [#/sec] (mean)
Time per request:       121.931 [ms] (mean)
Time per request:       0.610 [ms] (mean, across all concurrent requests)
Transfer rate:          700.00 [Kbytes/sec] received

日志显示所有的响应为非2xx,查看日志可以发现所有响应码都是302:

10.1.2.66 - - [19/Mar/2017:13:59:48 +0800] "GET / HTTP/1.0" 302 167 "-" "ApacheBench/2.3"

由此可见,这可以达到防御CC攻击的目的。

0x07 结语

这里有一个很重要的地方要注意的:如果开启了浏览器验证功能,也就是防御CC的功能,切记要定义放行的UA,例如百度、Google这类蜘蛛的UA。经过测试发现,蜘蛛大都不会跟随跳转,所以会导致索引量急剧下降或不收录。

这里建议如非必要,请勿开启浏览器验证功能!

经过几天的使用,我觉得这个比naxsi用起来要方便,添加规则也极为方便快捷。

还有一点要注意的是,请不要将这个服务暴露在公网中。如果必须暴露公网中,则务必要做好保护工作,例如使用HTTPS和双向身份验证。可以参考以下文章中双向身份验证的相关内容: