記一次LVS/Nginx環境下的訪問控制

jopen 9年前發布 | 15K 次閱讀 Nginx Web服務器

原文  http://huoding.com/2015/01/23/412

偶然間,我發現 Graphite 顯示服務器網卡流量呈鋸齒狀,于是查了一下 Nginx 日志,發現有人在周期性抓我們的接口數據。我這爆脾氣自然不能容忍這種行徑。

簡單分析一下訪問日志,很容易就能拿到了可疑的 IP 段,直接用 iptables 封殺:

shell> iptables -A INPUT -s x.y.z.0/24 -j DROP

本以為世界會就此清凈,可沒想到一點兒用都沒有。莫非小偷已經突破鎖頭的限制?不能夠啊!直覺告訴我問題應該和 LVS 有關,可惜我對 LVS 的了解極其匱乏,唯一知道的就是項目用的是 FULLNAT 模式,那就以此為切入點開始挖掘:

記一次LVS/Nginx環境下的訪問控制

LVS FULLNAT

所謂 FULLNAT 模式,是指當用戶請求經由 LVS 轉發給 RS 服務器的時候,其來源 IP 會從用戶 IP 改成 LVS 內網 IP,目標 IP 會從 LVS 的 VIP 改成 RS 服務器的 IP;當 RS 服務器生成響應數據經由 LVS 返回給用戶的時候,其來源 IP 會從 RS 服務器 IP 改成 LVS 的 VIP,目標 IP 會從 LVS 內網 IP 改成用戶 IP。

說明:關于 LVS 更詳細的介紹請參考「 從一個開發的角度看負載均衡和LVS 」一文。

對于 RS 服務器而言,實際上它看到的是 LVS。可我們明明在 Nginx 日志里看到了客戶端的 IP,而不是 LVS 的 IP,這又是什么原因呢?原來 LVS 為了解決 FULLNAT 模式下傳遞用戶 IP 的問題,引入了一個名為 TOA 的補丁機制,在 TCP 的三次握手階段,通過 TCP 的 options 來傳遞用戶 IP 和端口等信息,繼而覆蓋 socket 的 IP 和端口數據。

換句話說,在 RS 服務器上,從 iptables 的角度看,因為 NAT 的緣故,來源 IP 都是 LVS 的 IP;而從 Nginx 的角度看,因為 TOA 的緣故,來源 IP 都是用戶的 IP。關于這一點也可以通過 tcpdump 命令抓包來印證:

記一次LVS/Nginx環境下的訪問控制

tcpdump

說明:如上圖所示那一堆 254 開頭的字符串里保存的就是用戶 IP 和端口等信息。

于是乎可以得出結論:在 RS 服務器上通過 iptables 來封殺用戶 IP 無疑是沒有意義的,如果一定要用 iptables,應該在 LVS 服務器上用,但實際情況是我無權操作 LVS 服務器,只能在 RS 服務器上想辦法。既然 Nginx 能拿到用戶 IP,那么我們就可以在 Nginx 上解決問題,有 AccessGEO 等模塊可供選擇,這里我們選擇的是 GEO 模塊:

geo $bad {
  default 0;
  x.y.z.0/24 1;
}
location / {
  if ($bad) {
    return 403;
  }
}

關于 GEO 模塊的例子,有一些不錯的 資料 可供參考,這里我就不多說了。

</div> </div>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!