Iis

IIS 中反向代理背後的基於 Websocket 的網站

  • August 12, 2021

我正在嘗試讓一個基於 websocket 的網站工作,該網站正在被 IIS 伺服器反向代理。

情況

  • IIS v10.0.19041.1執行Windows 10 Pro
  • 來自IIS並由其LetsEncrypt安裝/管理的SSL 證書。Win-ACME
  • FoundryVTT v0.7.3執行在 a 中的專用伺服器FreeNAS 11.4-RELEASE-p2 jail(這是基於 websocket 的網站)。
  • FoundryVTTsocket.io用於node.js.
  • FoundryVTT 伺服器位於IP 192.168.2.36Port 30000

觀察

  • FoundryVTT 伺服器在 LAN 上執行良好。
  • SSL 證書有效且有效,伺服器可從 WAN 訪問。
  • 通過 WAN 載入 FoundryVTT 設置頁面後一切正常,但是一旦我輸入了我的管理員訪問密鑰,我就會看到一個空的設置頁面。FoundryVTT 社區提到這是代理配置錯誤的一個已知問題。 空設置頁面
  • 在使用 Fiddler v5.0.2020.18177 觀察網路流量時,我發現我確實到達了將協議切換到 websocket 的 101 HTTP 響應的地步。Fiddler websocket 響應
  • 點兩下擷取不會讓我轉到 websocket 選項卡來檢查那裡的流量。我懷疑根本沒有建立任何連接,因為在最初的第一個響應之後,我看到了更多的 101 交換協議響應,中間有輕微的延遲。

我試過什麼

  • 我已驗證我已安裝 WebSocket 協議功能。Windows 功能 - WebSocket 協議
  • 我已經在 IIS 中驗證了我的網站上啟用了 websocket。IIS - 配置編輯器 - webSocket
  • 我已經嘗試web.config通過遵循人們在網際網路上提出的各種建議(即thisthisthis)來解決這個問題。web.config 現在的樣子:
 <?xml version="1.0" encoding="UTF-8"?>
 <configuration>
     <system.webServer>
         <rewrite>
             <rules>
                 <clear />
                 <rule name="Web Socket Reverse" enabled="true" stopProcessing="true">
                     <match url="ws:///example.com:30000(.*)" />
                     <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                     </conditions>
                     <action type="Rewrite" url="ws://192.168.2.36:30000/{R:1}" />
                 </rule>
                 <rule name="Web Socket Reverse 2" enabled="true" stopProcessing="true">
                     <match url="wss://example.com:30000(.*)" />
                     <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                     </conditions>
                     <action type="Rewrite" url="wss://192.168.2.36:30000/{R:1}" />
                 </rule>
                 <rule name="HTTPS redirect" enabled="true" stopProcessing="true">
                     <match url="(.*)" />
                     <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                         <add input="{HTTPS}" pattern="^OFF$" />
                     </conditions>
                     <action type="Redirect" url="https://{HTTP_HOST}{REQUEST_URI}" />
                 </rule>     
                 <rule name="FoundryVTT proxy" stopProcessing="true">
                   <match url="(.*)" />
                   <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                     <add input="{HTTP_HOST}" pattern="example.com" />
                   </conditions>
                   <action type="Rewrite" url="http://192.168.2.36:30000/{R:1}" />
                   <serverVariables>
                     <set name="HTTP_X_ORIGINAL_ACCEPT_ENCODING" value="{HTTP_ACCEPT_ENCODING}" />
                     <set name="HTTP_ACCEPT_ENCODING" value="" />
                   </serverVariables>
                 </rule>
                 <rule name="RequestBlockingRule1" enabled="true" patternSyntax="Wildcard" stopProcessing="true">
                     <match url="*" />
                     <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                         <add input="{URL}" pattern="*" />
                         <add input="{HTTP_HOST}" pattern="example.com" negate="true" />
                     </conditions>
                     <action type="CustomResponse" statusCode="403" statusReason="Forbidden: Access is denied." statusDescription="You do not have permission to view this directory or page using the credentials that you supplied." />
                 </rule>
             </rules>
             <outboundRules>
                 <rule name="RestoreAcceptEncoding" preCondition="NeedsRestoringAcceptEncoding">
                   <match serverVariable="HTTP_ACCEPT_ENCODING" pattern="^(.*)" />
                   <conditions logicalGrouping="MatchAll" trackAllCaptures="true" />
                   <action type="Rewrite" value="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" />
                 </rule>
                 <rule name="ReverseProxyOutboundRule1" preCondition="ResponseIsHtml1">
                     <match filterByTags="A, Form, Img" pattern="^http(s)?://192.168.2.36:30000/(.*)" />
                     <action type="Rewrite" value="http{R:1}://example.com/{R:2}" />
                 </rule>
                 <preConditions>
                   <preCondition name="ResponseIsHtml1">
                     <add input="{RESPONSE_CONTENT_TYPE}" pattern="^text/html" />
                   </preCondition>
                   <preCondition name="NeedsRestoringAcceptEncoding">
                     <add input="{HTTP_X_ORIGINAL_ACCEPT_ENCODING}" pattern=".+" />
                   </preCondition>
                 </preConditions>
               </outboundRules>
             <rewriteMaps>
                 <!--{MapProtocol:{HTTPS}}-->
                 <rewriteMap name="MapProtocol">
                     <add key="on" value="https" />
                     <add key="off" value="http" />
                 </rewriteMap>
             </rewriteMaps>
         </rewrite>
         <urlCompression doStaticCompression="false" doDynamicCompression="false" />
     </system.webServer>
 </configuration>
  • 我重新啟動了 IIS 網站,在瀏覽器中使用了隱身模式,禁用了載入項並使用了不同的瀏覽器。
  • 我已經查看了有關如何為NGINXCaddyApache配置它的指南(IIS 上不存在 wiki)。
  • 我在他們的 Discord 聊天中四處詢問,但似乎沒有人對 IIS 有足夠的了解。

