Nginx基础 - Nginx+Lua实现灰度发布与WAF

2021-08-03 10:44:33 浏览数 (1)

1.Nginx加载Lua环境 默认情况下Nginx不支持Lua模块, 需要安装LuaJIT解释器, 并且需要重新编译Nginx, 建议使用openrestry

1)环境准备

代码语言:javascript复制
1[root@localhost ~]# yum -y install gcc gcc-c   make pcre-devel zlib-devel openssl-devel
2

2)下载luajit和ngx_devel_kit以及lua-nginx-module

代码语言:javascript复制
1[root@localhost ~]# cd /usr/local/src
2[root@localhost src]# wget http://luajit.org/download/LuaJIT-2.0.4.tar.gz
3[root@localhost src]# wget https://github.com/simpl/ngx_devel_kit/archive/v0.2.19.tar.gz
4[root@localhost src]# wget https://github.com/openresty/lua-nginx-module/archive/v0.10.13.tar.gz
5

3)解压ngx_devel_kit和lua-nginx-module

代码语言:javascript复制
1[root@localhost src]# tar xf v0.2.19.tar.gz 
2[root@localhost src]# tar xf v0.10.13.tar.gz
3

4)安装LuaJIT Luajit是Lua即时编译器。

代码语言:javascript复制
1[root@localhost src]# tar zxvf LuaJIT-2.0.3.tar.gz 
2[root@localhost src]# cd LuaJIT-2.0.3
3[root@localhost LuaJIT-2.0.3]# make && make install
4

5)安装Nginx并加载模块

代码语言:javascript复制
1[root@localhost ~]# cd /usr/local/src
2[root@localhost src]# wget http://nginx.org/download/nginx-1.12.2.tar.gz
3[root@localhost src]# tar xf nginx-1.12.2.tar.gz
4[root@localhost src]# cd nginx-1.12.2
5[root@localhost nginx-1.12.2]# ./configure --prefix=/usr/local/nginx --with-http_ssl_module 
6--with-http_stub_status_module --with-http_dav_module 
7--add-module=../ngx_devel_kit-0.2.19/ 
8--add-module=../lua-nginx-module-0.10.13 
9[root@localhost nginx-1.12.2]# make -j2 && make install
10
11#建立软链接, 不建立会出现share object错误
12[root@localhost ~]#ln -s /usr/local/lib/libluajit-5.1.so.2 /lib64/libluajit-5.1.so.2
13
14#加载lua库,加入到ld.so.conf文件
15[root@localhost ~]# echo "/usr/local/LuaJIT/lib" >> /etc/ld.so.conf
16[root@localhost ~]# ldconfig
17

2.Nginx调用Lua指令 Nginx调用Lua模块指令, Nginx的可插拔模块加载执行, 共11个处理阶段

代码语言:javascript复制
1语法	
2set_by_lua
3set_by_lua_file	设置Nginx变量,可以实现负载的赋值逻辑
4access_by_lua
5access_by_lua_file	请求访问阶段处理, 用于访问控制
6content_by_lua
7content_by_lua_file	内容处理器, 接受请求处理并输出响应
8

Nginx调用Lua API

代码语言:javascript复制
1变量	
2ngx.var	nginx变量
3ngx.req.get_headers	获取请求头
4ngx.req.get_uri_args	获取url请求参数
5ngx.redirect	重定向
6ngx.print	输出响应内容体
7ngx.say	输出响应内容体,最后输出一个换行符
8ngx.header	输出响应头
9

3.Nginx Lua实现代码灰度发布 使用Nginx结合lua实现代码灰度发布 按照一定的关系区别,分不分的代码进行上线,使代码的发布能平滑过渡上线

1.用户的信息cookie等信息区别 2.根据用户的ip地址, 颗粒度更广

代码语言:javascript复制
1执行过程:
21.用户请求到达前端代理Nginx, 内嵌的lua模块会解析Nginx配置文件中Lua脚本
32.Lua脚本会获取客户端IP地址,查看Memcached缓存中是否存在该键值
43.如果存在则执行@java_test,否则执行@java_prod
54.如果是@java_test, 那么location会将请求转发至新版代码的集群组
65.如果是@java_prod, 那么location会将请求转发至原始版代码集群组
76.最后整个过程执行后结束
8

实践环境准备:

代码语言:javascript复制
1系统	服务	地址
2CentOS7	Nginx Lua Memached	10.0.0.11
3CentOS7	Tomcat集群8080_Prod	10.0.0.12
4CentOS7	Tomcat集群9090_Test	10.0.0.13
5

1)安装两台服务器Tomcat,分别启动8080和9090端口

代码语言:javascript复制
1[root@tomcat-node1 ~]# yum install java -y
2[root@tomcat-node1 ~]# cd /usr/local/src
3[root@tomcat-node1 src]# wget https://mirrors.tuna.tsinghua.edu.cn/apache/tomcat/tomcat-9/v9.0.36/bin/apache-tomcat-9.0.36.tar.gz
4[root@tomcat-node1 src]# tar xf apache-tomcat-9.0.36.tar.gz
5[root@tomcat-node1 src]# cp -r apache-tomcat-9.0.36 /usr/local/tomcat-8080
6[root@tomcat-node1 src]# /usr/local/tomcat-8080/bin/startup.sh
7#tomcat默认监听在8080端口, 如果需要启动9090端口需要修改server.xml配置文件
8

