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

Как заставить Google Cloud Load Balancer уважать полученный X-Forwarded-Proto?

В моей структуре приложения используются GKE и CloudFlare. Выглядит это так:

CloudFlare -> GKE -> Ingress -> My app running nginx

Я использую гибкий SSL в CloudFlare, поэтому только соединение между пользователем и CloudFlare использует HTTPS, все остальные используют HTTP. Я знаю, что CloudFlare устанавливает X-Forwarded-Proto к https в этой ситуации, но когда я вижу заголовки, которые получает мое приложение nginx, оно получает X-Forwarded-Proto: http.

Я почти уверен, что это происходит где-то между балансировщиком нагрузки GKE и Ingress, поскольку я вижу, что CF-Visitor: {"scheme": "https"} заголовок, настроенный CloudFlare, установлен на HTTPS. Насколько я понимаю, это означает, что CloudFlare установил X-Forwarded-Proto к https, но по ходу дела он был перезаписан.

К сожалению, мне не удалось получить журналы заголовков из GKE Load Balancer (похоже, они не регистрируют X-Forwarded-* заголовки вообще), поэтому я не могу на 100% подтвердить, что CloudFlare действительно устанавливает заголовки, но я был бы очень удивлен, если это не так.

Если это правда, Google Cloud перезаписывает X-Forwarded-Proto заголовок с http. Как мне этого избежать?

Редактировать: Я настроил вход nginx вместо gce после https://cloud.google.com/community/tutorials/nginx-ingress-gke, а X-Forwarded-Proto установлен на https как и ожидалось. Это еще один сигнал, что это gce входной контроллер, который перезаписывает X-Forwarded-Proto заголовок.

Как описано в Эта статья Cloudflare добавляет заголовок X-Forwarded-Proto, который может быть HTTP или HTTPS в зависимости от протокола, который пользователь использовал для посещения сайта. Если вы считаете, что значение X-Forwarded-Proto должно быть сохранено, но было изменено GCLB, я бы рекомендовал открыть для этого запрос функции на Система отслеживания проблем Google.

Вы можете создать промежуточное ПО:

# frozen_string_literal: true

require 'json'

class CloudflareProxy
  def initialize(app)
    @app = app
  end

  def call(env)
    return @app.call(env) unless env['HTTP_CF_VISITOR']

    env['HTTP_X_FORWARDED_PROTO'] = JSON.parse(env['HTTP_CF_VISITOR'])['scheme']
    @app.call(env)
  end
end

Использовать в config/application.rb:

config.middleware.use CloudflareProxy

Ссылка на CF-Visitor заголовок:

https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-

CF-Visitor

Объект JSON, содержащий только один ключ, называемый схемой. Значение идентично значению X-Forwarded-Proto (HTTP или HTTPS). CF-Visitor актуален только при использовании гибкого SSL.