Exchange 2013 Layer 7 single namespace loadbalancing with Citrix NetScaler

** Updated with custom Ciphers, SSLv3 disabled on Content Switch and LBs, and SSL certificate bindings to the vServers***

I recently had to engage on a very complex deployment, where one of the goals was to utilize the Citrix NetScaler for Exchange 2013 services for a single namespace with Layer 7 and no session affinity.

In this scenario, a single namespace is deployed for all the HTTP protocol clients (mail.yourdomain.com). The load balancer is configured to utilize Layer 7, meaning SSL termination occurs and the load balancer and it knows about the target URLs. The NetScaler is also configured to check the health of the target services in the load balancing pool which requires a health probe to be configured on each Exchange virtual directory.

With this, as long as the health probes response is healthy, the NetScaler will keep the traffic in the load balancing pool. However, if lets say OWA health probe fails for any reason, the NetScaler will remove the target server(s) from the load balancing pool for future requests.

The key to this deployment is to set up Content Switching which enables the NetScaler appliance to direct requests sent to the same Web host to different servers with different content. For example, you can configure the appliance to direct requests for dynamic content (such as URLs with a suffix of .asp, .dll, or .exe) to one server and requests for static content to another server. You can configure the appliance to perform content switching based on TCP/IP headers and payload.

Environment:

  • Windows 2012
  • Citrix NetsScaler NS10.1: Build 129.22.nc
  • Exchange 2013
  • Layer 7 Loadbalancing (no session affinity)

NetScaler Prerequisites:

  • Content switching
  • Load balancing
  • Health monitoring
  • SSL offload

Lets start with a visual of what we are trying to accomplish

L7_exchange_lb

Now lets work on the config

1. Add Content Switch and Load Balancing VIPs

add cs vserver exch_cs_vserver SSL YOUR_IP_ADDRESS 443 -cltTimeout 180 -caseSensitive OFF

add lb vserver exch_owa_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver exch_ecp_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver exch_ews_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver exch_eas_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver exch_oab_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver exch_rpc_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver exch_mapi_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver exch_autodiscover_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180
add lb vserver exch_fqdn_autodiscover_lb_vserver SSL 0.0.0.0 0 -persistenceType NONE -cltTimeout 180

2. Add Content Switch actions and bind to you load balancing VIPs

add cs action exch_owa_cs_action -targetLBVserver exch_owa_lb_vserver
add cs action exch_ecp_cs_action -targetLBVserver exch_ecp_lb_vserver
add cs action exch_ews_cs_action -targetLBVserver exch_ews_lb_vserver
add cs action exch_eas_cs_action -targetLBVserver exch_eas_lb_vserver
add cs action exch_oab_cs_action -targetLBVserver exch_oab_lb_vserver
add cs action exch_rpc_cs_action -targetLBVserver exch_rpc_lb_vserver
add cs action exch_mapi_cs_action -targetLBVserver exch_mapi_lb_vserver
add cs action exch_autodiscover_cs_action -targetLBVserver exch_autodiscover_lb_vserver
add cs action exch_fqdn_autodiscover_cs_action -targetLBVserver exch_fqdn_autodiscover_lb_vserver

3. Add your Content Switch Policies and bind to the previous Content Switch actions you just created.  This is where the magic is, notice the Expressions which will tell NS to direct requests based on the URLs ( Ex: “HTTP.REQ.URL.CONTAINS(\”/owa\”)”)

add cs policy exch_owa_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/owa\”)” -action exch_owa_cs_action
add cs policy exch_autodiscover_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/autodiscover\”)” -action exch_autodiscover_cs_action
add cs policy exch_eas_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/Microsoft-Server-ActiveSync\”)” -action exch_eas_cs_action
add cs policy exch_ecp_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/ecp\”)” -action exch_ecp_cs_action
add cs policy exch_ews_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/ews\”)” -action exch_ews_cs_action
add cs policy exch_mapi_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/mapi\”)” -action exch_mapi_cs_action
add cs policy exch_oab_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/oab\”)” -action exch_oab_cs_action
add cs policy exch_rpc_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/rpc\”)” -action exch_rpc_cs_action
add cs policy exch_fqdn_autodiscover_cs_pol -rule “HTTP.REQ.HOSTNAME.CONTAINS(\”autodiscover\”)” -action exch_fqdn_autodiscover_cs_action
Do not add cs policy exch_eas_cs_pol -rule “HTTP.REQ.URL.CONTAINS(\”/eas\”)” -action exch_eas_cs_action