2)配置Memcached并让其支持Lua调用

代码语言:javascript复制
1#安装memcached服务
2[root@localhost ~]# yum install memcached -y
3
4#配置memcached支持lua
5[root@localhost ~]# cd /usr/local/src
6[root@localhost src]# wget https://github.com/openresty/lua-resty-memcached/archive/lua-resty-memcached-master.zip
7[root@localhost src]# tar xf v0.11.tar.gz [root@localhost src]# cp -r lua-resty-memcached-0.11/lib/resty/memcached.lua /usr/local/nginx/lua/
8
9#启动memcached
10[root@localhost ~]# systemctl start memcached
11[root@localhost ~]# systemctl enable memcached
12

3)配置负载均衡调度

代码语言:javascript复制
1#必须在http层
2lua_package_path "/usr/local/nginx/lua/memcached.lua";
3upstream java_prod {
4server 10.0.0.12:8080;
5}
6
7upstream java_test {
8server 10.0.0.13:9090;
9}
10
11server {
12listen 80;
13server_name 10.0.0.11;
14
15
16location /hello {
17default_type 'text/plain';
18content_by_lua 'ngx.say("hello ,lua scripts")';
19}
20
21location /myip {
22default_type 'text/plain';
23content_by_lua '
24clientIP = ngx.req.get_headers()["x_forwarded_for"]
25ngx.say("Forwarded_IP:",clientIP)
26if clientIP == nli then
27clientIP = ngx.var.remote_addr
28ngx.say("Remote_IP:",clientIP)
29end
30';
31}
32location / {
33default_type 'text/plain';
34content_by_lua_file /usr/local/nginx/lua/dep.lua;
35}
36location @java_prod {
37proxy_pass http://java_prod;
38include proxy_params;
39}
40
41location @java_test {
42proxy_pass http://java_test;
43include proxy_params;
44}
45}
46
47
48#nginx反向代理tomcat,必须配置头部信息否则返回400错误
49
50proxy_redirect default;
51proxy_set_header Host $http_host;
52proxy_set_header X-Real-IP $remote_addr;
53proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
54
55proxy_connect_timeout 30;
56proxy_send_timeout 60;
57proxy_read_timeout 60;
58
59proxy_buffer_size 32k;
60proxy_buffering on;
61proxy_buffers 4 128k;
62proxy_busy_buffers_size 256k;
63proxy_max_temp_file_size 256k;
64

4)编写Nginx调用灰度发布Lua脚本

代码语言:javascript复制
1[root@localhost ~]# vim /usr/local/nginx/lua/dep.lua 
2--获取x-real-ip
3clientIP = ngx.req.get_headers()["X-Real-IP"]
4
5--如果IP为空-取x_forwarded_for
6if clientIP == nil then
7clientIP = ngx.req.get_headers()["x_forwarded_for"]
8end
9
10--如果IP为空-取remote_addr
11if clientIP == nil then
12clientIP = ngx.var.remote_addr
13end
14
15--定义本地,加载memcached
16local memcached = require "resty.memcached"
17--实例化对象
18local memc, err = memcached:new()
19--判断连接是否存在错误
20if not memc then
21ngx.say("failed to instantiate memc: ", err)
22return
23end
24--建立memcache连接
25local ok, err = memc:connect("127.0.0.1", 11211)
26--无法连接往前端抛出错误信息
27if not ok then
28ngx.say("failed to connect: ", err)
29return
30end
31--获取对象中的ip-存在值赋给res
32local res, flags, err = memc:get(clientIP)
33--
34--ngx.say("value key: ",res,clientIP)
35if err then
36ngx.say("failed to get clientIP ", err)
37return
38end
39--如果值为1则调用local-@java_test
40if res == "1" then
41ngx.exec("@java_test")
42return
43end
44--否则调用local-@java_prod
45ngx.exec("@java_prod")
46return
47

5)使用Memcache set IP, 测试灰度发布

代码语言:javascript复制
1#telnet传入值
2[root@localhost ~]# telnet 127.0.0.1 11211
3# set对应IP
4set 10.0.0.10 0 0 1
5# 输入1
61
7

4.基本安全概述 1)常见的恶意行为 爬虫行为和恶意抓取,资源盗取 防护手段 基础防盗链功能不让恶意用户能够轻易的爬取网站对外数据 access_moudle->对后台,部分用户服务的数据提供IP防护 解决方法

