前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Nginx基础 - Nginx+Lua实现灰度发布与WAF

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

作者头像
子润先生
修改2021-08-03 10:44:33
1.4K0
修改2021-08-03 10:44:33
举报

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
17\sor\s+
18
19#防止CC攻击
20[root@localhost ~]# vim /usr/local/nginx/conf/waf/config.lua
21CCDeny="on"
22CCrate="100/60"
23

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
负载均衡
负载均衡(Cloud Load Balancer,CLB)提供安全快捷的流量分发服务,访问流量经由 CLB 可以自动分配到云中的多台后端服务器上,扩展系统的服务能力并消除单点故障。负载均衡支持亿级连接和千万级并发,可轻松应对大流量访问,满足业务需求。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档