Exchange 2016 共存 - OWA 在負載平衡器後面時不會登錄
我目前正在開發實驗室環境以將我們的混合 Exchange 2010 和 2013 環境遷移到 Exchange 2016。
我已經在實驗室共存執行 1x 2013 和 2x 2016 幾個星期了,它執行良好 - 我已經完成了 RPC、OWA、ActiveSync 和 EWS 的測試。一切似乎都很好。
本週我嘗試通過在前面引入負載均衡器來完成我的部署,併計劃在我的 2013 年和 2016 年 CAS 節點之間提供循環 LB。從我研究的所有內容來看,2013 年和 2016 年 CAS 與 CAS 角色完全兼容,因為它們很樂意在彼此之間進行代理。為了確保我通過每個 CAS(沒有負載均衡器)進行的手動測試似乎表明了這一點。
但是既然前面已經介紹了HA Proxy,OWA似乎就不想正常工作了。
症狀
這裡有一些症狀:
- 當我通過 2016 OWA 登錄到 2013 郵箱時,它確實正確登錄、重定向我並開始載入收件箱。但是在載入收件箱一兩秒鐘後,我被重定向回 OWA 登錄頁面,就好像我從未登錄過一樣。
- 只要我通過 2016 CAS 登錄,我可以多次重複此操作,並且似乎做同樣的事情。
- 有時當我通過 2016 登錄時,它只會掛起“仍在工作”。不過,這遠沒有讓我退出的頻率那麼高。
- 有時它會很快重定向回登錄頁面,我什至根本無法告訴我是否已登錄,並且沒有錯誤消息。這只是一個閃光然後回到登錄頁面。
- 我已經在 Mac 和 Windows 8.1 上嘗試了 Chrome 和 Firefox 的最新版本。所以這不是終端設備問題。
- 如果我通過 2013 CAS 上的 OWA 登錄到 2013 郵箱,即使通過負載均衡器,它似乎第一次正確登錄。
- 我在負載均衡器上有一個 IP,然後以循環方式代理到每個 CAS 節點的流量。這是我用來測試我的 LB 的。我有其他 IP 直接指向單個 CAS 節點。
- 如果我直接登錄到 2016 CAS 節點到 2013 郵箱,這工作正常。這是我通過出現問題的負載均衡器登錄到 2016 CAS 的一個。
- 有趣的是,我只是注意到即使登錄 2016 郵箱也會出現完全相同的問題。因此,只要我登錄 2016 CAS,它就會註銷。
- 通過 2013 CAS 成功登錄後,我可以多次刷新頁面,會話仍將保持打開狀態。對我來說,這表明一旦建立會話,代理必須在某種程度上工作正常,因為我的 LB 是循環的,所以每次刷新 OWA 頁面時,流量都應該重新分配到各個 CAS 節點。
我似乎很清楚,在負載平衡器後面時,還有其他人在使用 Exchange 2010 - 2016 時遇到了類似的問題。不幸的是,這是我們第一次使用負載均衡器,因為我們正在從單個 CAS 遷移到 3,升級到 Exchange 2016。
我發現了一些具有類似症狀的文章:
- https://devcentral.f5.com/questions/microsoft-exchange-2013-iapp-cant-login-to-owa-or-ecp-if-more-than-one-server-is-active-in-pool
- http://www.360ict.nl/blog/owa-does-not-work-after-load-balancing-exchange-2016-while-using-kemp-loadbalancers/
- https://devcentral.f5.com/questions/exchange-2013-session-affinity-once-again
我試過的
- 我已經確認我們所有的 SSL 前端(第三方 CA)證書在所有 CAS 節點上都與相同的指紋和序列匹配。我讀過這會影響事情。我正在使用生產證書來正確測試我的實驗室。
- 後端證書保留為預設的 Microsoft Exchange 證書,據我所知,這很好。無論如何,我實際上嘗試在後端使用我們的萬用字元證書,它似乎破壞了一切。
- 我已經驗證,在沒有負載均衡器的情況下訪問 2016 CAS 時,一切似乎都正常。基於此,我想如果我要在負載均衡器上啟用完整的會話持久性,以便特定使用者只處理一個 CAS,它將解決問題。但是,我不應該那樣做。這讓我擔心有一個更深層次的錯誤需要解決。
- 我已啟用 IIS 失敗請求跟踪。我發現一些關於 powershell 請求的 500 個錯誤的報告。但它們似乎與失敗的健康監控請求有關,並且在時間上似乎不一定與我的 OWA 測試讓我退出。
- 我已經通過 Wireshark 進行了一些基本檢查,以尋找任何奇怪的東西。我注意到單個 OWA 頁面載入肯定至少分佈在多個 CAS 節點上。有時兩個 2016 節點,有時一個 2016 和一個 2013 節點。
- 我在擷取(在負載均衡器上)中確實注意到,在一次失敗的登錄嘗試期間,我不斷收到來自 CAS 節點的重複**440 Login Timeout響應。**在這種情況下,我得到了多個,每個 CAS 節點至少有一個。
- 初始登錄請求之後有很多單獨的 HTTP 請求,很難確定問題出在哪裡,但似乎瀏覽器開始發送一堆 OWA service.svc 請求,並且在某些時候它們都被返回與來自 CAS 節點的響應相同的**440 Login Timeout錯誤。**然後最終我們被重定向回登錄頁面。
- 通過我的研究,我還沒有發現任何實際導致 440 登錄超時的原因,或者它是否是預期的行為等……
- 我已經根據我們的生產設置重新檢查了我的所有虛擬目錄設置。他們看起來不錯。
編輯:2017-03-04
我嘗試了多種不同的 VirtualDirectory 內部和外部 URL 組合。exchange.isp.com.au 是內部 AD 域(這與實時設置相匹配)。實驗室的外部 URL 是 exchlab.isp.com.au。
我試過了:
- exchlab.isp.com.au 用於內部和外部。
- exchange.isp.com.au 用於內部和外部。
- 我堅持使用 exchlab 進行外部交換並交換內部。這些組合都沒有產生任何影響。
此後,我還在 HA Proxy 中添加了基於 Cookie 的會話持久性,似乎有所作為。我只對OWA和ECP做了持久化,其餘的都沒有持久化。注意事項:
- 我不再重複退出 OWA。它變得更加穩定。
- 當我第一次退出郵箱(例如 2013 年)並登錄到不同版本的郵箱時,它仍然會發生。(例如 2016 年)。但是,在我第一次註銷後,我現在可以成功重新登錄。
- 如果我退出郵箱並太快(在 10 秒內)重新登錄,那麼我經常會立即被踢出。
我還決定繼續測試除 OWA 之外的服務的 HA 代理。我可以確認:
- Outlook Anywhere 在所有 3 個 CAS 節點上進行負載平衡並且工作正常。
- EWS 還對所有 3 個進行負載平衡,並且工作正常。
- Active Sync 似乎只想超過 2x 2016 CASes,但負載平衡也很好。
我需要嘗試的事情
- 重置我所有的虛擬目錄
- 重新同步 IIS IUSR 帳戶:https ://technet.microsoft.com/en-us/library/dd789741(v=exchg.80).aspx
- 驗證 IUSR 授權級別。
我還沒有真正做到這些,因為我覺得有一個實際的配置問題。此外,由於沒有負載平衡器,一切似乎都可以正常工作,我看不到這有幫助。
更多環境資訊
有關我正在測試的實驗室環境的更多詳細資訊。
- 我們的負載均衡器配置取自這裡:https ://www.haproxy.com/doc/aloha/7.0/deployment_guides/microsoft_exchange_2013.html#aloha-configuration - 我們使用“SSL 解除安裝 - HTTP 反向代理”配置(高級版)。
- 我們正在根據本指南進行 SSL 解除安裝:https ://serversforhackers.com/using-ssl-certificates-with-haproxy和本指南:https ://jaapwesselius.com/2014/02/28/exchange-2013-sp1 -ssl-解除安裝/
- 我們的 Exchange 2013 機器正在執行 SP1 \w CU11
- 我們的 Exchange 2016 機器正在執行 CU2。我有意避免升級到 CU4,因為我想使用負載平衡器測試並記錄一個優雅的升級過程。
- 我們正在執行 2 倍額外的虛擬機作為專用 AD。Exchange 節點上沒有 AD。
- 所有 Windows 系統(包括 AD)都執行 Windows 2012 R2。
- 我們的路由器是一個做 NAT 的 Linux 機器。負載平衡器與 Exchange 伺服器和 AD 框位於同一 /24 子網中。
- LB HTTP 前端是 .7,交換框是 .1、.2 和 .3
- 我們還在 .4、.5 和 .6 上的每個 Exchange 框的專用 IP 上執行簡單的 HTTP 重定向。雖然我計劃將這個簡單的重定向轉移到負載均衡器,因為它可以輕鬆地進行 HTTP 重定向。
我的負載均衡器配置的相關位:
# This is the L7 HTTPS Front End # ------------------------------ # We redirect to different backends depending on the URI # Each backend has its own separate health checks. So that each service can fail on an Exchange CAS node without affecting the other services. frontend ft_ISP_EXCHANGE_https bind 172.16.10.7:80 name INT_http bind 172.16.10.7:443 name INT_https ssl crt wildcard.isp.com.au.pem # Specify SSL Cert for offloading. mode http option http-keep-alive option prefer-last-server no option httpclose no option http-server-close no option forceclose no option http-tunnel timeout client 600s log global capture request header Host len 32 capture request header User-Agent len 64 capture response header Content-Length len 10 # log-format directive must be written on a single line # it is splitted for documentation convnience log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ {%sslv/%sslc/%[ssl_fc_sni]/%[ssl_fc_session_id]}\"%[capture.req.method]\ %[capture.req.hdr(0)]%[capture.req.uri]\ HTTP/1.1 maxconn 1000 acl ssl_connection ssl_fc # Set ACL ssl_connection if ssl_fc returns TRUE # Route request to a different backend depending on the path: # http://serverfault.com/questions/127491/haproxy-forward-to-a-different-web-server-based-on-uri acl host_mail hdr(Host) -i exchange.isp.com.au acl path_slash path / acl path_autodiscover path_beg -i /Autodiscover/Autodiscover.xml acl path_activesync path_beg -i /Microsoft-Server-ActiveSync acl path_ews path_beg -i /ews/ acl path_owa path_beg -i /owa/ acl path_oa path_beg -i /rpc/rpcproxy.dll acl path_ecp path_beg -i /ecp/ acl path_oab path_beg -i /oab/ acl path_mapi path_beg -i /mapi/ acl path_check path_end -i HealthCheck.htm # HTTP deny rules http-request deny if path_check # HTTP redirect rules http-request redirect scheme https code 302 unless ssl_connection # Force SSL http-request redirect location /owa/ code 302 if path_slash host_mail # Redirect / to /owa # HTTP routing rules -- This is where we decide where to send the request # Based on HTTP path. use_backend bk_ISP_EXCHANGE_https_autodiscover if path_autodiscover use_backend bk_ISP_EXCHANGE_https_ews if path_ews # other services go here default_backend bk_ISP_EXCHANGE_https_default # Backends # -------- # Now we define each backend individually # Most of these backends will contain all the same Exchange CAS nodes, pointing to the same IPs # The reason we define each backend individually is because it allows us to do separate Health Checks # for each individual service running on each CAS node. # The failure of one service on a CAS node does not exclude that CAS node from participating in other # types of requests. This gives us better overall high-availability design. # HTTPS OWA # I have added additional comments on this definition, but the same applies to all Exchange HTTPS backends. backend bk_ISP_EXCHANGE_https_owa balance roundrobin # Use round-robin load balancing for requests option http-keep-alive # Enable HTTP Keepalives for session re-use and lowest latency for requests. option prefer-last-server # Prefer to keep related connections for a session on the same server. # This is not the same as persistence, and is mainly to try and take advantage of HTTP Keepalives. # See here for an example of why this is needed: http://stackoverflow.com/questions/35162527/haproxy-keep-alive-not-working-as-expected no option httpclose # Disable all options that are counter to keepalives no option http-server-close no option forceclose no option http-tunnel mode http # Operate in L7 HTTP Mode (vs TCP mode etc) log global option httplog option forwardfor # Enable insertion of the X_FORWARDED_FOR HTTP Header option httpchk GET /owa/HealthCheck.htm # Use L7 HTTP Health Check. This is recommended by Microsoft. http-check expect string 200\ OK default-server inter 3s rise 2 fall 3 timeout server 60s # Define CAS Nodes for this service. We're using SSL offloading to allow L7 HTTP Checks # We've avoided SSL Bridging as that would halve our LB's throughput. server ISP_exch16_syd_01 172.16.10.2:80 maxconn 1000 weight 10 check server ISP_exch16_syd_02 172.16.10.3:80 maxconn 1000 weight 10 check server ISP_exch13 172.16.10.1:80 maxconn 1000 weight 10 check
我最終合理地解決了這個問題。一些文章提到了類似的問題,在他們的負載均衡器上添加基於 Cookie 的持久性已經為他們解決了這個問題。
我拒絕了這種“因為我不應該這樣做”,微軟的所有技術文章都說不再需要,而且確實不推薦。
但我屈服了,最終為 OWA 和 ECP 添加了持久性。結果是問題沒有完全解決,但幾乎沒有引起注意。我遇到問題的唯一一次是如果我在一個郵箱上註銷 OWA,然後立即登錄到另一個郵箱。即使那樣,它也會將您踢出一次,但如果您嘗試再次登錄,它會正常工作。
在此之後沒有持續的問題。此外,我僅在從 2013 年遷移到 2016 年郵箱時才注意到剩下的問題。
這不是我們的最終使用者可能會做的事情,而且我們幾乎完成了將所有郵箱遷移到 2016 年的工作。所以我正在考慮圍繞“足夠好”進行這項工作。
由於我們使用的是 HA 代理,因此在配置中添加一些基於第 7 層 cookie 的持久性並不是什麼大問題。事實上,只花了大約 5 分鐘就弄清楚了:
# HTTPS Outlook Web App (OWA) backend bk_EXCHANGE_https_owa cookie LB01 insert indirect nocache # <-- Added this balance roundrobin mode http ... # Added the "cookie <name>" at the end of each CAS node definition # These names must be unique to each node. server n1_exch16_syd_01 172.16.10.2:80 maxconn 1000 weight 10 check cookie EXCH16-SYD-01 server n1_exch16_syd_02 172.16.10.3:80 maxconn 1000 weight 10 check cookie EXCH16-SYD-02 server n1_exch13 172.16.10.1:80 maxconn 1000 weight 10 check cookie EXCH13-SYD