在 NGINX 中根據使用者真實 IP 進行限制

東風微鳴發表於2023-01-13

需求

需要根據使用者的真實 IP 進行限制, 但是 NGINX 前邊還有個 F5, 導致 deny 指令不生效.

阻止使用者的真實 IP 不是 192.168.14.*192.168.15.* 的訪問請求.

實現

最簡單的實現如下:

? 前置條件:

需要 nginx 前邊的 load balancer 裝置(如 F5)開啟 X-Forwarded-For 支援.

proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

if ($proxy_add_x_forwarded_for !~ "192\.168\.1[45]")  {
    return 403;
}      

說明如下:

  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; 獲取請求頭 X-Forwarded-For 中的使用者真實 IP, 並附加到 $proxy_add_x_forwarded_for 變數
  • if...
    • (...) 變數 $proxy_add_x_forwarded_for 不匹配正則 192\.168\.1[45] (即 192.168.14.*192.168.15.*)
    • return 403, 如果上邊的條件滿足, 返回 403
    • 即: 如果真實IP不是 192.168.14.*192.168.15.*, 返回403.

如果有更復雜的需求, 可以參考這個示例:

proxy_set_header HOST $http_host;
proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;

if ($http_host ~ "yourdomain.hypernode.io:8443")  {
  set $block_me_now A;
}
 
if ($proxy_add_x_forwarded_for != YOURIP) {
  set $block_me_now "${block_me_now}B";
}
 
 
if ($block_me_now = AB) {
    return 403;
    break;
}

為啥 deny 配置不起作用?

? 疑問: 為啥以下的配置不起作用?

allow 192.168.14.0/24;
allow 192.168.15.0/24;
deny all;

根據nginx官方文件, deny 指令是根據「client address」進行限制的.

? 引用:

The ngx_http_access_module module allows limiting access to certain client addresses.

而「client address」對應的變數是: $remote_addr

? 引用:

$remote_addr:
​ client address

關於 $remote_addr:

是 nginx 與客戶端進行 TCP 連線過程中,獲得的客戶端真實地址. Remote Address 無法偽造,因為建立 TCP 連線需要三次握手,如果偽造了源 IP,無法建立 TCP 連線,更不會有後面的 HTTP 請求

remote_addr 代表客戶端的 IP,但它的值不是由客戶端提供的,而是服務端根據客戶端的 ip 指定的,當你的瀏覽器訪問某個網站時,假設中間沒有任何代理,那麼網站的 web 伺服器(Nginx,Apache 等)就會把 remote_addr 設為你的機器IP,如果你用了某個代理(其實 F5 就是這個反向代理),那麼你的瀏覽器會先訪問這個代理,然後再由這個代理轉發到網站,這樣 web 伺服器就會把 remote_addr 設為這臺代理機器的 IP。

但是實際某些特殊場景中,我們即使有代理,也需要將 $remote_addr 設定為真實的使用者 IP,以便記錄在日誌當中,當然 nginx 是有這個功能,但是需要編譯的時候新增 --with-http_realip_module 這個模組,預設是沒有安裝的。(我也沒有安裝)

三人行, 必有我師; 知識共享, 天下為公. 本文由東風微鳴技術部落格 EWhisper.cn 編寫.

相關文章