Tommy 碎碎念

Tommy Wu's blog

« 上一篇 | 下一篇 »

讓 Nginx 的 real_ip 模組找不到對應的 header 時, 使用 proxy protocol 傳入的 IP
post by tommy @ 24 三月, 2023 10:08

最近把 DNS 轉到 Cloudflare 使用, 原本在主機上使用 HAProxy 把 SSL 的封包轉到個別對應的軟體是使用 Proxy Protocol 將來源 IP 通知處理的軟體. 在改用 Cloudflare 之後, 這個 IP 就變成 Cloudflare 的 IP 了. 這個在需要知道來源 IP 的軟體上, 就反而造成問題.

通常會走 Cloudflare 進來的, 也都是網頁的服務 (其他同樣使用 SSL 走 443 的服務, 也不需要透過 Cloudflare 處理, 通常可以在 DNS 上另外設定來避開). 依據 Cloudflare 的作法, 是應該使用 HTTP 的 header CF-Connecting-IP 來取得真實的來源 IP. 不過.... 由於我這邊是先透過 HAProxy 處理過, 混雜了來自 Cloudflare 與沒經過 Cloudflare 的封包 (例如內部網路的機器), 這時, 就變成使用 CF-Connecting-IP 時, 非來自 Cloudflare 的 IP 變成 HAProxy 的 127.0.0.1, 如果使用 Proxy Protocol 時, 那些透過 Cloudflare 的封包, 來源 IP 又全變成 Cloudflare 的 IP 了.

看了一下 Nginx 的 real_ip 模組設定, real_ip_header 就只能設定一種, 不能有多重的設定, 所以就只好看一下 source, 自己動手來修改.

--- nginx-1.23.3/src/http/modules/ngx_http_realip_module.c.orig 2023-03-19 11:18:38.033783262 +0800
+++ nginx-1.23.3/src/http/modules/ngx_http_realip_module.c      2023-03-19 11:17:30.029338872 +0800
@@ -157,7 +157,8 @@
     case NGX_HTTP_REALIP_XREALIP:

         if (r->headers_in.x_real_ip == NULL) {
-            return NGX_DECLINED;
+            //return NGX_DECLINED;
+            goto try_proxy_protocol;
         }

         value = &r->headers_in.x_real_ip->value;
@@ -170,7 +171,8 @@
         xfwd = r->headers_in.x_forwarded_for;

         if (xfwd == NULL) {
-            return NGX_DECLINED;
+            //return NGX_DECLINED;
+            goto try_proxy_protocol;
         }

         value = NULL;
@@ -178,6 +180,7 @@
         break;

     case NGX_HTTP_REALIP_PROXY:
+try_proxy_protocol:
         if (r->connection->proxy_protocol == NULL) {
             return NGX_DECLINED;
         }
@@ -219,7 +222,8 @@
             }
         }

-        return NGX_DECLINED;
+        //return NGX_DECLINED;
+        goto try_proxy_protocol;
     }

 found:

修改的方式其實不難, 這邊的處理雖然是用 switch case 來獨立處理, 不過可以發現其實是不是透過 Proxy Protocol 處理過, 是有方法可以判斷的, 所以我們只要在其中每一種用來取得 real_ip 的 case 中, 如果最後沒有處理到, 就轉給 Proxy Protocol 那一段來處理就可以.

這樣子修改後, 我們依舊可以在 Nginx 中設定

real_ip_header CF-Connecting-IP;

就算是沒有這個 header 的來源, 一樣仍透過 Proxy Protocol 處理, 就算也沒透過 Proxy Protocol, 一樣可以判斷出來而不會造成問題.

Del.icio.us Furl HEMiDEMi Technorati MyShare
迴響
暱稱:
標題:
個人網頁:
電子郵件:
authimage

迴響

  

Bad Behavior 已經阻擋了 60 個過去 7 天試圖闖關的垃圾迴響與引用。
Power by LifeType. Template design by JamesHuang. Valid XHTML and CSS