Nginx配合Lua

案例

今天实现一个非常简单的例子.

云服务器上部署的了一个很通用的应用程序(它没有保护策略),其端口是a,但是我想使用他,就要通过公网ip:端口去访问它。暴露在外面很不安全。

那么就可以通过nginx反向代理,就达到了不暴露端口的目的了。

但是,我又不想别人随便访问,要加一些限制。比如必须要有指定的请求头。

解决方案: 用nginx配置就行了呗。

但是,还是不安全呐,随便别人如果F12查看请求的话,还是可以发现我的请求头啊。他随便捏造一个也可以访问这个应用了呀。

终极方案: lua脚本 + nginx反向代理

  1. 生成的请求头的值value,存到Redis里面【有一定时限】
  2. 用lua脚本获取请求头,如果是空的,返回指定的json字符串
  3. 如果第二步通过了,把请求头的值去Redis查一查,如果有,就通过;如果Redis里面没有,返回指定的json字符串

环境:openresty【它就是升级版的nginx,里面要记得安装redis的模块】

我这里是宝塔面板的openresty,安装的自带有redis模块。(这个安装就不放了)

配置

通用配置:nginx.conf

user  www www;
worker_processes auto;
error_log /www/wwwlogs/nginx_error.log crit;
pid /www/server/nginx/logs/nginx.pid;
worker_rlimit_nofile 51200; stream {
log_format tcp_format '$time_local|$remote_addr|$protocol|$status|$bytes_sent|$bytes_received|$session_time|$upstream_addr|$upstream_bytes_sent|$upstream_bytes_received|$upstream_connect_time'; access_log /www/wwwlogs/tcp-access.log tcp_format;
error_log /www/wwwlogs/tcp-error.log;
include /www/server/panel/vhost/nginx/tcp/*.conf;
} events
{
use epoll;
worker_connections 51200;
multi_accept on;
} http
{
include mime.types;
#include luawaf.conf; include proxy.conf; default_type application/octet-stream; server_names_hash_bucket_size 512;
client_header_buffer_size 32k;
large_client_header_buffers 4 32k;
client_max_body_size 50m; sendfile on;
tcp_nopush on; keepalive_timeout 60; tcp_nodelay on; fastcgi_connect_timeout 300;
fastcgi_send_timeout 300;
fastcgi_read_timeout 300;
fastcgi_buffer_size 64k;
fastcgi_buffers 4 64k;
fastcgi_busy_buffers_size 128k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on; gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 2;
gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/json image/jpeg image/gif image/png font/ttf font/otf image/svg+xml application/xml+rss text/x-js;
gzip_vary on;
gzip_proxied expired no-cache no-store private auth;
gzip_disable "MSIE [1-6]\."; limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m; server_tokens off;
access_log off; server {
................... 重点配置
}
} include /www/server/panel/vhost/nginx/*.conf;
}

server的重点配置

server {
listen 监听的端口;
location / {
# 使用 Lua 脚本进行请求认证 (可以将这里一块抽取出去)
access_by_lua_block {
local redis = require "resty.redis"
local cjson = require "cjson" -- 用于处理 JSON 格式的响应
-- 创建 Redis 客户端
local red = redis:new()
red:set_timeout(1000) -- 设置连接超时,单位是毫秒 -- Redis 连接池设置
local pool_size = 100 -- 连接池大小
local keepalive_timeout = 60000 -- 连接池中连接的超时时间(单位:毫秒)
local keepalive_pool_size = 100 -- Redis 连接池的大小
local redis_host = "Redis的ip" -- 更新 Redis IP 地址
local redis_port = 6379
local redis_password = "密码" -- Redis 密码 -- 获取请求头中的 judge-auth 值
local auth_val = ngx.req.get_headers()["judge-auth"] -- 判断 judge-auth 是否为空
if not auth_val or auth_val == "" then
local response = {
code = 403,
message = "请求头缺失!"
}
ngx.header.content_type = 'application/json; charset=utf-8'
ngx.status = 403
ngx.say(cjson.encode(response))
return ngx.exit(ngx.HTTP_OK)
end -- 连接到 Redis,使用连接池
local ok, err = red:connect(redis_host, redis_port)
if not ok then
ngx.log(ngx.ERR, "failed to connect to Redis: ", err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end -- Redis 密码验证
local res, err = red:auth(redis_password) -- Redis 密码
if not res then
ngx.log(ngx.ERR, "failed to authenticate with Redis: ", err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end -- 查询 Redis 中是否存在该 key
local res, err = red:get(auth_val)
if not res then
ngx.log(ngx.ERR, "failed to query Redis: ", err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end -- 如果 Redis 中没有该 key,返回 403 错误
if res == ngx.null then
local response = {
code = 403,
message = "尚未认证!"
}
ngx.header.content_type = 'application/json; charset=utf-8'
ngx.status = 403
ngx.say(cjson.encode(response))
return ngx.exit(ngx.HTTP_OK)
end -- 认证成功,将连接放回连接池
local pool_ok, pool_err = red:set_keepalive(keepalive_timeout, keepalive_pool_size)
if not pool_ok then
ngx.log(ngx.ERR, "failed to set keepalive for Redis: ", pool_err)
return ngx.exit(ngx.HTTP_INTERNAL_SERVER_ERROR)
end
}
proxy_pass http://127.0.0.1:应用的端口号;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}

nginx + lua脚本的更多相关文章

  1. 使用nginx+lua脚本读写redis缓存

    配置 新建spring boot项目增加redis配置 <dependency> <groupId>org.springframework.boot</groupId&g ...

  2. Nginx 中利用 Lua 脚本做访问控制

    使用场景 需要在后端服务之前做访问控制,或没有后端服务的场景,如静态文件. 实验环境 Ubuntu 14.04 Nginx 1.4.6 安装 Lua 运行环境 sudo apt-get install ...

  3. nginx插入lua脚本访问redis

    目标:收集用户日志 流程: 浏览器端get方法将数据传到nginx服务 nginx收集到数据,执行内嵌lua脚本,访问redis,根据token获得用户id 将日志信息存入文件 1.nginx安装,参 ...

  4. Nginx 内嵌lua脚本,结合Redis使用

    0x00 Nginx 内嵌Lua脚本有下面特点: 20k个并发连接 Lua脚本能够在Nignx 11个层次的不同层次发挥作用,扩展Ngnix功能 Lua速度极快(寄存器指令) 0x01 应用场景 在w ...

  5. 使用lua脚本在nginx上进行灰度流量转发

    参考资料 idea+openresty+lua开发环境搭建 OpenResty最佳实践 灰度发布基于cookie分流 从请求中获取值 -- 从请求中获取请求头为 Sec-WebSocket-Proto ...

  6. 服务降级 托底预案 Nginx中使用Lua脚本检测CPU使用率,当达到阀值时开启限流,让用户排队

    https://mp.weixin.qq.com/s/FZAcQQAKomGEe95kln1HCQ 在京东我们是如何做服务降级的 https://mp.weixin.qq.com/s/FZAcQQAK ...

  7. 运维实践-最新Nginx二进制构建编译lua-nginx-module动态链接Lua脚本访问Redis数据库读取静态资源隐式展现

    关注「WeiyiGeek」公众号 设为「特别关注」每天带你玩转网络安全运维.应用开发.物联网IOT学习! 希望各位看友[关注.点赞.评论.收藏.投币],助力每一个梦想. 本章目录 目录 0x0n 前言 ...

  8. 使用Nginx+Lua代理Hadoop HA

    一.Hadoop HA的Web页面访问 Hadoop开启HA后,会同时存在两个Master组件提供服务,其中正在使用的组件称为Active,另一个作为备份称为Standby,例如HDFS的NameNo ...

  9. #研发解决方案#基于Apriori算法的Nginx+Lua+ELK异常流量拦截方案

    郑昀 基于杨海波的设计文档 创建于2015/8/13 最后更新于2015/8/25 关键词:异常流量.rate limiting.Nginx.Apriori.频繁项集.先验算法.Lua.ELK 本文档 ...

  10. 用Nginx+Lua(OpenResty)开发高性能Web应用

    在互联网公司,Nginx可以说是标配组件,但是主要场景还是负载均衡.反向代理.代理缓存.限流等场景:而把Nginx作为一个Web容器使用的还不是那么广泛.Nginx的高性能是大家公认的,而Nginx开 ...

随机推荐

  1. 长连接网关技术专题(十):百度基于Go的千万级统一长连接服务架构实践

    本文由百度技术团队分享,引用自百度Geek说,原题"千万级高性能长连接Go服务架构实践",为了阅读便利,本文进行了排版优化等. 1.引言 移动互联网时代,长连接服务成为了提升应用实 ...

  2. 【Java 温故而知新系列】基础知识-01 概述

    1.什么是Java Java是一门面向对象编程语言,不仅吸收了C++语言的各种优点,还摒弃了 C++里难以理解的多继承. 指针等概念,因此Java语言具有功能强大和简单易 用两个特征.Java语言作为 ...

  3. 一款简单易用的印章设计工具 --(可转为ofd文件)

    本人开发了一款印章设计软件:不但可以将印章保存为图片,而且可以保存为ofd格式文件. 将印章保存为ofd格式,有很多优势:占用资源少.缩放不失真.可添加元数据. 矢量化图形格式一般为svg.pdf.很 ...

  4. 创建企业级地理数据库——PostgreSQL版

    创建PostgreSQL空间数据库 填写相应的参数,选择授权文件 报错 默认安装postgresql后,执行以上操作报错 "You must copy the latest ST_GEOME ...

  5. linux-大数据常用命令

    1. vi/vim一般模式语法 功能描述yy 复制光标当前一行y数字y 复制一段(从第几行到第几行)p 箭头移动到目的行粘贴u 撤销上一步dd 删除光标当前行d数字d 删除光标(含)后多少行x 删除一 ...

  6. java设计模式---总则

    设计模式总则 一.概述 1.什么是设计模式 设计模式是一套被反复使用.多数人知晓的.经过分类编目的.代码设计经验的总结. 解释下: 分类编目:就是说可以找到一些特征去划分这些设计模式,从而进行分类. ...

  7. 多方安全计算(6):MPC中场梳理

    学习&转载文章:多方安全计算(6):MPC中场梳理 前言 诚为读者所知,数据出域的限制约束与数据流通的普遍需求共同催生了数据安全计算的需求,近一两年业界又统将能够做到多方数据可用不可见的技术归 ...

  8. C++:typedef 与 #define 的区别

    1.执行上不同 关键字 typedef 在编译阶段有效,由于是在编译阶段,因此 typedef 有类型检查的功能. #define 则是宏定义,发生在预处理阶段,也就是编译之前,它只进行简单而机械的字 ...

  9. 131:在红帽Linux中获得帮助

  10. vue平铺日历组件

    vue日历自定义平铺组件 <sy-icon @click="preMon" class="copy-icon" iconClass="iconj ...