[開發環境] IIS ARR 環境設定
IIS ARR(Application Request Routing),是微軟 Internet Information Services(IIS)提供的一個擴充功能,它的主要功能是提供負載平衡和反向代理服務。
何謂負載平衡(Load Balancing)?它是一種分配請求或工作負載到多個伺服器或資源上的技術,通常位於客戶端和伺服器之間,接收來自客戶端的請求,然後根據特定的算法(如輪詢、最小連接數、最少負載等)將這些請求分發到多個伺服器上,這樣可以確保每個伺服器都能夠平均處理請求,從而避免單個伺服器負載過重,提高整個系統的性能和可靠性。
何謂反向代理(Reverse Proxy)?主要的目的是接收來自客戶端的請求,然後將這些請求轉發到內部伺服器或者後端伺服器上,並將伺服器的響應返回給客戶端,這樣客戶端看到的是反向代理伺服器的地址,而不是後端伺服器的地址。這樣可以幫助隱藏內部伺服器的資訊,增加安全性。
常見的類似服務有 Nginx、Traffic,下文為安裝 ARR 服務的相關說明。
安裝必要模組
- 下載並安裝 URL Rewrite。
- 下載並安裝 Application Request Routing。
ARR 環境設定
- 先檢視模組是否安裝正確,你先點選「伺服器節點」,再看看 IIS 區段中有沒有 Application Request Routing 與 URL Rewrite 模組。
- 對 Application Request Routing 進行底下的設定。
- 啟用 Proxy 功能。
- 取消勾選 "Reverse rewrite host in response headers" 選項。
- (非必要) 若在內部伺服器抓取 Client IP 不須記錄到 port 的話,也一併將 "Include TCP port from client IP" 取消勾選。
- 然後再點選右邊的「套用」按鈕,其他預設值都可以不用修改。此步驟修正完成後必須重新啟動 IIS 才會生效。
ARR 轉址設定(Reverse Proxy)
- 新增要當作轉址的主要站台,這邊建議把 HTTPS 的設定也都放在 ARR 這邊統一管理。
- 到該站台的 URL Rewrite 設定-> Add Rule > Reverse Proxy,進行要轉至內部站台的 "網址/IP" 及 "port"。
- 若有需要進行 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>
內部虛擬機站台設定
- 請記得將防火牆開啟。
- 設定 IIS Log 用來記錄原始 Client IP 的網址,否則每次都需要到 ARR 主機查詢有點麻煩。
- 在 [記錄檔] 下的 [格式] 欄位中,選取[W3C],然後按一下 [選取欄位...]。
- 在 [ W3C 記錄欄位] 對話方塊中,按一下 [ 新增欄位...],並輸入底下設定。
- 欄位名稱 : OriginalIP
- 來源類型 : 要求標頭
- 來源 : X-FORWARDED-FOR
- 設定完畢後,按一下 [動作] 窗格中的 [套用] 以套用新的組態。
- 設定完成後可到 %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
- Microsoft - ARR 作為轉寄 Proxy
- 保哥 - 在 IIS 8 安裝設定 ARR 與 Web Farm Framework 的注意事項
- 保哥 - 如何利用 IIS7 的 ARR 模組實做 Reverse Proxy 機制
- 使用IIS ARR (Application Request Routing) 來做Exchange 2010的負載平衡器
- [IIS][GitLab] 利用 IIS Reverse Proxy 將 GitLab 加上 Https
- 配置IIS反向代理教程
- [IIS] 修正 reverse proxy 的 host 問題
- [實作筆記] 使用 IIS 作為 Reverse Proxy Server
- IIS Reverse Proxy 反向代理
- IIS使用ARR(Application Request Routing)和URL Rewrite实现反向代理
留言
張貼留言
您好,我是 Lawrence,這裡是我的開發筆記的網誌,如果你對我的文章有任何疑問或者有錯誤的話,歡迎留言讓我知道。