HAProxy as reverse proxy for AWS API Gateway

Solution 1:

If you don't use HTTPS then CloudFront will return the 400 Bad Request¹ error because API Gateway doesn't support HTTP.

Adding ssl verify none enables HTTPS to the back-end, CloudFront just closes the connection, causing HAProxy to log the session state at disconnection as SC-- and return the local 503 Service Unavailable error.

The solution is indeed sending Server Name Identification (SNI). Otherwise, CloudFront's front-end doesn't know which SSL certificate to offer you -- the generic *.cloudfront.net wildcard cert, or the one for *.execute-api.ap-southeast-2.amazonaws.com or one of probably hundreds of thousands of other possibilities. That's what SNI does in this case -- it tells the server what name you're connecting to.

The solution -- this is a single line, shown as multiple lines for clarity:

server api-gateway 
       xxxxx.execute-api.ap-southeast-2.amazonaws.com:443
       ssl
       verify none
       sni str(xxxxx.execute-api.ap-southeast-2.amazonaws.com)

You have to use the str() string sample fetch here, because the sni server keyword expects a sample fetch expression (for cases where you wanted to use the incoming request's SNI, for example).

The problem in the question on the forum was not actually related to SNI -- that part of the configuration was correct. The problem there was that they failed to do what you already did correctly -- http-request set-header host ... so that CloudFront sees the correct Host: header.


Note also the advice on the forum that this is a "very bad idea" seems distinctly misplaced.


¹ 400 CloudFront -- in some cases -- returns "Bad Request" in the body but the actual HTTP status code is 403 which corresponds to Forbidden.