2015年1月21日 星期三

nginx 設定反向代理伺服器

反向代理:真實的伺服器在反向代理伺服器後面,使用者訪問反向代理伺服器,反向代理伺服器再將 request 轉給真實伺服器處理。所以使用者不知道真實伺服器在哪邊(可能在內網,也可能在其他國家),可隱藏真正伺服器的位置。

nginx 設定反向代理伺服器範例
server {
    listen 80;
    server_name aa.example.com
    location / {
        # 設定真實伺服器 
        proxy_pass http://192.168.0.10:80;

        # 真實伺服器接收到的網址,會是 proxy_pass 設定的網址
        # 若真實伺服器 server_name 設定,也跟反向伺服器一樣(aa.example.com)
        # 可將Host設定 $host (預設為$proxy_host,本例$proxy_host等同192.168.0.10)
        proxy_set_header Host $host;

        # 自訂一個header變數,名稱可隨意設定(一般是X-Real-IP),帶上使用者的 IP 
        proxy_set_header X-Real-IP $remote_addr;

        # 自訂一個header變數,名稱可隨意設定(一般是X-Forwarded-Proto),帶上反向代理是http或https
        # 因為可能跟真實伺服器不一樣,而真實伺服器上的程式,可能需要知道使用者是使用http或https
        # 可直接用nginx 的 $scheme 變數,request scheme, “http” or “https”
        proxy_set_header X-Forwarded-Proto $scheme;

        # 加上中間經過的代理IP,逗號區隔(client, proxy1, proxy2...)
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}


經過反向代理伺服器的時候,真正提供服務的 server 用 REMOTE_ADDR 取得的 IP 將會是代理伺服器的 IP,要知道使用者真正的 IP,可在代理伺服器上加上自訂的 Header 參數,代入 clinet 端的 IP。

上面的範例,在 PHP 中,則可以用 $_SERVER['HTTP_X_REAL_IP']、$_SERVER['HTTP_X_FORWARDED_FOR'] 取得相關的 IP 資訊。
$_SERVER["HTTP_X_FORWARDED_PROTO"]:取得反向代理設定的http或https資訊。

其他設定:
  • proxy_buffers
        proxy_buffering on;
        proxy_buffer_size 32k;
        proxy_buffers 64 32k;
    
  • proxy_redirect
    Sets the text that should be changed in the “Location” and “Refresh” header fields of a proxied server response. Suppose a proxied server returned the header field “Location: http://localhost:8000/two/some/uri/”. The directive
    經過反向代理時,反向代理將真實主機傳過來 header 中「Location」、「Refresh」改寫
    例如:
    proxy_redirect http:// https://;
    表示當程式中有(以PHP為例)
    header('Location: http://zz.exapmle.com');
    經過反向代理時,http://zz.exapmle.com 會被改寫成 https://zz.exapmle.com

    一般若只是要將瀏覽器輸入的 http 網址,轉成 https,
    不需要去改真實主機程式傳過來的 header
    可用以下方式處理
    rewrite ^(.*) https://$host$1 permanent;

    return 301 https://$host$request_uri;

    return 308 https://$host$request_uri;

    因為程式會連 http 都寫出,不寫相對路徑,通常是「確定」要連到其他 http 網站。
    強制將 http 改寫成 https,可能反產生錯誤。


參考:



沒有留言:

張貼留言