– Jan's Cloud – online Gedankenstütze ;)

16. Juli 2018

Exchange und Remotedesktopgateway über eine IP veröffentlichen

Mit dem Netscaler VPX Express (Freemium) Exchange und Remotedekstopgateway bzw. Outlook WebApp, Outlook Anywhere, Exchange ActiveSync, Remotedesktopgateway und die Remotedesktop Web Services über eine öffentliche IP betreiben

Ich komme häufig in Kundenumgebungen, in denen es nur noch eine freie externe IP Adresse gibt, und dennoch die Exchange- sowie Remotedesktopdienste nach außen veröffentlicht werden sollen. Hier kann man jetzt „unschön“ ansetzen und die Ports für Exchange oder RDS auf z.B. 10443 verbiegen und damit in diverse andere Probleme laufen oder man bedient sich dem kostenlosen Netscaler VPX Freemium (formerly known as Netscaler VPX Express) und größtenteils dem Content Switching.

Ich würde an dieser Stelle einfach mal voraussetzen, dass der Exchange Server entsprechend sauber mit Split DNS konfiguriert ist, die Remotedesktopdienste ebenfalls funktionstüchtig sind und der Netscaler grundkonfiguriert ist. Ebenfalls sollte es ein vertrauenswürdiges SAN Zertifikat mit den passenden FQDNs geben. In meinem Beispiel:

  • „app.<domain>.<tld>“
  • „autodiscover.<domain>.<tld>“
  • „outlook.<domain>.<tld>“

Dieses Zertifikat muss im ersten Step auf dem Netscaler installiert werden. Dazu kann man sich zum Beispiel dem Citrix Knowledge Center bedienen: https://support.citrix.com/article/CTX205404

Der Einfachheit halber starte ich direkt mal mit dem Weg über das Command Line Interface bzw. per SSH. Evtl. wird der Beitrag ja später noch um eine GUI Variante erweitert. 🙂 Also legen wir als erstes die Server im Load Balancing an, erstellen die Dienste sowie die Load Balancing Virtual Servers (GUI: Traffic Management -> Server bzw. -> Services bzw. -> Virtual Servers):

add server SRV_EXCHSRV <IP ADRESSE DES EXCHANGES>
add server SRV_CBSRV <IP ADRESSE DES RDGW / RDWEB>

add service SVC_Exchange_SSL SRV_EXCHSRV SSL 443 -gslb NONE -maxClient 0 -maxReq 0 -cip DISABLED -usip NO -useproxyport YES -sp OFF -cltTimeout 180 -svrTimeout 360 -CKA YES -TCPB YES -CMP NO
add service SVC_RDWeb-RDGW_SSL SRV_CBSRV SSL 443 -gslb NONE -maxClient 0 -maxReq 0 -cip DISABLED -usip NO -useproxyport YES -sp OFF -cltTimeout 180 -svrTimeout 360 -CKA YES -TCPB YES -CMP NO
add service SVC_RDWeb-RDGW_UDP-3391 SRV_CBSRV UDP 3391 -gslb NONE -maxClient 0 -maxReq 0 -cip DISABLED -usip NO -useproxyport NO -sp OFF -cltTimeout 120 -svrTimeout 120 -CKA YES -TCPB YES -CMP NO

add lb vserver LB_VS_Exchange SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver LB_VS_RDWeb-RDGW SSL 0.0.0.0 0 -persistenceType SOURCEIP -cltTimeout 180
add lb vserver LB_VS_RDWeb-RDGW-UDP UDP 0.0.0.0 0 -persistenceType SOURCEIP -cltTimeout 120
bind lb vserver LB_VS_Exchange SVC_Exchange_SSL
bind lb vserver LB_VS_RDWeb-RDGW SVC_RDWeb-RDGW_SSL
bind lb vserver LB_VS_RDWeb-RDGW-UDP SVC_RDWeb-RDGW_UDP-3391

set ssl vserver LB_VS_Exchange -ssl3 DISABLED
set ssl vserver LB_VS_RDWeb-RDGW -ssl3 DISABLED
bind ssl vserver LB_VS_Exchange -certkeyName <NAME DES IMPORTIERTEN ZERTIFIKATES>
bind ssl vserver LB_VS_RDWeb-RDGW -certkeyName <NAME DES IMPORTIERTEN ZERTIFIKATES>

Damit die Server nicht „blank“ per http(s) erreichbar sind, schränke ich den Zugriff auf die gewollten Verzeichnisse des WebServer (IIS) ein (GUI: AppExpert -> Pattern Sets bzw. -> Rewrite -> Actions / Policies):

add policy patset patt_set_rdweb_path
add policy patset patt_set_exchange_path

bind policy patset patt_set_rdweb_path "/" -index 4
bind policy patset patt_set_rdweb_path "/rpcwithcert" -index 1
bind policy patset patt_set_rdweb_path "/rpc" -index 2
bind policy patset patt_set_rdweb_path "/rdweb" -index 3
bind policy patset patt_set_exchange_path "/mapi" -index 1
bind policy patset patt_set_exchange_path "/ecp" -index 2
bind policy patset patt_set_exchange_path "/owa" -index 3
bind policy patset patt_set_exchange_path "/oab" -index 4
bind policy patset patt_set_exchange_path "/ews" -index 5
bind policy patset patt_set_exchange_path "/autodiscover" -index 6
bind policy patset patt_set_exchange_path "/rpcwithcert" -index 7
bind policy patset patt_set_exchange_path "/rpc" -index 8
bind policy patset patt_set_exchange_path "/microsoft-server-activesync" -index 9

add rewrite action rew_act_exchange_invalid_path replace http.REQ.URL.PATH "\"/owa\""
add rewrite action rew_act_rdweb_invalid_path replace http.REQ.URL.PATH "\"/rdweb\""

