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