本次展示的架構如下 :
其中代理伺服器使用 CentOS 7 的 HAProxy 1.5.14 套件,而 Web 服務器使用 CentOS 7 的 Apache 套件。
我們先在 Web 服務器放置內容如下的 PHP 腳本,而在 PHP 中,$_SERVER["HTTP_X_FROWARDED_FOR"] 這個變數就代表 HTTP 檔頭 X-Forwarded-For。
<?php echo nl2br("X-Forwarded-For: " . $_SERVER["HTTP_X_FORWARDED_FOR"] . PHP_EOL); echo nl2br("Remote Address: " . $_SERVER["REMOTE_ADDR"] . PHP_EOL);
用戶端直接連結 Web 服務器
當用戶端直接連往 Web 服務器 (192.168.10.12) 上的 PHP 腳本後,可以看到如下的輸出:
HTTP-X-Forwarded-For: Remote Address: 192.168.10.10在這種單純的情況下,直接使用 REMOTE_ADDR 變數即可取得用戶端的 IP 位址。
用戶端透過 HAProxy 的 HTTP 模式連往 Web 服務器
我們在 HAProxy 使用下列設定:
listen http-proxy bind 0.0.0.0:80 mode http option httpchk option forwardfor balance source server web-1 192.168.10.12:80 weight 1 check當用戶端透過代理伺服器 (192.168.10.11) 連往 Web 服務器 (192.168.10.12) 上的 PHP 腳本後,可以看到如下的輸出:
X-Forwarded-For: 192.168.10.10 Remote Address: 192.168.10.11在這種情況下,儘管 REMOTE_ADDR 變數顯示為代理伺服器的 IP 位址,但是使用 HTTP_X_FROWARDED_FOR 變數依舊可取得用戶端的 IP 位址。
用戶端透過 HAProxy 的 HTTP 模式連往 Web 服務器
我們將 HAProxy 的設定修改成如下:
listen http-proxy bind 0.0.0.0:80 mode tcp balance source server web-1 192.168.10.12:80 weight 1 check當用戶端透過代理伺服器 (192.168.10.11) 連往 Web 服務器 (192.168.10.12) 上的 PHP 腳本後,可以看到如下的輸出:
X-Forwarded-For: Remote Address: 192.168.10.11在這種情況下,不存在 HTTP_X_FROWARDED_FOR 變數,而 REMOTE_ADDR 顯示的也是代理伺服器 IP 位址。也就是程式無法正確獲得用戶端 IP 位址。
用戶端透過支援 Proxy Protocol 的設定連往 Web 服務器
因為 HAProxy 本身就內建支援 Proxy Protocol,所以不需安裝額外的套件,只要把設定修改成如下即可:
listen http-proxy bind 0.0.0.0:80 mode tcp balance source server web-1 192.168.10.12:80 weight 1 check send-proxy至於 Apache 的部分,因為 Apache 目前尚未內建 Proxy Protocol 的支援,所以我們需要安裝另外的模組。在此,我以 myfixip 模組為例,相關步驟如下:
yum install git gcc httpd-devel cd /tmp git clone https://github.com/ggrandes/apache24-modules.git cd apache24-modules apxs –i –c mod_myfixip.c新增檔案 /etc/httpd/conf.modules.d/00-myfixip.conf,內容如下
LoadModule myfixip_module modules/mod_myfixip.so <IfModule mod_myfixip.c> RewriteIPResetHeader off RewriteIPAllow 192.168.10.0/24 127.0.0.1 </IfModule> systemctl restart httpd需特別注意的是因為 Proxy Protocol 會改變代理伺服器與 Web 服務器之間的溝通方式,所以需要兩邊同時啟用,否則將無法正常運作,甚至可能導致無法存取服務。
當用戶端再次透過代理伺服器 (192.168.10.11) 連往 Web 服務器 (192.168.10.12) 上的 PHP 腳本後,可以看到如下的輸出:
X-Forwarded-For: Remote Address: 192.168.10.10在這種情況下,即使經過代理伺服器的作用,但是 REMOTE_ADDR 變數依舊可以正確地顯示出用戶端的 IP 位址。
透過 myfixip 模組,可以讓 Apache 支援 Proxy Protocol,有效地取得用戶端 IP 位址。
除了 HAProxy 之外,如果你使用了 AWS ELB 的 TCP 或 SSL 模式,透過 myfixip 擴充 Apache 使其支援 Proxy Protocol 也同樣會有很大的助益。比較麻煩的是,目前 AWS 的管理介面並不支援 Proxy Protocol 的設定,而必須使用命令列模式控制 Proxy Protocol 的開啟或關閉。有需要的讀者可參考官方文件。
沒有留言:
張貼留言