不知道中間代理 IP 地址時使用 Nginx real_ip
Nginx 的real_ip 模組允許您
$remote_addr
根據特定標頭欄位中發送的值設置變數。它對header有特殊的理解,X-Forwarded-For
能夠將header中最右邊的untrusted值作為連接IP地址。我想使用 real_ip 模組來設置
$remote_addr
連接 IP 地址。**我遇到的問題是我知道從末尾返回多少跳X-Forwarded-For
,但不知道中間代理的 IP 地址。**據我了解,這意味著我不能set_real_ip_from
用來指定代理的 IP 地址。我想要做的是配置 nginx 選擇列表中倒數第二個地址作為
$remote_addr
. 似乎 real_ip 模組僅在您擁有知道代理 IP 地址的基礎架構時才有效。有沒有辦法用 real_ip 模組做到這一點?我已經制定了一個基於正則表達式的解決方案,但如果可能的話,我更願意使用 real_ip 模組。
我不認為這是nginx real_ip_header 的欺騙,而 X-Forwarded-For 似乎是錯誤的或類似的問題。重申問題:
- 我知道連接IP地址從末端有多少跳。
- 我不知道連接 IP 和我的伺服器之間的中間代理的可信 IP 地址,所以我不能使用
set_real_ip_from
.有關細節的更多詳細資訊:
我在 Google Cloud HTTP 負載均衡器後面的 Google Cloud 中執行 nginx。Google Cloud使用標
X-Forwarded-For
頭指示 Google Cloud 網路的入口點。我知道X-Forwarded-For
列表中倒數第二個值是我想要的值,但我不知道最後一個值(代理)的 IP 地址是什麼。即使我可以為代理列舉所有 Google Cloud 的地址空間(沒有指定 GCLB 僅在 GCP 的地址空間內執行),這也會為任何其他可以在該地址空間內獲取伺服器的使用者打開它。
我最終使用了基於正則表達式的版本。從我的 nginx 配置中:
http { # Regexes are: # (?<connecting_ip>\d+\.\d+\.\d+\.\d+), (?<proxy_ip>\d+\.\d+\.\d+\.\d+)$ # IPv4 only # (?<connecting_ip_x>[0-9a-f:.]+),\s*(?<proxy_ip>[0-9a-f:.]+)$ # IPv6 and IPv4, and more robust # # The last IP address is the one from the GCP front end load balancer # The second to last IP address in the list is the connecting IP address (i.e. user IP address) # We capture both of them. X-Forwarded-For is separated by commas, hopefully whitespace as well # but we don't want to trust that too much. # # Note that ~ at the start of the string in Nginx marks it as a regex. It's not part # of the regex. # # Test cases for regex101 # 1.1.1.1, 2.2.2.2 # 1.1.1.1, 2.2.2.2, 3.3.3.3 # 1.1.1.1 # ::ffff:130.211.1.102, 2.2.2.2 # 2001:0db8:85a3:0000:0000:8a2e:0370:7334, 2.2.2.2 # 2001:41d0:8:e8ad::1, 2600:1901:0:2ad2:: # 1.1.1.1,2.2.2.2,3.3.3.3 # # It would be better to use the real_ip module, if that is possible # https://serverfault.com/q/947835/334330 might get answered for this. # Get the IP address of the connecting IP. If we get a direct connection from # GCP's health checkers, there won't be an X-Forwarded-For header. We shouldn't # be getting any direct connections from other sources without XFF header. map $http_x_forwarded_for $connecting_ip { # Capture the proxy IP and connecting_ip_x, then assign the connecting_ip_x "~(?<connecting_ip_x>[0-9a-f:.]+),\s*(?<proxy_ip>[0-9a-f:.]+)$" $connecting_ip_x; default $remote_addr; } # ... }
然後我在我的伺服器定義中使用 $connecting_ip :
server { # ... location / { proxy_set_header X-Real-IP $connecting_ip; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_set_header X-Forwarded-Host ""; proxy_redirect off; proxy_next_upstream error; } }