[開發環境] IIS ARR 環境設定

IIS ARR(Application Request Routing),是微軟 Internet Information Services(IIS)提供的一個擴充功能,它的主要功能是提供負載平衡和反向代理服務。

何謂負載平衡(Load Balancing)?它是一種分配請求或工作負載到多個伺服器或資源上的技術,通常位於客戶端和伺服器之間,接收來自客戶端的請求,然後根據特定的算法(如輪詢、最小連接數、最少負載等)將這些請求分發到多個伺服器上,這樣可以確保每個伺服器都能夠平均處理請求,從而避免單個伺服器負載過重,提高整個系統的性能和可靠性。

何謂反向代理(Reverse Proxy)?主要的目的是接收來自客戶端的請求,然後將這些請求轉發到內部伺服器或者後端伺服器上,並將伺服器的響應返回給客戶端,這樣客戶端看到的是反向代理伺服器的地址,而不是後端伺服器的地址。這樣可以幫助隱藏內部伺服器的資訊,增加安全性。

常見的類似服務有 Nginx、Traffic,下文為安裝 ARR 服務的相關說明。


安裝必要模組

  1. 下載並安裝 URL Rewrite
  2. 下載並安裝 Application Request Routing

ARR 環境設定

  1. 先檢視模組是否安裝正確,你先點選「伺服器節點」,再看看 IIS 區段中有沒有 Application Request Routing 與 URL Rewrite 模組。

  2. 對 Application Request Routing 進行底下的設定。
    • 啟用 Proxy 功能。
    • 取消勾選 "Reverse rewrite host in response headers" 選項。
    • (非必要) 若在內部伺服器抓取 Client IP 不須記錄到 port 的話,也一併將 "Include TCP port from client IP" 取消勾選。
    • 然後再點選右邊的「套用」按鈕,其他預設值都可以不用修改。此步驟修正完成後必須重新啟動 IIS 才會生效。

ARR 轉址設定(Reverse Proxy)

  1. 新增要當作轉址的主要站台,這邊建議把 HTTPS 的設定也都放在 ARR 這邊統一管理。
  2. 到該站台的 URL Rewrite 設定-> Add Rule > Reverse Proxy,進行要轉至內部站台的 "網址/IP" 及 "port"。

  3. 若有需要進行 HTTP -> HTTPS 也可一併調整設定,相關設定如下 web.config。
    <?xml version="1.0" encoding="UTF-8"?>
    <configuration> 
        <system.webServer>  
            <rewrite>
              <rules> 
    	    <!-- http to https -->
                <rule name="Redirect to https" stopProcessing="true">
                  <match url="(.*)" />
                  <conditions>
                    <add input="{HTTPS}" pattern="^OFF$" />
                    <add input="{HTTP_HOST}" pattern="localhost" negate="true" />
                  </conditions>
                  <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" />
                </rule>
    			
    	    <!-- Reverse Proxy 設定 -->
    	    <rule name="ReverseProxyToPrimeEagle" stopProcessing="true">
                  <match url="(.*)" />
                  <conditions>
                    <!-- 符合條件的網域 -->
                    <add input="{HTTP_HOST}" pattern="^(primeeagle\.net|www\.primeeagle\.net)$" />   
                  </conditions>
                  <action type="Rewrite" url="http://內部電腦名稱/{R:1}" />
                </rule>
              </rules>
            </rewrite>
        </system.webServer>
    </configuration>
    

內部虛擬機站台設定

  1. 請記得將防火牆開啟。
  2. 設定 IIS Log 用來記錄原始 Client IP 的網址,否則每次都需要到 ARR 主機查詢有點麻煩。
  3. 在 [記錄檔] 下的 [格式] 欄位中,選取[W3C],然後按一下 [選取欄位...]。

  4. 在 [ W3C 記錄欄位] 對話方塊中,按一下 [ 新增欄位...],並輸入底下設定。
    • 欄位名稱 : OriginalIP
    • 來源類型 : 要求標頭
    • 來源 : X-FORWARDED-FOR
  5. 設定完畢後,按一下 [動作] 窗格中的 [套用] 以套用新的組態。 
  6. 設定完成後可到 %SystemDrive%\inetpub\logs\LogFiles 查看各站台 Log 紀錄,至於各站台 ID,可以到底下畫面的功能處查詢。

IIS 轉址設定

