我们都知道Nginx有很多的特性和好处,但是在Nginx上开发成了一个难题,Nginx模块需要用C开发,而且必须符合一系列复杂的规则,最重要的用C开发模块必须要熟悉Nginx的源代码,使得开发者对其望而生畏。为了开发人员方便,所以接下来我们要介绍一种整合了Nginx和lua的框架,那就是OpenResty,它帮我们实现了可以用lua的规范开发,实现各种业务,并且帮我们弄清楚各个模块的编译顺序。关于OpenResty,我想大家应该不再陌生,随着系统架构的不断升级、优化,OpenResty在被广泛的应用。
Nginx 采用的是 master-worker 模型,一个 master 进程管理多个 worker 进程,基本的事件处理都是放在 woker 中,master 负责一些全局初始化,以及对 worker 的管理。在OpenResty中,每个 woker 使用一个 LuaVM,当请求被分配到 woker 时,将在这个 LuaVM 里创建一个 coroutine(协程)。协程之间数据隔离,每个协程具有独立的全局变量_G。
ps. 协程和多线程下的线程类似:有自己的堆栈,自己的局部变量,有自己的指令指针,但是和其他协程程序共享全局变量等信息。线程和协程的主要不同在于:多处理器的情况下,概念上来说多线程是同时运行多个线程,而协程是通过代码来完成协程的切换,任何时刻只有一个协程程序在运行。并且这个在运行的协程只有明确被要求挂起时才会被挂起。
首先我们选择使用OpenResty,其是由Nginx核心加很多第三方模块组成,其最大的亮点是默认集成了Lua开发环境,使得Nginx可以作为一个Web Server使用。
借助于Nginx的事件驱动模型和非阻塞IO,可以实现高性能的Web应用程序。
而且OpenResty提供了大量组件如Mysql、Redis、Memcached等等,使在Nginx上开发Web应用更方便更简单。目前在京东如实时价格、秒杀、动态服务、单品页、列表页等都在使用Nginx+Lua架构,其他公司如淘宝、去哪儿网等。
机器规划
192.168.10.191 |
安装openresty |
192.168.10.192 |
压力测试访问策略 |
部署,不难,很多地方都能能找到就不多说了
yum -y install gcc gcc-c++ automake pcre pcre-devel zlib zlib-devel openssl openssl-devel useradd www -u 10000 -s /sbin/nologin -M mkdir -p /application wget https://openresty.org/download/openresty-1.15.8.2.tar.gz tar xf openresty-1.15.8.2.tar.gz -C /application/ cd /application/openresty-1.15.8.2/ ./configure --prefix=/application/openresty-1.15.8.2 --with-luajit --with-pcre --with-pcre-jit --user=www --group=www --with-http_stub_status_module --with-http_ssl_module gmake && gmake install ln -s /application/openresty-1.15.8.2 /application/openresty
测试openresty安装
#修改nginx.conf文件,添加如下location段
vim /application/openresty/nginx/conf/nginx.conf
location /hi { default_type text/html; content_by_lua_block{ ngx.say("hello openrastry!!!"); } }
#重载openresty中的nginx服务
/application/openresty/nginx/sbin/nginx -t /application/openresty/nginx/sbin/nginx -s reload
基于openresty来部署WAF
在github上克隆下代码
git clone https://github.com/unixhot/waf.git
将waf文件拷贝到openresty的nginx路径下
cp -r waf/waf/ /application/openresty/nginx/conf/
修改waf中的config.lua文件,修改lua防火前规则路径
vim /application/openresty/nginx/conf/waf/config.lua
--WAF config file,enable = "on",disable = "off" --waf status config_waf_enable = "on" --log dir config_log_dir = "/tmp/waf_logs" --rule setting config_rule_dir = "/application/openresty/nginx/conf/waf/rule-config" --enable/disable white url config_white_url_check = "on" --enable/disable white ip config_white_ip_check = "on" --enable/disable block ip config_black_ip_check = "on" --enable/disable url filtering config_url_check = "on" --enalbe/disable url args filtering config_url_args_check = "on" --enable/disable user agent filtering config_user_agent_check = "on" --enable/disable cookie deny filtering config_cookie_check = "on" --enable/disable cc filtering config_cc_check = "on" --cc rate the xxx of xxx seconds config_cc_rate = "30/60" --enable/disable post filtering config_post_check = "on" --config waf output redirect/html config_waf_output = "html" --if config_waf_output ,setting url config_waf_redirect_url = "https://www.cnblogs.com/huanglingfa" config_output_html=[[ <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <meta http-equiv="Content-Language" content="zh-cn" /> <title>网站防火墙</title> </head> <body> <h1 align="center"> 您的行为已违反本网站相关规定,注意操作规范。</h1> </body> </html> ]]
修改openresty中nginx的配置文件,在http段添加如下内容
vim /application/openresty/nginx/conf/nginx.conf
lua_shared_dict limit 50m; #防cc使用字典,大小50M lua_package_path "/application/openresty/nginx/conf/waf/?.lua"; init_by_lua_file "/application/openresty/nginx/conf/waf/init.lua"; access_by_lua_file "/application/openresty/nginx/conf/waf/access.lua";
根据日志记录位置,创建日志目录并授予www用户的权限
mkdir /tmp/waf_logs chown www.www /tmp/waf_logs/
检查nginx语法并重载nginx服务
/application/openresty/nginx/sbin/nginx -t /application/openresty/nginx/sbin/nginx -s reload
至于lua语言的编写可以参考Nginx API for Lua :
https://github.com/openresty/lua-nginx-module#nginx-api-for-lua
模拟sql注入即url攻击
http://192.168.10.191/mysql.sql
这时候日志显示如下,记录了UA,匹配规则,URL,客户端类型,攻击的类型,请求的数据
tail -f /tmp/waf_logs/2020-10-18_waf.log {"local_time":"2020-10-18 20:38:16","client_ip":"192.168.10.1","rule_tag":"\.(bak|inc|old|mdb|sql|backup|java|class|tgz|gz|tar|zip)$","attack_method":"Deny_URL","server_name":"localhost","req_url":"/mysql.sql","req_data":"-","user_agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.75 Safari/537.36"}
使用一台客户端,使用ab压测工具模拟防cc攻击
yum install httpd-tools -y
压力并发测试
ab -c 50 -n 1000 http://192.168.10.191/
Server Software: openresty/1.15.8.2 Server Hostname: 192.168.10.191 Server Port: 80 Document Path: / Document Length: 649 bytes Concurrency Level: 50 Time taken for tests: 1.588 seconds Complete requests: 1000 Failed requests: 989 (Connect: 0, Receive: 0, Length: 989, Exceptions: 0)
#从上面可以看出失败了989此请求,这是由config.lua配置文件配置决定的
vim /application/openresty/nginx/conf/waf/config.lua
--cc rate the xxx of xxx seconds
config_cc_rate = "10/60"
当然还可以模拟ip黑名单和模拟ip白名单,配置类似,只要在
/application/openresty/nginx/conf/waf/rule-config/whiteip.rule 或 blackip.rule
规则文件添加白名单的ip或黑名单的ip
模拟URL参数检测: 浏览器输入:
http://192.168.10.191/?id=select * from name where name="huanglingfa"
显示如下:
WAF上线注意事项
初期上线只记录日志,不开启WAF,防止误杀 WAF规则管理使用saltstack工具 要知道并不是有了WAF就安全,安全在很大一部分是人为因素
参考地址:https://www.cnblogs.com/wangbin/p/13542024.html