openresty / stream-lua-nginx-module

Embed the power of Lua into NGINX TCP/UDP servers
BSD 2-Clause "Simplified" License
728 stars 198 forks source link

When using OpenResty as a proxy for forwarding TCP traffic, how can I obtain the address of the backend server that the client wants to access from the captured traffic? #328

Open ZxyNull0 opened 1 year ago

oowl commented 1 year ago

You need to self-parse your traffic data by ngx.req.socket, Or match your protocol in the preread buffer. It depends on your traffic data pattern.

ZxyNull0 commented 1 year ago

您需要通过 自行解析您的流量数据ngx.req.socket,或者在预读缓冲区中匹配您的协议。这取决于您的流量数据模式。 Thank you very much for your response. I am a newcomer to OpenResty. Here is my configuration file, and I want to obtain the destination address from the raw data using ngx.req.socket, but it seems that I only get the request content without the desired destination address.


stream {
lua_package_path "/usr/local/openresty/nginx/conf/lua/?.lua;;"; 
preread_by_lua_no_postpone on;
lua_add_variable $tcp_backend;

upstream backend_tcp_server {
    server 172.31.102.229:8888;
}

server {
    error_log "/usr/local/openresty/logs/TCP_error.log" debug;
    listen 8083;
    preread_by_lua_block {
        local sock = assert(ngx.req.socket(raw))
        local data, err = sock:receive("*a") 
        if data then
            local data_str = tostring(data)  
            ngx.log(ngx.INFO, "Raw data: ", data_str)
        else
            ngx.log(ngx.ERR, "Failed to receive data: ", err)
        end
    }

    # preread_by_lua_file "/usr/local/openresty/nginx/conf/lua/TCP_access.lua";
    # proxy_pass $tcp_backend;
    proxy_pass backend_tcp_server; 
}

}


 I am hopeful to receive your guidance and insights on this matter.
![image](https://github.com/openresty/stream-lua-nginx-module/assets/81354529/804b2853-84ab-48e7-a248-b5044d802027)
oowl commented 1 year ago

No, I mean which have two approaches

  1. using ngx.req.socket(raw) to hook the whole proxy_pass path, that means you can not using proxy_pass
  2. using socket peek API in the preread phase to peek some traffic what do you use, that's can not break your proxy_pass https://github.com/openresty/stream-lua-nginx-module#reqsockpeek
ZxyNull0 commented 1 year ago

No, I mean which have two approaches

  1. using ngx.req.socket(raw) to hook the whole proxy_pass path, that means you can not using proxy_pass
  2. using socket peek API in the preread phase to peek some traffic what do you use, that's can not break your proxy_pass https://github.com/openresty/stream-lua-nginx-module#reqsockpeek My requirement is to obtain the destination address of TCP traffic redirected to OpenResty using iptables. I tried using 'peek' , as shown below, but I only received the transmitted content and did not retrieve the original destination IP.
    preread_by_lua_block{
    ngx.log(ngx.INFO,"coming in")
    local sock = assert(ngx.req.socket())
    local data = assert(sock:peek(1)) -- peek the first 1 byte that contains the length
    ngx.log(ngx.INFO, "1-----")
    data = string.byte(data)
    ngx.log(ngx.INFO, "2-----")
    ngx.log(ngx.INFO, "data:"..data)
    data = assert(sock:peek(data+1)) -- peek the length + the size byte
    ngx.log(ngx.INFO, "3-----")
    local payload = data:sub(1) -- trim the length byte to get actual payload
    ngx.log(ngx.INFO, "payload is: ", payload)
    }
Qu6133326intinaLouise commented 1 year ago

No, I mean which have two approaches

  1. using ngx.req.socket(raw) to hook the whole proxy_pass path, that means you can not using proxy_pass
  2. using socket peek API in the preread phase to peek some traffic what do you use, that's can not break your proxy_pass https://github.com/openresty/stream-lua-nginx-module#reqsockpeek My requirement is to obtain the destination address of TCP traffic redirected to OpenResty using iptables. I tried using 'peek' , as shown below, but I only received the transmitted content and did not retrieve the original destination IP.
        preread_by_lua_block{
            ngx.log(ngx.INFO,"coming in")
            local sock = assert(ngx.req.socket())
            local data = assert(sock:peek(1)) -- peek the first 1 byte that contains the length
            ngx.log(ngx.INFO, "1-----")
            data = string.byte(data)
            ngx.log(ngx.INFO, "2-----")
            ngx.log(ngx.INFO, "data:"..data)
            data = assert(sock:peek(data+1)) -- peek the length + the size byte
            ngx.log(ngx.INFO, "3-----")
            local payload = data:sub(1) -- trim the length byte to get actual payload
            ngx.log(ngx.INFO, "payload is: ", payload)
        }

sock:peek(1) not contains the length. why?

zhuizhuhaomeng commented 1 year ago

You need to write a Nginx module to get the original IP address.

ZxyNull0 commented 1 year ago

不,我的意思是有两种方法

  1. 使用ngx.req.socket(raw)hook整个proxy_pass路径,这意味着你不能使用proxy_pass
  2. 在预读阶段使用socket peek API来查看一些流量你用什么,这不能破坏你的proxy_pass https://github.com/openresty/stream-lua-nginx-module#reqsockpeek 我的要求是使用iptables获取目标地址重定向到 OpenResty 的 TCP 流量。我尝试使用 'peek' ,如下所示,但我只收到了传输的内容,并没有搜索到原始的目标IP。
        preread_by_lua_block{
            ngx.log(ngx.INFO,"coming in")
            local sock = assert(ngx.req.socket())
            local data = assert(sock:peek(1)) -- peek the first 1 byte that contains the length
            ngx.log(ngx.INFO, "1-----")
            data = string.byte(data)
            ngx.log(ngx.INFO, "2-----")
            ngx.log(ngx.INFO, "data:"..data)
            data = assert(sock:peek(data+1)) -- peek the length + the size byte
            ngx.log(ngx.INFO, "3-----")
            local payload = data:sub(1) -- trim the length byte to get actual payload
            ngx.log(ngx.INFO, "payload is: ", payload)
        }

sock:peek(1) 不包含长度。为什么?

The result I obtained using sock:peek(1) is a valid numerical value, representing the length of the message.

ZxyNull0 commented 1 year ago

您需要编写一个Nginx模块来获取原始IP地址。

Could you please provide a more detailed explanation?,It seems that this project does not yet support this function.

zhuizhuhaomeng commented 10 months ago

This module will not provide this function. I think you can refer to https://stackoverflow.com/questions/5615579/how-to-get-original-destination-port-of-redirected-udp-message.