HAProxy as reverse proxy for AWS API Gateway
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
.