add rewrite policy rew_pol_exchange_invalid_path "!http.REQ.URL.PATH.TO_LOWER.CONTAINS_ANY(\"patt_set_exchange_path\")" rew_act_exchange_invalid_path
add rewrite policy rew_pol_rdweb_invalid_path "!http.REQ.URL.PATH.TO_LOWER.CONTAINS_ANY(\"patt_set_rdweb_path\")" rew_act_rdweb_invalid_path

bind lb vserver LB_VS_Exchange -policyName rew_pol_exchange_invalid_path -priority 100 -gotoPriorityExpression END -type REQUEST
bind lb vserver LB_VS_RDWeb-RDGW -policyName rew_pol_rdweb_invalid_path -priority 100 -gotoPriorityExpression END -type REQUEST

In der GUI müssen die letzten beiden Schritte natürlich unter Traffic Management -> Load Balancing -> Virtual Servers und dann den entsprechenden LB VServern vorgenommen werden. Damit wären die Vorbereitungen der Load Balancing Objekte (Server, Dienste, virtuelle Server) fertig und es geht nahtlos über zum Conten Switching (Traffic Management -> Content Switching -> Policies bzw. Virtual Servers).

add cs policy CS_POL_Exchange -rule "http.REQ.HOSTNAME.TO_LOWER.STARTSWITH(\"outlook.<domain>.<tld>\") || http.REQ.HOSTNAME.TO_LOWER.STARTSWITH(\"autodiscover.<domain>.<tld>.de\")"
add cs policy CS_POL_RDWeb-RDGW1 -rule "http.REQ.HOSTNAME.TO_LOWER.STARTSWITH(\"app.<domain>.<tld>\") && http.REQ.HEADER(\"User-Agent\").SET_TEXT_MODE(IGNORECASE).CONTAINS(\"MS-RDGateway/1.0\")"
add cs policy CS_POL_RDWeb-RDGW2 -rule "http.REQ.HOSTNAME.TO_LOWER.STARTSWITH(\"app.<domain>.<tld>\") && http.REQ.HEADER(\"User-Agent\").SET_TEXT_MODE(IGNORECASE).CONTAINS(\"MSRPC\")"
add cs policy CS_POL_RDWeb-RDGW3 -rule "http.REQ.HOSTNAME.TO_LOWER.STARTSWITH(\"app.<domain>.<tld>\") && http.REQ.URL.REGEX_MATCH(re-^/RDWeb/*-)"

add ns httpProfile nshttp_profile_websocket -webSocket ENABLED

add responder action res_act_http_redirect respondwith q{"HTTP/1.1 301 Moved Permanently\r\nLocation: https://" + HTTP.REQ.HOSTNAME.HTTP_URL_SAFE + "/\r\n\r\n"}
add responder policy res_pol_http_redirect true res_act_http_redirect

add cs vserver cs_EXCH_RDS-SSL SSL <IP ADRESSE DES CONTENT SWITCH VSERVERS> 443 -cltTimeout 180 -caseSensitive OFF -httpProfileName nshttp_profile_websocket
add cs vserver cs_EXCH_RDS-SSL_HTTP_redirect HTTP <IP ADRESSE DES CONTENT SWITCH VSERVERS> 80 -cltTimeout 180
add cs vserver cs_RDS-UDP UDP <IP ADRESSE DES CONTENT SWITCH VSERVERS> 3391 -cltTimeout 120

bind cs vserver cs_EXCH_RDS-SSL -policyName CS_POL_Exchange -targetLBVserver LB_VS_Exchange -priority 5
bind cs vserver cs_EXCH_RDS-SSL -policyName CS_POL_RDWeb-RDGW1 -targetLBVserver LB_VS_RDWeb-RDGW -priority 10
bind cs vserver cs_EXCH_RDS-SSL -policyName CS_POL_RDWeb-RDGW2 -targetLBVserver LB_VS_RDWeb-RDGW -priority 11
bind cs vserver cs_EXCH_RDS-SSL -policyName CS_POL_RDWeb-RDGW3 -targetLBVserver LB_VS_RDWeb-RDGW -priority 12
bind cs vserver cs_EXCH_RDS-SSL_HTTP_redirect -policyName res_pol_http_redirect -priority 100 -gotoPriorityExpression END -type REQUEST
bind cs vserver cs_RDS-UDP -lbvserver LB_VS_RDWeb-RDGW-UDP

set ssl vserver cs_EXCH_RDS-SSL -ssl3 DISABLED
bind ssl vserver cs_EXCH_RDS-SSL -certkeyName <NAME DES IMPORTIERTEN ZERTIFIKATES>

Damit wären wir in der Theorie auch schon fertig. An der Firewall müssten jetzt noch die Ports tcp 80, tcp 443 sowie udp 3391 auf die <IP ADRESSE DES CONTENT SWITCH VSERVERS> genatted werden. Falls es jemanden aufgefallen ist: Ich erstelle ein neues httpProfile und aktiviere dort webSocket. Warum? Ohne aktivierte Web Sockets im http Profil lässt sich von einem „normalen“ Client über die mstsc.exe oder auch über RDWeb problemlos eine Verbindung herstellen. Sollte es Macs oder Clients mit der Microsoft Remotedesktop App geben, so wird man feststellen, dass eine Verbindung über die „modernen“ Clients (Windows 10 mit o.g. App, macOS, iPhone, iPad) nicht zustande kommt, da diese über eine Web Socket Verbindung gehen.

Keine Kommentare »

No comments yet.

RSS feed for comments on this post. TrackBack URL

Leave a comment

Powered by WordPress