4. Bind your Content Switch Vserver to policies and provide priorities

bind cs vserver exch_cs_vserver -policyName exch_owa_cs_pol -priority 100
bind cs vserver exch_cs_vserver -policyName exch_autodiscover_cs_pol -priority 110
bind cs vserver exch_cs_vserver -policyName exch_eas_cs_pol -priority 120
bind cs vserver exch_cs_vserver -policyName exch_ecp_cs_pol -priority 130
bind cs vserver exch_cs_vserver -policyName exch_ews_cs_pol -priority 140
bind cs vserver exch_cs_vserver -policyName exch_mapi_cs_pol -priority 150
bind cs vserver exch_cs_vserver -policyName exch_oab_cs_pol -priority 160
bind cs vserver exch_cs_vserver -policyName exch_rpc_cs_pol -priority 170
bind cs vserver exch_cs_vserver -policyName exch_fqdn_autodiscover_cs_pol -priority 180

5. Now lets create the Service Groups

add serviceGroup exch_owa_service_group SSL
add serviceGroup exch_ecp_service_group SSL
add serviceGroup exch_eas_service_group SSL
add serviceGroup exch_ews_service_group SSL
add serviceGroup exch_rpc_service_group SSL
add serviceGroup exch_autodiscover_service_group SSL
add serviceGroup exch_oab_service_group SSL
add serviceGroup exch_mapi_service_group SSL
add serviceGroup exch_fqdn_autodiscover_service_group SSL

6. Create your custom monitors

add lb monitor exch_ecp_monitor HTTP-ECV -send “GET /ecp/healthcheck.htm” -recv “200 OK” -LRTM ENABLED -secure YES
add lb monitor exch_ews_monitor HTTP-ECV -send “GET /ews/healthcheck.htm” -recv “200 OK” -LRTM ENABLED -secure YES
add lb monitor exch_eas_monitor HTTP-ECV -send “GET /eas/healthcheck.htm” -recv “200 OK” -LRTM ENABLED -secure YES
add lb monitor exch_oab_monitor HTTP-ECV -send “GET /oab/healthcheck.htm” -recv “200 OK” -LRTM ENABLED -secure YES
add lb monitor exch_rpc_monitor HTTP-ECV -send “GET /rpc/healthcheck.htm” -recv “200 OK” -LRTM ENABLED -secure YES
add lb monitor exch_mapi_monitor HTTP-ECV -send “GET /mapi/healthcheck.htm” -recv “200 OK” -LRTM ENABLED -secure YES
add lb monitor exch_autodiscover_monitor HTTP-ECV -send “GET /autodiscover/healthcheck.htm” -recv “200 OK” -LRTM ENABLED -secure YES
add lb monitor exch_owa_monitor HTTP-ECV -send “GET /owa/healthcheck.htm” -recv “200 OK” -LRTM ENABLED -secure YES

7. Now lets bind the member servers to the new Service Groups and bind the custom monitors

bind serviceGroup exch_owa_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_owa_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_owa_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_owa_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_owa_service_group -monitorName exch_owa_monitor

bind serviceGroup exch_ecp_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_ecp_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_ecp_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_ecp_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_ecp_service_group -monitorName exch_ecp_monitor

bind serviceGroup exch_eas_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_eas_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_eas_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_eas_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_eas_service_group -monitorName exch_eas_monitor

bind serviceGroup exch_ews_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_ews_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_ews_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_ews_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_ews_service_group -monitorName exch_ews_monitor

bind serviceGroup exch_rpc_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_rpc_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_rpc_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_rpc_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_rpc_service_group -monitorName exch_rpc_monitor

bind serviceGroup exch_autodiscover_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_autodiscover_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_autodiscover_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_autodiscover_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_autodiscover_service_group -monitorName exch_autodiscover_monitor

bind serviceGroup exch_oab_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_oab_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_oab_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_oab_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_oab_service_group -monitorName exch_oab_monitor

bind serviceGroup exch_mapi_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_mapi_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_mapi_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_mapi_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_mapi_service_group -monitorName exch_mapi_monitor

bind serviceGroup exch_fqdn_autodiscover_service_group exch03 443 -CustomServerID “\”None\””
bind serviceGroup exch_fqdn_autodiscover_service_group exch04 443 -CustomServerID “\”None\””
bind serviceGroup exch_fqdn_autodiscover_service_group exch01 443 -CustomServerID “\”None\””
bind serviceGroup exch_fqdn_autodiscover_service_group exch02 443 -CustomServerID “\”None\””
bind serviceGroup exch_fqdn_autodiscover_service_group -monitorName exch_autodiscover_monitor

