HAProxy community

Rules processing order

Greetings,

I’m using the following configuration of the HAproxy

[root@haproxy1 ~]# haproxy -v
HA-Proxy version 1.8.20 2019/04/25
Copyright 2000-2019 Willy Tarreau <willy@haproxy.org>

defaults
        log     global
        mode    http

        option  httplog
        option  redispatch
        option  http-keep-alive
        option  forwardfor      except 127.0.0.0/8
        option  log-health-checks
        #option dontlognull
        #option dontlog-normal

        no option httpclose

        retries 3
        backlog 10000
        balance leastconn

        timeout connect         30s
        timeout http-keep-alive 15s
        timeout http-request    15s
        timeout queue           30s
        timeout tarpit          1m

        timeout client          30s
        timeout server          30s

        default-server inter 5s rise 2 fall 3

        stats   enable
        stats   refresh 30s
        stats   show-node
        stats   auth    %commented%
        stats   uri     %commented%
frontend web_frt
        bind 192.168.60.7:443 ssl crt-list /etc/haproxy/cer.list
        bind 192.168.60.7:80

        acl     not_https       ssl_fc,not
        acl     is_ca_web       hdr(host)       -m str -i ca.crpt.ru
        acl     is_portal       hdr(host)       -m str -i portal.crpt.ru
        acl     is_autodiscover hdr(host)       -m str -i autodiscover.crpt.ru
        acl     is_rpc          path_beg        -m beg -i /rpc/
        acl     is_owa          path_beg        -m beg -i /owa/
        acl     is_ews          path_beg        -m beg -i /ews/
        acl     is_oab          path_beg        -m beg -i /oab/
        acl     is_eas          path_beg        -m beg -i /eas/
        acl     is_mapi         path_beg        -m beg -i /mapi/
        acl     is_ecp          path_beg        -m beg -i /ecp/
        acl     is_healthcheck  path_beg        -m end -i healthcheck.htm

        use_backend     ca_web                          if is_ca_web

        http-request    deny                            if is_ecp
        http-request    deny                            if is_healthcheck
        #http-request   redirect scheme https code 301  if not_https

        use_backend     autodiscover_bck                if is_autodiscover
        use_backend     rpc_bck                         if is_rpc
        use_backend     owa_bck                         if is_owa
        use_backend     ews_bck                         if is_ews
        use_backend     oab_bck                         if is_oab
        use_backend     eas_bck                         if is_eas
        use_backend     mapi_bck                        if is_mapi
        use_backend     portal_bck                      if is_portal

        default_backend owa_bck

With this configuration I get my ca_web backend working on http. My my real goal is to force all backends, except for ca_web, to work with https. If I uncomment the http-request redirect scheme rule, I will get https redirection for the ca_web backend which is not acceptable. Is there any way to exclude ca_web backend from https redirection?

Upd.

I’ve tried

        acl     not_https       ssl_fc,not
        acl     is_ca_web       hdr(host)       -m str -i ca.crpt.ru
        acl     is_portal       hdr(host)       -m str -i portal.crpt.ru
        acl     is_autodiscover hdr(host)       -m str -i autodiscover.crpt.ru
        acl     is_rpc          path_beg        -m beg -i /rpc/
        acl     is_owa          path_beg        -m beg -i /owa/
        acl     is_ews          path_beg        -m beg -i /ews/
        acl     is_oab          path_beg        -m beg -i /oab/
        acl     is_eas          path_beg        -m beg -i /eas/
        acl     is_mapi         path_beg        -m beg -i /mapi/
        acl     is_ecp          path_beg        -m beg -i /ecp/
        acl     is_healthcheck  path_beg        -m end -i healthcheck.htm

        use_backend     ca_web                          if is_ca_web

        http-request    deny                            if is_ecp
        http-request    deny                            if is_healthcheck
        http-request    redirect scheme https code 301  if not_https !is_ca_web

But it seems it is not helping either.

I’ve managed to fix this issue on my own by splitting http and https to different frontends and creating necessary redirect rule, please find config below

frontend web_frt_http
        bind 192.168.60.7:80

        acl     is_ca_web       hdr(host)       -m str -i ca.crpt.ru
        acl     is_empty_query  query           -m found
        acl     is_ecp          path            -m reg -i (^\/ecp$|^\/ecp\/)
        acl     is_healthcheck  path            -m reg -i healthcheck\.htm$

        http-request deny if is_ecp
        http-request deny if is_healthcheck
        http-request redirect location https://%[hdr(host)]%[path] code 301 if !is_ca_web !is_empty_query
        http-request redirect location https://%[hdr(host)]%[path]?%[query] code 301 if !is_ca_web is_empty_query

        use_backend ca_web if is_ca_web

frontend web_frt_https
        bind 192.168.60.7:443 ssl crt-list /etc/haproxy/cer.list

        acl     is_ca_web       hdr(host)       -m str -i ca.crpt.ru
        acl     is_portal       hdr(host)       -m str -i portal.crpt.ru
        acl     is_autodiscover hdr(host)       -m str -i autodiscover.crpt.ru
        acl     is_mail         hdr(host)       -m str -i mail.crpt.ru
        acl     is_empty_path   path            -m reg -i (^\/$|^$)
        acl     is_rpc          path            -m reg -i (^\/rpc$|^\/rpc\/)
        acl     is_owa          path            -m reg -i (^\/owa$|^\/owa\/)
        acl     is_ews          path            -m reg -i (^\/ews$|^\/ews\/)
        acl     is_oab          path            -m reg -i (^\/oab$|^\/oab\/)
        acl     is_eas          path            -m reg -i (^\/eas$|^\/eas\/)
        acl     is_mapi         path            -m reg -i (^\/mapi$|^\/mapi\/)
        acl     is_ecp          path            -m reg -i (^\/ecp$|^\/ecp\/)
        acl     is_healthcheck  path            -m reg -i healthcheck.htm$

        http-request deny if is_ecp
        http-request deny if is_healthcheck
        http-request redirect location http://ca.crpt.ru/ code 301 if is_ca_web

        use_backend     autodiscover_bck                if is_autodiscover
        use_backend     rpc_bck                         if is_rpc
        use_backend     owa_bck                         if is_owa
        use_backend     ews_bck                         if is_ews
        use_backend     oab_bck                         if is_oab
        use_backend     eas_bck                         if is_eas
        use_backend     mapi_bck                        if is_mapi
        use_backend     portal_bck                      if is_portal
        use_backend     owa_bck                         if is_mail is_empty_path

If anyone knows a better solution I’d be glad to have it here