Назад | Перейти на главную страницу

HAProxy как обратный прокси для AWS API Gateway

Как следует из названия, у меня есть конечная точка 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.