Как следует из названия, у меня есть конечная точка AWS API Gateway, которую я хочу разместить за HAProxy.
Это моя текущая конфигурация HAProxy
defaults
mode http
log global
option httplog
option dontlognull
option http-server-close
option forwardfor except 127.0.0.0/8
option redispatch
retries 3
timeout http-request 10s
timeout queue 1m
timeout connect 10s
timeout client 1m
timeout server 1m
timeout http-keep-alive 10s
timeout check 10s
maxconn 3000
listen http
bind 127.0.0.1:8080
maxconn 18000
acl api_gateway path_beg /api-gateway
use_backend api-gateway-backend if api-gateway
backend api-gateway-backend
http-request set-header Host xxxxx.execute-api.ap-southeast-2.amazonaws.com
server api-gateway xxxxx.execute-api.ap-southeast-2.amazonaws.com:443
Когда я попал в /api-gateway
конечная точка на моем HAProxy, я получаю 400 Bad Request
. Увидеть ниже:
Я попытался изменить серверную часть, чтобы использовать это server api-gateway xxxxx.execute-api.ap-southeast-2.amazonaws.com:443 ssl verify none
но я получил 503 Service Unavailable
вместо.
Я думаю, это может быть связано с конфигурацией SSL SNI, которую мне нужно включить на HAProxy, см. Это сообщение на форуме https://forums.aws.amazon.com/thread.jspa?threadID=240197
Если вы не используете HTTPS, CloudFront вернет 400 Bad Request
¹ ошибка, потому что API Gateway не поддерживает HTTP.
Добавление ssl verify none
включает HTTPS в серверной части, CloudFront просто закрывает соединение, в результате чего HAProxy регистрирует состояние сеанса при отключении так как SC--
и вернуть местный 503 Service Unavailable
ошибка.
Решение действительно отправляет идентификацию имени сервера (SNI). В противном случае интерфейс CloudFront не знает, какой SSL-сертификат вам предложить - общий *.cloudfront.net
сертификат с подстановочными знаками или для *.execute-api.ap-southeast-2.amazonaws.com
или одна из сотен тысяч других возможностей. Вот что делает в данном случае SNI - он сообщает серверу, к какому имени вы подключаетесь.
Решение - это одна строка, показанная для наглядности в виде нескольких строк:
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)
Вы должны использовать str()
выборка образца строки здесь, потому что sni
ключевое слово сервера ожидает образец выражения выборки (например, для случаев, когда вы хотите использовать SNI входящего запроса).
Проблема в вопросе на форуме на самом деле не была связана с SNI - эта часть конфигурации была правильной. Проблема заключалась в том, что они не смогли сделать то, что вы уже сделали правильно - http-request set-header host ...
чтобы CloudFront увидел правильный Host:
заголовок.
Обратите внимание на то, что совет на форуме о том, что это «очень плохая идея», кажется явно неуместным.
¹ 400 CloudFront - в некоторых случаях - возвращает в теле сообщения "Bad Request", но фактический код состояния HTTP - 403
что соответствует Forbidden
.
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)
Для тех, кто в будущем: вы можете удалить это : 443, поскольку подразумевается как минимум 1.8, подразумевается ssl, и если вы используете ключевые слова SSL и / или SNI с определенным портом, вы получите сообщения об ошибках, которые могут привести вас к повторной компиляции.
Я получил:
неизвестные ключевые слова для ssl и то же самое для sni, и я не мог понять почему, пока не перечитал: https://cbonte.github.io/haproxy-dconv/1.8/configuration.html#5.2 ближе.
Сообщение об ошибке заставляет вас поверить, что haproxy не был скомпилирован с поддержкой SSL, но haproxy -vv покажет вам, есть ли это.
Чтобы быть справедливым, если вы не компилировали с USE_OPENSSL = 1 и / или имеете нестандартный дистрибутив, используйте SSL_INC = / usr / include / openssl / (заменить путь) SSL_LIB = / usr / lib64 / openssl (заменить путь)
если haproxy -vv показывает, что не создан для ssl.