8. Finally lets bind the Service Groups to load balance vServers

bind lb vserver exch_owa_lb_vserver exch_owa_service_group

bind lb vserver exch_ecp_lb_vserver exch_ecp_service_group

bind lb vserver exch_eas_lb_vserver exch_eas_service_group

bind lb vserver exch_ews_lb_vserver exch_ews_service_group

bind lb vserver exch_rpc_lb_vserver exch_rpc_service_group

bind lb vserver exch_autodiscover_lb_vserver exch_autodiscover_service_group

bind lb vserver exch_oab_lb_vserver exch_oab_service_group

bind lb vserver exch_mapi_lb_vserver exch_mapi_service_group

bind lb vserver exch_fqdn_autodiscover_lb_vserver exch_fqdn_autodiscover_service_group

9. Create custom cipher which will get you an A- based on Qualys SSL test and FW and HW version on the NS I am using.

add ssl cipher my_cipher
bind ssl cipher my_cipher -cipherName SSL3-DES-CBC3-SHA
bind ssl cipher my_cipher -cipherName TLS1-AES-256-CBC-SHA
bind ssl cipher my_cipher -cipherName TLS1-AES-128-CBC-SHA
bind ssl cipher my_cipher -cipherName SSL3-EDH-DSS-DES-CBC3-SHA
bind ssl cipher my_cipher -cipherName TLS1-DHE-DSS-AES-256-CBC-SHA
bind ssl cipher my_cipher -cipherName TLS1-DHE-DSS-AES-128-CBC-SHA
bind ssl cipher my_cipher -cipherName SSL3-EDH-RSA-DES-CBC3-SHA
bind ssl cipher my_cipher -cipherName TLS1-DHE-RSA-AES-256-CBC-SHA
bind ssl cipher my_cipher -cipherName TLS1-DHE-RSA-AES-128-CBC-SHA

10. Bind your custom cipher to your vServers

bind ssl vserver exch_ecp_lb_vserver -cipherName my_cipher
bind ssl vserver exch_eas_lb_vserver -cipherName my_cipher
bind ssl vserver exch_oab_lb_vserver -cipherName my_cipher
bind ssl vserver exch_rpc_lb_vserver -cipherName my_cipher
bind ssl vserver exch_mapi_lb_vserver -cipherName my_cipher
bind ssl vserver exch_autodiscover_lb_vserver -cipherName my_cipher
bind ssl vserver exch_fqdn_autodiscover_lb_vserver -cipherName my_cipher
bind ssl vserver exch_owa_lb_vserver -cipherName my_cipher
bind ssl vserver ctx_wi_lb_vserver -cipherName my_cipher
bind ssl vserver exch_cs_vserver -cipherName my_cipher
bind ssl vserver exch_cs_vserver_int -cipherName my_cipher
bind ssl vserver ctx_csg_vserver -cipherName my_cipher

11. Bind SSL cert to your vservers

bind ssl vserver exch_ecp_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_ews_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_eas_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_oab_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_rpc_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_mapi_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_autodiscover_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_fqdn_autodiscover_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_owa_lb_vserver -certkeyName exch_ssl_cert
bind ssl vserver ctx_wi_lb_vserver -certkeyName wa_com_ssl_cert
bind ssl vserver exch_cs_vserver -certkeyName exch_ssl_cert
bind ssl vserver exch_cs_vserver_int -certkeyName exch_ssl_cert

12. Disable SSLv3 on CS vserver and LB vservers

set ssl vserver exch_ecp_lb_vserver -ssl3 DISABLED
set ssl vserver exch_ews_lb_vserver -ssl3 DISABLED
set ssl vserver exch_eas_lb_vserver -ssl3 DISABLED
set ssl vserver exch_oab_lb_vserver -ssl3 DISABLED
set ssl vserver exch_rpc_lb_vserver -ssl3 DISABLED
set ssl vserver exch_mapi_lb_vserver -ssl3 DISABLED
set ssl vserver exch_autodiscover_lb_vserver -ssl3 DISABLED
set ssl vserver exch_fqdn_autodiscover_lb_vserver -ssl3 DISABLED
set ssl vserver exch_owa_lb_vserver -ssl3 DISABLED
set ssl vserver ctx_wi_lb_vserver -ssl3 DISABLED
set ssl vserver exch_cs_vserver -ssl3 DISABLED
set ssl vserver ctx_csg_vserver -ssl3 DISABLED

Hope this helps and feel free to drop me a note if you need additional pointers 🙂