代码语言:javascript复制
1server {
2listen 80;
3server_name localhost;
4
5set $ip 0;
6if ($http_x_forward_for ~ 10.0.0.10){
7set $ip 1;
8}
9if ($remote_addr ~ 10.0.0.10){
10set $ip 1;
11}
12# 如果$ip值为0,则返回403, 否则允许访问
13location /admin {
14if ($ip = "0"){
15return 403;
16}
17default_type application/json;
18return 200 '{"status":"success"}';
19}
20

2)常见的攻击手段(代码植入) 后台密码撞库,通过猜测密码字典不断对后台系统登陆性尝试,获取后台登陆密码 防护手段 1.后台登陆密码复杂度 2.使用access_module-对后台提供IP防控 3.预警机制 文件上传漏洞,利用上传接口将恶意代码植入到服务器中,再通过url去访问执行代码 执行方式admin.com/1.jpg/1.php 解决办法

代码语言:javascript复制
1location ^~ /upload {
2root /usr/local/openresty/nginx/html/upload;
3if ($request_filename ~* (.*).php){
4return 403;
5}
6}
7

3)常见的攻击手段(SQL注入) 利用未过滤/未审核的用户输入进行Sql注入的攻击方法, 让应用运行本不应该运行的SQL代码 防护手段 1.php配置开启安全相关限制 2.开发人员对sql提交进行审核,屏蔽常见的注入手段 3.Nginx Lua构建WAF应用层防火墙, 防止Sql注入

5.Nginx Lua实现WAF应用防火墙 1)快速安装lnmp架构(略) 2)配置MySQL

代码语言:javascript复制
1[root@localhost ~]# systemctl start mariadb
2[root@localhost ~]# mysql
3
4MariaDB [(none)]> create database info;
5MariaDB [(none)]> use info;
6MariaDB [info]> create table user(id int(11),username varchar(64), password varchar(64), email varchar(64));
7MariaDB [info]> desc user;
8 ---------- ------------- ------ ----- --------- ------- 
9| Field | Type | Null | Key | Default | Extra |
10 ---------- ------------- ------ ----- --------- ------- 
11| id | int(11) | YES | | NULL | |
12| username | varchar(64) | YES | | NULL | |
13| password | varchar(64) | YES | | NULL | |
14| email | varchar(64) | YES | | NULL | |
15 ---------- ------------- ------ ----- --------- ------- 
16
17#插入数据
18MariaDB [info]> insert into user (id,username,password,email) values(1,'admin',('123'),'admin@example.com');
19MariaDB [info]> select * from info.user;
20 ------ ---------- ---------------------------------- ----------------- 
21| id | username | password | email |
22 ------ ---------- ---------------------------------- ----------------- 
23| 1 | admin | 123 | admin@example.com |
24 ------ ---------- ---------------------------------- ----------------- 
251 row in set (0.00 sec)
26

3)配置php代码

代码语言:javascript复制
1[root@localhost ~]# vim /usr/local/nginx/html/login.html 
2<html>
3<head>
4<title> Sql注入演示场景 </title>
5<meta http-equiv="content-type"content="text/html;charset=utf-8">
6</head>
7<body>
8<form action="sql.php" method="post">
9<table>
10<tr>
11<td> 用 户: </td>
12<td><input type="text" name="username"></td>
13</tr>
14
15<tr>
16<td> 密 码: </td>
17<td><input type="text" name="password"></td>
18</tr>
19<tr>
20<td><input type="submit" value="提交"></td>
21<td><input type="reset" value="重置"></td>
22</tr>
23</table>
24</form>
25</body>
26</html>
27
28#被html调用的sql.php文件
29[root@localhost ~]# vim /usr/local/nginx/html/sql.php
30<?php
31$conn = mysql_connect("localhost",'root','') or die("数据库连接失败!");
32mysql_select_db("info",$conn) or die ("您选择的数据库不存在");
33$name=$_POST['username'];
34$pwd=$_POST['password'];
35$sql="select * from user where username='$name' and password='$pwd'";
36echo $sql."<br />";
37$query=mysql_query($sql);
38$arr=mysql_fetch_array($query);
39if($arr){
40echo "login success!<br />";
41echo $arr[1];
42echo $arr[3]."<br /><br />";
43}else{
44echo "login failed!";
45}
46?>
47

4.部署Waf相关防护代码

代码语言:javascript复制
1[root@localhost ~]# cd /usr/local/src/
2[root@localhost src]# git clone https://github.com/loveshell/ngx_lua_waf.git
3[root@localhost src]# cp -r ngx_lua_waf/ /usr/local/nginx/conf/waf
4
5#在nginx.conf的http段添加
6lua_package_path "/usr/local/nginx/conf/waf/?.lua";
7lua_shared_dict limit 10m;
8init_by_lua_file /usr/local/nginx/conf/waf/init.lua; 
9access_by_lua_file /usr/local/nginx/conf/waf/waf.lua;
10
11#配置config.lua里的waf规则目录
12[root@localhost ~]# vim /usr/local/nginx/conf/waf/config.lua
13RulePath = "/usr/local/nginx/conf/waf/wafconf/"
14
15#防止Sql注入
16[root@localhost ~]# vim /usr/local/nginx/conf/waf/wafconf/post
17sors 
18
19#防止CC攻击
20[root@localhost ~]# vim /usr/local/nginx/conf/waf/config.lua
21CCDeny="on"
22CCrate="100/60"
23

0 人点赞