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;
    }
}
相关推荐
米粉030514 小时前
深入剖析Nginx:从入门到高并发架构实战
java·运维·nginx·架构
静水楼台x18 小时前
nginx日志的一点理解
运维·nginx
欧先生^_^18 小时前
ingress-nginx 开启 Prometheus 监控 + Grafana 查看指标
nginx·grafana·prometheus
什么都想学的阿超19 小时前
【Redis系列 03】掌握Redis编程艺术:事务、管道与Lua脚本完全指南
redis·junit·lua
眠修20 小时前
Nginx + Tomcat负载均衡群集
nginx·tomcat·负载均衡
编程乐学(Arfan开发工程师)1 天前
42、响应处理-【源码分析】-浏览器与PostMan内容协商完全适配
java·spring boot·后端·测试工具·lua·postman
瘦皮猴1 天前
golang context canceled异常排查
后端·nginx
啾啾Fun1 天前
【Java微服务组件】分布式协调P4-一文打通Redisson:从API实战到分布式锁核心源码剖析
java·redis·分布式·微服务·lua·redisson
多多*1 天前
LUA+Reids实现库存秒杀预扣减 记录流水 以及自己的思考
linux·开发语言·redis·python·bootstrap·lua
hunter1271 天前
Nginx 事件驱动理解
nginx