My config for HAPRoxy and Exchange 2013
-
I have not had time to get my HAProxy guide all put together.
But in the interim, here is my config file for a site with Exchange 2013.
As you can see, I have two certificates setup and I am also proxying for Nextcloud (nc/oc.domain.com), SnipeIT (assets.domain.com), and a PBX (pbx.domain.com).
global log 127.0.0.1 local0 debug chroot /var/lib/haproxy # stats socket /run/haproxy/admin.sock mode 660 level admin stats socket /var/lib/haproxy/stats mode 660 level admin stats timeout 30s user haproxy group haproxy daemon ssl-server-verify none crt-base /etc/pki/tls/certs ca-base /etc/pki/tls/certs # Default ciphers to use on SSL-enabled listening sockets. # For more information, see ciphers(1SSL). This list is from: # https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/ ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS ssl-default-bind-options no-sslv3 tune.ssl.default-dh-param 2048 defaults log global mode http option httplog option dontlognull option http-keep-alive option prefer-last-server option forwardfor no option httpclose no option http-server-close no option forceclose no option http-tunnel balance leastconn default-server inter 3s rise 2 fall 3 timeout client 600s timeout http-request 10s timeout connect 4s timeout server 60s # errorfile 400 /etc/haproxy/errors/400.http # errorfile 403 /etc/haproxy/errors/403.http # errorfile 408 /etc/haproxy/errors/408.http # errorfile 500 /etc/haproxy/errors/500.http # errorfile 502 /etc/haproxy/errors/502.http # errorfile 503 /etc/haproxy/errors/503.http # errorfile 504 /etc/haproxy/errors/504.http frontend ft_exchange_https bind 10.1.1.22:80 name http bind 10.1.1.22:443 name https ssl crt /etc/pki/tls/certs/remote.domain.com.pem crt /etc/pki/tls/certs/pbx.domain.com.pem capture request header Host len 32 capture request header User-Agent len 64 capture response header Content-Length len 10 log-format %ci:%cp\ [%t]\ %ft\ %b/%s\ %Tq/%Tw/%Tc/%Tr/%Tt\ %ST\ %B\ %CC\ %CS\ %tsc\ %ac/%fc/%bc/%sc/%rc\ %sq/%bq\ %hr\ %hs\ {%sslv/%sslc/%[ssl_fc_sni]/%[ssl_fc_session_id]}\ "%[capture.req.method]\ %[capture.req.hdr(0)]%[capture.req.uri]\ HTTP/1.1" option socket-stats stats uri /haproxy?stats stats realm Strictly\ Private stats auth YOURSTATLOGINUSER:YOURSTATLOGINPASSWORD maxconn 1000 #tcp-request content accept if { ssl_fc_has_crt } acl ssl_connection ssl_fc acl host_mail hdr(Host) -i remote.domain.com acl host_assets hdr(Host) -i assets.domain.com acl host_nc hdr(Host) -i nc.domain.com acl host_oc hdr(Host) -i oc.domain.com acl host_pbx hdr(Host) -i pbx.domain.com acl path_slash path / acl path_autodiscover path_beg -i /Autodiscover/Autodiscover.xml acl path_activesync path_beg -i /Microsoft-Server-ActiveSync acl path_ews path_beg -i /ews/ acl path_owa path_beg -i /owa/ acl path_oa path_beg -i /rpc/rpcproxy.dll acl path_ecp path_beg -i /ecp/ acl path_oab path_beg -i /oab/ acl path_mapi path_beg -i /mapi/ acl path_check path_end -i HealthCheck.htm http-request deny if path_check http-request redirect scheme https code 302 unless ssl_connection http-request redirect scheme https code 301 if !{ ssl_fc } http-request redirect location /owa/ code 302 if path_slash host_mail use_backend bk_exchange_https_autodiscover if path_autodiscover use_backend bk_exchange_https_activesync if path_activesync use_backend bk_exchange_https_ews if path_ews use_backend bk_exchange_https_owa if path_owa use_backend bk_exchange_https_oa if path_oa use_backend bk_exchange_https_ecp if path_ecp use_backend bk_exchange_https_oab if path_oab use_backend bk_exchange_https_mapi if path_mapi use_backend bk_assets if host_assets use_backend bk_nc if host_oc use_backend bk_nc if host_nc use_backend bk_pbx if host_pbx default_backend bk_exchange_https_default backend bk_exchange_https_activesync option httpchk GET /Microsoft-Server-ActiveSync/HealthCheck.htm http-check expect string 200\ OK server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check backend bk_exchange_https_autodiscover option httpchk GET /Autodiscover/HealthCheck.htm http-check expect string 200\ OK server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check backend bk_exchange_https_ecp option httpchk GET /ECP/HealthCheck.htm http-check expect string 200\ OK server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check backend bk_exchange_https_ews option httpchk GET /EWS/HealthCheck.htm http-check expect string 200\ OK server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check backend bk_exchange_https_mapi option httpchk GET /mapi/HealthCheck.htm http-check expect string 200\ OK timeout server 600s server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check backend bk_exchange_https_oab option httpchk GET /OAB/HealthCheck.htm http-check expect string 200\ OK server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check backend bk_exchange_https_oa option httpchk GET /RPC/HealthCheck.htm http-check expect string 200\ OK timeout server 600s server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check backend bk_exchange_https_owa option httpchk GET /owa/HealthCheck.htm http-check expect string 200\ OK server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check backend bk_exchange_https_default timeout server 60s server mail1 10.1.1.5:443 ssl verify none maxconn 1000 weight 10 check #frontend ft_exchange_smtp # mode tcp # bind 10.1.1.22:25 name smtp # maxconn 10000 # default_backend bk_exchange_smtp #backend bk_exchange_smtp # mode tcp # server mail1 10.1.1.5:25 maxconn 10000 weight 10 check #frontend ft_exchange_smtps # mode tcp # bind 10.1.1.22:587 name smtps # maxconn 10000 # default_backend bk_exchange_smtps #backend bk_exchange_smtps # mode tcp # server mail1 10.1.1.5:587 maxconn 10000 weight 10 check #frontend ft_exchange_imaps # mode tcp # bind 10.1.1.22:993 name imaps # maxconn 10000 # default_backend bk_exchange_imaps #backend bk_exchange_imaps # mode tcp # balance leastconn # stick store-request src # stick-table type ip size 200k expire 30m # server mail1 10.1.1.5:993 maxconn 10000 weight 10 check backend bk_assets option httpclose option forwardfor http-request set-header X-Forwarded-Port %[dst_port] http-request add-header X-Forwarded-Proto https if { ssl_fc } http-check expect string 200\ OK server asset1 10.1.1.32:80 maxconn 1000 weight 10 check backend bk_pbx option httpclose option forwardfor http-request set-header X-Forwarded-Port %[dst_port] http-request add-header X-Forwarded-Proto https if { ssl_fc } http-check expect string 200\ OK server pbx1 10.1.1.30:80 maxconn 1000 weight 10 check backend bk_nc option httpclose option forwardfor http-request set-header X-Forwarded-Port %[dst_port] http-request add-header X-Forwarded-Proto https if { ssl_fc } http-check expect string 200\ OK server nc1 10.1.1.21:80 maxconn 1000 weight 10 check
-
Stats page
-
Not having actually used HAProxy myself, when is it the way to go over an nginx proxy?
-
@travisdh1 said in My config for HAPRoxy and Exchange 2013:
Not having actually used HAProxy myself, when is it the way to go over an nginx proxy?
I think it's mostly a matter of preference. I've seen benchmarks that put nginx ahead of haproxy in terms of absolute speed, not by much though.
-
JB found that nginx didn't support Exchange on the free version. HAProxy does.
-
@dashrender said in My config for HAPRoxy and Exchange 2013:
JB found that nginx didn't support Exchange on the free version. HAProxy does.
Oh, right. Now that you mention it, I remember that conversation.
-
Nginx has a paid solution that does fully support Exchange.
-
@jaredbusch said in My config for HAPRoxy and Exchange 2013:
Stats page
I have that, I haven’t updated it but now that you show it I will.
-
Thank you so much for sharing your config, I have not found anything else that works for Exchange 2016 and this works perfectly. :grinning_face_with_smiling_eyes:
-
@bradhawkins said in My config for HAPRoxy and Exchange 2013:
Thank you so much for sharing your config, I have not found anything else that works for Exchange 2016 and this works perfectly. :grinning_face_with_smiling_eyes:
Glad it works for you. I do not have a client with on prem 2016 to test with.