使用 Reverse Proxy 轉入指定站台後,在無調整的情況下預設 HttpContext.Request 的網址會抓到錯誤的網址和協定,原因是因為 User 請求到 Host 但由 Host 轉發內部請求,導致抓到的是內部的 Url,例如 https://xxxx.primeeagle.net -> http://pordap01:8001,會抓到 prodap01:8001,底下為解決方法的說明,亦可參考 此處 說明。

  • 在 Host 的 IIS 新增信任的伺服器變數,URL Rewrite -> 管理伺服器變數 -> 檢視伺服器變數。
    HTTP_X_FORWARDED_HOST
    HTTP_X_FORWARDED_PROTO

  • 站台轉址設定中指定要轉到內部伺服器的數值,如下圖,亦可直接調整 web.config 中的設定。
    <rewrite>
      <rules> 
        <rule name="Global_Http" stopProcessing="true">
          <match url="(.*)" />
          <conditions trackAllCaptures="true">
             <add input="{HTTP_HOST}" pattern="localhost" />
          </conditions>
          <!-- 目的伺服器 -->
          <action type="Rewrite" url="http://localhost:5000/{R:1}" logRewrittenUrl="true" /> 
          <serverVariables>
             <!-- 要轉送的參數 -->
             <set name="HTTP_X_FORWARDED_HOST" value="{HTTP_HOST}" />
             <set name="HTTP_X_FORWARDED_PROTO" value="http" /> 
          </serverVariables>
        </rule> 
      </rules>
    </rewrite>

  • 另外 Net Core 程式也需要配合在 Middleware 中調整,可參考 此處 的說明。
  • (選擇性設定) 如果程式無法配合調整的話(例如套裝軟體),這個時候只能透過修改 IIS 保留主機標頭的設定,也就是請求端的網址是什麼就會將 Host 原封不動的網內部轉址伺服器送過去,但這個設定將會影響整台的 IIS 伺服器,可參考 此處 的說明,相關設定步驟如下。
    • 開啟 IIS 管理員,選擇伺服器節點。
    • 選擇管理 → 雙擊設定編輯器。
    • 從下拉式選單中選擇區段 system.webServer/proxy。
    • 設定 preserveHostHeader 為 true。


內部伺服器 Tomcat 設定

在我們的環境中,我們使用了套裝軟體,該軟體使用 Tomcat 作為 Web 伺服器,並通過 JSP 的 request.getScheme 方法來判斷網站是使用 HTTP 還是 HTTPS,但因為我們使用了 ARR(Application Request Routing)作為反向代理伺服器,套專軟體檢測到的協議是 HTTP,這導致 HTTPS 站台錯誤地使用了 HTTP 的內部 CSS 和 JavaScript 資源,而這種行為會被瀏覽器阻擋,因而引發了一連串的錯誤。

由於無法更改第三方軟體的程式碼,若你有跟我一樣的問題,或許可以透過修改 Tomcat 的設定來解決這個問題,請按照以下步驟進行操作

  • 在 IIS 中完成 URL 重寫,設定 HTTP_X_FORWARDED_PROTO 參數,可參考上面的步驟設定,將其值設定為 https。
  • 修改 Tomcat 的配置文件。在 conf/server.xml 中找到您的 <Host> 元素,並在其內添加以下配置。
    <Valve className="org.apache.catalina.valves.RemoteIpValve"
       internalProxies=".*"
       protocolHeader="X-Forwarded-Proto" /> 
    
  • 重新啟動 Tomcat。

若你想要測試修改的參數是否生效,底下我有寫一個簡單的 JSP 程式讓你可以看到 Request 的相關參數,一併提供給打大家參考。

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8"> 
</head>
<body> 
    <p>Request Scheme: <%= request.getScheme() %></p>
    <table border="1">
        <tr>
            <th>Header Name</th>
            <th>Header Value</th>
        </tr>
        <%
            java.util.Enumeration<String> headerNames = request.getHeaderNames();
            while (headerNames.hasMoreElements()) {
                String headerName = headerNames.nextElement();
                String headerValue = request.getHeader(headerName);
        %>
        <tr>
            <td><%= headerName %></td>
            <td><%= headerValue %></td>
        </tr>
        <%
            }
        %>
    </table>
</body>
</html>


參考網站

ARR


Server Farm


其它

留言