Как спрятать ASP.NET Core приложение за Reverse Proxy так, чтобы не было больно?

ASP.NET Core Docker Reverse Proxy

Когда вы разрабатываете web-приложение, заранее зная, что оно будет находиться за балансировщиком нагрузки, следует учитывать ряд особенностей. Примером может служить запуск сайта в Docker кластере (например Swarm).

Что меняется?

Если ваше приложение попробует определить:

  • имя хоста,
  • протокол: http или https,
  • IP адрес клиента,

то получит совсем не то, что надо. Причиной является то, что балансировщик нагрузки, по сути, на каждый запрос клиента делает аналогичный запрос к узлу кластера. Именно в этот момент интересующие нас параметры и меняются.

Как это исправить?

Чтобы этого избежать, необходимо дополнительно настроить балансировщик нагрузки и дописать немного кода.

Балансировщик нагрузки должен установить HTTP заголовки:

  • Host
  • X-Forwarded-Proto - протокол
  • X-Forwarded-For - IP адрес клиента

Приложение, в свою очередь, должно правильно обработать последние 2 заголовка. Для ASP.NET Core можно использовать следующий код:

public class Startup
{
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        app.Use(async (context, next) =>
        {
            const string XForwardedProto = "X-Forwarded-Proto";
            if (context.Request.Headers.TryGetValue(XForwardedProto, out StringValues proto))
            {
                context.Request.Protocol = proto;
                context.Request.Scheme = proto;
            }

            await next();
        });
    }
}

Этот код решает первые 2 проблемы глобально. Кроме того, он не требует изменения кода, который определяет текущий хост и протокол. Что касается определения IP адреса клиента, то получить можно аналогичный образом.