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

1)环境准备

  1. [root@localhost ~]# yum -y install gcc gcc-c++ make pcre-devel zlib-devel openssl-devel

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

  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

3)解压ngx_devel_kit和lua-nginx-module

  1. [root@localhost src]# tar xf v0.2.19.tar.gz
  2. [root@localhost src]# tar xf v0.10.13.tar.gz

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

  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

5)安装Nginx并加载模块

  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

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

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

Nginx调用Lua API

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

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

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

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

实践环境准备:

  1. 系统 服务 地址
  2. CentOS7 Nginx+Lua+Memached 10.0.0.11
  3. CentOS7 Tomcat集群8080_Prod 10.0.0.12
  4. CentOS7 Tomcat集群9090_Test 10.0.0.13

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

  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配置文件

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

  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

3)配置负载均衡调度

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

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

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

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

  1. #telnet传入值
  2. [root@localhost ~]# telnet 127.0.0.1 11211
  3. # set对应IP
  4. set 10.0.0.10 0 0 1
  5. # 输入1
  6. 1

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

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

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

  1. location ^~ /upload {
  2. root /usr/local/openresty/nginx/html/upload;
  3. if ($request_filename ~* (.*)\.php){
  4. return 403;
  5. }
  6. }

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

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

  1. [root@localhost ~]# systemctl start mariadb
  2. [root@localhost ~]# mysql
  3.  
  4. MariaDB [(none)]> create database info;
  5. MariaDB [(none)]> use info;
  6. MariaDB [info]> create table user(id int(11),username varchar(64), password varchar(64), email varchar(64));
  7. MariaDB [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. #插入数据
  18. MariaDB [info]> insert into user (id,username,password,email) values(1,'admin',('123'),'admin@example.com');
  19. MariaDB [info]> select * from info.user;
  20. +------+----------+----------------------------------+-----------------+
  21. | id | username | password | email |
  22. +------+----------+----------------------------------+-----------------+
  23. | 1 | admin | 123 | admin@example.com |
  24. +------+----------+----------------------------------+-----------------+
  25. 1 row in set (0.00 sec)

3)配置php代码

  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("数据库连接失败!");
  32. mysql_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'";
  36. echo $sql."<br />";
  37. $query=mysql_query($sql);
  38. $arr=mysql_fetch_array($query);
  39. if($arr){
  40. echo "login success!<br />";
  41. echo $arr[1];
  42. echo $arr[3]."<br /><br />";
  43. }else{
  44. echo "login failed!";
  45. }
  46. ?>

4.部署Waf相关防护代码

  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段添加
  6. lua_package_path "/usr/local/nginx/conf/waf/?.lua";
  7. lua_shared_dict limit 10m;
  8. init_by_lua_file /usr/local/nginx/conf/waf/init.lua;
  9. access_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
  13. RulePath = "/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
  21. CCDeny="on"
  22. CCrate="100/60"

