Nginx真实客户端IP到TCP流后端

时间:2016-11-29 18:42:50

标签: nginx

我尝试使用Nginx作为我的TCP守护程序的代理,使Nginx成为SSL / TLS前端,以及加载控制。

我的后端应用程序需要真正的客户端IP,这是一个问题。

stream {
    server {
        listen     3333;
        proxy_pass 127.0.0.1:2222;
    }
}

我在docs中找到了一个解决方案:

proxy_bind $remote_addr transparent;

但它太复杂了:

  

"为了使此参数有效,必须运行nginx   工作进程具有超级用户权限并配置内核   路由表拦截来自代理服务器的网络流量。"

还有其他方法可以将$ remote_addr传递给后端吗?

我尝试使用sub_filter修改客户端消息体,发送http标头等等。但是所有这些只能用于http上下文,而不能用于流。

3 个答案:

答案 0 :(得分:1)

“set_real_ip_from”指令应该是边缘设备的地址/ CIDR

sudo chown -R $(whoami) /usr/local

答案 1 :(得分:1)

我的设置

  1. Nginx 流模块作为 ssh 和 https 的 Tcp 代理
  2. Nginx http 模块为我的内容提供服务

我的要求: 在 access.log 中拥有真实的客户端 IP(而不是来自流模块的 127.0.0.1),也用于地理封锁

我的解决方案

  1. 激活proxy_protocol(在请求中添加附加信息)
  2. 在 http 监听指令中添加“proxy_procotol”(让 http 服务器接受)
  3. 在流模块和 ssh 之间添加额外的代理以删除 proxy_protocol 以便 ssh 能够读取
  4. 将 access.log 中的“$remote_addr”替换为“$proxy_protocol_addr”

对于地理封锁,您还必须使用 proxy_protocol_addr,但为了简短起见,我将在此处省略对此的描述。

nginx.conf:

...
stream {

    upstream ssh {
        server 127.0.0.1:2222;
    }

    upstream https {
        server 127.0.0.1:444;
    }

    map $ssl_preread_protocol $upstream {
        default ssh;
        "TLSv1.2" https;
        "TLSv1.3" https;
        "TLSv1.1" https;
        "TLSv1.0" https;
    }

    server {
        listen 443;
        proxy_pass $upstream;
        proxy_protocol on;
        ssl_preread on;
    }

    server {
        listen 2222 proxy_protocol;
        proxy_pass 192.168.2.76:22;
    }
}

http {
    log_format  main  '$proxy_protocol_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

    ...
    server {
        listen 444 ssl proxy_protocol;
    ... 
    }
}

答案 2 :(得分:0)

据我所知,只有两种解决方案:proxy_bindproxy_protocol

proxy_bind

正如您从文档中引用的那样,工作流程需要超级用户权限。明显。这不是最好的做法。此外,它可能会导致连接问题回到远程客户端。

假设Nginx作为nginx用户运行,请运行此命令为其授予权限。

usermod -aG sudo nginx

proxy_protocal

此解决方案要求上游目的地(例如后端应用程序)接受PROXY协议。

stream {
    server {
        listen         3333;
        proxy_pass     127.0.0.1:2222;
        proxy_protocol on;
    }
}

以上解决方案假设Nginx服务器是网络的入口点。如果存在边缘设备(例如负载平衡器),则很可能正在改变源IP。在这种情况下,您需要在边缘设备上启用代理协议,并在proxy_protocol块中启用server侦听器。我还没有测试过,但这样的事情应该可行。

stream {
    server {
        listen            3333 proxy_protocol;
        proxy_pass        127.0.0.1:2222;
        proxy_protocol    on;
        set_real_ip_from  $proxy_protocol_addr;
    }
}