Haproxy and url rewrites to internal servers and urls

i have a few external websites which now works with nginx. As i need to host an internal exchange 2013 server (which free nginx doesn’t like) i am looking into haproxy.

I have some urls which i now use like mail.lex-it.com, wiki.lex-it.com and helpdesk.lex-it.com

https://mail.lex-it.com needs to be redirected to the internal exchange 2013 servers

https://wiki.lex-it.com needs to be redirected using url rewrite to internal server https://wiki.lan.local/xwiki

https://helpdesk.lex-it.com needs to be redirected to just an internal server https://helpdesk.lan.local (no further url rewrite)

The mail i still need to figure out but as i am new to the haproxy just wanted to focus in the simpler websites.

The problem i face is with the wiki rewrite which i don’t know how to do and i hope one off you can help me with this.

I have managed to create the following config, but the wiki is bogus offcourse :slight_smile: :

global
        log 127.0.0.1   local0
        log 127.0.0.1   local1 notice
        maxconn 25000
        user haproxy
        group haproxy
        daemon

defaults
        log     global
        mode    http
        option  httplog
        option  dontlognull
        option  forwardfor
        option  http-server-close
        stats   enable
        # stats auth someuser:somepassword
        stats uri /haproxy?stats
	retries 3
		
frontend http-in
        bind *:443

        # Define hosts
        acl host_helpdesk hdr(host) -i helpdesk.lex-it.com
        acl host_wiki hdr(host) -i wiki.lex-it.com

        ## figure out which one to use
        use_backend helpdesk_cluster if host_helpdesk
        use_backend wiki_cluster if host_wiki

backend helpdesk_cluster
        balance leastconn
        option httpclose
        option forwardfor
        cookie JSESSIONID prefix
        server node1 helpdesk.lan.local cookie A check

backend wiki_cluster
        balance leastconn
        option httpclose
        option forwardfor
        cookie JSESSIONID prefix
        server node1 wiki.lan.local/xwiki cookie A check

I managed with lots of help from google to have most of the options i need.
With this config i have my exchange services fully operational and my 2 internal websites are available based on the host header.
This means i don’t need my nginx proxy anymore :slight_smile:

I still however need to rewrite my wiki.lex-it.com to wiki.lex-it.com/xwiki
This i haven’t managed yet and help would really be appreciated

for google i add the search words: haproxy exchange 2013 exchange 2016 host header https forward

haproxy.cfg

global
   log 127.0.0.1 local1 debug
   chroot /var/lib/haproxy
   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 

frontend ft_default_http
   bind *:80 name http
   mode    http

   option  httplog

   # show stats in http mode
   stats   enable
   stats uri /haproxy?stats
   # stats auth someuser:somepassword
    
   # redirect all other trafic to https
   redirect scheme https if !{ ssl_fc }

frontend ft_default_https
   bind *:443 name https ssl crt /etc/pki/tls/certs/lex-it.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_i
d]}\ "%[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
 
   acl ssl_connection ssl_fc
   acl host_mail hdr(Host) -i mail.lex-it.com
   acl host_helpdesk hdr(Host) -i helpdesk.lex-it.com
   acl host_wiki hdr(Host) -i wiki.lex-it.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_helpdesk if host_helpdesk
   use_backend bk_wiki if host_wiki
   
   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.0.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.0.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.0.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.0.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.0.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.0.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.0.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.0.5:443 ssl verify none maxconn 1000 weight 10 check

backend bk_exchange_https_default
   timeout server 60s
   server mail1 10.1.0.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.0.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.0.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.0.5:993 maxconn 10000 weight 10 check

backend bk_helpdesk
   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 helpdesk1 10.1.0.22:443 ssl verify none maxconn 1000 weight 10 check

backend bk_wiki
   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 wiki1 10.1.0.22:443 ssl verify none maxconn 1000 weight 10 check

if i add code

http-request redirect code 301 location https://wiki.lex-it.com/xwiki if { hdr(host) -i wiki.lex-it.com }

it gets in a loop as i can asume. I only need to rewrite if there is nothing at the end of the url e.g. wiki.lex-it.com/

Still searching for a solution, anyone ??

Eureka, i found it…

I needed to add the following in my backend:

  acl p_root path -i /
  http-request set-path /xwiki if p_root

so my complete wiki backend now looks like:

backend bk_wiki
   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
   acl p_root path -i /
   http-request set-path /xwiki if p_root
   server wiki1 10.1.0.22:443 ssl verify none maxconn 1000 weight 10 check
1 Like

Hi,

I am trying to do the same process as you for our network, we have a web server + an exchange 2010 server that will sit behind the 1 IP address and using domain names and HAProxy I am trying to get it to forward the domains on.

I can get the webserver working, and I tried to copy your config and setup for our Exchange 2010 but OWA redirects me to /owa but then says 503 Service Unavailable and autodiscovery does not work and phones are not working.

Do you have any suggestion why I would be getting “no server is available to handle this request”.

As well as this config, did you need to do anything to the exchange server?

I needed to reset the the exchange settings to the defaults and set my urls on the exchange server to my external domain (using split dns in my environment).
I used this perfect powershell script to achieve this: https://github.com/cunninghamp/ConfigureExchangeURLs.ps1

Also in my network i needed to set the split dns records so my internal and external users used the same records nomather where they where.