If you get the task to load balance Exchange with NetScaler you will find a lot of whitepapers from Citrix with missing information and false configuration recommendations. I was bumping my head against the wall until I got a running configuration with all desired features. Here is the complete walkthrough guide to setup your Exchange environment with a single public ip address. Additional features like AAA, Front End Optimization and Integrated Caching will depend on your current NetScaler licence.
Table of Contents
Change Log
2020-11-02
– Emails with attachments never leave Outbox via RPC/MAPI/EAS
Thanks @ Julian Jakob
2019-12-07
– Updated expressions for the Authorization Policies (AAA.USER)
– Fixxed missing binding point for Traffic Session Policy “tm_pol_exchange2016_owa_sso” on the AAA vServer. Thanks @ Christian Demmerer
2019-10-28
– AAA-default settings changed with Citrix ADC (NetScaler) 13 build 41.20
2018-05-23
– Added 401 Based Authentication for MAPI, RPC, OAB, EWS
– Added Group Filtering for OWA, Outlook Anywhere and ActiveSync
2018-05-16
– Changed Persistence for the RPC/MAPI LB vServer from RULE to SOURCEIP
– Increased timeout from 240 to 30 minutes (RPC/MAPI)
Feature Matrix
Licence |
Load Balancing |
Content Switching |
Responder |
AAA |
Front End Optimization |
Integrated Caching |
Standard |
x |
x |
x |
– |
– |
– |
Enterprise |
x |
x |
x |
x |
x |
– |
Platinum |
x |
x |
x |
x |
x |
x |
Network Topology
Requirements
- One public ip address
- Two private IP addresses (Content Switch and Load Balancer)
- Working DNS/NTP on NetScaler
- Wildcard SSL certificate
Firewall Rules
From |
To |
Port |
Description |
SNIP |
DNS Server |
UDP/TCP 53 |
DNS |
SNIP |
NTP Server |
UDP 123 |
NTP |
SNIP |
Domain Controller |
TCP 389 |
LDAP |
SNIP |
Domain Controller |
TCP 636 |
LDAPS |
NSIP |
Exchange Server |
TCP 25, 465, 587 |
SMTP Monitor |
SNIP |
Exchange Server |
TCP 25, 465, 587 |
SMTP |
SNIP |
Exchange Server |
TCP 143, 993 |
IMAP |
SNIP |
Exchange Server |
HTTPS – 443 |
OWA, AutoDiscover, ActiveSync, MAPI, etc. |
Internet |
SMTP LB IP |
TCP 25, 465, 587 |
SMTP |
Internet |
IMAP LB IP |
TCP 143, 993 |
IMAP |
Internet |
Content Switch VIP |
HTTP – 80 |
Web Traffic |
Internet |
Content Switch VIP |
HTTPS – 443 |
Web Traffic |
If you dont load balance DNS/LDAPS/NTP the traffic will flow from the NSIP. In my setup the servers are load balanced –> The SNIP is communicating with the backend servers.
Configuration
Features
1 2 |
#Features enable ns feature CS,RESPONDER,LB,SSL |
Server
1 2 3 4 |
#Create serves #Replace FQDN and ip address regarding your environment add server EX01.lab.local 192.168.2.102 add server EX02.lab.local 192.168.2.103 |
Monitors
Name |
Type |
Standard Parameter |
Send String |
mon_smtp |
SMTP |
– |
– |
mon_owa |
HTTP-ECV |
Secure |
“GET /owa/healthcheck.htm” |
mon_activesync |
HTTP-ECV |
Secure |
“GET /Microsoft-Server-ActiveSync/healthcheck.htm” |
mon_rpc |
HTTP-ECV |
Secure |
“GET /rpc/healthcheck.htm” |
mon_ews |
HTTP-ECV |
Secure |
“GET /ews/healthcheck.htm” |
mon_autodiscover |
HTTP-ECV |
Secure |
“GET /Autodiscover/healthcheck.htm” |
mon_mapi |
HTTP-ECV |
Secure |
“GET /mapi/healthcheck.htm” |
mon_ecp |
HTTP-ECV |
Secure |
“GET /ecp/healthcheck.htm” |
1 2 3 4 5 6 7 8 9 10 |
#Create monitors add lb monitor mon_smtp SMTP add lb monitor mon_owa HTTP-ECV -send "GET /owa/healthcheck.htm" recv 200 -LRTM DISABLED -secure YES add lb monitor mon_activesync HTTP-ECV -send "GET /Microsoft-Server-ActiveSync/healthcheck.htm" recv 200 -LRTM DISABLED -secure YES add lb monitor mon_rpc HTTP-ECV -send "GET /rpc/healthcheck.htm" recv 200 -LRTM DISABLED -secure YES add lb monitor mon_ews HTTP-ECV -send "GET /ews/healthcheck.htm" recv 200 -LRTM DISABLED -secure YES add lb monitor mon_autodiscover HTTP-ECV -send "GET /Autodiscover/healthcheck.htm" recv 200 -LRTM DISABLED -secure YES add lb monitor mon_oab HTTP-ECV -send "GET /oab/healthcheck.htm" recv 200 -LRTM DISABLED -secure YES add lb monitor mon_mapi HTTP-ECV -send "GET /mapi/healthcheck.htm" recv 200 -LRTM DISABLED -secure YES add lb monitor mon_ecp HTTP-ECV -send "GET /ecp/healthcheck.htm" recv 200 -LRTM DISABLED -secure YES |
Service Groups
Name |
Protocol |
Monitor |
svcgrp_ex2016_smtp_25 |
TCP |
mon_smtp |
svcgrp_ex2016_smtp_465 |
TCP |
mon_smtp |
svcgrp_ex2016_smtp_587 |
TCP |
mon_smtp |
svcgrp_ex2016_imap_143 |
TCP |
TCP |
svcgrp_ex2016_imap_993 |
TCP |
TCP |
svcgrp_ex2016_owa |
SSL |
mon_owa |
svcgrp_ex2016_activesync |
SSL |
mon_activesync |
svcgrp_ex2016_rpc |
SSL |
mon_rpc |
svcgrp_ex2016_ews |
SSL |
mon_ews |
svcgrp_ex2016_autodisover |
SSL |
mon_autodiscover |
svcgrp_ex2016_oab |
SSL |
mon_oab |
svcgrp_ex2016_mapi |
SSL |
mon_mapi |
svcgrp_ex2016_epc |
SSL |
mon_epc |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#Create Service Groups add serviceGroup svcgrp_ex2016_smtp_25 TCP add serviceGroup svcgrp_ex2016_smtp_465 TCP add serviceGroup svcgrp_ex2016_smtp_587 TCP add serviceGroup svcgrp_ex2016_imap_143 TCP add serviceGroup svcgrp_ex2016_imap_993 TCP add serviceGroup svcgrp_ex2016_owa SSL add serviceGroup svcgrp_ex2016_activesync SSL add serviceGroup svcgrp_ex2016_rpc SSL add serviceGroup svcgrp_ex2016_ews SSL add serviceGroup svcgrp_ex2016_autodisover SSL add serviceGroup svcgrp_ex2016_oab SSL add serviceGroup svcgrp_ex2016_mapi SSL add serviceGroup svcgrp_ex2016_ecp SSL |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 |
#Bind Service Groups #Replace FQDN and ip address regarding your environment bind servicegroup svcgrp_ex2016_smtp_25 EX01.lab.local 25 bind servicegroup svcgrp_ex2016_smtp_25 EX02.lab.local 25 bind serviceGroup svcgrp_ex2016_smtp_25 -monitorName mon_smtp bind servicegroup svcgrp_ex2016_smtp_465 EX01.lab.local 465 bind servicegroup svcgrp_ex2016_smtp_465 EX02.lab.local 465 bind serviceGroup svcgrp_ex2016_smtp_465 -monitorName mon_smtp bind servicegroup svcgrp_ex2016_smtp_587 EX01.lab.local 587 bind servicegroup svcgrp_ex2016_smtp_587 EX02.lab.local 587 bind serviceGroup svcgrp_ex2016_smtp_587 -monitorName mon_smtp bind servicegroup svcgrp_ex2016_imap_143 EX01.lab.local 143 bind servicegroup svcgrp_ex2016_imap_143 EX02.lab.local 143 bind serviceGroup svcgrp_ex2016_imap_143 -monitorName TCP bind servicegroup svcgrp_ex2016_imap_993 EX01.lab.local 993 bind servicegroup svcgrp_ex2016_imap_993 EX02.lab.local 993 bind serviceGroup svcgrp_ex2016_imap_993 -monitorName TCP bind servicegroup svcgrp_ex2016_owa EX01.lab.local 443 bind servicegroup svcgrp_ex2016_owa EX02.lab.local 443 bind serviceGroup svcgrp_ex2016_owa -monitorName mon_owa bind servicegroup svcgrp_ex2016_activesync EX01.lab.local 443 bind servicegroup svcgrp_ex2016_activesync EX02.lab.local 443 bind servicegroup svcgrp_ex2016_activesync -monitorName mon_activesync bind servicegroup svcgrp_ex2016_rpc EX01.lab.local 443 bind servicegroup svcgrp_ex2016_rpc EX02.lab.local 443 bind servicegroup svcgrp_ex2016_rpc -monitorName mon_rpc bind servicegroup svcgrp_ex2016_ews EX01.lab.local 443 bind servicegroup svcgrp_ex2016_ews EX02.lab.local 443 bind servicegroup svcgrp_ex2016_ews -monitorName mon_ews bind servicegroup svcgrp_ex2016_autodisover EX01.lab.local 443 bind servicegroup svcgrp_ex2016_autodisover EX02.lab.local 443 bind servicegroup svcgrp_ex2016_autodisover -monitorName mon_autodiscover bind servicegroup svcgrp_ex2016_oab EX01.lab.local 443 bind servicegroup svcgrp_ex2016_oab EX02.lab.local 443 bind servicegroup svcgrp_ex2016_oab -monitorName mon_oab bind servicegroup svcgrp_ex2016_mapi EX01.lab.local 443 bind servicegroup svcgrp_ex2016_mapi EX02.lab.local 443 bind servicegroup svcgrp_ex2016_mapi -monitorName mon_mapi bind servicegroup svcgrp_ex2016_ecp EX01.lab.local 443 bind servicegroup svcgrp_ex2016_ecp EX02.lab.local 443 bind servicegroup svcgrp_ex2016_ecp -monitorName mon_ecp |
Load Balancer
vServer |
IP address |
Method |
Persistence |
Timeout |
Protocol |
Authentication (AAA) |
SMTP |
192.168.2.248 |
Least Connection |
NONE |
Default |
TCP |
|
IMAP |
192.168.2.248 |
Least Connection |
NONE |
Default |
TCP |
|
OWA |
0.0.0.0 |
Least Connection |
NONE |
Default |
SSL |
FBA |
ECP |
0.0.0.0 |
Least Connection |
NONE |
Default |
SSL |
FBA |
ActiveSync |
0.0.0.0 |
SRCIPDESTIP |
NONE |
Default |
SSL |
401 |
AutoDiscover |
0.0.0.0 |
SourceIP |
NONE |
30 |
SSL |
401 |
RPC |
0.0.0.0 |
Least Connection |
SOURCEIP |
30 |
SSL |
401 |
EWS |
0.0.0.0 |
Least Connection |
NONE |
Default |
SSL |
401 |
OAB |
0.0.0.0 |
Least Connection |
NONE |
Default |
SSL |
401 |
MAPI |
0.0.0.0 |
Least Connection |
SOURCEIP |
30 |
SSL |
401 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
#Create Load Balancer add lb vserver lb_vsrv_ex2016_smtp_25 TCP 192.168.2.248 25 add lb vserver lb_vsrv_ex2016_smtp_465 TCP 192.168.2.248 465 add lb vserver lb_vsrv_ex2016_smtp_587 TCP 192.168.2.248 587 add lb vserver lb_vsrv_ex2016_imap_143 TCP 192.168.2.248 143 add lb vserver lb_vsrv_ex2016_imap_993 TCP 192.168.2.248 993 add lb vserver lb_vsrv_ex2016_owa SSL 0.0.0.0 0 -persistenceType NONE add lb vserver lb_vsrv_ex2016_activesync SSL 0.0.0.0 0 -persistenceType SRCIPDESTIP add lb vserver lb_vsrv_ex2016_rpc SSL 0.0.0.0 0 -persistenceType SOURCEIP -timeout 30 add lb vserver lb_vsrv_ex2016_ews SSL 0.0.0.0 0 -persistenceType NONE add lb vserver lb_vsrv_ex2016_autodiscover SSL 0.0.0.0 0 -persistenceType SOURCEIP -timeout 30 add lb vserver lb_vsrv_ex2016_oab SSL 0.0.0.0 0 -persistenceType NONE add lb vserver lb_vsrv_ex2016_mapi SSL 0.0.0.0 0 -persistenceType SOURCEIP -timeout 30 add lb vserver lb_vsrv_ex2016_ecp SSL 0.0.0.0 0 -persistenceType NONE[/sourcecode] #Bind Service Groups to vServer bind lb vserver lb_vsrv_ex2016_smtp_25 svcgrp_ex2016_smtp_25 bind lb vserver lb_vsrv_ex2016_smtp_465 svcgrp_ex2016_smtp_465 bind lb vserver lb_vsrv_ex2016_smtp_587 svcgrp_ex2016_smtp_587 bind lb vserver lb_vsrv_ex2016_imap_143 svcgrp_ex2016_imap_143 bind lb vserver lb_vsrv_ex2016_imap_993 svcgrp_ex2016_imap_993 bind lb vserver lb_vsrv_ex2016_owa svcgrp_ex2016_owa bind lb vserver lb_vsrv_ex2016_activesync svcgrp_ex2016_activesync bind lb vserver lb_vsrv_ex2016_rpc svcgrp_ex2016_rpc bind lb vserver lb_vsrv_ex2016_ews svcgrp_ex2016_ews bind lb vserver lb_vsrv_ex2016_autodiscover svcgrp_ex2016_autodisover bind lb vserver lb_vsrv_ex2016_oab svcgrp_ex2016_oab bind lb vserver lb_vsrv_ex2016_mapi svcgrp_ex2016_mapi bind lb vserver lb_vsrv_ex2016_ecp svcgrp_ex2016_ecp |
1 2 3 4 5 6 7 8 9 10 |
#Bind SSL certificate #Replace certificate name bind ssl vserver lb_vsrv_ex2016_owa -certkeyName 'Wildcard-Flashmob' bind ssl vserver lb_vsrv_ex2016_activesync -certkeyName 'Wildcard-Flashmob' bind ssl vserver lb_vsrv_ex2016_rpc -certkeyName 'Wildcard-Flashmob' bind ssl vserver lb_vsrv_ex2016_ews -certkeyName 'Wildcard-Flashmob' bind ssl vserver lb_vsrv_ex2016_autodiscover -certkeyName 'Wildcard-Flashmob' bind ssl vserver lb_vsrv_ex2016_oab -certkeyName 'Wildcard-Flashmob' bind ssl vserver lb_vsrv_ex2016_mapi -certkeyName 'Wildcard-Flashmob' bind ssl vserver lb_vsrv_ex2016_ecp -certkeyName 'Wildcard-Flashmob' |
Content Switch
Name |
Action |
Target |
Expression |
cs_pol_owa |
cs_act_owa |
lb_vsrv_ex2016_owa |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/owa”) |
cs_pol_ews |
cs_act_ews |
lb_vsrv_ex2016_ews |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/ews”) |
cs_pol_activesync |
cs_act_activesync |
lb_vsrv_ex2016_activesync |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“Microsoft”) |
cs_pol_autodiscover |
cs_act_autodiscover |
lb_vsrv_ex2016_autodiscover |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/autodiscover”) |
cs_pol_rpc |
cs_act_rpc |
lb_vsrv_ex2016_rpc |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/rpc”) |
cs_pol_ews |
cs_act_ews |
lb_vsrv_ex2016_ews |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/ews”) |
cs_pol_oab |
cs_act_oab |
lb_vsrv_ex2016_oab |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/oab”) |
cs_pol_mapi |
cs_act_mapi |
lb_vsrv_ex2016_mapi |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/mapi”) |
cs_pol_cgi |
cs_act_owa |
lb_vsrv_ex2016_owa |
HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS(“/cgi”) |
cs_pol_owa_redirect |
cs_act_owa |
lb_vsrv_ex2016_owa |
HTTP.REQ.HOSTNAME.EQ(“mail.flashmob-saulgau.de”) |
1 2 3 4 5 6 |
#Create Content Switch #Replace IP address of Content Switch add cs vserver cs_exchange2016_http HTTP 192.168.1.20 80 add cs vserver cs_exchange2016_ssl SSL 192.168.1.20 443 #Replace certificate name bind ssl vserver cs_exchange2016_ssl -certkeyName 'Wildcard-Flashmob' |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
#Create Content Switch Policies add cs action cs_act_owa -targetLBVserver lb_vsrv_ex2016_owa add cs policy cs_pol_owa -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("/owa")' -action cs_act_owa add cs action cs_act_ews -targetLBVserver lb_vsrv_ex2016_ews add cs policy cs_pol_ews -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("/ews")' -action cs_act_ews add cs action cs_act_autodiscover -targetLBVserver lb_vsrv_ex2016_autodiscover add cs policy cs_pol_autodiscover -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("/autodiscover")' -action cs_act_autodiscover add cs action cs_act_activesync -targetLBVserver lb_vsrv_ex2016_activesync add cs policy cs_pol_activesync -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("Microsoft")' -action cs_act_activesync add cs action cs_act_oab -targetLBVserver lb_vsrv_ex2016_oab add cs policy cs_pol_oab -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("/oab")' -action cs_act_oab add cs action cs_act_mapi -targetLBVserver lb_vsrv_ex2016_mapi add cs policy cs_pol_mapi -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("/mapi")' -action cs_act_mapi add cs action cs_act_rpc -targetLBVserver lb_vsrv_ex2016_rpc add cs policy cs_pol_rpc -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("/rpc")' -action cs_act_rpc add cs action cs_act_ecp -targetLBVserver lb_vsrv_ex2016_ecp add cs policy cs_pol_ecp -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("/ecp")' -action cs_act_ecp #OWA Fix https://support.citrix.com/article/CTX209060 add cs policy cs_pol_cgi -rule 'HTTP.REQ.URL.SET_TEXT_MODE(IGNORECASE).CONTAINS("/cgi")' -action cs_act_owa #Redirect to OWA if only https://mail.flashmob-saulgau.de will be entered #Replace the mail FQDN add cs policy cs_pol_owa_redirect -rule 'HTTP.REQ.HOSTNAME.EQ("mail.flashmob-saulgau.de")' -action cs_act_owa |
1 2 3 4 5 6 7 8 9 10 11 |
#Bind Content Switch Policies bind cs vserver cs_exchange2016_ssl -policyName cs_pol_owa -priority 100 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_ews -priority 110 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_autodiscover -priority 120 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_activesync -priority 130 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_oab -priority 140 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_mapi -priority 150 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_rpc -priority 160 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_ecp -priority 170 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_cgi -priority 180 bind cs vserver cs_exchange2016_ssl -policyName cs_pol_owa_redirect -priority 190 |
1 2 3 4 5 |
#OWA HTTP Redirect (Responder) #Replace the mail FQDN add responder action resp_act_owa redirect '"https://"+HTTP.REQ.HOSTNAME+"/owa/"' add responder policy resp_pol_owa 'HTTP.REQ.HOSTNAME.CONTAINS("mail.flashmob-saulgau.de")' resp_act_owa bind cs vserver cs_exchange2016_http -policyName resp_pol_owa -priority 100 |
AAA (Enterprise)
If you have an enterprise licence you can let take the authenication on the AAA server and redirect the credentials to OWA. This feature offers improved security integration and n-factor authentication like RADIUS, SAML and certificate authentication is possible. If you enter the mail domain you will be redirected to the AAA login page.
If you want to you use “401 Based Authentication” on the Autodiscover service you need to set the following registry key in the user profile.
1 |
HKCU\SOFTWARE\Microsoft\Office\16.0\Common\Identity\EnableADAL (REG_DWORD 0) |
Otherwise Outlook 2016 is crashing while setting up the profile (ADAL is enabled by default)
NetScaler is not supporting ADAL at the moment.
https://discussions.citrix.com/topic/376086-outlook-2016-and-autodiscover/
Update (2018-05-23): When using NetScaler >= 12.0 there is no need to create the “EnableADAL” key. https://support.citrix.com/article/CTX216539
Update (2019-10-28): Johannes Norz reached out to me that there is a problem with the authentication when running the Citrix ADC on firmware 13.41.20 and higher. You will receive the message “Error: Not an privileged user” after the succesfull authentication. Citrix changed the default authorization action to “DENY” which is causing the issue. You can change it back to “ALLOW” or create an authorization policy. For more information check his blog post.
Update (2020-11-02): Julian Jakob informed me that it can happen that mails with an attachment will never leave the outbox when working in RPC/MAPI/EAS mode. In Outlook you will receive the message “Cannot Procedure”. After disabling AAA for preauthentication everything was working fine. After enabling AAA any mail attachment < 10 KB was sent succesfully. Everything > 10 KB stays in the outbox. After going through the syslog messages he found the following hint “SSO: Special Post request SSO handling initiated for session-id:37295 content-length 980KB”. This brought him to CTX225681 which is saying you should modify the handling of post requests when uploading large files. Execute the following command on the ADC shell to fix the issue:
1 |
echo "nsapimgr_wr.sh -ys arg1=0 -ys arg2=1 -ys arg3=16 -ys call=\"set_sso_post_data_handler\"" >> /nsconfig/rc.netscaler |
1 2 3 4 5 6 7 8 9 |
#Enable AAA Feature enable ns feature AAA #Create AAA Server add authentication vserver AAA_Exchange_2016 SSL 0.0.0.0 #Replace certificate name bind ssl vserver AAA_Exchange_2016 -certkeyName 'Wildcard-Flashmob' bind authentication vserver AAA_Exchange_2016 -portaltheme X1 #Replace AAA FQDN set authentication vserver AAA_Exchange_2016 -authenticationDomain 'flashmob-saulgau.de' |
Authentication Policies
In this setup we will authenticate with LDAP only. For this we need create two policies.
1.) LDAP with sAMAccountName
2.) LDAP with userPrincipalName
The user can login with “test” or “test@lab.local”.
1 2 3 4 5 6 |
#LDAP SAM + UPN Policy #Replace server ip, ldapbase, bind user and password add authentication ldapaction LDAP_UPN -serverip 192.168.2.1 -secType SSL -serverPort 636 -ldapBase "DC=lab,DC=local" -ldapBindDn ns-ldap@lab.local -ldapBindDnPassword ##password## -ldapLoginName userPrincipalName -groupAttrName "memberOf" -subAttributeName "cn" -ssoNameAttribute userPrincipalName -passwdChange ENABLED -followReferrals ON add authentication ldapaction LDAP_SAM -serverip 192.168.2.1 -secType SSL -serverPort 636 -ldapBase "DC=lab,DC=local" -ldapBindDn ns-ldap@lab.local -ldapBindDnPassword ##password## -ldapLoginName sAMAccountName -groupAttrName "memberOf" -subAttributeName "cn" -ssoNameAttribute userPrincipalName -passwdChange ENABLED -followReferrals ON add authentication ldappolicy LDAP_UPN ns_true LDAP_UPN add authentication ldappolicy LDAP_SAM ns_true LDAP_SAM |
1 2 3 |
#Bind LDAP Policies bind authentication vserver AAA_Exchange_2016 -policy LDAP_UPN -priority 100 bind authentication vserver AAA_Exchange_2016 -policy LDAP_SAM -priority 110 |
SSO Traffic Policies
1 2 3 4 |
#Create AAA Session Policy #Replace "ssoDomain" add tm sessionAction tm_act_exchange2016_owa_sso -defaultAuthorization ALLOW -SSO ON -ssoDomain 'lab.local' add tm sessionPolicy tm_pol_exchange2016_owa_sso 'HTTP.REQ.URL.CONTAINS("/owa/auth/logon.aspx")' tm_act_exchange2016_owa_sso |
1 2 3 4 5 6 7 8 |
#Create SSO Form and Policies add tm formSSOAction sso_profile_exchange_2016_owa -actionURL "/owa/auth.owa" -userField "username" -passwdField "password" -responsesize "60000" -ssoSuccessRule 'HTTP.RES.SET_COOKIE.COOKIE("cadata").VALUE("cadata").LENGTH.GT(70)' -nvtype DYNAMIC -submitMethod POST add tm trafficAction traffic_prof_exchange_2016_owa -SSO ON -appTimeout 1 -formSSOAction sso_profile_exchange_2016_owa add tm trafficAction traffic_prof_exchange_2016_owa_logout -InitiateLogout ON add tm trafficPolicy traffic_pol_exchange_2016_owa 'HTTP.REQ.URL.CONTAINS("/owa/auth/logon.aspx")' traffic_prof_exchange_2016_owa add tm trafficPolicy traffic_pol_exchange_2016_owa_logout 'HTTP.REQ.URL.CONTAINS("/owa/logoff.owa")' traffic_prof_exchange_2016_owa_logout |
1 2 |
#Bind Traffic Session Policy to the AAA vServer bind authentication vserver AAA_Exchange_2016 -policy tm_pol_exchange2016_owa_sso -priority 100 -gotoPriorityExpression NEXT |
1 2 3 |
#Bind SSO Policies to the OWA vServer bind lb vserver lb_vsrv_ex2016_owa -policyName traffic_pol_exchange_2016_owa -priority 100 -gotoPriorityExpression END -type REQUEST bind lb vserver lb_vsrv_ex2016_owa -policyName traffic_pol_exchange_2016_owa_logout -priority 110 -gotoPriorityExpression END -type REQUEST |
1 2 3 4 5 6 7 8 9 10 |
#Set FBA and 401 authentication #Replace AuthenticationHost FQDN set lb vserver lb_vsrv_ex2016_owa -Authentication ON -authnVsName AAA_Exchange_2016 -AuthenticationHost aaa.flashmob-saulgau.de set lb vserver lb_vsrv_ex2016_ecp -Authentication ON -authnVsName AAA_Exchange_2016 -AuthenticationHost aaa.flashmob-saulgau.de set lb vserver lb_vsrv_ex2016_activesync -authn401 ON -authnVsName AAA_Exchange_2016 set lb vserver lb_vsrv_ex2016_autodiscover -authn401 ON -authnVsName AAA_Exchange_2016 set lb vserver lb_vsrv_ex2016_rpc -authn401 ON -authnVsName AAA_Exchange_2016 set lb vserver lb_vsrv_ex2016_ews -authn401 ON -authnVsName AAA_Exchange_2016 set lb vserver lb_vsrv_ex2016_oab -authn401 ON -authnVsName AAA_Exchange_2016 set lb vserver lb_vsrv_ex2016_mapi -authn401 ON -authnVsName AAA_Exchange_2016 |
1 2 3 4 5 |
#Content Switch AAA #Replace AuthenticationHost FQDN add cs action cs_act_aaa -targetVserver AAA_Exchange_2016 add cs policy cs_pol_aaa -rule 'HTTP.REQ.HOSTNAME.EQ("aaa.flashmob-saulgau.de")' -action cs_act_aaa bind cs vserver cs_exchange2016_ssl -policyName cs_pol_aaa -priority 90 |
The priorty of the AAA content switch policy must be the one with the lowest priority.
Group Filtering
If you need to restrict the external access to security groups in Active Directory, create the following authorization policies.
1 2 3 4 5 |
#Group Filtering #Replace AD Groups add authorization policy pol_auth_owa "AAA.USER.IS_MEMBER_OF(\"External-OWA\").NOT" DENY add authorization policy pol_auth_outlook "AAA.USER.IS_MEMBER_OF(\"External-Outlook\").NOT" DENY add authorization policy pol_auth_activesync "AAA.USER.IS_MEMBER_OF(\"External-ActiveSync\").NOT" DENY |
Bind the authorization policies to the vServers.
1 2 3 4 5 6 7 |
bind lb vserver lb_vsrv_ex2016_owa -policyName pol_auth_owa -priority 100 -gotoPriorityExpression END -type REQUEST bind lb vserver lb_vsrv_ex2016_ecp -policyName pol_auth_owa -priority 100 -gotoPriorityExpression END -type REQUEST bind lb vserver lb_vsrv_ex2016_rpc -policyName pol_auth_outlook -priority 100 -gotoPriorityExpression END -type REQUEST bind lb vserver lb_vsrv_ex2016_mapi -policyName pol_auth_outlook -priority 100 -gotoPriorityExpression END -type REQUEST bind lb vserver lb_vsrv_ex2016_ews -policyName pol_auth_outlook -priority 100 -gotoPriorityExpression END -type REQUEST bind lb vserver lb_vsrv_ex2016_oab -policyName pol_auth_outlook -priority 100 -gotoPriorityExpression END -type REQUEST bind lb vserver lb_vsrv_ex2016_activesync -policyName pol_auth_activesync -priority 100 -gotoPriorityExpression END -type REQUEST |
When your user is not in the “External-OWA” group and the authentication against the AAA server was succesfull you will get the following notification:
“Error: Not a privileged User.”
I created a responder html page, to present a more user friendly message. This can’t be done via CLI. Go to AppExpert –> Responder –> HTML Page Imports
1 2 3 4 |
You are not authorized to use the OWA service.<br> Please contact the Helpdesk.<br> 0049 - 0000 - 0000<br> helpdesk@flashmob-saulgau.de |
Now you can create the responder policy & action.
1 2 3 4 |
#OWA Deny Responder add responder action resp_act_owa_deny respondwithhtmlpage html_owa -responseStatusCode 200 add responder policy resp_pol_owa_deny "AAA.USER.IS_MEMBER_OF(\"External-OWA\").NOT" resp_act_owa_deny bind lb vserver lb_vsrv_ex2016_owa -policyName resp_pol_owa_deny -priority 100 -gotoPriorityExpression END -type REQUEST |
Front End Optimization (Enterprise)
I couldnt test this feature too much so I configured like descriped in the Citrix whitepaper. If the optimization action “Moderate” is not suiting your expectations you can try the “Aggresive” mode. You can verify if FOE is working within the GUI. Go to Optimization –> Front End Optimization –> Statics (“stat feo” in CLI)
1 2 3 4 5 6 |
#Enable Front End Optimization enable ns feature FEO #Front End Optimization #Replace FQDN add feo policy feo_pol_exchange2016 'HTTP.REQ.HOSTNAME.CONTAINS("mail.flashmob-saulgau.de")' MODERATE bind cs vserver cs_exchange2016_ssl -policyName feo_pol_exchange2016 -priority 100 |
Integrated Caching (Platinum)
In the Citrix docs its recommended to allocate less than half of the NetScalers memory for integrated caching. Set the parameter “memLimit” fitting to your appliance. I’m using 500MB. You can verify if the cache is working within the GUI. Go to Optimization –> Integrated Caching –> View Cache Objects (“show cache object” in CLI)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
#Enable Integrated Caching enable ns feature IC #Integrated Caching set cache parameter -memLimit 500 set serviceGroup svcgrp_ex2016_owa -CMP YES set serviceGroup svcgrp_ex2016_activesync -CMP YES set serviceGroup svcgrp_ex2016_rpc -CMP YES set serviceGroup svcgrp_ex2016_ews -CMP YES set serviceGroup svcgrp_ex2016_autodisover -CMP YES set serviceGroup svcgrp_ex2016_oab -CMP YES set serviceGroup svcgrp_ex2016_mapi -CMP YES set serviceGroup svcgrp_ex2016_ecp -CMP YES add cache contentGroup cache_group_exchange2016 -type HTTP -weakNegRelExpiry 233 -weakPosRelExpiry 233 add cache policy cache_pol_exchange2016 -rule 'TRUE' -action CACHE -storeInGroup cache_group_exchange2016 bind cs vserver cs_exchange2016_ssl -policyName cache_pol_exchange2016 -priority 100 -type REQUEST |
I hope this guide helped you to load balance Exchange with Citrix NetScaler.
If you find any misconfigurations or have improvments please contact me.
hi julian, awesome blog thank you for that, and i love to have directly the netscaler commands not the GUI. i did create after 2 days same netscaler config, but for me in all of this guides, it is not normal to make also the loadbalancing steps also for the SMTP and IMAP Traffic? I mean, what is the BestPractice here? Only Loadbalance SMTP Port25 or also Port 587, 143 and so on? Or did that make Exchange 2016 with other Tools? regards frank
Hi Frank. You need to create additional LB vServers with the proper monitors for IMAP and SMTP traffic. I will update the blog article on thursday 🙂
hi julian, i have make this, only on the monitors i am not sure, if there is maybe a better monitor as http-evc
# Create and Bind LB Server for SMTP Traffic / only for SMTP Traffic / when you want / must be configured with Exchange Admin / Relay Rules than on Netscaler
# Create and Bind LB Server for SMTP Traffic Port 25 and Port 465 and Port 587 and also IMAP Port 143
add serviceGroup lb_svg_exch2016_smtp TCP
add lb vserver lb_exch2016_vsrv_smtp TCP 192.168.0.11 25
bind lb vserver lb_exch2016_vsrv_smtp lb_svg_exch2016_smtp
bind serviceGroup lb_svg_exch2016_smtp exchange01.your.domain 25
bind serviceGroup lb_svg_exch2016_smtp exchange02.your.domain 25
bind serviceGroup lb_svg_exch2016_smtp -monitorName tcp
add serviceGroup lb_svg_exch2016_smtp_587 TCP
add lb vserver lb_exch2016_vsrv_smtp_587 TCP 192.168.0.11 587
bind lb vserver lb_exch2016_vsrv_smtp_587 lb_svg_exch2016_smtp_587
bind serviceGroup lb_svg_exch2016_smtp_587 exchange01.your.domain 587
bind serviceGroup lb_svg_exch2016_smtp_587 exchange02.your.domain 587
bind serviceGroup lb_svg_exch2016_smtp_587 -monitorName tcp
add serviceGroup lb_svg_exch2016_imap TCP
add lb vserver lb_exch2016_vsrv_imap TCP 192.168.0.11 143
bind lb vserver lb_exch2016_vsrv_imap lb_svg_exch2016_imap
bind serviceGroup lb_svg_exch2016_imap exchange01.your.domain 143
bind serviceGroup lb_svg_exch2016_imap exchange02.your.domain 143
bind serviceGroup lb_svg_exch2016_imap -monitorName tcp
add serviceGroup lb_svg_exch2016_smtp_465 TCP
add lb vserver lb_exch2016_vsrv_smtp_465 TCP 192.168.0.11 465
bind lb vserver lb_exch2016_vsrv_smtp_465 lb_svg_exch2016_smtp_465
bind serviceGroup lb_svg_exch2016_smtp_465 exchange01.your.domain 465
bind serviceGroup lb_svg_exch2016_smtp_465 exchange02.your.domain 465
bind serviceGroup lb_svg_exch2016_smtp_465 -monitorName tcp
maybe you make it same or better
regards frank
I just updated the post regarding SMTP/IMAP. I have created and additonal monitor for the SMTP service. For IMAP/SMPT I am using the default tcp monitor.
perfect, that Looks very awesome and pretty, merci
Nice post. Quick question.
If I create a LB VIP on the NetScaler with port/protocol of */ANY to the back-end CAS servers, All of the services work fine, OWA, Active Sync, OAB, RPC, etc, all function..
BY following the guide it breaks my outlook clients (externally) they prompt for password continuously and users cannot login.
Any ideas?
If you only use one LB VIP you can’t configure the needed Method/Perstistence for the services. Can you see failed login attempts in the Exchange Security eventlog? For troubleshooting the connection from external its always good to use the Microsoft Remote Connectivity Analyzer (https://testconnectivity.microsoft.com).
How do you configure IMAP monitor for Exchange 2013? Netscaler routes traffic to Exchange even if the server is in maintenance mode because it sees that port 993 is available. Based from packet capture, it is receiving acknowledgement from the server when it checks port 993. Once the traffic is routed to Exchange, it fails because the associated IMAP service is in maintenance mode.
You could ceate a TCP-ECV Monitor. Go to Special Parameter and set the receive string to: “The Microsoft Exchange IMAP4 service is ready”.
Hi Julian,
great blog. Help so much.
But I have some questions about the general structure of your topology, because I am also quite new to NetScaler.
1. Where do you need the LB VIP 192.168.2.248? According to the sketch, the internal clients alsoconnect to CS VIP?! And there is no reference to the LB VIP … should it have to be entered internally somewhere?
2. Where do you use an external IP – mentioned in requirements? I find in your deployment only the internal CS VIP. Where and how should I set up the external address? Another CS for external or how is externel traffic redirected to internal CS VIP?
Thank you in advance
Greetings Kevin
Hi Kevin,
1.) The LB VIP .248 is only for load balancing IMAP/SMTP traffic. Internal Clients should connect to the internal NetScaler appliance. If you only have a NetScaler in the DMZ you can create an additional vServer without AAA authenication and create a dns record which pointing to the VIP.
2.) For the external access you need to create a DNAT to your NetScaler CS VIP. Internal access is going directly to the Content Switch.
Greets
Julian
Hey Julian,
Thank you very much. Your explanation helped me a lot. Then I have only one more question.
If I was slipping internal Clients, as well as external Clients via a NetScaler in the DMZ, would I create another LB vServer for each Exchange LB (SMTP, IMAP, OWA, EWS, …) without attached AAA? And would I need a second CS vServer (internal use) without AAA?
If so, is this a possible setup?:
> external IP via INAT to CS VIP (with AAA for external)
– > LB VIP for SMTP and IMAP (with AAA for external)
– > LBs 0.0.0.0 for OWA, autodiscover, … (with AAA for external)
>CS VIP (without AAA for internal)
– > LB VIP for SMTP and IMAP (without AAA for internal)
– > LBs 0.0.0.0 for OWA, autodiscover, … (with AAA for external)
Is this a clean and supported solution or is there some mistake?
Or can this be done with CS policies (for internal and external clients) an the same CS forwarding to different LB VIPs?
Thank you again 🙂
Greetings Kevin
You Need to setup vServer with and without AAA enabled. You are correct 😉
– lb_owa_external
– lb_owa_internal
In big environments you normaly have an internal NetScaler pair and can just create a Service on the DMZ NS which is pointing to the internal OWA LB. Then Setup a LB vServer, specify the Service (Internal) and enable AAA.
Greets
Julian
Hi Julian,
Thank you for your answers so far. They help me a lot to get deeper into Netscaler.
So I only need two different LB vServers (one for OWA internally without AAA and one for OWA externally with AAA).
But what would a policy look like at CS VIP that can distinguish whether request is for internal or external OWA LB vServer?
Or is a second CS needed just for external requests?
Greetings Kevin
Method 1 – You could create CS Policy which is filtered by the requested Hostname/URL and the Client Source IP (CLIENT.IP.SRC.IN_SUBNET(x.x.x.x/x)
Method 2 – Create a second CS and Point internal DNS requests to this VIP
Hi Julian,
Great blog. This is far better explained and indepth than what the “official” Citrix documentation recommends.
One question:
In your scenario you use one IP address for the HTTP/HTTPS Content Switch and another IP address for SMTP and IMAP.
Presumably this means that Outlook and OWA would connect to one DNS A record (e.g. mail.domain.com) and SMTP and IMAP would connect to another (e.g. smtp.domain.com).
Is it possible to use just one IP address for HTTP, HTTPS, SMTP and IMAP?
The reason I’m asking is because there are currently around 300 servers and printers using SMTP relay to send email to a plethora of different DNS entries pointing at the old Exchange environment and it’d be quite a daunting task to update them to point at the correct DNS A record that is pointing at the SMTP/IMAP load balanced VIP.
Kind regards
David
Of course, you can create a Content Switch with the IP 192.168.2.240 (HTTPS) and a Load-Balancing vServer using the same ip address with your SMTP/IMAP ports. Keep in mind: You can not use the same port for a single ip address.
Valid:
CS – 192.168.2.240 – SSL – 443 (OWA)
LB – 192.168.2.240 – TCP – 25 (SMTP)
LB – 192.168.2.240 – TCP – 143 (IMAP)
Not valid:
CS – 192.168.2.240 – SSL – 443 (OWA)
LB – 192.168.2.240 – TCP – 443 (SMTP)
LB – 192.168.2.240 – TCP – 143 (IMAP)
Thanks for getting back to me so quick Julian.
I will give this a try.
Kind regards
David
Excellent article Julian!
I am running into a little authentication issue with this setup, and I was hoping you can guide me in the right direction, we are not using any of the features highlighted in 4.7, 4.8 and 4.9. I also added an entry for the powershell virtual directory.
Phones, OWA and ECP are working as expected but the Outlook clients (2010 and 2016 in online mode because we use Citrix lol) keep prompting for credentials and for some reason I can’t get passed that. I was able to connect once using Outlook 2010 but as soon as I closed it I was challenged with the credentials prompt again.
Any ideas? Do we need to enable AAA?
Thanks a lot!
You don’t need AAA. It’s only for improved security implementation. Can you see a failed login attempt in the Exchange Security eventlog? Are you using NTLM or Kerberos authentication for RPC/MAPI?
Julian
Thanks for getting back to me so soon.
Unfortunately the logs already rolled, but I’ll try to catch it tonight.
What I noticed is that the MAPI virtual directory on one of our Exchange servers is set to Ntlm,Negotiate,OAuth and the other one for some reason is set to Ntlm,Negotiate, I’m going to make sure both are set to Ntlm,Negotiate,OAuth and then try this exercise again, thanks for the tip.
We are still in the middle of the migration so we also have some RPC connections going back to the Exchange 2010 CAS servers for Public Folder access, there is an lb vserver (*/any) going to back to the CAS servers that will decommissioned once the migration is completed, could this be a factor as well?
Thanks again.
Did you check this article already? https://support.microsoft.com/en-us/help/4051374/outlook-asks-for-password-over-and-over
I’ll try that as well, thanks!
Julian,
I was able to bypass the Outlook authentication issue by setting the MAPI persistence to SOURCEIP as defined here: https://www.citrix.com/content/dam/citrix/en_us/documents/guide/deploying-netscaler-with-microsoft-exchange-2016.pdf
I definitely like your approach a lot more, but couldn’t figure out what was preventing me from logging in, I saw the header in Fiddler and that’s what made me switch the persistence.
Any thoughts?
And again many thanks!
Thanks for the update. In my Lab it was working with the “HTTP.REQ.HEADER” rule. Glad that it’s working with modified SourceIP Persistence 👍
Hi Julian,
Little mistake at the commands at chapter 4.8
#Enable Front End Optimization
enable ns feature FEO
#Front End Optimization
#Replace FQDN
add feo policy feo_pol_exchange2016 ‚HTTP.REQ.HOSTNAME.CONTAINS(„mail.flashmob-saulgau.de“)‘ MODERATE
bind lb vserver cs_exchange2016_ssl -policyName feo_pol_exchange2016 -priority 100
I think you would like to bind the FEO Policy to the CS vServer, not a LB vServer, so
bind cs vserver cs_exchange2016_ssl -policyName feo_pol_exchange2016 -priority 100
would be correct.
Thanks for your article, very good Job!
Regards
Julian 😉
You are right. Thanks for the hint 🙂
Hi there, great articel! Did you ever tried 2-Factor for MAPIoverHTTP as well for external Outlook Clients?
Hi Bernd this is not working. If you find how please tell me 🙂👍
Thanks Julian! One more question: if you activate AAA for autodiscover, will you be redirected only for first time ocnfiguration, or will this ocure more than once? can this be seen as a 2-factor auth. for outlook sync if you do not use mapioverhttp?`
After you have been authenticated to the AAA Server the credentials can be used for different sevices. After you logout for example from OWA Service you Need to Login again to use AutoDiscover or ECP. It’s No 2-Factor.
I’m starting to feel dumb because I have followed 3 guides like this to load balance Exchange 2016 and I can’t get it to work!
After following all the steps in this guide I then simulate a server failure by disconnecting the NIC and everything works great at this stage but if I simulate a SERVICE failure by stopping the web service then my Outlook disconnects and I can’t use OWA/ECP anymore. Is this expected behaviour? I can see the services like owa/ecp/ews/etc as being down on the Netscaler but Outlook is disconnected and OWA/ECP in a browser doesn’t work (I get error 500 or 503). Only after starting the web service again does everything start to work again.
Any ideas?
Great walkthrough. Have this working in the lab for Exchange 2013 (had to disable the FrontEndOptimization to get to work properly will have to look into that). But other than that it works great. I do have a question.
Not being an Exchange admin can you tell me how much different the configuration would be to support Exchange 2010?
With Exchange Release 2010 you cannot create the healtcheck monitors (/xxx/healthcheck.htm) as with 2013/2016.
So in theory it should work as long as modify the health checks? And possibly use the „PBack“ insert method? Basically I have tried the same configuration and its not passing SSO. Everything else seems to be ok. I just disabled monitoring on the services for testing. I will keep at it. Thanks for the reply.
Check the AAA SSO article for Exchange 2010. CTX128197
The configuration is a little bit different.
Thank you for the article link. I had been trying both methods. It appears the rewrite is getting hits but still no SSO. I am assuming the PBack Cookie is not being passed from the AAA. I will take a NetScaler/Wireshark trace and see what it shows. Not sure exactly where to look but the plan would be to capture directly hitting OWA (which fiddler shows the PBACK) and then capture the AAA traffic once it stops on the OWA page where I don’t see PBack Cookie.
Was able to get this to pass the SSO for 2010 by adding in a “Name Value Pair” and setting it to Static vs Dynamic on the SSO Profile.
For the health monitors for Exchange 2010 just remove the receive portion of it. I removed “recv 200” and it worked fine.
So I started from the beginning again and now my OWA/ECP works in a browser but Outlook is always disconnected?
What about the health status of your MAPI LB vServer? Do you get a popup window which is asking for credentials? Try to change the persistence to “SOURCEIP”.
The MAPI LB vServer is showing as up/healthy. I did get a popup for my password when opening Outlook but after changing persistence to SOURCEIP this got Outlook to connect again so thanks!
The next issue I keep getting is that when I stop the web service on one of the mailbox servers to simulate a service failure Outlook then disconnects and when I try to login to OWA/ECP I get a blank page? The Netscaler is correctly showing that the service group is partially down but I still can’t use Outlook/OWA/ECP. Any ideas?
Take a trace with WireShark and look whats going on. Difficult to guess from the distance 😉
What URL is showing up in the browser while accessing the OWA site?
Are you using AAA?
I guess I should first ask, if I stop the web service on one of the Exchange servers, should Outlook/OWA/ECP continue to work on the other servers?
I’m not too familar with Wireshark so what am I looking for?
I use the URL: owa.domain.com and that always shows in the browsers address bar.
I’m not using AAA (yet).
Besides Wireshark is there anything else I can check on the Netscaler to troubleshoot this (like logs etc)?
Im not an Exchange expert but I guess it should work.
You also could debug with Fiddler to find a hint whats going wrong.
Thanks for the help!
I tried Fiddler and it shows me: HTTP/1.1 503 Service Unavailable (I get this when I stop the web service on one of the Exchange servers)
Which is odd because I thought the Netscaler should stop sending traffic to a service on a server when it detects that it is down (using the health monitors)?
Whats interesting is that, if I simulate a server failure (by disconnecting the NIC from my VM) then Outlook/OWA/ECP works perfectly after the failure. It’s only if I simulate a web service failure that I get HTTP/1.1 503 Service Unavailable errors!
Can you access the healtcheck site after you have disabled the service? If the Service is down in NetScaler it shouldnt get “Routed” to the machine.
Yes! If I stop the service on EX01 then when I browse owa.domain.com/owa/healthcheck.htm I get a 200 OK EX02.domain.com!
On the Netscaler I can see the service group showing as partially down.
When the web service is stopped/disabled, is there anything I could be missing in the Netscaler config (monitors, lb servers etc) where you have to tell the Netscaler to NOT send traffic to services that are in a down state?
I’m just confused as to why traffic is still being sent to a server that is in a down state?
So I asked this question on the Exchange forum and basically if you have a service failure (planned or not) the cluster will not work.
So this wasn’t a Netscaler issue but a design limitation with Exchange.
Thanks for the Update 👍
What I have been wondering is, why have the healthcheck.htm page for each virtual directory if the cluster goes down with a service failure?
Hi Julian, great article thx for that ! How would you configure an ip based relay restriction i.e. on port 25 ?
Relay Restriction should be configured on your Exchange Server.
For whatever reason my outlook clients refused to connect after redirecting my DNS records to the CS vServer. This particular environment was still using RPC for Outlook connectivity with Exchange 2016. Making the following change to the persistence on the RPC LB vServer resolved my issue. I followed BlackJack82’s recommendation and also did the same for MAPI. I am not using AAA, Front End Optimization, or Integrated Caching (4.7 – 4.9).
add lb vserver lb_vsrv_ex2016_rpc SSL 0.0.0.0 0 -persistenceType SRCIPDESTIP
add lb vserver lb_vsrv_ex2016_mapi SSL 0.0.0.0 0 -persistenceType SRCIPDESTIP
Thank you for the great write-up Julian! This was exactly what I needed to get this configured. Thanks
I think you choose the wrong persistence.
Choose “Source IP” not “SRCIPDESTIP” 👍
Does the caching for OAB Vdir really makes sense, or the other way around, might it cause problems? –> https://blogs.technet.microsoft.com/stevenha/2013/01/09/offline-address-book-full-download-fails-if-hardware-load-balancer-in-use/
Interesting article. Are you running into issues with the posted configuration?
hi Julian
this blog is so fantastic, maybe it is time for part2, “restrict smtp relay with URL pattern set file and responder policy” ? i get today this question, and when i look in Citrix Forums, there are many different ways, but i think to make a whitelist with URL pattern set and a responder policy, this will be a very good Option? what did you think about that? is it a blog what you can / want make? thx and best regards
frank
Hi Frank I have worked with pattern sets before but not for SMTP traffic. What are you trying to achieve? I can not follow you completly 🙂
I would go with NetScaler ACL. Pattern sets are only for HTTP traffic.
Hello Julian nice blog I have one query I want to load balance IMAPS (993) service on Citrix netscaler. I am using exchange 2013 in backend and netscaler 11.0.53 VPX. I have configured the IMAPS successfully but while configuring IMAP account in local email client (outlook) am getting CAS server local certificate warning instead of my Exchange SAN which already installed and mapped on netscaler.
Please help it’s bit urgent.Thanks in advance.
Did you Install and cofigure the certificate correctly on your CAS? Sounds more like an Exchange problem. Why are you using IMAP when running Outlook as your mail client?
Yes certificate installed correctly on CAS as when had tried skipping Citrix loadbalancer and directly using CAS server while configuring the IMAP on local system correct SSL cert it is showing
But when same query come from Citrix LB then it is showing CAS server local root CA
Is it working via NetScaler when you offload IMAPS (993) to IMAP (143)?
hi Julian
i want allow only a range of ip Adresses that can relay to the Exchange. i want not that everybody from Network can relaying to the smtp/Exchange. that is my Goal. and someone do it with acl what is Network, some do it with URL pattern and a whitelist file, what will be easier to handle. but i am not realy sure, what will best Option for that case.
Give it a try with that pattern set whitelist regarding my knowledge and what I could find in the edocs this is for Web Traffic (http,https) only and will not work. The best option is always a matter of taste. For me this is a network demand and should be configured on the firewall. When there is a lot of change in the whitelist maybe its the better Option to go with NetScaler ACL because you dont need to ask the network team all the time to change the configuration.
Thanks for the post, where you have a second site which holds e.g. two of the Exchange DAG members (4 members in total (2 in Primary/2 in DR site) A/A site how would LB work with Netscalers at a site Level please.
Have a look at NetScaler GSLB.
Hi Julian, you forgot to bind the tm_pol_exchange2016_owa_sso to the AAA_Exchange_2016 server.
Hi, you need to bind the traffic policy to the OWA vServer. There is no need to bind it to the AAA vServer.
You commands do not include binding that tm policy to anything. 🙂
Do you have the recommended IIS and Virtual Directory permissions for authentication to match this config in Netscaler?
The default settings should work out of the box. Any official source for recommendations?
I was load balancing them and going straight to the LB vServer, and moved over to your configuration. As soon as I moved over I have some users that now get a continuous Outlook login prompt, removing the profile and nothing works.
What is the difference between the working and non working clients?
Not much. On 2 users sitting side by side, one had a slightly higher version of Outlook 2013. Same database and same server. But then another user that had issues had that same slightly higher version as the 2 users sitting side by side.
Is it working when you take out on Exchange server from the service group?
Did you already check the CAS logs?
Hi Julian,
Have all your config in place and everything seems to run fine with the exception of anything involving the 401 Authentication for Autodiscover and Activesync. The clients will continuously prompt for credentials.
If I remove the binding for AAA on either they both work fine. The only client that seems to work with 401 AAA is Outlook 2016, though majority of clients in environment is Outlook 2013. Our NS is version 12.x
I checked the Authentication LDAP logs and it is accepting the credentials from what I can see. Any ideas?
Hi Robert, did you solve the credential prompt? Just came back from my vacation.
Hi Julian,
I was able to resolve by putting in the following config and binding the policy to both my autodiscover and activesync loadbalancing VIPs:
add tm trafficAction SSO_Profile -SSO ON -persistentCookie OFF -InitiateLogout OFF
add tm trafficPolicy SSO true SSO_Profile
The first complete NetScaler-Exchange2016-with-SSO-walk-through!
Great, Thaks!
Julian,
I was wondering if you had a recommendation for the timeout value of the MAPI lb_vsrv; for RPC it is set to 30 minutes so I have started with using that, but has anyone found that to be too short or too long? What are people using for the timeout for MAPI with SOURCEIP persistence?
add lb vserver lb_vsrv_ex2016_mapi SSL 0.0.0.0 0 -persistenceType RULE -rule ‘HTTP.REQ.HEADER(“Authorization”)’ -timeout 240
add lb vserver lb_vsrv_ex2016_mapi SSL 0.0.0.0 0 -persistenceType SOURCEIP -timeout 30
### As a note, maybe you should update the blog post to replace the persistence to SOURCEIP in general to keep the config up to date with all that’s been learned.
Also, just wanted to THANK YOU for putting this blog post together. This is by far the most comprehensive write up on configuring LB of Exchange 2016 I have found. It is extremely useful.
After rethinking I have changed the MAPI timeout to 240 to match what you had recommended for the service when using RULE persistence. I assume that in itself answers the question, but if you have anything to add please let me know.
add lb vserver lb_vsrv_ex2016_mapi SSL 0.0.0.0 0 -persistenceType SOURCEIP -timeout 240
Hello Mike,
regarding your question for the recommendation of the ideal timeout value for the MAPI/RPC service.
I could find the following article: https://blogs.technet.microsoft.com/david231/2015/03/30/for-exchange-2010-and-2013-do-this-before-calling-microsoft
M$ is saying that 15-30 minutes should be the optimal value.
Thanks for your feedback.
I will update the blog post shortly.
Thank you for the quick reply. As I am interpreting it, so long as the LB_VS timeout is longer than the keepalive interval than everything should be good. In that case assuming the TCP keepalive is setup to 15-20 min, than 30 min timeout would be fine. It also then should be the same that keeping it as a 240 min timeout wouldn’t hurt either. I actually left the timeouts as 240 mins to match the service timeout values you had indicated while they were setup as RULE instead of SOURCEIP and so far so good. I have left Outlook clients with both 2010 mailboxes access via 2016 Exchange NetScaler CS VIP / 2016 Exch Servers Proxy and Outlook clients accessing 2016 mailboxes via the CS VIP and haven’t had any issues with the connectivity timing out, disconnecting, or continually prompting for credentials. All 3 of those issues were seen while using the RULE persistence so from what my testing is showing I think everything is now working as it should be without issue with SOURCEIP -timeout 240 for RPC and MAPI.
If I am misunderstanding that timeout setting and you believe I should change it down to 30 from 240 for some reason please let me know. Otherwise I appreciate the work done and sense of community you have on this topic and wish you a great day!
You interpreted correctly. Doesn‘t matter if the LB vServer is configured for 30 or 240 minutes timeout. The value configured on the Exchange server will win. Thanks for your feedback. Appreciate it. Wish you a nice weekend 🙂
Thank you for such a great setup guide. We have a slightly different scenario: Netscaler VIP in the DMZ with similar settings as the above, that then points the authenticated traffic in to the internal Netscaler VIP that handles the load balancing for internal clients to the exchange servers. This setup seems to work fine for Exchange 2010 as it replaced our TMG setup a couple months ago. But now that we’re trying to get it to start using our 2016 servers, it runs into multiple issues. Anything from double logins (once for AAA, and once for Exchange OWA), to not being able to get logged into a 2010 mailbox, but it works with a 2016 mailbox, to just going to a blank page. This also seems to differ based on browser used. Safari and Chrome work mostly as expected though sometimes double logins on each, Firefox always has double logins or just a blank page, and IE is all of the above. And it seems everyone’s setup guide basically has a single netscaler (or HA pair) with 2 vips (1 for AAA and the main vip) that connects directly to AD for authentication and then load balances to any of the exchange 2016 servers.
Any ideas are greatly appreciated, we’ve been banging our heads against the wall for about a month now with 3 failed attempts at cutting over. Thanks!
Without AAA everything is working? I configured a NetScaler (Exchange 2010) the day before yesterday with the same commands (excpect the monitors and AAA) –> no problems. I changed the persistence for the MAPI/RPC vServer from RULE to SOURCEIP last week. The RULE expression was somehow denying the authentication for the services. You always got a credential prompt. Do you have this already implemented?
When using Exchange 2010 your SSO Form action needs to be configured a little bit different. https://support.citrix.com/article/CTX128197
If you are using a NetScaler in the DMZ & LAN:
– Create OWA/MAPI services on the DMZ NetScaler (LB VIPs from the LAN NS)
– Create LB vServer with this services (DMZ)
– Configure AAA for the LB vServer (DMZ)
P.S: For testing the OWA SSO just edit your local host file. The webmail URL should resolve to the CS VIP.
Julian
The current setup is DMZ netscaler with AAA for pre-auth, that points to the LAN netscaler for load balancing. The LAN netscaler only has the 2010 CAS servers. This is working.
The new setup (and our test VIPs) is DMZ netscaler with AAA for pre-auth that points to the LAN netscaler for load balancing. the LAN netscaler new test VIP just points to the new Exchange 2016 servers.
So would we set up the above all on the DMZ netscalers, and have those still point to the LAN netscaler VIP, and should that LAN vip be just load balancing, or should it also have the same setup as above?
We’re also tossing around the idea to have the DMZ netscaler just go directly to the exchange 2016 servers. Essentially have the setup you describe on both the DMZ netscaler and the LAN netscaler, but have each set of netscalers go directly to the exchange 2016 servers, instead of having the DMZ netscaler point to the LAN netscaler vip.
Thanks again for your help and blog post!
Excellent write up on the Citrix side of things! I am curious what if any action I need to take with Exchange send or receive connectors to make this work. Or the URLs for the virtual directories? You must need to do *something*
Thanks in advance kind sir!
There is no change at all on the send/receive connector or virtual directories. OWA is configured for FBA (default setting) and your internal and external urls depends on your environment. If there is something unclear feel free to ask.
Thank you for the quick reply! In the process of writing a reply to clarify my question, I answered it myself. I was getting hung up on the NetScaler’s role in all of this, and over complicated it. The send and receive connectors only manage SMTP flow, which we are doing simple LB on, so I don’t have to worry about Exchange’s mail-flow there. I’m good now! Thanks again!
Small typo> under Service Groups
svcgrp_ex2016_epc SSL mon_epc
Should be ecp
Thanks
MarcAnt
Hi Julian excellent blog I have not seen any blog thats better than this one.I just had a small question to you regarding Exchange running on 2 sites with mpx netscalers 8005 enterprise edition on both sites in that setup what is the best way to get HA in case i loose the entire sites as from exchange 2016 dag perspective i have active database on one site and passive on another site and a lagged on the active site issues that i have is if one site goes down my mails stop working. I was wondering if i can have a quick chat with you through email and get some opinion from you.cheers Jack
Thanks very much for compiling all this information; it was quite helpful.
One point that might be of interest.. I’ve noticed URLs like GET /owa/prem/15.1.1466.8/resources/images/0/ewsprite1.mouse.css which would potentially match both CONTAINS(„/ews“) and CONTAINS(„/owa“), which makes the CS policy binding priority important (though I notice you have /owa first, presumably for this reason).
I chose to use HTTP.REQ.URL.PATH.SET_TEXT_MODE(IGNORECASE).STARTSWITH to match the IIS virtual applications (/Autodiscover /EWS etc). It also might be a less costly comparison than CONTAINS.
Also, it seems that CONTAINS(“Microsoft”) might properly be replaced with STARTSWITH(„/Microsoft-Server-ActiveSync“). I realize that one came from Citrix documentation.
Hello,
Thank you for the fantastic blog post!
I have a little issue, I followed the instructions but after a successful authentication via hostname, the AAA server displays the following error: Target URL not found for redirect after successful login. Please contact your administrator.
Any idea how to redirect this to OWA?
Thank you,
Ryan
Are you accesing the CS/LB VIP or the AAA server directly? Normaly you get this message when the NSC_TASS cookie is missing on your client. This happens if you browse to the AAA server and login. It’s only working from the LB/CS (Redirection).
Hello,
Thank you for the quick reply!
I changed the priority of the command from 90 to 105, and the cookie appeared:
bind cs vserver cs_exchange2016_ssl -policyName cs_pol_aaa -priority 90
Thank you again!
Beautiful blog post, Julian!! thank you so very much. ran into the issue just as Ryan.
I had the same issue. “Target URL not found for redirect after successful login. Please contact your administrator.”
changed the policy binding priority to 105. and it works.
however, it only works when i enter http://mail.xyz.com and auto Redirects to https://mail.xyz.com.
if i enter https://xyz.com directly the issue persists. and goes back to target URL not found for redirect after successful login”
Wondering what i should be doing to fix the Https.
Hi Julian,
I have the same issue as Ryan. Note that I did copy&paste (changed values to match my domain) of your commands up to 4.7 as 4.8 and beyond and additional functionality which I will continue later.
url entered in the browser: https://mail.domain.com/owa
Here is an optput of the ns.log
Jul 2 09:58:12 192.168.20.191 07/02/2018:06:58:12 GMT ns-int-1 0-PPE-2 : default AAA Message 71637 0 : „In update_aaa_cntr: Succeeded policy for user testSSO = LDAP_SAM“
Jul 2 09:58:12 192.168.20.191 07/02/2018:06:58:12 GMT ns-int-1 0-PPE-2 : default SSLVPN Message 71638 0 : „get_session aaa_info flags 91 flags2 0, new webview 0, sess flags2 21, flags3 0 “
Jul 2 09:58:12 192.168.20.191 07/02/2018:06:58:12 GMT ns-int-1 0-PPE-2 : default AAATM LOGIN 71639 0 : Context testsso@10.0.0.50 – SessionId: 27- User testsso – Client_ip 10.0.0.50 – Nat_ip „Mapped Ip“ – Vserver 192.168.20.193:443 – Browser_type „Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/17.171“ – Group(s) „N/A“
Jul 2 09:58:12 192.168.20.191 07/02/2018:06:58:12 GMT ns-int-1 0-PPE-2 : default AAATM Message 71640 0 : „AAATM Login: created session for with cookie: “
Jul 2 09:58:12 192.168.20.191 07/02/2018:06:58:12 GMT ns-int-1 0-PPE-2 : default AAATM Message 71641 0 : „AAATM: LOGIN: invalid redirect url ▒▒^Z“
Jul 2 09:58:12 192.168.20.191 07/02/2018:06:58:12 GMT ns-int-1 0-PPE-2 : default SSLVPN Message 71642 0 : „AAA Client Handler: Found extended error code 262157, ReqType 16388 request /cgi/login, cookie hdr _ga=GA1.2.1957678141.1529053026; NSC_TASS=/owa“
Can you check your “Action URL” in the form sso profile? Should be “/owa/auth.owa”.
Are both traffic policies bound to the OWA LB?
Is it working without the cs policy “cs_pol_owa_redirect”?
ignore, I’ve resolved it.
Thanks, also I’ve added OTP.
What was the issue? 🙂
seemes tha this name needed to be different add cs policy cs_pol_aaa -rule ‘HTTP.REQ.HOSTNAME.EQ(“”)’ -action cs_act_aaa
I had it point to the same url as the mail server.
mail.domain.com for both instead of mail.domain.com for owa/ecp and aaa.domain.com for the authentication server.
We are using the (/xxx/healthcheck.htm) monitors for LB our Exchange 2016 services. I need to disable TLS 1.0 on our Exchange servers for PCI compliance but when I do the healthcheck.htm monitors fail the handshake. When will these work with TLS 1.1 or 1.2.? Or is there a different monitor you recommend that works with TLS 1.2?
Which CU is installed on your Exchange? Im not sure but I think it’s supported with CU8 and higher.
We are running CU9 for Exchange 2016 on 2012R2 servers
Did you follow this article?
https://blogs.technet.microsoft.com/exchange/2018/04/02/exchange-server-tls-guidance-part-2-enabling-tls-1-2-and-identifying-clients-not-using-it/
Maybe you ask in the Microsoft Exchange forum. I think there will be someone with an answer.
If you follow this guide and use the AAA feature does that mean that ALL of the traffic and requests go to the AAA server first?
It seems like with the AAA enables the free-busy and calendars do not work….
I am not a master of Net Scalers but i know Exchange and was asked if we could block everything except activesync and of course mailflow externally. No EWS,, No ECP, no OWA. Internally yes but no external access on those.
There are 5 exchange servers load balanced with Netscaler.
I know you can block do this with an F5 and there is a messy way to do this with Kemp but since I am not fully aware of the Netscalar capabilities I thought I would ask in here.
You could only publish AS over your external Content Switch. It should also work when you create a listen policy which only allows internal traffic for the specific services.
Hi Julian,
Thank you so much for this guide it was really helpful and worked like a charm.
I have Exchange 2013 and the AAA feature active without group filtering.
The only problem that i have is that the external outlook doesn’t work. I see in the exchange security logs audit failures which say unknown username and password.
We have ntlm active on outlookAnywhere for internal and external clients. Am I correct that this setup only works when i have basic active as externalauthentification method?
Login to owa works fine with the same credentials / user / endclient.
Thank you so much for your help and guide 🙂
Best,
Kim
Hi Kim, ff you are using NTLM you need to create a negotiate policy with a kdc account. Please take a look at the following article: https://www.citrix.com/blogs/2016/02/23/kerberos-authentication-with-ntlm-fallback-kcd-sso-to-the-backend/
Please tell me if its working and I can update the blogpost with your configuration steps.
Julian
Hi Julian, Thanks for the link. I’m going to try this next week and will update you 🙂
Hi Julian,
I finally was able to look into it and made it working. The article above was so confusing, here is my attempt in explaining it.
I tried to adopt your naming of the actions/policies so that it is easier to understand.
1. Create an AD Account in the Active directory for the KCD and set the spns for your CAS Servers (or MBX if you ran 2016, my customer has 2013)
My account is named KCD
I have
setspn -A http/aaa.contoso.com CONTOSO\kcd
setspn -A host/aaa.contoso.com CONTOSO\kcd
setspn -A host/owa.contoso.com CONTOSO\kcd
setspn -A http/owa.contoso.com CONTOSO\kcd
setspn -A host/autodiscover.contoso.com CONTOSO\kcd
setspn -A http/autodiscover.contoso.com CONTOSO\kcd
Now on the KCD user in AD an new tab “Delegation” is visible and you need to add all of your CAS Servers (or MBX in 2016) with HOST and http
As seen here (but he forgot the HOST service type) https://www.citrix.com/blogs/wp-content/uploads/2016/02/Capture5.jpg
2. Verify that on the CAS Server, in the mapi subsite in IIS, under authentication option , under windows authentication, the NTLM Provider is added (is done by default when you enable ntlm on mapi VD, but good to know/check)
3. on the netscaler:
# Add Negotiate authentication policy and action
add authentication negotiateAction negotiate_act_EXC_KCD -domain contoso.com -domainUser kcd -domainUserPasswd ****** -NTLMPath “http://CAS01.contoso.com/mapi”
add authentication negotiatePolicy negotiate_pol_EXC_KCD ns_true negotiate_act_EXC_KCD
# Create the previously kerberos account and session policy for SSO
add aaa kcdAccount KCD_contoso.com -realmStr contoso.com -delegatedUser kcd -kcdPassword ******** -userRealm contoso.com
add tm sessionAction tm_act_exchange2013_KCD_sso -SSO ON -ssoDomain ‘contoso.com’ -kcdAccount KCD_contoso.com -defaultAuthorization ALLOW
add tm sessionPolicy tm_pol_exchange2013_KCD_sso ns_true tm_act_exchange2013_KCD_sso
# Create a new AAA vserver that uses KCD and bind the wildcard cert
add authentication vserver AAA_Exchange_2013_KCD SSL 0.0.0.0 -AuthenticationDomain contoso.com
bind ssl vserver AAA_Exchange_2013_KCD -certkeyName ‘Wildcard-Flashmob’
# bind the negotiate and SSO policies to the new AAA Server
bind authentication vserver AAA_Exchange_2013_KCD -policy negotiate_pol_EXC_KCD -priority 100
bind authentication vserver AAA_Exchange_2013_KCD -policy tm_pol_exchange2013_KCD_sso -priority 100
# bind the new AAA Server to the Load balancers that need KCD
set lb vserver lb_vsrv_ex2013_mapi -authnVsName AAA_Exchange_2013_KCD
set lb vserver lb_vsrv_ex2013_rpc -authnVsName AAA_Exchange_2013_KCD
set lb vserver lb_vsrv_ex2013_autodiscover -authnVsName AAA_Exchange_2013_KCD
Done!
Let me know if this helps
Best,
Kim
Hello Kim,
thanks for the feedback.
I think you can make the setup even more simple. Just create a kdc account with the specific realm and bind it to the aaa action. I assume the login is happening with username and password. Otherwise kerberos impersonation is not working.
Hi Julian,
Thanks for a great article.
I set up Exchange 2010 access via a Netscaler but only using Standard license features. Everything works as expected, except when Exchange tries to proxy the connection between two CAS servers. When logging into OWA, the error “Exception message: The proxy CAS failed to authenticate to the second CAS (it returned a 401)” is returned, which does not happen if I bypass the Netscaler.
The errors in Exchange point to a Kerberos issue but I’m not really sure where to go from here. If you have any ideas on how to solve this, that would be much appreciated.
Cheers.
Hi Julian.
Excellent article, but I have a question, if I wanted to configure the NetScaler to serve as a reverse proxy for SSL connections and offload SSL connections to the backend Exchange, what would I need to configure?
Hi Michel. Stick to the guide but when creating the Service Groups and binding them to the LB vServer (HTTPS) they should of the protocol HTTP. That’s it.
thanks Julian.
Change the service group for http but this not working.
Question, In my environment, the Exchange servers redirect the http to https, so,this is the reason because the http don’t work?
Jullian,
In section 3.1 you noted: “If you dont load balance DNS/LDAPS/NTP the traffic will flow from the NSIP. In my setup the servers are load balanced –> The SNIP is communicating with the backend servers.” Are you saying that you must create a LB VIP for DSN/LDAPS/NTP? My DNS and NTP are set in the appliance configuration section on the Load Balancing section.
I meant to say that my DNS and NTP are set in the System Configuration section of the Netscaler not the Load Balancing Section.
You don’t need to load balance DNS and LDAP but why you shouldn’t when you have the ability to do it? 🙂 In some cases maybe it’s even necessary to source the DNS/LDAP traffic by your SNIP because the NSIP is only used for management traffic (SSH/WebGUI)
Hi Julian,
Very nice and extensive article 🙂 I followed the steps in the Article, however after Logging in on my AAA Server I get stuck in a “loop” where the page keeps reloading and the Log in /var/log/ns.log keeps giving the following message:
FORMSSO: POST: NVPAIRS: name passwordText has no value, not copying
FORMSSO: Could not find form in the response buffer of size 60000
The authentication on the AAA Server is successful, but it looks like the redirect is going wrong. When I stop the browser, and open the Site again I can login on OWA. Any ideas?
Hi Kevin, what is the version of the Exchange server? Can you double check the action url in the traffic profile?
I’m using Exchange 2013, and the action url is /owa/auth.owa
Can you try to access the owa with the full url not just the hostname? Example: https://mail.company.com/owa —> Is this changing something? If yes maybe try to bind the rewrite policy for /owa directly the LB vServer for OWA.
I tried, but get the same results. This is what I’m doing:
Open https://webmail.**.com, I then get redirected to https://authentication.**.com and fill in the credenials. Then I get redirected to https://webmail.**.com/owa/auth/logon.aspx?url=https%3a%2f%2fwebmail.**.com%2fowa%2f&reason=0 in and endless loop. If I then close the browser, and go back to https://webmail.**.com I can successfully login into OWA.
It’s this happening with another web browser as well? Strange I never have seen this behavior before.
I tried several different browsers (Chrome, Edge, Safari) and different computers but all show the same behaviour. The A Record for webmail.**.com and authenticatie.**.com both point to the same VS IP. Did I make a mistake with that maybe?
You can use the same VIP when it’s a CS which is redirecting the traffic to the correct AAA/LB vServers. Looks like there is no problem with the traffic profile/SSO profile because you get the authorization cookie and single sign on is working. Can you remove any rewrite/redirect policies which is associated with the CS and the OWA LB vServer?
Hi Julian,
Awesome blog. I am experiencing problem in configuring a email connector for our mail box to configure IMAP, so that this cloud based application will fetch the email from this email box and raise a ticket against each email.
Exchange is currently load balanced using Netscaler. Now I need to configure IMAP over SSL (993). I have done below steps.
On our firewall, I have created a NAT rule to send traffic to Netscaler LBVS VIP.
Created service group in Netscaler and binded exchange servers using port 993TCP and assigned the TCP monitor.
Created LBVS VIP and bind the service group to the LBVS.
Now the netscaler is listening to 993 from exchange boxed as I can see all service is UP and GREEN.
Note : Since it is TCP port i couldn’t bind any SSL certs at netscaler level.
Testing that I have done – Telnet the hostname with 993 failed externally.
Telnet to the local netscaler LBVS VIP from exchange box on 993 port connecting.
Telnet to the local netscaler LBVS VIP from netscaler appliance SSH on 993 port is connecting.
I am not sure what I am missing.Should we require the MAPI content switching config also to be in place to make this work?
Your help is much appreciated.!
Thanks
Hi Abdul,
from LAN the MAPI LB vServer is accessible and working as desired? You can not content switch the MAPI protocol > DNAT directly to the LB VIP
HI Julian,
From LAN IMAP LBVS is accessible, however apart from exchange box and netscaler I can’t telnet 993 even from lan machines.. I am not sure what I am missing. here.
Already I have the direct NAT of public IP to LB VIP.
As of now, I don’t have any MAPI configurations in place. This is my earler question whether I need MAPI configuration to make this work. you have cleared it now in your reply saying not required.
Thanks
Abdul
Firewall inside the LAN? Using the same setup (TCP-993) at a customer. No problem with IMAP connections. Can you take a trace with WireShark?
Firewall is at DMZ. Can you please confirm the below configuration made is as per standards?
Created service group in Netscaler and binded exchange servers using port 993-TCP and assigned the TCP monitor.
Created LBVS VIP and bind the service group to the LBVS.
Sorry for the confusion. I have checked in other LAN machines. I can telnet to port 993 internally to the LBVS VIP.
It is only not working from externally. I have made necessary changes in the Firewall, still not working.
Any ideas
Thanks
Yes but I would create a more specific monitor. You can poll for the receive string. It’s like „IMAP Exchange Service is running..“ You can see the exact message via telnet. If it’s not working from external I suggest there is a problem with your NAT. Can you create the DNAT directly to your Exchange for testing?
Hello, thank you for this awesome guide!
We have a problem that the user is prompted to enter his password after he switches from one network to another. (LAN to WiFi)
Is this made by design (session persistence sourceip) or is there any way to avoid those outlook prompts.
Thanks in advance.
Best regards,
Christian
Hi,
Thanks for a great article, stumbled upon a small problem. I am not able to catch the /owa/logoff.owa since its never sent. (verified with sniffer). Using Exchange 2016.
Do you know if there is a solution to this
Thanks,
@SLR – I am dealing with the same issue. I can’t get the force logoff or the cookie cleared and am not finding any solutions or alternatives. I am wondering if Exchange is sending a http://owa.domain.com/owa/logoff.aspx URL back to the client but it never reaches the Netscaler because we don’t have 80 allowed on the firewall. Traces ahead….
hey Citrix guy!
I noticed that you set up an LB server for SMTP services. was this set up using SourceIP? I’m just curious if you have set up SMTP sourceIP LB using different subnets (NS in one subnet, exchange servers in another subnet). I’ve been asked to do this and although I have set up sourceIP LB for exchange on the same subnet as the NS, I have not done so when there are 2 subnets. I’m thinking it may not be possible but thought I would check anyway.
Hello Paul the thing with SourceIP persistence is that its working without any problems for an internal client. If we take a look at the external client access which is happening over a DNAT (in most of the cases) the backend server load could be very high because its always coming from the same source IP. I would go with NONE persistence for SMTP. But I am not an Exchange/SMTP guru 🙂
Hello,
Thank you for the guide. Do you have a blog on restricting access to SMTP Traffic. Currently in the configuration you have and I have implemented, any device that knows the relay VIP can now send traffic through the relay. I would like to restrict by IP as you can in the Exchange Relay setting in Exchange ECP.
Luke E. – If you want to restrict allowed relays / senders then you need to add ACLs. What I have done previously is add ACLs for individual IP addresses or networks with a priority of 1-100 or whatever number you need and then add a blanket DENY ACL and give it a very high priority number like 5000. If you have a lot of IPs to add you can use CONCANTENATE in excel to help build your commands and use Get-ReceiveConnector -Identity “Mail Relay” | select-object Identity,RemoteIPRanges to dump the allowed relays on your existing relay connector in Exchange. The only alternative would be to route your mail relays direct to a secondary IP bound on an Exchange Server NIC – but no HA. You can view your configured ACLs at any time by running show ns acl.
If you do not want to work with ACLs this should be possible with a listen policy on the LB vServer as well.
Example: CLIENT.IP.SRC.EQ(192.168.2.2) or CLIENT.IP.SRC.IN_SUBNET(192.168.2.0/24)
I can´t see avalible any https VS, looking in the owa VS, service groups members monitors; I get the Failure – Time out during SSL handshake stage error
Hello
Could you clarify why do you use SSL-based LB vServers (0.0.0.0) behind CS vServer instead of HTTP ones ? At the first look HTTP will be enough because these servers are not directly accessible outside ADC and all communications are only between CS and LB one. So additional ADC resources will be used for encrypting/decrypting the stream between them if SSL is used.
Or I miss something?
Thanks in Advance
Hello Alexey, it should work with a HTTP as well. Give it a try.
Julian, I just upgraded to Citrix ADC 13 built 41.20. This broke my exchange deployment as default authorization changed from allow to deny. You’ll need an additional authorization policy in future (see https://blog.norz.at/aaa-default-settings-changed-with-citrix-adc-netscaler-13-built-41-20/)
Hello Johannes, thanks for the information. I am going to update the blog in the next days 👍🏽
But I’m right, there is no problem?
Hey Julian,
Perfect Blog articel, Thank you alot.
I have one question.
You configure a session action and policy for the SSO.
Ist it just me and i havent found it, or ist this policy not bound to the AAA Server?
BR Christian
Thanks for this good guide 🙂
The OWA redirect for default server is wrong and potentially dangerous.
Undefinded URLs/content switches will be passed through to the backend server(s), because its basically a /* which negates all the other content switches.
For example, if /activesync or /mapi is not configured. This particular redirect will execute the owa action and this will simply pass the transaction to the servicegroup.
I suppose the problem with this lies in the concept of the netscaler. In its basic form its only a loadbalancer, with enterprise or platinum it also becomes an AAA solution, whereas with AAA you can add restriction with it.
if you don’t have access to AAA features and want to use the redirect to owa. You would at least need to explicitly deny all the valid content switches you don’t want allow through. Like /mapi /ecp /activesync /rpc etc…
Good afternoon, I have a question about it, can different versions of MS Exchange coexist in Balancing, for example 2013 and 2019?
Hi Julian,
if i want to route mail traffic through the IMSS server how I can route?
through the CS VIP or LB VIP?
All,
Great Article!
Recently I load balance exchange 2019, as per details it this topic which works perfect until I attach cache policy, which makes owa inaccessible, basically keeps asking credentials but once removed all works fine. I would appreciate any suggestions.
Thanks
Hi guys,
Thanks for the great article. Everything worked as expected, but we are facing a really strange problem. If we enable AAA for MAPI or EWS, users will not be able to send a message with an attachment. Without an attachment the mail flow works fine. As soon as I remove the AAA, sending a message with an attachment works again. Is this a known problem with NS version 13?
Thank you in advance for your help and best regards,
Flo
Hi Flo,
I have the same issue, did you solve it?
Hello guys,
there is a fix for the mentioned problem.
Please check the updated post with the information from Julian Jakob.
Cheers
Julian
I had issues getting this to work on Windows Server 2019 using Exchange 2019 with latest CU.
On my ADC (13.0.58.32) I had to use: set ssl parameter -denySSLReneg NONSECURE
After that the monitoring settings showed as up.
Reference links below…
https://docs.citrix.com/en-us/tech-zone/build/tech-papers/networking-tls-best-practices.html
https://discussions.citrix.com/topic/401441-basic-load-balancing-for-owa-exchange-2019
Hi Julian,
Thanks for your great article! Based upon it we are configuring this for Exchange 2013. We keep struggling with RPC. It produces a Http/1.1 Internal Server Error 43550. We currently use ADC 13.0 67.39 for our test setup.
Does this ring a bell?
Hello Joost. Is AAA in play?
Is it working without AAA? I think for Exchange 2013 you need to have a slightly different form sso profile.
Totally missed you reply, sorry about that.
AAA is in play. It looks like a problem between the ADC and Exchange. After a case with Citrix and a consultant we decided to disable authentication for RPC as we are switching to MAPI.
would you please describe more about Authentication FQDN in Virtual server?
Which server it should be pointed to, It cannot refer me to OWA webpage
I have a problem with AAA, what is Authentication FQDN role play, and what should I set there?
Isn’t it needed to set IP address for Authentication Virtual Server?
It’s configure to the DNS A-Record of your published AAA vServer.
If I use GSLB between 2 datacenters, I have to create separate GSLB vServers for SSL & TCP. And I bind webmail domain to SSL vServer and mailrelay domain to TCP vServer. Will this impact other components – IMAP/POP3? They should use webmail DNS, I guess.
I am having issues with autodiscover.
Not sure how its supposed to work. My OWA SSO setup works perfectly fine.
On my autodiscover VS, when i remove the auth, I get prompted for auth from server and even after adding credentials it keeps on prompting(loops).
When I add 401 form basd auth profile, its the same behaviour.
I tried to add the traffic policy to auto discover VS,as mentioned in one of the comments above but still no luck.
Is anyone having this similar issue?
Mo
Citrixguy, am I right about the current Exchange flaws: Your deployment is not vulnerable, as there is pre-authentication on ADC?
Thanks
Johannes
You should be save when using AAA due the Exchange is only accessible after a successful authentication.
Hi There,
Looking at your article and it has raised a question around whether you could integrate Azure AD MFA with this as well? To provide MFA support for Exchange OWA, as you would only want it on OWA not ActiveSync etc.
Hello Charlie. Yes this will work. But it depends with the integration of Azure MFA. If you go the SAML way with Conditional Access and Azure is your IDP you need a way to authenticate to the exchange server. The easiest way would be to use the Azure NPS extension then you already have the password of the user.
Hi Julian
I would like to do an internal LB and CS only. Can I not use the same setup and connect the internal Outlook clients to the SMTP LB IP? Or what is the different?
Hi Roland. It’s the same setup. Regarding SMTP: Maybe you want to see the real client ip on the exchange server (relay). If this is needed you need to configure USIP/DSR mode.
Hi Julian
Thank you for your reply!
I have an customer with an bad setup.
And I want to do an parallel setup and when tested a traffic switchover .
I have a lot of experience in other LB products but not in ADC.
And I would like to ask you if you see any problems here?
Hi mate, thanks for the article. I have followed this article to set up the reverse proxy for our exchange 2013 with AAA pre-auth. The owa/ecp MFA+pre auth on the Citrix landing page works perfectly. The apple native mail client on iPhone works without any issue. However, the Microsoft outlook app downloaded from the app store will not work with the pre-auth for active sync. it keeps complaining about incorrect email addresses or credentials. if I take the aaa pre-auth off from the lb, it will work again. Any idea. Your help will be highly appreciated.
David
Hi Julian
Any assistance for the question above will be highly appreciated. Thanks
David
Hi David,
on my Setup it works with native MS Outlook iOS App configured with my onprem Exchange 2016 server with adc aaa for preauth for active sync without any issues. Check if you have enabled the Advanced settings when adding your email account as you have to Setup your AD domain and your public exchange server fqdn.
Best Regards
Julian
Hi
There seems to be a problem with the integrated caching and/or FEO in Version 13.0 (79.64). It breaks OWA. When you switch it off, it works again.
mapi is still broken, even when you switch off the AAA Server, Outlook keeps me asking for the password.
EWS and other services are working fine. (With AAA)
Anybody else is having the same issue?
Any hint will. be appreciated
Radek
I have had 3 Exchange 2013 servers LB with CS supporting Outlook, OWA & ActiveSync with a single VIP and it works perfectly. Even with 2FA.
Now, I am migrating to O365 and need to add SMTP and EWS only for O365 servers for the hybrid connector (HCW). Your article above has so many separate VIPs and services, my config is much simpler. How can I add the services I need without breaking production?
Hi!
Thank you very much and congratulations for this guide! Works perfectly with Exchange 2019 & NetScaler/ADC-VPX 13. What I also needed was the SSO-traffic-policy, as Robert commented on May 16, 2018. Otherwise, I always had an authentication error with Mapi.
What bothers me now is the “Authn”-Type in the connection status in Outlook (right click with CTRL key on the Outlook icon). Because it says “Clear*”. What does that mean? Did I forget something?
We’ve followed this guide and have the issue with Outlook prompting for credentials frequently.
If disabling AAA for MAPI then everything is running fine.
Is there a workaround?
What I also needed was the SSO-traffic-policy, as Robert commented on May 16, 2018. Otherwise, I always had an authentication error with Mapi.
add tm trafficAction SSO_Profile -SSO ON -persistentCookie OFF -InitiateLogout OFF
add tm trafficPolicy SSO true SSO_Profile
Problem solved:
it seems, that with newer versions of ADC, weak SSO is disabled due to security reason, which causes Outlook prompting for credentials, or show’s problem with mobile clients (IOS or Android).
The workaround is to enable weak SSO using the CLI command:
nsapimgr_wr.sh -ys call=ns_weak_sso_type_enable
Thank you for posting this guide. When upgrading from exchange 2016 to exchange 2019, would this same guide work fine? Are there additional steps with Exchange 2019 that need to be taken? Thank you!
Hi and thanks for very good guide. I was able to make it work without any problems..
It was working perfectly, just some time ago it breaks. After authentification on AAA and redirection to exchange, I just get white page keep blinking and redirecting at “https://mail.domain.eu/owa/auth/logon.aspx?url=https%3a%2f%2fmail.domain.eu%2fowa%2f&reason=0”
Anyone one experiencing the issue? Any ideas?
Thanks..
Hi Adam,
did you installed the latest Exchange Security Updates? Checkout Cause 2 and Resolution 2 from https://support.microsoft.com/en-us/topic/cannot-log-in-to-owa-or-ecp-after-july-2021-su-for-exchange-server-2019-2016-and-2013-kb-5005341-476948d6-e124-4a60-bcc7-b0d5341e24ae
That was the problem with one of my environments and the Fix is to switch to Persistence SOURCEIP for the OWA LB vServer.
Regards
Julian
Hi Julian,
I stumbled over your great blog searching for ‘Loadbalancing SMTP Port 25 with Netscaler’.
Sorry, my question is not Exchange-specific but I need a working solution for the following problem and I hope, you can give some hints. If you think, this is not the right place for my question, feel free to delete it …:
I want to use the Netscaler as a loadbalancer for two spamfilter agents in front of our Exchange server. A loadbalancer created by me ‘the usual way’ works fine, BUT: the spamfilter servers only ‘see’ the Netscaler’s SIP. And this is not helpful for some of the filter modules (for example: host reputation etc.) because they need to ‘see’ the original sender’s/mailhost’s ip-address. I came aware of an option called ‘Use client ip’/’Use source ip’ and activated it in the Netscaler’s server-group settings. But as soon as I do it, no traffic hits the systems any more.
The Citrix documentation is not very helpful and more confusing than clarifying anything.
Asking Citrix support for help, lead to nothing until today.
If you have any ideas, I would appreciate to read from you. If not, I apologize for bothering you.
However, thanks
Rolf
Hi Rolf if you want to work with USIP-Mode you need to change the default gateway of the backend server to a ADC owned IP. In this case the Subnet IP. Otherwise this will not work.
Hi Julian,
thanks for looking into my request.
I have no experience in using the Netscaler as gateway, so: will all other queries (DNS for name resolution, https-traffic to the Internet and and and work as normal or have I to do addirional settings/services on the Netscaler?
Thanks again,
Rolf
Everything will get routed through the ADC. Make sure you have enough bandwith on the VPX/MPX. Another more easy approach would be to go with SNIP Mode and work with Network ACLs or a Listen Policy Expression on the SMTP vServer.
This guide is nice, but it is missing the requirement to load balance /api which is needed in hybrid scenarios.
Hi Julian,
we followed your instructions described in the above superb article!
Unfortunately we are facing some issues with our ADC/Exchange setup – authentication for autodiscover and RPC is not working. The Remote Connectivity Analyzer shows errors like you described in this Citrix forum post:
https://discussions.citrix.com/topic/388524-exchange-autodiscover-with-401-authentication/
So my question is if you could find an answer what was wrong in your config back then? It seems that I can’t find any suitable info on the internet how to fix this issue…
So thanks a lot for your work and maybe you could give me a small hint 🙂
Is RPC/MAPI working when you remove pre-auth for the autodiscover vServer? I think back in the days the issue was related to ADAL.
Thanks a lot for the answer!
I guess you’re talking about disabling AAA for RPC/MAPI? So yes, currently AAA is disabled for this and everything is working fine.
For Autodiscover it is still enabled but as mentioned the Remote Connectivity Analyser throws out the error.
Could you please specify the ADAL info a bit :-)?
Hi,
Thanks first for the grat job!
For me everthing is working fine, also AAA ActiveSync with iOS and Android and the buildin mail clients. But if the user use the Outlook app, it does not work. Sometimes the user is locked, mostly it happens nothing, so no mail is coming in. If I remove the 401 Auth from LB-Activesync, it works fine again, but we would to use AAA also on activesync. Any Idea how to solve?
Hi Julian,
thanks for your guide.
When I run Outlook in cache mode, it keeps disconnecting., mails cannot be sent.
When I switch the outlook client to online, everything works.
I have Outlook 2019 and Excahnge 2019 running.
Netscaler 13.0.83.27.nc
Thanks!
When I run Outlook in cache mode, it keeps disconnecting.
Mails cannot be sent.
When I switch the client to online, everything works.
I have Outlook 2019 and Excahnge 2019 running.
Netscaler 13.0.83.27.nc
When I try to use the expression HTTP.REQ.URL.CONTAINS(“/owa/auth/logon.aspx”) in session policy that is bound to the AAAvserver; it seems that it didn’t work. I changed the expression to true, and now it works. Am i overlooking something? I’m using NS13 build 83.
Thank you for the great walkthrough guide!
I have one questions concerning the autodiscover persistence settings:
The table states:
vServer, IP address, Method, Persistence, Timeout, Protocol, Authentication (AAA)
AutoDiscover, 0.0.0.0, SourceIP, NONE, 30, SSL, 401
The configuration code states:
add lb vserver lb_vsrv_ex2016_autodiscover SSL 0.0.0.0 0 -persistenceType SOURCEIP -timeout 30
Wouldn’t that mean that persistence type is not set to “NONE”?
Does the AAA for MAPI work for someone after activating “Extended Protection”?
HTTP/1.1 401 Unauthorized
POST /mapi/nspi/?mailboxId=e2a52fdc-990f-4f4b-b24f-87ebbe62d59c@lab.at HTTP/1.1
Content-Type: application/octet-stream
User-Agent: MapiHttpClient
https://microsoft.github.io/CSS-Exchange/Security/Extended-Protection/
Great Article, I haven’t worked with NetScaler in a long while so it was configured by another Admin. The issue is he setup dual NICs on the same subnet for Exchange and now Exchange is having issues. One NIC has the Gateway for the Subnet and the other has the Gateway configured for the NetScaler. This results in an error of the Cluster Network. Was adding the second Nic the best solution or what would you have recommended?
Hello Markus, was the second NetScaler NIC added for USIP mode? I prefer to work with a single NIC instance and combine it with listen policy expressions to filter the traffic for specific client IPs or subnets.
But it always depends on the environment and use-cases.
Julian
Hi everyone!
Thanks for the great guide Julian, it was very good base for many configs ive done.
But as many asked, does anyone solved the problem with 401 AAA for MAPI? Outlook keeps asking for credentials, same behavior on Exchange 2016 & 2019.
Thanks anyone for response!
Adam
Hi everyone,
did someone have a solution for this 2 errors/warnings:
set authentication vserver AAA_Exchange_2019 -authenticationDomain ‘xyz.com’
Warning: Argument deprecated [AuthenticationDomain]
add authentication ldappolicy LDAP_UPN ns_true LDAP_UPN
Warning: Classic authentication policies are deprecated and will be removed in the next major release. Please use advanced authentication policies (i.e. add/set authentication policy).
Is there maybe a new configuration guide?
Regards,
Adrian
@Adrian – The only Workaround we could figure out so far is to change the Setting;
IIS Website / Virtual Directory / Recommended Extended Protection / Recommended sslFlags
Default Website / MAPI / Required / Ssl,Ssl128
From Required to Accepted >
We are still Troubleshooting.
Hi, very nice tutorial.
If you do not attribute an IP-address to the AAA vserver, to what address then you apply the DNS record?
When executing:
#Enable AAA Feature
enable ns feature AAA
#Create AAA Server
add authentication vserver AAA_Exchange_2016 SSL 0.0.0.0
#Replace certificate name
bind ssl vserver AAA_Exchange_2016 -certkeyName ‘Wildcard-Flashmob’
bind authentication vserver AAA_Exchange_2016 -portaltheme X1
#Replace AAA FQDN >
set authentication vserver AAA_Exchange_2016 -authenticationDomain ‘flashmob-saulgau.de’
We get error that -authenticationDomain is deprecated. How do we apply aaa.domainname.com to the AAA_Exchange_2016 vserver?