栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 系统运维 > 运维 > Linux

Nginx Lua OpenResty 反向代理websocket并对响应内容进行过滤

Linux 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Nginx Lua OpenResty 反向代理websocket并对响应内容进行过滤

【需求】

目前的需求是有一个需要身份认证的Websocket接口,目前用户可以调用,但是我们需要过滤掉一些敏感信息,让包含这些信息的text不发送给用户。

【前期尝试】

首先我知道nginx可以直接反向代理 websocket。
其次我也知道可以通过openresty中的body_filter_by_lua对响应进行处理。
那么将这两者结合起来能否实现websocket的消息过滤呢?
答案是不能。或者说可以实现但是非常复杂,涉及到一系列协议,因此放弃了。

【最终方案】

经过广泛搜集资料:发现了一个日本小哥写的Gists websocketをフックする
他使用了 lua-resty-websocket 这个库,通过一个桥连接非常优雅的实现了websocket上下游通讯。
通过对小哥的方案进行修改,非常完美的达到了自己的目的。

【lua-resty-websocket库】

https://github.com/openresty/lua-resty-websocket
大家先去lua-resty-websocket官网把websocket依赖下载下来放到自己的resty目录下。

【nginx.conf】
location = /ws_filter
{
	content_by_lua_file "ws_filter.lua";
}
【ws_filter.lua】
local server = require "resty/websocket/server"
local client = require "resty/websocket/client"
local protocol = require "resty/websocket/protocol"

-- websocket server
local sock_server, err = server:new()

if not sock_server then
    ngx.log(ngx.ERR, "failed to new websocket: ", err)
    return ngx.exit(403)
end

local sock_client, err = client:new()
-- 此处是代理的目标 ws 地址,可根据自己的需求进行重写等操作。
-- local uri = "ws://" ..  ngx.var.http_host ..  ngx.var.uri ..  ngx.var.is_args ..  ngx.var.args
local uri = "ws://www.myhost.com/api/websocket?pass=pass"
local ok, err = sock_client:connect(uri)

if not ok then
    ngx.log(ngx.ERR, "failed to connect remote: ", err)
    ngx.exit(403)
end

local function ws_proxy(sock_from, sock_to, flip_masking)
    local opcode_mapper = {
        ["continuation"] = 0x0,
        ["text"] = 0x1,
        ["binary"] = 0x2,
        ["close"] = 0x8,
        ["ping"] = 0x9,
        ["pong"] = 0x9,
    }

    while true do
        local data, typ, err = sock_from:recv_frame(flip_masking)

        if data == nil then
            -- socket already closed
            sock_to:send_close()
            break
        else
            ngx.log(ngx.INFO, data .. " (" .. typ .. ")")

            local fin = (typ ~= "continuation")

            if typ == "close" then
                sock_from:send_close()
            end
            
            -- 在这里对data进行处理
            -- data = 'filterdata'

            local bytes, err = sock_to:send_frame(fin, opcode_mapper[typ], data, flip_masking)

            if bytes == nil then
                sock_from:send_close()
                break
            end
        end

    end
end

local s2c = ngx.thread.spawn(ws_proxy, sock_client, sock_server, false)
local c2s = ngx.thread.spawn(ws_proxy, sock_server, sock_client, true)

if not ngx.thread.wait(s2c) then
    ngx.log(ngx.ERR, "s2c wait failed")
end

if not ngx.thread.wait(c2s) then
    ngx.log(ngx.ERR, "c2s wait failed")
end
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/740506.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号