Nginx基础 - Nginx+Lua实现灰度发布与WAF的更多相关文章

  1. nginx+lua实现灰度发布/waf防火墙

    nginx+lua 实现灰度发布 waf防火墙 课程链接:[课程]Nginx 与 Lua 实现灰度发布与 WAF 防火墙(完)_哔哩哔哩 (゜-゜)つロ 干杯~-bilibili 参考博客 Nginx ...

  2. Nginx详解二十四:Nginx深度学习篇之灰度发布

    实战场景 - 灰度发布 灰度发布的作用:按照一定的关系区别,分部分的代码进行上线,使代码的发布能平滑过渡上线实现方式: 1.用户的信息cookie等信息区别 2.根据用户的IP地址 安装memcach ...

  3. Openresty+Lua+Redis灰度发布

    灰度发布,简单来说,就是根据各种条件,让一部分用户使用旧版本,另一部分用户使用新版本.百度百科中解释:灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式.AB test就是一种灰度发布方式,让一部分 ...

  4. 使用Nginx实现灰度发布

    灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式.AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B ...

  5. 使用Nginx实现灰度发布(转)

    灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式.AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见,那么逐步扩大范围,把所有用户都迁移到B ...

  6. 01 . OpenResty简介部署,优缺点,压测,适用场景及用Lua实现服务灰度发布

    简介 OpenResty 是一个基于 Nginx 与 Lua 的高性能 Web 平台,其内部集成了大量精良的 Lua 库.第三方模块以及大多数的依赖项.用于方便地搭建能够处理超高并发.扩展性极高的动态 ...

  7. 利用nginx+lua+memcache实现灰度发布

    一.灰度发布原理说明 灰度发布在百度百科中解释: 灰度发布是指在黑与白之间,能够平滑过渡的一种发布方式.AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什 ...

  8. nginx+lua+redis实现灰度发布_test

    nginx+lua+redis实现灰度发布: 灰度发布是指在黑白之间能够平滑过渡的一种方式 AB test就是一种灰度发布方式,让一部分用户继续用A,一部分用户开始用B,如果用户对B没有什么反对意见, ...

  9. Nginx配之负载均衡、缓存、黑名单和灰度发布

    一.Nginx安装(基于CentOS 6.5) 1.yum命令安装 yum install nginx –y(若不能安装,执行命令yum install epel-release) 2. 启动.停止和 ...

随机推荐

  1. mysql5.5 升级至5.7

    mysql5.5 升级至5.7 1.下载mysql5.7.32 官方下载地址 解压 tar xvf mysql.tar.gz mysql/ 2. 进入旧的mysql的bin目录下导出mysql的数据 ...

  2. Spring入门及IoC的概念

    Spring入门 Spring是一个轻量级的Java开发框架,最早由Robd Johnson创建,目的为了解决企业级应用开发的业务逻辑层和其他各层的耦合问题,它是一个分层的JavaSE/EE轻量级开源 ...

  3. 如何在 crontab 中让 source ~/.bashrc 生效

    cron 是许多类 Unix 操作系统中都自带的用来调度定时任务的工具,定时任务的配置是写在 crontab 文件中的,但是 crontab 文件不允许直接编辑,一般都是通过命令 crontab -e ...

  4. 把Win10变成Mac OS:比任何美化主题都好用的工具

    摘要:把Win10变成Mac OS:比任何美化主题都好用的工具 - 这是一款真正意义上的把Windows变成MacOS的软件,不用更换主题,不用修改Dll,直接是程序接管了Explorer,比任何美化 ...

  5. tcpdump 参数详解及使用案例

    参数 -A 以ASCII码方式显示每一个数据包(不会显示数据包中链路层头部信息). 在抓取包含网页数据的数据包时, 可方便查看数据(nt: 即Handy for capturing web pages ...

  6. Spring Boot使用MongoDB GridFS进行文件的操作

    1. GridFS简介 GridFS 用于存储和恢复那些超过16M(BSON文件限制)的文件(如:图片.音频.视频等),但是它是存储在MonoDB的集合中. GridFS 会将文件对象分割成多个的ch ...

  7. Trie(字典树)

    没时间整理了,老吕又讲课了@ @ 概念 Trie即字典树,又称单词查找树或键树,是一种树形结构,是一种哈希树的变种,典型应用是统计和排序大量的字符串(不限于字符串) Trie字典树主要用于存储字符串, ...

  8. dp - 斜率优化笔记

    (原来的题解没得了,只好重写一份) 斜率优化一般是,\(dp\) 是枚举一个 \(i\),然后前面找一个 \(j\),式子中有些和 \(j\) 有关,有些和 \(i\) 有关,有些和俩都有关. 过程中 ...

  9. loj10172

    涂抹果酱 Tyvj 两周年庆典要到了,Sam 想为 Tyvj 做一个大蛋糕.蛋糕俯视图是一个 N×M 的矩形,它被划分成 N×M 个边长为 1×1 的小正方形区域(可以把蛋糕当成 NNN 行 MMM  ...

  10. Golang 版的ssh爆破小工具

    源码如下: package main import ( "bufio" "flag" "fmt" "golang.org/x/cr ...