HAProxy "unable to set SSL curves list to 'secp38r1'"

Hi, I’m trying to setup HAProxy on my OPNSense box as a reverse proxy for Plex. I’ve followed the tutorial at OPNSense

I’m pretty sure I’ve followed the instructions to the letter, but I keep getting the following error when I test the syntax:

[NOTICE] (67139) : haproxy version is 3.0.9-7f0031e
[NOTICE] (67139) : path to executable is /usr/local/sbin/haproxy
[ALERT] (67139) : config : Proxy '1_HTTPS_frontend': unable to set SSL curves list to 'secp38r1' for bind '127.4.4.3:443' at [/usr/local/etc/haproxy.conf.staging:72].
Proxy '1_HTTPS_frontend': unable to set SSL curves list to 'secp38r1' for bind '127.4.4.3:443' at [/usr/local/etc/haproxy.conf.staging:72].
[ALERT] (67139) : config : Fatal errors found in configuration.

Upon Googling, the only thing that seems relevant is a bug report from around 5 years ago.

Wondering if anyone might know why HAProxy might throw this error?

My config is as follows:

#
# Automatically generated configuration.
# Do not edit this file manually.
#

global
    uid                         80
    gid                         80
    chroot                      /var/haproxy
    daemon
    stats                       socket /var/run/haproxy.socket group proxy mode 775 level admin
    nbthread                    2
    hard-stop-after             60s
    no strict-limits
    maxconn                     1000
    ocsp-update.mindelay 300
    ocsp-update.maxdelay 3600
    httpclient.resolvers.prefer   ipv4
    tune.ssl.default-dh-param   4096
    spread-checks               2
    tune.bufsize                16384
    tune.lua.maxmem             0
    log                         /var/run/log local0 info
    lua-prepend-path            /tmp/haproxy/lua/?.lua

defaults
    log     global
    option redispatch -1
    maxconn 1000
    timeout client 30s
    timeout connect 30s
    timeout server 30s
    retries 3
    default-server init-addr last,libc

# autogenerated entries for ACLs


# autogenerated entries for config in backends/frontends

# autogenerated entries for stats




# Frontend: 0_SNI_frontend ()
frontend 0_SNI_frontend
    bind 0.0.0.0:443 name 0.0.0.0:443 
    bind 0.0.0.0:80 name 0.0.0.0:80 
    mode tcp
    default_backend SSL_Backend

    # logging options

# Frontend: 1_HTTP_frontend ()
frontend 1_HTTP_frontend
    bind 127.4.4.3:80 name 127.4.4.3:80 accept-proxy 
    mode http
    option http-keep-alive
    option forwardfor

    # logging options
    # ACL: NoSSL_Condition
    acl acl_67acd47edcffd7.39391092 ssl_fc

    # ACTION: HTTPtoHTTPS_rule
    http-request redirect scheme https code 301 if !acl_67acd47edcffd7.39391092

# Frontend: 1_HTTPS_frontend ()
frontend 1_HTTPS_frontend
    http-response set-header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    bind 127.4.4.3:443 name 127.4.4.3:443 accept-proxy ssl curves secp38r1  no-sslv3 no-tlsv10 no-tlsv11 no-tls-tickets ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES256-GCM-SHA384 ciphersuites TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256 alpn h2,http/1.1 crt-list /tmp/haproxy/ssl/67ace1f419a770.60014933.certlist 
    mode http
    option http-keep-alive
    option forwardfor
    timeout client 15m

    # logging options

    # ACTION: Public_Subdomains_Rule
    # NOTE: actions with no ACLs/conditions will always match
    use_backend %[req.hdr(host),lower,map_dom(/tmp/haproxy/mapfiles/67acddcce077a4.68710516.txt)] 

# Backend: SSL_Backend ()
backend SSL_Backend
    # health checking is DISABLED
    mode tcp
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m  
    stick on src
    server ssl_server 127.4.4.3 send-proxy-v2 check-send-proxy

# Backend: PLEX_Backend ()
backend PLEX_Backend
    # health check: check_plex_server
    option httpchk
    http-check send meth OPTIONS uri / ver HTTP/2 hdr Host localhost
    mode http
    balance source
    # stickiness
    stick-table type ip size 50k expire 30m  
    stick on src
    http-reuse safe
    server Plex_Server 192.168.1.94:32400 check inter 60s port 32400  ssl verify none



# statistics are DISABLED

Because the underlying ssl library rejects this curve.

I recommend not messing with SSL curve settings, unless you know very well what you are doing and what your SSL library supports.

You certainly should not set this options because it is in some tutorial on the internet.

Thanks for the quick response Lukas. I’m by no means an expert but I understand that some ciphers are more secure than others, and that secp38r1 is one of the more common and secure ones - hence why it’s important to specify we want to use it. As I understand it, OPNSense 25.1 uses FreeBSD 14, which in turn supports OpenSSL 3.0.9, which in turn should support this cipher. I’ve cross-posted the question over on the OPNSense forum to see if it’s something specific to OPNSense.

the OPNSense forum guys spotted the problem - a typo in “secp38r1”. It should be “secp384r1”

2 Likes