訪問 FoundryVTT 網站時的 IIS 日誌片段:

   2020-10-12 16:04:13 192.168.2.11 POST /setup X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=8c5986c1-768f-4833-b71b-04ed4bae47f1&SERVER-STATUS=302 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 302 0 0 35
   2020-10-12 16:04:13 192.168.2.11 GET /setup X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=fddb90ae-27b7-4cce-b3b0-a6864d451514&SERVER-STATUS=200 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 200 0 0 25
   2020-10-12 16:04:13 192.168.2.11 GET /css/style.css X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=0a2d276f-6985-4fd7-9d21-1e4f63cacb80&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 26
   2020-10-12 16:04:13 192.168.2.11 GET /fonts/fontawesome/css/all.min.css X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=78f40fa3-22bd-47ac-8987-03ec7ea70a5d&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 23
   2020-10-12 16:04:13 192.168.2.11 GET /scripts/jquery.min.js X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=f94993ac-23a7-4b71-8db9-45b564c91a40&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 22
   2020-10-12 16:04:13 192.168.2.11 GET /scripts/handlebars.min.js X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=cf0118b0-6a3d-4fb1-8654-abfbcfc6af35&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 21
   2020-10-12 16:04:13 192.168.2.11 GET /scripts/handlebars-intl.min.js X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=b76f116d-213f-44b8-9479-8ed79157c623&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 21
   2020-10-12 16:04:13 192.168.2.11 GET /scripts/foundry.js X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=94e56a90-ae3e-4095-bb40-00ae04033be1&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 27
   2020-10-12 16:04:13 192.168.2.11 GET /scripts/howler.min.js X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=31c85a47-e7f8-40e6-b242-79377bb9136f&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 27
   2020-10-12 16:04:13 192.168.2.11 GET /scripts/pixi.min.js X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=ffb1b3d7-00cf-4d68-8cf9-e3e87bf6b811&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 27
   2020-10-12 16:04:13 192.168.2.11 GET /scripts/socket.io.slim.js X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=4f937d01-ead6-437c-9e4e-fc050ccd2556&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 27
   2020-10-12 16:04:13 192.168.2.11 GET /scripts/tinymce.min.js X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=343bfaca-427e-47a1-a168-b4250f62fc0e&SERVER-STATUS=304 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 https://example.com/setup 304 0 0 27
   2020-10-12 16:04:13 192.168.2.11 GET /socket.io/ session=ne19sc1orug1dsk7ndn1u4i7&EIO=3&transport=websocket&X-ARR-CACHE-HIT=0&X-ARR-LOG-ID=7afb0d81-b323-4e94-8ae7-c1a90bc2ef1c&SERVER-STATUS=101 443 - SOMEHOST.net Mozilla/5.0+(Windows+NT+10.0;+Win64;+x64)+AppleWebKit/537.36+(KHTML,+like+Gecko)+Chrome/86.0.4240.75+Safari/537.36 - 502 5 12152 53

所以顯然 IIS 無法處理標頭的permessage-deflate(請參閱此問題)副檔名Sec-WebSocket-Extensions。解決方案是清除標頭,因為這是 FoundryVTT 使用的唯一擴展:

<serverVariables>
 <set name="HTTP_SEC_WEBSOCKET_EXTENSIONS" value="" />
</serverVariables>

不要忘記HTTP_SEC_WEBSOCKET_EXTENSIONS為您的站點添加為允許的伺服器變數。

Web Socket ReverseWeb Socket Reverse 2並且ReverseProxyOutboundRule1不需要使 FoundryVTT 與 IIS 一起工作。

引用自:https://serverfault.com/questions/1037407