ACL trouble, only works if I negate the ACL in the if statement



acl evil path_beg /evil/
acl evil path_end /evil
http-request deny if evil

acl allow path_beg /EWS/
acl allow path_beg /Microsoft-Server-ActiveSync/
acl allow path_beg /OAB/
acl allow path_beg /owa/
acl allow path_beg /Rpc/

log /dev/log local0
log /dev/log local1 notice
chroot /var/lib/haproxy
stats socket /run/haproxy/admin.sock mode 660 level admin expose-fd listeners
stats timeout 30s
maxconn 1024
user haproxy
group haproxy
ssl-server-verify none

    # Default SSL material locations
    ca-base /etc/ssl/certs
    crt-base /etc/ssl/private

    # See:
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options ssl-min-ver TLSv1.2 no-tls-tickets

log global
mode http
option logasap
option tcplog

option dontlognull

    retries         3
    timeout connect 5000
    timeout client  50000
    timeout server  50000
    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 stats
acl white_list src
stats enable
stats uri /stats
stats refresh 10s
stats admin if white_list

frontend exch-outside-443
acl allow_url path_beg -i /ecp/ /ews/ /microsoft-server-activesync/ /oab/ /owa/ /rpc/
mode tcp
log global
description exchange outside port 443
option socket-stats
option tcplog
use_backend exch-server-443 if allow_url

backend exch-server-443
server exch-server01 check-ssl verify none
server exch-server02 check-ssl verify none
stick store-request src
stick-table type ip size 50k expire 5m
mode tcp
balance leastconn
timeout server 1m
timeout connect 40s

any suggestions would be gratefully recieved.




root@haproxy01:~# haproxy -vv
HAProxy version 2.4.7-1ppa1~focal 2021/10/07 -
Status: long-term supported branch - will stop receiving fixes around Q2 2026.
Known bugs:
Running on: Linux 5.4.0-89-generic #100-Ubuntu SMP Fri Sep 24 14:50:10 UTC 2021 x86_64
Build options :
TARGET = linux-glibc
CPU = generic
CC = cc
CFLAGS = -O2 -g -O2 -fdebug-prefix-map=/build/haproxy-s1iGIG/haproxy-2.4.7=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wall -Wextra -Wdeclaration-after-statement -fwrapv -Wno-address-of-packed-member -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wno-cast-function-type -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference


Default settings :
bufsize = 16384, maxrewrite = 1024, maxpollevents = 200

Built with multi-threading support (MAX_THREADS=64, default=4).
Built with OpenSSL version : OpenSSL 1.1.1f 31 Mar 2020
Running on OpenSSL version : OpenSSL 1.1.1f 31 Mar 2020
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with Lua version : Lua 5.3.3
Built with the Prometheus exporter as a service
Built with network namespace support.
Built with libslz for stateless compression.
Compression algorithms supported : identity(“identity”), deflate(“deflate”), raw-deflate(“deflate”), gzip(“gzip”)
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE2 version : 10.34 2019-11-21
PCRE2 library supports JIT : yes
Encrypted password support via crypt(3): yes
Built with gcc compiler version 9.3.0

Available polling systems :
epoll : pref=300, test result OK
poll : pref=200, test result OK
select : pref=150, test result OK
Total: 3 (3 usable), will use epoll.

Available multiplexer protocols :
(protocols marked as cannot be specified using ‘proto’ keyword)
h2 : mode=HTTP side=FE|BE mux=H2 flags=HTX|CLEAN_ABRT|HOL_RISK|NO_UPG
fcgi : mode=HTTP side=BE mux=FCGI flags=HTX|HOL_RISK|NO_UPG
: mode=HTTP side=FE|BE mux=H1 flags=HTX
h1 : mode=HTTP side=FE|BE mux=H1 flags=HTX|NO_UPG
: mode=TCP side=FE|BE mux=PASS flags=
none : mode=TCP side=FE|BE mux=PASS flags=NO_UPG

Available services : prometheus-exporter
Available filters :
[SPOE] spoe
[CACHE] cache
[FCGI] fcgi-app
[COMP] compression
[TRACE] trace


You are passing ENCRYPTED traffic from one place to another, you cannot access it’s contents.

You need to decrypt TLS (installing the proper certificate) and reconfigure haproxy in http mode for this to work.

Hi Lukas,

Thank you for your reply.

Yes, I see that now. I’m migrating from an existing load balancing system which does terminate https (which I had assumed was not the case, my bad).
I’ll update my config.

A further question please; once the termination is working the contents should be accessible on the frontend to apply the ACLs?

Many thanks,


Yeah, once you have only “mode http” in your default section on no other “mode tcp” directives in your front and backend, and you are succesfully passing traffic, than those ACL’s will work.

But like I said, you also need certificates and configure the SSL part.

Again, thank you.

I’ve already added the necessary certificates and appear to have the ACLs applying but I just have to figure out why the exchange server is now responding with a ‘Bad Request’ message using port 80 on the backend or a gateway time out using 443. Oh the joys!



pleased to write that I managed to fix for port 443.
for those interested, I simply re-encrypted the connection using the correct bind;


server exch-server01 check ssl



1 Like