Nginx + Lua脚本打配合

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

nginx 复制代码
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的重点配置

lua 复制代码
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;
    }
}
相关推荐
苹果醋311 分钟前
React源码02 - 基础知识 React API 一览
java·运维·spring boot·mysql·nginx
阿松哥哥20188 小时前
linux环境使用源码方式安装nginx(centos)
linux·nginx·centos
与君共勉1213813 小时前
Nginx 负载均衡的实现
运维·服务器·nginx·负载均衡
miss writer14 小时前
Redis分布式锁释放锁是否必须用lua脚本?
redis·分布式·lua
青灯文案114 小时前
前端 HTTP 请求由 Nginx 反向代理和 API 网关到后端服务的流程
前端·nginx·http
小屁不止是运维14 小时前
麒麟操作系统服务架构保姆级教程(五)NGINX中间件详解
linux·运维·服务器·nginx·中间件·架构
恩爸编程1 天前
探索 Nginx:Web 世界的幕后英雄
运维·nginx·nginx反向代理·nginx是什么·nginx静态资源服务器·nginx服务器·nginx解决哪些问题
努力--坚持1 天前
电商项目-网站首页高可用(一)
nginx·lua·openresty
黄名富1 天前
Redis 附加功能(二)— 自动过期、流水线与事务及Lua脚本
java·数据库·redis·lua