簡體   English   中英

Nginx 真實客戶端 IP 到 TCP stream 后端

[英]Nginx real client IP to TCP stream backend

我正在嘗試使用 Nginx 作為我的 TCP 守護程序的代理,使 Nginx 成為 SSL/TLS 前端以及負載控制。

我的后端應用程序需要真正的客戶端 IP,這是一個問題。

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

我在文檔中找到了一種解決方案:

proxy_bind $remote_addr transparent;

但這太復雜了:

“為了使此參數起作用,需要以超級用戶權限運行 nginx 工作進程並配置 kernel 路由表以攔截來自代理服務器的網絡流量。”

還有其他方法可以將 $remote_addr 傳遞給后端嗎?

我嘗試使用 sub_filter 修改客戶端消息正文,發送 http 標頭等。但不幸的是,所有這些只能在 http 上下文中使用,不適用於 stream。

我的設置

  1. Nginx stream 模塊作為 Tcp ssh 和 https 的代理
  2. Nginx http 模塊來提供我的內容

我的要求:在 access.log 中擁有真正的客戶端 ip(而不是來自 stream 模塊的 127.0.0.1)並且還用於地理封鎖

我的解決方案

  1. 激活 proxy_protocol(在請求中添加附加信息)
  2. 在 http listen 指令中添加“proxy_procotol”(供 http 服務器接受)
  3. 在 stream 模塊和 ssh 之間添加額外的代理,以刪除 ssh 能夠讀取的 proxy_protocol
  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;
    ... 
    }
}

“set_real_ip_from”指令應該是邊緣設備的地址/ CIDR

stream {
    server {
        listen            3333 proxy_protocol;
        proxy_pass        127.0.0.1:2222;
        proxy_protocol    on;
        set_real_ip_from  10.0.0.0/8;
    }
}

據我所知,只有兩個解決方案: 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。 在這種情況下,您需要在邊緣設備上啟用代理協議 ,並在server塊中啟用proxy_protocol偵聽器。 我還沒有測試過,但這樣的事情應該可行。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM