您当前的位置:首页 > 计算机 > 服务器 > Nginx

nginx使用lua文件动态代理websocket

时间:11-21来源:作者:点击数:

创建的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. http://192.168.11.199:81/?destip=192.168.11.199:21899
  2. http://192.168.11.199/js/hterm.js
  3. http://192.168.11.199/auth_token.js
  4. http://192.168.11.199:81/js/gotty.js
  5. http://192.168.11.199/favicon.png
  6. 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)  --日志)
方便获取更多学习、工作、生活信息请关注本站微信公众号城东书院 微信服务号城东书院 微信订阅号
推荐内容
相关内容
栏目更新
栏目热门
本栏推荐