nginx使用lua文件动态代理websocket

本文介绍了如何使用Nginx反向代理来隐藏WebSocket服务的端口号,以提高安全性。首先尝试通过设置$arg_destip变量进行动态代理,但因非首次请求缺少destip参数导致失败。然后,采用Lua脚本动态读取destip值并写入文件,在后续请求中读取该文件以实现代理,成功解决了问题。同时,文章还分享了在Nginx日志中查看Lua日志的相关注意事项。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

创建的websocket服务,可以直接使用 http://192.168.11.199:21899/ 访问,如下
但现在不想对外暴露websocket的端口号,通过nginx反向代理:待访问的url为 http://192.168.11.199:81/?destip=192.168.11.199:21899    destip参数即为websocket服务的ip与port

一、第一次的nginx.conf配置如下

1.1、nginx.conf

location / {
        #echo_before_body $remote_addr;      # 192.168.11.201
        #echo_before_body $args;             # destip=192.168.11.199:21899
        #echo_before_body $arg_destip;       # 192.168.11.199:21311
      
        proxy_pass http://$arg_destip/;     # 带变量不可以
        #proxy_pass http://192.168.11.199:21899/;  # 网址固定可以
       
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;

        proxy_set_header Host $host;
        proxy_set_header        X-Real-IP $remote_addr;
        proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header        X-Forwarded-Proto $scheme;
}
客户端:

1.2、分析错误原因

Webssh网页要打开需要如下请求:
  1. ws://192.168.11.199/ws
当请求 1到达nginx层,$arg_destip会将这个请求代理到 http://192.168.11.199:21899/,请求ok。
当请求2、3、4、5到达nginx层,它会先在本地找有没有静态文件,没有才会去在代理的服务器上查找,我已经把代理服务器上的静态文件存放到本地,所以该请求ok;
但当请求6到达nginx层,请求中没有destip参数,根本就不会代理到 http://192.168.11.199:21899/,协议转换失败。
而当写成固定url是, proxy_pass http://192.168.11.199:21311/ ,请求 1 2、3、4、5、6都会代理到代理服务器上,请求ok。

二、使用lua脚本实现动态代理websocket

根据章节1.2中的分析原因,我们只需要在访问请求2、3、4、5、6时,能够保证代理到 http://192.168.11.199:21899/,就可以。
那我们可以将接口 http://192.168.11.199:81/?destip=192.168.11.199:21899 中的destip值写入某个文件,等接口2、3、4、5、6请求时,读取这个文件下的destip值,用于反向代理,这样不就解决了嘛。

2.1、nginx.conf

server {
    listen       81;
    server_name localhost;
    location / {
        add_header Cache-Control no-store; # 不使用缓存,解决多webssh容器页面访问交叉感染
        set_by_lua_file $desturl '/etc/nginx/lua/dest_url.lua';
        #echo_before_body $desturl;
        proxy_pass http://$desturl;   # 后面不加“/”,否则js文件无法代理下载成功
        proxy_read_timeout 300s;
        
        proxy_set_header Origin '';   # 解决访问/ws 接口403错误
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection $connection_upgrade;
    }
}

2.2、dest_url.lua

ngx.log(ngx.NOTICE, "request uri:", ngx.var.request_uri)  --日志
if ngx.re.match(ngx.var.request_uri, "^(.*)destip=(.*)$") then
    local file, err = io.open ('/etc/nginx/lua/dest_url.txt',"w") --nginx使用root用户,否则无法创建
    if file==nil then
        ngx.log(ngx.ERR, "Couldn't open file:"..err)
    else
        local desturl = ngx.var.arg_destip
        file:write(desturl)
        file:close()
        return desturl
    end
else
    local f1, errormsg = io.open("/etc/nginx/lua/dest_url.txt", "r")
    if f1 == nil then
        ngx.log(ngx.ERR, "error:"..errormsg)
    else
        local desturl = f1:read()
        f1:close()
        ngx.log(ngx.NOTICE, "desturl:"..desturl)
        return desturl
    end
end

2.3、结果

成功将端口号写入到文件:

2.4、nginx日志

 若想在nginx的日志文件中看到nginx日志,需要注意以下几点:

  • access_log是无法更改日志级别的,指的是访问日志,用于记录客户端的请求(包含请求 IP、时间、访问 url等等),不会保存lua里的日志;

  • error_log并不是仅仅记录错误日志,它的level 可以是:debug、info、notice、warn、error、crit、alert、emerg 中的任意值,可以记录所有的日志记录。

  • 这里,为了使errer.log里不包括access.log的日志,设置成notice级别(error_log /var/log/nginx/error.log notice;),同时Lua脚本中使用如下方式记录日志(ngx.log(ngx.NOTICE, "request uri:", ngx.var.request_uri)  --日志)

三、参考链接

https://www.nginx.com/blog/websocket-nginx/ NGINX as a WebSocket Proxy
https://www.jianshu.com/p/0282eca0cd13?utm_campaign nginx反向代理websocket返回403
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值