Haproxy: Configuration parser fails since 2.2 when not ending with a new line

Created on 22 Jun 2020  路  4Comments  路  Source: haproxy/haproxy

Hi,

I upgraded my HAProxy from 2.1.7 to 2.2-dev10 and it wasn't able to parse my configuration anymore.

Output of haproxy -vv and uname -a

uname -a: 
Linux haproxy 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1+deb10u1 (2020-04-27) x86_64 GNU/Linux

haproxy -vv:
HA-Proxy version 2.2-dev10 2020/06/19 - https://haproxy.org/
Status: development branch - not safe for use in production.
Known bugs: https://github.com/haproxy/haproxy/issues?q=is:issue+is:open
Running on: Linux 4.19.0-8-amd64 #1 SMP Debian 4.19.98-1+deb10u1 (2020-04-27) x86_64
Build options :
  TARGET  = linux-glibc
  CPU     = native
  CC      = gcc
  CFLAGS  = -m64 -march=x86-64 -O2 -march=native -g -Wall -Wextra -Wdeclaration-after-statement -fwrapv -Wno-unused-label -Wno-sign-compare -Wno-unused-parameter -Wno-clobbered -Wno-missing-field-initializers -Wno-stringop-overflow -Wno-cast-function-type -Wtype-limits -Wshift-negative-value -Wshift-overflow=2 -Wduplicated-cond -Wnull-dereference
  OPTIONS = USE_PCRE=1 USE_OPENSSL=1

Feature list : +EPOLL -KQUEUE +NETFILTER +PCRE -PCRE_JIT -PCRE2 -PCRE2_JIT +POLL -PRIVATE_CACHE +THREAD -PTHREAD_PSHARED +BACKTRACE -STATIC_PCRE -STATIC_PCRE2 +TPROXY +LINUX_TPROXY +LINUX_SPLICE +LIBCRYPT +CRYPT_H +GETADDRINFO +OPENSSL -LUA +FUTEX +ACCEPT4 -ZLIB -SLZ +CPU_AFFINITY +TFO +NS +DL +RT -DEVICEATLAS -51DEGREES -WURFL -SYSTEMD -OBSOLETE_LINKER +PRCTL +THREAD_DUMP -EVPORTS

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

Built with multi-threading support (MAX_THREADS=64, default=1).
Built with OpenSSL version : OpenSSL 1.1.1d  10 Sep 2019
Running on OpenSSL version : OpenSSL 1.1.1d  10 Sep 2019
OpenSSL library supports TLS extensions : yes
OpenSSL library supports SNI : yes
OpenSSL library supports : TLSv1.0 TLSv1.1 TLSv1.2 TLSv1.3
Built with network namespace support.
Built without compression support (neither USE_ZLIB nor USE_SLZ are set).
Compression algorithms supported : identity("identity")
Built with transparent proxy support using: IP_TRANSPARENT IPV6_TRANSPARENT IP_FREEBIND
Built with PCRE version : 8.39 2016-06-14
Running on PCRE version : 8.39 2016-06-14
PCRE library supports JIT : no (USE_PCRE_JIT not set)
Encrypted password support via crypt(3): yes
Built with gcc compiler version 8.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 <default> cannot be specified using 'proto' keyword)
            fcgi : mode=HTTP       side=BE        mux=FCGI
       <default> : mode=HTTP       side=FE|BE     mux=H1
              h2 : mode=HTTP       side=FE|BE     mux=H2
       <default> : mode=TCP        side=FE|BE     mux=PASS

Available services : none

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

What's the configuration?

global
    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 socket [::1]:2342 mode 660 level admin expose-fd listeners
    stats timeout 30s
    user haproxy
    group haproxy
    daemon

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

    ssl-dh-param-file /opt/ssl/dhparams-4096.pem

    # See: https://ssl-config.mozilla.org/#server=haproxy&server-version=2.0.3&config=intermediate
    ssl-default-bind-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
    ssl-default-bind-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-bind-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets

    ssl-default-server-ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
    ssl-default-server-ciphersuites TLS_AES_128_GCM_SHA256:TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256
    ssl-default-server-options no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets

defaults
    log global
    mode    http
    option  httplog
    option  dontlognull
    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

backend web_servers
    balance roundrobin
    server server1 [::1]:8080 check maxconn 500

frontend https-in:
    bind [::]:80 v4v6
    bind [::]:443 v4v6 alpn h2,http/1.1 ssl crt-list /etc/haproxy/crt-list.txt
    default_backend web_servers
    http-request set-header X-Forwarded-Proto https if { ssl_fc }

Steps to reproduce the behavior

Use the current GIT repo or the 2.2-dev10 tag to run the posted configuration.
Very important: Do not put a new line at the end of the file! Last character is the "}".

Run /usr/local/sbin/haproxy -f /etc/haproxy/haproxy.cfg -d

Actual behavior

[NOTICE] 173/171725 (2862) : haproxy version is 2.2-dev10
[NOTICE] 173/171725 (2862) : path to executable is /usr/local/sbin/haproxy
[ALERT] 173/171725 (2862) : parsing [/etc/haproxy/haproxy.cfg:51] : error detected while parsing an 'http-request set-header' condition : missing closing '}' in condition.
[ALERT] 173/171725 (2862) : Error(s) found in configuration file : /etc/haproxy/haproxy.cfg

Expected behavior

Note: setting global.maxconn to 524274.
Available polling systems :
      epoll : pref=300,  test result OK
       poll : pref=200,  test result OK
     select : pref=150,  test result FAILED
Total: 3 (2 usable), will use epoll.

Available filters :
    [SPOE] spoe
    [CACHE] cache
    [FCGI] fcgi-app
    [TRACE] trace
    [COMP] compression
Using epoll() as the polling mechanism.

Do you have any idea what may have caused this?

This behaviour was introduced between 2.1.7 and 2.2-dev10. It works fine with 2.1.7, with the exact same build parameters, config and system.
If this is expected behaviour, feel free to close the issue (although a more speaking error message would really be nice in this case.)

This only happens when the } symbol is the last byte in the configuration. If you put a newline after it, the parsing works fine.

Do you have an idea how to solve the issue?

Unfortunately not :smile:

fixed bug

Most helpful comment

Now merged, closing. Thanks @Manawyrm for the report and @TimWolla for the fix!

All 4 comments

Wow, that's a record time for a bug fix :+1:

I tested the patch and it works like I'd expect:

Jun 22 18:38:34 haproxy systemd[1]: Starting HAProxy Load Balancer...
Jun 22 18:38:34 haproxy haproxy[6691]: [WARNING] 173/183834 (6691) : parsing [/etc/haproxy/haproxy.cfg:51]: line is not terminated by a newline (LF / '\n').
Jun 22 18:38:34 haproxy haproxy[6691]: Proxy web_servers started.

Should we close this issue? (or wait until the patch is merged?)

Thanks a lot!

or wait until the patch is merged?

Wait until it is merged, please. We only close issues once the fix reached all applicable branches.

Now merged, closing. Thanks @Manawyrm for the report and @TimWolla for the fix!

Was this page helpful?
0 / 5 - 0 ratings