Moving from HAPROXY 1.8 to 2.4 and a backend service is returning a HTTP 400

This config works fine on 1.8 but on 2.4 the back end appears to generate a HTTP 400. Any ideas of things I can try that would be standout differences between 1.8 and 2.4?

frontend service:8188
    #---------------------------------------------------------------------
    # Blacklist: Deny access to some IPs before anything else is checked
    #---------------------------------------------------------------------
    tcp-request content reject if { src -f /etc/haproxy/acl_lists/blacklist.lst }
    #---------------------------------------------------------------------

    bind 192.168.0.2:8188 ssl crt /etc/pki/tls/private/letsencrypt.pem

    http-response set-header    Strict-Transport-Security max-age=31536000;\ includeSubDomains
    http-response set-header    X-Frame-Option DENY
    http-response set-header    X-Content-Type-Options nosniff
    http-after-response replace-header Set-Cookie '(^((?!(?i)httponly).)*$)' "\1; HttpOnly"
    http-after-response replace-header Set-Cookie '(^((?!(?i)secure).)*$)' "\1; Secure" if { ssl_fc }
    option http-keep-alive

    default_backend             backend:8188

backend backend:8188
    #------------------------------
    timeout server 	300s
    #------------------------------
    balance     roundrobin
    option http-keep-alive
    option prefer-last-server
    option forwardfor
    option http-buffer-request
    server  APP 192.168.0.3:8188 check ssl verify none

Please let me know if you need more info. The app itself is not too helpful in explaining why it’s getting a 400 other than: HTTP/1.1 400 Bad Request

Thank you,
Matt

That’s likely happening to the case senstivity on the backend server.

Haproxy changed it’s behavior between those versions due to the generic HTTP implementation allowing h1, h2 and h3 interoperability. However this causes headers to go out lowercased in H1, which causes interoperability issues with clients that care about the case (which is a RFC violation).

You can workarounds this with the bogus-server / bogus-client directives.

For example:

global
 h1-case-adjust accept Accept
 h1-case-adjust authorization Authorization
 h1-case-adjust authrequired AuthRequired
 h1-case-adjust cache-control Cache-Control
 h1-case-adjust client-request-id Client-Request-Id
 h1-case-adjust connection Connection
 h1-case-adjust content-length Content-Length
 h1-case-adjust content-type Content-Type
 h1-case-adjust cookie Cookie
 h1-case-adjust date Date
 h1-case-adjust host Host
 h1-case-adjust persistent-auth Persistent-Auth
 h1-case-adjust pragma Pragma
 h1-case-adjust request-header Request-Header
 h1-case-adjust response-header Response-Header
 h1-case-adjust server Server
 h1-case-adjust set-cookie Set-Cookie
 h1-case-adjust status-code Status-Code
 h1-case-adjust transfer-encoding Transfer-Encoding
 h1-case-adjust user-agent User-Agent
 h1-case-adjust www-authenticate WWW-Authenticate
 h1-case-adjust x-anchormailbox X-AnchorMailbox
 h1-case-adjust x-clientapplication X-ClientApplication
 h1-case-adjust x-clientInfo X-ClientInfo
 h1-case-adjust x-content-type-options X-Content-Type-Options
 h1-case-adjust x-deviceinfo X-DeviceInfo
 h1-case-adjust x-elapsedtime X-ElapsedTime
 h1-case-adjust x-expirationinfo X-ExpirationInfo
 h1-case-adjust x-feserver X-FEServer
 h1-case-adjust x-mapihttpcapability X-MapiHttpCapability
 h1-case-adjust x-pendingperiod X-PendingPeriod
 h1-case-adjust x-powered-by X-Powered-By
 h1-case-adjust x-requestid X-RequestId
 h1-case-adjust x-requesttype X-RequestType
 h1-case-adjust x-responsecode X-ResponseCode
 h1-case-adjust x-serverapplication X-ServerApplication
 h1-case-adjust x-starttime X-StartTime
 h1-case-adjust x-user-identity X-User-Identity


backend backend:8188
 option h1-case-adjust-bogus-server
1 Like

Thank you lukastribus, I will give that a try and reply if it works.