Configuración de ASP.NET Core para trabajar con servidores proxy y equilibradores de cargaConfigure ASP.NET Core to work with proxy servers and load balancers

Por Chris RossBy Chris Ross

En la configuración recomendada de ASP.NET Core, la aplicación se hospeda mediante IIS/módulo ASP.NET Core, Nginx o Apache.In the recommended configuration for ASP.NET Core, the app is hosted using IIS/ASP.NET Core Module, Nginx, or Apache. Los servidores proxy, los equilibradores de carga y otros dispositivos de red con frecuencia ocultan información sobre la solicitud antes de que llegue a la aplicación:Proxy servers, load balancers, and other network appliances often obscure information about the request before it reaches the app:

  • Cuando las solicitudes HTTPS se redirigen mediante proxy a través de HTTP, el esquema original (HTTPS) se pierde y se debe reenviar en un encabezado.When HTTPS requests are proxied over HTTP, the original scheme (HTTPS) is lost and must be forwarded in a header.
  • Como una aplicación recibe una solicitud del proxy y no desde su verdadero origen en Internet o la red corporativa, la dirección IP del cliente de origen también se debe reenviar en el encabezado.Because an app receives a request from the proxy and not its true source on the Internet or corporate network, the originating client IP address must also be forwarded in a header.

Esta información puede ser importante en el procesamiento de las solicitudes, por ejemplo, en los redireccionamientos, la autenticación, la generación de vínculos, la evaluación de directivas y la geolocalización del cliente.This information may be important in request processing, for example in redirects, authentication, link generation, policy evaluation, and client geolocation.

Encabezados reenviadosForwarded headers

Por costumbre, los servidores proxy reenvían la información en encabezados HTTP.By convention, proxies forward information in HTTP headers.

HeaderHeader DescripciónDescription
X-Forwarded-ForX-Forwarded-For Contiene información sobre el cliente que inició la solicitud y los servidores proxy posteriores en una cadena de servidores proxy.Holds information about the client that initiated the request and subsequent proxies in a chain of proxies. Este parámetro puede contener direcciones IP (y, opcionalmente, números de puerto).This parameter may contain IP addresses (and, optionally, port numbers). En una cadena de servidores proxy, el primer parámetro indica al cliente dónde se realizó primero la solicitud.In a chain of proxy servers, the first parameter indicates the client where the request was first made. Le siguen los identificadores de proxy posteriores.Subsequent proxy identifiers follow. El último proxy en la cadena no se encuentra en la lista de parámetros.The last proxy in the chain isn't in the list of parameters. La última dirección IP del proxy y, opcionalmente, un número de puerto, está disponible como la dirección IP remota en la capa de transporte.The last proxy's IP address, and optionally a port number, are available as the remote IP address at the transport layer.
X-Forwarded-ProtoX-Forwarded-Proto El valor del esquema de origen (HTTP/HTTPS).The value of the originating scheme (HTTP/HTTPS). El valor también puede ser una lista de esquemas si la solicitud ha pasado por varios servidores proxy.The value may also be a list of schemes if the request has traversed multiple proxies.
X-Forwarded-HostX-Forwarded-Host El valor original del campo de encabezado de host.The original value of the Host header field. Por lo general, los servidores proxy no modifican el encabezado de host.Usually, proxies don't modify the Host header. Consulte Microsoft Security Advisory CVE-2018-0787 para información sobre una vulnerabilidad de elevación de privilegios que afecta a sistemas donde el proxy no valida ni restringe los encabezados de host a valores buenos conocidos.See Microsoft Security Advisory CVE-2018-0787 for information on an elevation-of-privileges vulnerability that affects systems where the proxy doesn't validate or restrict Host headers to known good values.

El Middleware de encabezados reenviados, del paquete Microsoft.AspNetCore.HttpOverrides, lee estos encabezados y rellena los campos asociados en HttpContext.The Forwarded Headers Middleware, from the Microsoft.AspNetCore.HttpOverrides package, reads these headers and fills in the associated fields on HttpContext.

El middleware realiza las siguientes actualizaciones:The middleware updates:

Se pueden configurar los valores predeterminados del Middleware de encabezados reenviados.Forwarded Headers Middleware default settings can be configured. Estos valores son:The default settings are:

  • Solo hay un proxy entre la aplicación y el origen de las solicitudes.There is only one proxy between the app and the source of the requests.
  • Solo las direcciones de bucle invertido se configuran para servidores proxy conocidos y redes conocidas.Only loopback addresses are configured for known proxies and known networks.
  • Los encabezados reenviados se denominan X-Forwarded-For y X-Forwarded-Proto.The forwarded headers are named X-Forwarded-For and X-Forwarded-Proto.

No todos los dispositivos de red agregan los encabezados X-Forwarded-For y X-Forwarded-Proto sin configuración adicional.Not all network appliances add the X-Forwarded-For and X-Forwarded-Proto headers without additional configuration. Consulte las instrucciones del fabricante de su dispositivo si las solicitudes redirigidas mediante proxy no contienen estos encabezados cuando llegan a la aplicación.Consult your appliance manufacturer's guidance if proxied requests don't contain these headers when they reach the app. Si el dispositivo usa nombres de encabezado distintos a X-Forwarded-For y X-Forwarded-Proto, establezca las opciones ForwardedForHeaderName y ForwardedProtoHeaderName para que coincidan con los nombres de encabezado empleados por el dispositivo.If the appliance uses different header names than X-Forwarded-For and X-Forwarded-Proto, set the ForwardedForHeaderName and ForwardedProtoHeaderName options to match the header names used by the appliance. Para obtener más información, vea Opciones del Middleware de encabezados reenviados y Configuración de un proxy que usa otros nombres de encabezado.For more information, see Forwarded Headers Middleware options and Configuration for a proxy that uses different header names.

IIS o IIS Express y el módulo ASP.NET CoreIIS/IIS Express and ASP.NET Core Module

El Middleware de encabezados reenviados se habilita de forma predeterminada mediante el Middleware de integración con IIS cuando la aplicación se hospeda fuera de proceso detrás de IIS y del módulo ASP.NET Core.Forwarded Headers Middleware is enabled by default by IIS Integration Middleware when the app is hosted out-of-process behind IIS and the ASP.NET Core Module. El Middleware de encabezados reenviados está activado para ejecutarse primero en la canalización de middleware con una configuración restringida específica del módulo ASP.NET Core debido a problemas de confianza con los encabezados reenviados (por ejemplo, suplantación de IP).Forwarded Headers Middleware is activated to run first in the middleware pipeline with a restricted configuration specific to the ASP.NET Core Module due to trust concerns with forwarded headers (for example, IP spoofing). El middleware está configurado para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto y está restringido a un único proxy localhost.The middleware is configured to forward the X-Forwarded-For and X-Forwarded-Proto headers and is restricted to a single localhost proxy. Si se requiere configuración adicional, consulte la sección Opciones del Middleware de encabezados reenviados.If additional configuration is required, see the Forwarded Headers Middleware options.

Otros escenarios de servidor proxy y equilibrador de cargaOther proxy server and load balancer scenarios

Al margen del uso de la integración con IIS al hospedar fuera de proceso, el Middleware de encabezados reenviados no está habilitado de forma predeterminada.Outside of using IIS Integration when hosting out-of-process, Forwarded Headers Middleware isn't enabled by default. El middleware de encabezados reenviados debe estar habilitado en una aplicación para procesar los encabezados reenviados con UseForwardedHeaders.Forwarded Headers Middleware must be enabled for an app to process forwarded headers with UseForwardedHeaders. Después de habilitar el middleware, si no se especifica ForwardedHeadersOptions para él, el valor predeterminado ForwardedHeadersOptions.ForwardedHeaders es ForwardedHeaders.None.After enabling the middleware if no ForwardedHeadersOptions are specified to the middleware, the default ForwardedHeadersOptions.ForwardedHeaders are ForwardedHeaders.None.

Configure el middleware con ForwardedHeadersOptions para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto en Startup.ConfigureServices.Configure the middleware with ForwardedHeadersOptions to forward the X-Forwarded-For and X-Forwarded-Proto headers in Startup.ConfigureServices. Invoque el método UseForwardedHeaders en Startup.Configure antes de llamar a otro middleware:Invoke the UseForwardedHeaders method in Startup.Configure before calling other middleware:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = 
            ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseForwardedHeaders();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();
    // In ASP.NET Core 1.x, replace the following line with: app.UseIdentity();
    app.UseAuthentication();
    app.UseMvc();
}

Nota

Si no se especifica ningún ForwardedHeadersOptions en Startup.ConfigureServices o directamente en el método de extensión con UseForwardedHeaders, los encabezados predeterminados para reenviar son ForwardedHeaders.None.If no ForwardedHeadersOptions are specified in Startup.ConfigureServices or directly to the extension method with UseForwardedHeaders, the default headers to forward are ForwardedHeaders.None. La propiedad ForwardedHeaders debe estar configurada con los encabezados que se van a reenviar.The ForwardedHeaders property must be configured with the headers to forward.

Configuración de NginxNginx configuration

Para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto, vea Hospedar ASP.NET Core en Linux con Nginx.To forward the X-Forwarded-For and X-Forwarded-Proto headers, see Hospedar ASP.NET Core en Linux con Nginx. Para obtener más información, consulte NGINX: Using the Forwarded header (NGINX: uso del encabezado Forwarded).For more information, see NGINX: Using the Forwarded header.

Configuración de ApacheApache configuration

X-Forwarded-For se agrega automáticamente. Consulte Apache Module mod_proxy: Reverse Proxy Request Headers (Módulo de Apache mod_proxy: Encabezados de solicitud de proxy inverso).X-Forwarded-For is added automatically (see Apache Module mod_proxy: Reverse Proxy Request Headers). Para obtener información sobre cómo reenviar el encabezado X-Forwarded-Proto, vea Hospedar ASP.NET Core en Linux con Apache.For information on how to forward the X-Forwarded-Proto header, see Hospedar ASP.NET Core en Linux con Apache.

Opciones del Middleware de encabezados reenviadosForwarded Headers Middleware options

ForwardedHeadersOptions controla el comportamiento del middleware de encabezados reenviados.ForwardedHeadersOptions control the behavior of the Forwarded Headers Middleware. En el ejemplo siguiente se cambian los valores predeterminados:The following example changes the default values:

  • Limite el número de entradas de los encabezados reenviados a 2.Limit the number of entries in the forwarded headers to 2.
  • Agregue una dirección de proxy conocida de 127.0.10.1.Add a known proxy address of 127.0.10.1.
  • Cambie el nombre del encabezado reenviado del valor predeterminado X-Forwarded-For a X-Forwarded-For-My-Custom-Header-Name.Change the forwarded header name from the default X-Forwarded-For to X-Forwarded-For-My-Custom-Header-Name.
services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardLimit = 2;
    options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
    options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
OpciónOption DescripciónDescription
AllowedHosts Restringe los hosts por el encabezado X-Forwarded-Host a los valores proporcionados.Restricts hosts by the X-Forwarded-Host header to the values provided.
  • Los valores se comparan mediante ordinal-ignore-case.Values are compared using ordinal-ignore-case.
  • Se deben excluir los números de puerto.Port numbers must be excluded.
  • Si la lista está vacía, se permiten todos los hosts.If the list is empty, all hosts are allowed.
  • Un carácter comodín de nivel superior * permite que todos los hosts que no están vacíos.A top-level wildcard * allows all non-empty hosts.
  • Se permiten caracteres comodín de subdominio, pero no coinciden con el dominio raíz.Subdomain wildcards are permitted but don't match the root domain. Por ejemplo, *.contoso.com coincide con el subdominio foo.contoso.com pero no con el dominio raíz contoso.com.For example, *.contoso.com matches the subdomain foo.contoso.com but not the root domain contoso.com.
  • Se permiten nombres de host Unicode, pero se convierten en Punycode para buscar la coincidencia.Unicode host names are allowed but are converted to Punycode for matching.
  • Las direcciones IPv6 deben incluir corchetes de enlace y estar en formato convencional (por ejemplo, [ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]).IPv6 addresses must include bounding brackets and be in conventional form (for example, [ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]). Las direcciones IPv6 no usan mayúsculas y minúsculas de forma especial para buscar la igualdad lógica entre diferentes formatos, y no se realiza ninguna canonización.IPv6 addresses aren't special-cased to check for logical equality between different formats, and no canonicalization is performed.
  • Si no se restringen los hosts permitidos, un atacante podría suplantar los vínculos generados por el servicio.Failure to restrict the allowed hosts may allow an attacker to spoof links generated by the service.
El valor predeterminado es un IList<string> vacío.The default value is an empty IList<string>.
ForwardedForHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XForwardedForHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XForwardedForHeaderName. Esta opción se usa cuando el reenviador o proxy no emplea el encabezado X-Forwarded-For sino algún otro para reenviar la información.This option is used when the proxy/forwarder doesn't use the X-Forwarded-For header but uses some other header to forward the information.

De manera predeterminada, es X-Forwarded-For.The default is X-Forwarded-For.
ForwardedHeaders Identifica qué reenviadores se deben procesar.Identifies which forwarders should be processed. Consulte ForwardedHeaders Enum para obtener la lista de campos que se aplican.See the ForwardedHeaders Enum for the list of fields that apply. Los valores típicos que se asignan a esta propiedad son ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.Typical values assigned to this property are ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.

El valor predeterminado es ForwardedHeaders.None.The default value is ForwardedHeaders.None.
ForwardedHostHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XForwardedHostHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XForwardedHostHeaderName. Esta opción se usa cuando el reenviador o proxy no emplea el encabezado X-Forwarded-Host sino algún otro para reenviar la información.This option is used when the proxy/forwarder doesn't use the X-Forwarded-Host header but uses some other header to forward the information.

De manera predeterminada, es X-Forwarded-Host.The default is X-Forwarded-Host.
ForwardedProtoHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XForwardedProtoHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XForwardedProtoHeaderName. Esta opción se usa cuando el reenviador o proxy no emplea el encabezado X-Forwarded-Proto sino algún otro para reenviar la información.This option is used when the proxy/forwarder doesn't use the X-Forwarded-Proto header but uses some other header to forward the information.

De manera predeterminada, es X-Forwarded-Proto.The default is X-Forwarded-Proto.
ForwardLimit Limita el número de entradas en los encabezados que se procesan.Limits the number of entries in the headers that are processed. Establézcalo en null para deshabilitar el límite, pero esto solo se debe realizar si están configurados KnownProxies o KnownNetworks.Set to null to disable the limit, but this should only be done if KnownProxies or KnownNetworks are configured. Establecerlo en un valor que no sea null es una medida de precaución (no una garantía) para protegerse contra los proxies mal configurados y las peticiones maliciosas que llegan desde los canales laterales de la red.Setting a non-null value is a precaution (but not a guarantee) to guard against misconfigured proxies and malicious requests arriving from side-channels on the network.

El middleware de encabezados reenviados procesa los encabezados en orden inverso, de derecha a izquierda.Forwarded Headers Middleware processes headers in reverse order from right to left. Si se usa el valor predeterminado (1), solo se procesa el valor más a la derecha de los encabezados, a menos que se aumente el valor de ForwardLimit.If the default value (1) is used, only the rightmost value from the headers is processed unless the value of ForwardLimit is increased.

De manera predeterminada, es 1.The default is 1.
KnownNetworks Intervalos de direcciones de redes conocidas de los que se aceptan encabezados reenviados.Address ranges of known networks to accept forwarded headers from. Proporcione intervalos de direcciones IP mediante la notación de Enrutamiento de interdominios sin clases (CIDR).Provide IP ranges using Classless Interdomain Routing (CIDR) notation.

Si el servidor usa sockets en modo dual, las direcciones IPv4 se suministran en formato IPv6 (por ejemplo, 10.0.0.1 en IPv4 se representa en IPv6 como ::ffff:10.0.0.1).If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format (for example, 10.0.0.1 in IPv4 represented in IPv6 as ::ffff:10.0.0.1). Consulte IPAddress.MapToIPv6.See IPAddress.MapToIPv6. Para determinar si este formato es necesario, examine HttpContext.Connection.RemoteIpAddress.Determine if this format is required by looking at the HttpContext.Connection.RemoteIpAddress. Para más información, consulte la sección Configuración de una dirección IPv4 representada como una dirección IPv6.For more information, see the Configuration for an IPv4 address represented as an IPv6 address section.

El valor predeterminado es un IList<IPNetwork> que contiene una única entrada para IPAddress.Loopback.The default is an IList<IPNetwork> containing a single entry for IPAddress.Loopback.
KnownProxies Direcciones de servidores proxy conocidos de los que se aceptan encabezados reenviados.Addresses of known proxies to accept forwarded headers from. Use KnownProxies para especificar las coincidencias exactas de direcciones IP.Use KnownProxies to specify exact IP address matches.

Si el servidor usa sockets en modo dual, las direcciones IPv4 se suministran en formato IPv6 (por ejemplo, 10.0.0.1 en IPv4 se representa en IPv6 como ::ffff:10.0.0.1).If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format (for example, 10.0.0.1 in IPv4 represented in IPv6 as ::ffff:10.0.0.1). Consulte IPAddress.MapToIPv6.See IPAddress.MapToIPv6. Para determinar si este formato es necesario, examine HttpContext.Connection.RemoteIpAddress.Determine if this format is required by looking at the HttpContext.Connection.RemoteIpAddress. Para más información, consulte la sección Configuración de una dirección IPv4 representada como una dirección IPv6.For more information, see the Configuration for an IPv4 address represented as an IPv6 address section.

El valor predeterminado es un IList<IPAddress> que contiene una única entrada para IPAddress.IPv6Loopback.The default is an IList<IPAddress> containing a single entry for IPAddress.IPv6Loopback.
OriginalForHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XOriginalForHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XOriginalForHeaderName.

De manera predeterminada, es X-Original-For.The default is X-Original-For.
OriginalHostHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XOriginalForHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XOriginalHostHeaderName.

De manera predeterminada, es X-Original-Host.The default is X-Original-Host.
OriginalProtoHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XOriginalProtoHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XOriginalProtoHeaderName.

De manera predeterminada, es X-Original-Proto.The default is X-Original-Proto.
RequireHeaderSymmetry Requiere que el número de valores de encabezado esté sincronizado entre los valores ForwardedHeadersOptions.ForwardedHeaders que se van a procesar.Require the number of header values to be in sync between the ForwardedHeadersOptions.ForwardedHeaders being processed.

El valor predeterminado en ASP.NET Core 1.x es true.The default in ASP.NET Core 1.x is true. El valor predeterminado en ASP.NET Core 2.0 o posterior es false.The default in ASP.NET Core 2.0 or later is false.

Escenarios y casos de usoScenarios and use cases

Cuando no es posible agregar encabezados reenviados y todas las solicitudes son segurasWhen it isn't possible to add forwarded headers and all requests are secure

En algunos casos, puede que no sea posible agregar encabezados reenviados a las solicitudes redirigidas mediante proxy a la aplicación.In some cases, it might not be possible to add forwarded headers to the requests proxied to the app. Si el proxy está forzando a que todas las solicitudes externas públicas sean HTTPS, el esquema se puede establecer manualmente en Startup.Configure antes de usar cualquier tipo de middleware:If the proxy is enforcing that all public external requests are HTTPS, the scheme can be manually set in Startup.Configure before using any type of middleware:

app.Use((context, next) =>
{
    context.Request.Scheme = "https";
    return next();
});

Este código puede deshabilitarse con una variable de entorno u otro valor de configuración en un entorno de desarrollo o ensayo.This code can be disabled with an environment variable or other configuration setting in a development or staging environment.

Tratar con la ruta de acceso base y los servidores proxy que cambian la ruta de acceso de la solicitudDeal with path base and proxies that change the request path

Algunos servidores proxy pasan la ruta de acceso sin cambios pero con una ruta de acceso base de aplicación que se debe quitar para que el enrutamiento funcione correctamente.Some proxies pass the path intact but with an app base path that should be removed so that routing works properly. El middleware UsePathBaseExtensions.UsePathBase divide la ruta de acceso en HttpRequest.Path y la ruta de acceso base de aplicación en HttpRequest.PathBase.UsePathBaseExtensions.UsePathBase middleware splits the path into HttpRequest.Path and the app base path into HttpRequest.PathBase.

Si /foo es la ruta de acceso base de aplicación para una ruta de acceso de proxy que se pasa como /foo/api/1, el middleware establece Request.PathBase en /foo y Request.Path en /api/1 con el siguiente comando:If /foo is the app base path for a proxy path passed as /foo/api/1, the middleware sets Request.PathBase to /foo and Request.Path to /api/1 with the following command:

app.UsePathBase("/foo");

La ruta de acceso base y la ruta de acceso original se vuelven a aplicar cuando se llama de nuevo al middleware en orden inverso.The original path and path base are reapplied when the middleware is called again in reverse. Para obtener más información sobre el procesamiento de pedidos del middleware, vea Middleware de ASP.NET Core.For more information on middleware order processing, see Middleware de ASP.NET Core.

Si el proxy recorta la ruta de acceso (por ejemplo, el reenvío /foo/api/1 a /api/1), corrija los redireccionamientos y los vínculos mediante el establecimiento de la propiedad PathBase de la solicitud:If the proxy trims the path (for example, forwarding /foo/api/1 to /api/1), fix redirects and links by setting the request's PathBase property:

app.Use((context, next) =>
{
    context.Request.PathBase = new PathString("/foo");
    return next();
});

Si el proxy va a agregar datos de ruta de acceso, descarte parte de esta ruta para corregir los redireccionamientos y los vínculos; para ello, use StartsWithSegments y asígnelo a la propiedad Path:If the proxy is adding path data, discard part of the path to fix redirects and links by using StartsWithSegments and assigning to the Path property:

app.Use((context, next) =>
{
    if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
    {
        context.Request.Path = remainder;
    }

    return next();
});

Configuración de un proxy que usa otros nombres de encabezadoConfiguration for a proxy that uses different header names

Si el proxy no usa los encabezados denominados X-Forwarded-For y X-Forwarded-Proto para reenviar el puerto o la dirección de proxy y originar información de esquema, establezca las opciones ForwardedForHeaderName y ForwardedProtoHeaderName de modo que coincidan con los nombres de encabezado empleados por el proxy:If the proxy doesn't use headers named X-Forwarded-For and X-Forwarded-Proto to forward the proxy address/port and originating scheme information, set the ForwardedForHeaderName and ForwardedProtoHeaderName options to match the header names used by the proxy:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedForHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-For_Header";
    options.ForwardedProtoHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-Proto_Header";
});

Configuración de una dirección IPv4 representada como una dirección IPv6Configuration for an IPv4 address represented as an IPv6 address

Si el servidor usa sockets en modo dual, las direcciones IPv4 se suministran en formato IPv6 (por ejemplo, 10.0.0.1 en IPv4 se representa en IPv6 como ::ffff:10.0.0.1 o ::ffff:a00:1).If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format (for example, 10.0.0.1 in IPv4 represented in IPv6 as ::ffff:10.0.0.1 or ::ffff:a00:1). Consulte IPAddress.MapToIPv6.See IPAddress.MapToIPv6. Para determinar si este formato es necesario, examine HttpContext.Connection.RemoteIpAddress.Determine if this format is required by looking at the HttpContext.Connection.RemoteIpAddress.

En el ejemplo siguiente, se agrega una dirección de red que proporciona encabezados reenviados a la lista KnownNetworks en formato IPv6.In the following example, a network address that supplies forwarded headers is added to the KnownNetworks list in IPv6 format.

Dirección IPv4: 10.11.12.1/8IPv4 address: 10.11.12.1/8

Dirección IPv6 convertida: ::ffff:10.11.12.1Converted IPv6 address: ::ffff:10.11.12.1
Longitud de prefijo convertida: 104Converted prefix length: 104

También puede proporcionar la dirección en formato hexadecimal (10.11.12.1 se representa en IPv6 como ::ffff:0a0b:0c01).You can also supply the address in hexadecimal format (10.11.12.1 represented in IPv6 as ::ffff:0a0b:0c01). Al convertir una dirección IPv4 en IPv6, agregue 96 a la longitud de prefijo de CIDR (8 en el ejemplo) para tener en cuenta el prefijo de IPv6 ::ffff: adicional (8 + 96 = 104).When converting an IPv4 address to IPv6, add 96 to the CIDR Prefix Length (8 in the example) to account for the additional ::ffff: IPv6 prefix (8 + 96 = 104).

// To access IPNetwork and IPAddress, add the following namespaces:
// using using System.Net;
// using Microsoft.AspNetCore.HttpOverrides;
services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders =
        ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    options.KnownNetworks.Add(new IPNetwork(
        IPAddress.Parse("::ffff:10.11.12.1"), 104));
});

Reenvío del esquema para servidores proxy inversos Linux y que no son de IISForward the scheme for Linux and non-IIS reverse proxies

Las aplicaciones que llaman a los métodos UseHttpsRedirection y UseHsts incluyen un sitio en un bucle infinito si se implementan en una instancia de Azure App Service de Linux, una máquina virtual Linux de Azure, o bien detrás de cualquier otro servidor proxy inverso, además de IIS.Apps that call UseHttpsRedirection and UseHsts put a site into an infinite loop if deployed to an Azure Linux App Service, Azure Linux virtual machine (VM), or behind any other reverse proxy besides IIS. El servidor proxy inverso termina TLS y Kestrel no es consciente del esquema de solicitud correcto.TLS is terminated by the reverse proxy, and Kestrel isn't made aware of the correct request scheme. En esta configuración también se produce un error de OAuth y OIDC, ya que generan redirecciones incorrectas.OAuth and OIDC also fail in this configuration because they generate incorrect redirects. UseIISIntegration agrega y configura middleware de encabezados reenviados cuando se ejecuta detrás de IIS, pero no hay ninguna configuración automática coincidente para Linux (integración de Apache o Nginx).UseIISIntegration adds and configures Forwarded Headers Middleware when running behind IIS, but there's no matching automatic configuration for Linux (Apache or Nginx integration).

Para reenviar el esquema desde el servidor proxy en escenarios que no sean de IIS, agregue y configure Middleware de encabezados reenviados.To forward the scheme from the proxy in non-IIS scenarios, add and configure Forwarded Headers Middleware. En Startup.ConfigureServices, use el código siguiente:In Startup.ConfigureServices, use the following code:

// using Microsoft.AspNetCore.HttpOverrides;

if (string.Equals(
    Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"), 
    "true", StringComparison.OrdinalIgnoreCase))
{
    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | 
            ForwardedHeaders.XForwardedProto;
        // Only loopback proxies are allowed by default.
        // Clear that restriction because forwarders are enabled by explicit 
        // configuration.
        options.KnownNetworks.Clear();
        options.KnownProxies.Clear();
    });
}

Reenvío de certificadosCertificate forwarding

AzureAzure

Para configurar Azure App Service para el reenvío de certificados, consulte Configuración de la autenticación mutua de TLS en Azure App Service.To configure Azure App Service for certificate forwarding, see Configure TLS mutual authentication for Azure App Service. La guía siguiente se aplica a la configuración de la aplicación de ASP.NET Core.The following guidance pertains to configuring the ASP.NET Core app.

En Startup.Configure, agregue el código siguiente antes de llamar a app.UseAuthentication();:In Startup.Configure, add the following code before the call to app.UseAuthentication();:

app.UseCertificateForwarding();

Configure el middleware de reenvío de certificados para especificar el nombre de encabezado que Azure usa.Configure Certificate Forwarding Middleware to specify the header name that Azure uses. En Startup.ConfigureServices, agregue el código siguiente para configurar el encabezado desde el que el middleware crea un certificado:In Startup.ConfigureServices, add the following code to configure the header from which the middleware builds a certificate:

services.AddCertificateForwarding(options =>
    options.CertificateHeader = "X-ARR-ClientCert");

Otros servidores proxy webOther web proxies

Si se usa un proxy que no es IIS ni Enrutamiento de solicitud de aplicaciones de Azure App Service, configure el proxy para reenviar el certificado que recibió en un encabezado HTTP.If a proxy is used that isn't IIS or Azure App Service's Application Request Routing (ARR), configure the proxy to forward the certificate that it received in an HTTP header. En Startup.Configure, agregue el código siguiente antes de llamar a app.UseAuthentication();:In Startup.Configure, add the following code before the call to app.UseAuthentication();:

app.UseCertificateForwarding();

Configure el middleware de reenvío de certificados para especificar el nombre del encabezado.Configure the Certificate Forwarding Middleware to specify the header name. En Startup.ConfigureServices, agregue el código siguiente para configurar el encabezado desde el que el middleware crea un certificado:In Startup.ConfigureServices, add the following code to configure the header from which the middleware builds a certificate:

services.AddCertificateForwarding(options =>
    options.CertificateHeader = "YOUR_CERTIFICATE_HEADER_NAME");

Si el proxy no codifica en Base64 el certificado (como ocurre con Nginx), establezca la opción HeaderConverter.If the proxy isn't base64-encoding the certificate (as is the case with Nginx), set the HeaderConverter option. Considere el ejemplo siguiente de Startup.ConfigureServices:Consider the following example in Startup.ConfigureServices:

services.AddCertificateForwarding(options =>
{
    options.CertificateHeader = "YOUR_CUSTOM_HEADER_NAME";
    options.HeaderConverter = (headerValue) => 
    {
        var clientCertificate = 
           /* some conversion logic to create an X509Certificate2 */
        return clientCertificate;
    }
});

Solucionar problemasTroubleshoot

Cuando no se reenvíen los encabezados como estaba previsto, habilite el registro.When headers aren't forwarded as expected, enable logging. Si los registros no proporcionan suficiente información para solucionar el problema, enumere los encabezados de solicitud recibidos por el servidor.If the logs don't provide sufficient information to troubleshoot the problem, enumerate the request headers received by the server. Use middleware insertado para escribir encabezados de solicitud en la respuesta de una aplicación o para registrar los encabezados.Use inline middleware to write request headers to an app response or log the headers.

Para escribir los encabezados en la respuesta de la aplicación, coloque el siguiente middleware insertado terminal inmediatamente después de la llamada a UseForwardedHeaders en Startup.Configure:To write the headers to the app's response, place the following terminal inline middleware immediately after the call to UseForwardedHeaders in Startup.Configure:

app.Run(async (context) =>
{
    context.Response.ContentType = "text/plain";

    // Request method, scheme, and path
    await context.Response.WriteAsync(
        $"Request Method: {context.Request.Method}{Environment.NewLine}");
    await context.Response.WriteAsync(
        $"Request Scheme: {context.Request.Scheme}{Environment.NewLine}");
    await context.Response.WriteAsync(
        $"Request Path: {context.Request.Path}{Environment.NewLine}");

    // Headers
    await context.Response.WriteAsync($"Request Headers:{Environment.NewLine}");

    foreach (var header in context.Request.Headers)
    {
        await context.Response.WriteAsync($"{header.Key}: " +
            $"{header.Value}{Environment.NewLine}");
    }

    await context.Response.WriteAsync(Environment.NewLine);

    // Connection: RemoteIp
    await context.Response.WriteAsync(
        $"Request RemoteIp: {context.Connection.RemoteIpAddress}");
});

Puede escribir en registros en lugar de en el cuerpo de respuesta.You can write to logs instead of the response body. Así el sitio funcionará con normalidad durante la depuración.Writing to logs allows the site to function normally while debugging.

Para ello, siga estos pasos:To write logs rather than to the response body:

app.Use(async (context, next) =>
{
    // Request method, scheme, and path
    _logger.LogDebug("Request Method: {Method}", context.Request.Method);
    _logger.LogDebug("Request Scheme: {Scheme}", context.Request.Scheme);
    _logger.LogDebug("Request Path: {Path}", context.Request.Path);

    // Headers
    foreach (var header in context.Request.Headers)
    {
        _logger.LogDebug("Header: {Key}: {Value}", header.Key, header.Value);
    }

    // Connection: RemoteIp
    _logger.LogDebug("Request RemoteIp: {RemoteIpAddress}", 
        context.Connection.RemoteIpAddress);

    await next();
});

Si se procesa, los valores X-Forwarded-{For|Proto|Host} se trasladan a X-Original-{For|Proto|Host}.When processed, X-Forwarded-{For|Proto|Host} values are moved to X-Original-{For|Proto|Host}. Si hay varios valores en un encabezado determinado, el middleware de encabezados reenviados procesa los encabezados en orden inverso, de derecha a izquierda.If there are multiple values in a given header, Forwarded Headers Middleware processes headers in reverse order from right to left. El valor predeterminado de ForwardLimit es 1 (uno), por lo que solo el valor más a la derecha de los encabezados se procesa, a menos que se aumente el valor de ForwardLimit.The default ForwardLimit is 1 (one), so only the rightmost value from the headers is processed unless the value of ForwardLimit is increased.

La dirección IP remota original de la solicitud debe coincidir con una entrada de las listas KnownProxies o KnownNetworks antes de procesar los encabezados reenviados.The request's original remote IP must match an entry in the KnownProxies or KnownNetworks lists before forwarded headers are processed. Esto limita la suplantación de encabezados al no aceptarse reenviadores de servidores proxy que no son de confianza.This limits header spoofing by not accepting forwarders from untrusted proxies. Cuando se detecta un servidor proxy desconocido, el registro indica la dirección de dicho proxy:When an unknown proxy is detected, logging indicates the address of the proxy:

September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321

En el ejemplo anterior, 10.0.0.100 es un servidor proxy.In the preceding example, 10.0.0.100 is a proxy server. Si se trata de un servidor proxy de confianza, agregue la dirección IP del servidor a KnownProxies o agregue una red de confianza a KnownNetworks en Startup.ConfigureServices.If the server is a trusted proxy, add the server's IP address to KnownProxies (or add a trusted network to KnownNetworks) in Startup.ConfigureServices. Para más información, vea la sección Opciones del Middleware de encabezados reenviados.For more information, see the Forwarded Headers Middleware options section.

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

Importante

Admita solo las redes y los servidores proxy de confianza para reenviar encabezados.Only allow trusted proxies and networks to forward headers. De lo contrario, se pueden producir ataques de suplantación de IP.Otherwise, IP spoofing attacks are possible.

Recursos adicionalesAdditional resources

En la configuración recomendada de ASP.NET Core, la aplicación se hospeda mediante IIS/módulo ASP.NET Core, Nginx o Apache.In the recommended configuration for ASP.NET Core, the app is hosted using IIS/ASP.NET Core Module, Nginx, or Apache. Los servidores proxy, los equilibradores de carga y otros dispositivos de red con frecuencia ocultan información sobre la solicitud antes de que llegue a la aplicación:Proxy servers, load balancers, and other network appliances often obscure information about the request before it reaches the app:

  • Cuando las solicitudes HTTPS se redirigen mediante proxy a través de HTTP, el esquema original (HTTPS) se pierde y se debe reenviar en un encabezado.When HTTPS requests are proxied over HTTP, the original scheme (HTTPS) is lost and must be forwarded in a header.
  • Como una aplicación recibe una solicitud del proxy y no desde su verdadero origen en Internet o la red corporativa, la dirección IP del cliente de origen también se debe reenviar en el encabezado.Because an app receives a request from the proxy and not its true source on the Internet or corporate network, the originating client IP address must also be forwarded in a header.

Esta información puede ser importante en el procesamiento de las solicitudes, por ejemplo, en los redireccionamientos, la autenticación, la generación de vínculos, la evaluación de directivas y la geolocalización del cliente.This information may be important in request processing, for example in redirects, authentication, link generation, policy evaluation, and client geolocation.

Encabezados reenviadosForwarded headers

Por costumbre, los servidores proxy reenvían la información en encabezados HTTP.By convention, proxies forward information in HTTP headers.

HeaderHeader DescripciónDescription
X-Forwarded-ForX-Forwarded-For Contiene información sobre el cliente que inició la solicitud y los servidores proxy posteriores en una cadena de servidores proxy.Holds information about the client that initiated the request and subsequent proxies in a chain of proxies. Este parámetro puede contener direcciones IP (y, opcionalmente, números de puerto).This parameter may contain IP addresses (and, optionally, port numbers). En una cadena de servidores proxy, el primer parámetro indica al cliente dónde se realizó primero la solicitud.In a chain of proxy servers, the first parameter indicates the client where the request was first made. Le siguen los identificadores de proxy posteriores.Subsequent proxy identifiers follow. El último proxy en la cadena no se encuentra en la lista de parámetros.The last proxy in the chain isn't in the list of parameters. La última dirección IP del proxy y, opcionalmente, un número de puerto, está disponible como la dirección IP remota en la capa de transporte.The last proxy's IP address, and optionally a port number, are available as the remote IP address at the transport layer.
X-Forwarded-ProtoX-Forwarded-Proto El valor del esquema de origen (HTTP/HTTPS).The value of the originating scheme (HTTP/HTTPS). El valor también puede ser una lista de esquemas si la solicitud ha pasado por varios servidores proxy.The value may also be a list of schemes if the request has traversed multiple proxies.
X-Forwarded-HostX-Forwarded-Host El valor original del campo de encabezado de host.The original value of the Host header field. Por lo general, los servidores proxy no modifican el encabezado de host.Usually, proxies don't modify the Host header. Consulte Microsoft Security Advisory CVE-2018-0787 para información sobre una vulnerabilidad de elevación de privilegios que afecta a sistemas donde el proxy no valida ni restringe los encabezados de host a valores buenos conocidos.See Microsoft Security Advisory CVE-2018-0787 for information on an elevation-of-privileges vulnerability that affects systems where the proxy doesn't validate or restrict Host headers to known good values.

El Middleware de encabezados reenviados, del paquete Microsoft.AspNetCore.HttpOverrides, lee estos encabezados y rellena los campos asociados en HttpContext.The Forwarded Headers Middleware, from the Microsoft.AspNetCore.HttpOverrides package, reads these headers and fills in the associated fields on HttpContext.

El middleware realiza las siguientes actualizaciones:The middleware updates:

Se pueden configurar los valores predeterminados del Middleware de encabezados reenviados.Forwarded Headers Middleware default settings can be configured. Estos valores son:The default settings are:

  • Solo hay un proxy entre la aplicación y el origen de las solicitudes.There is only one proxy between the app and the source of the requests.
  • Solo las direcciones de bucle invertido se configuran para servidores proxy conocidos y redes conocidas.Only loopback addresses are configured for known proxies and known networks.
  • Los encabezados reenviados se denominan X-Forwarded-For y X-Forwarded-Proto.The forwarded headers are named X-Forwarded-For and X-Forwarded-Proto.

No todos los dispositivos de red agregan los encabezados X-Forwarded-For y X-Forwarded-Proto sin configuración adicional.Not all network appliances add the X-Forwarded-For and X-Forwarded-Proto headers without additional configuration. Consulte las instrucciones del fabricante de su dispositivo si las solicitudes redirigidas mediante proxy no contienen estos encabezados cuando llegan a la aplicación.Consult your appliance manufacturer's guidance if proxied requests don't contain these headers when they reach the app. Si el dispositivo usa nombres de encabezado distintos a X-Forwarded-For y X-Forwarded-Proto, establezca las opciones ForwardedForHeaderName y ForwardedProtoHeaderName para que coincidan con los nombres de encabezado empleados por el dispositivo.If the appliance uses different header names than X-Forwarded-For and X-Forwarded-Proto, set the ForwardedForHeaderName and ForwardedProtoHeaderName options to match the header names used by the appliance. Para obtener más información, vea Opciones del Middleware de encabezados reenviados y Configuración de un proxy que usa otros nombres de encabezado.For more information, see Forwarded Headers Middleware options and Configuration for a proxy that uses different header names.

IIS o IIS Express y el módulo ASP.NET CoreIIS/IIS Express and ASP.NET Core Module

El Middleware de encabezados reenviados se habilita de forma predeterminada mediante el Middleware de integración con IIS cuando la aplicación se hospeda fuera de proceso detrás de IIS y del módulo ASP.NET Core.Forwarded Headers Middleware is enabled by default by IIS Integration Middleware when the app is hosted out-of-process behind IIS and the ASP.NET Core Module. El Middleware de encabezados reenviados está activado para ejecutarse primero en la canalización de middleware con una configuración restringida específica del módulo ASP.NET Core debido a problemas de confianza con los encabezados reenviados (por ejemplo, suplantación de IP).Forwarded Headers Middleware is activated to run first in the middleware pipeline with a restricted configuration specific to the ASP.NET Core Module due to trust concerns with forwarded headers (for example, IP spoofing). El middleware está configurado para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto y está restringido a un único proxy localhost.The middleware is configured to forward the X-Forwarded-For and X-Forwarded-Proto headers and is restricted to a single localhost proxy. Si se requiere configuración adicional, consulte la sección Opciones del Middleware de encabezados reenviados.If additional configuration is required, see the Forwarded Headers Middleware options.

Otros escenarios de servidor proxy y equilibrador de cargaOther proxy server and load balancer scenarios

Al margen del uso de la integración con IIS al hospedar fuera de proceso, el Middleware de encabezados reenviados no está habilitado de forma predeterminada.Outside of using IIS Integration when hosting out-of-process, Forwarded Headers Middleware isn't enabled by default. El middleware de encabezados reenviados debe estar habilitado en una aplicación para procesar los encabezados reenviados con UseForwardedHeaders.Forwarded Headers Middleware must be enabled for an app to process forwarded headers with UseForwardedHeaders. Después de habilitar el middleware, si no se especifica ForwardedHeadersOptions para él, el valor predeterminado ForwardedHeadersOptions.ForwardedHeaders es ForwardedHeaders.None.After enabling the middleware if no ForwardedHeadersOptions are specified to the middleware, the default ForwardedHeadersOptions.ForwardedHeaders are ForwardedHeaders.None.

Configure el middleware con ForwardedHeadersOptions para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto en Startup.ConfigureServices.Configure the middleware with ForwardedHeadersOptions to forward the X-Forwarded-For and X-Forwarded-Proto headers in Startup.ConfigureServices. Invoque el método UseForwardedHeaders en Startup.Configure antes de llamar a otro middleware:Invoke the UseForwardedHeaders method in Startup.Configure before calling other middleware:

public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc();

    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = 
            ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    });
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseForwardedHeaders();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }
    else
    {
        app.UseExceptionHandler("/Home/Error");
    }

    app.UseStaticFiles();
    // In ASP.NET Core 1.x, replace the following line with: app.UseIdentity();
    app.UseAuthentication();
    app.UseMvc();
}

Nota

Si no se especifica ningún ForwardedHeadersOptions en Startup.ConfigureServices o directamente en el método de extensión con UseForwardedHeaders, los encabezados predeterminados para reenviar son ForwardedHeaders.None.If no ForwardedHeadersOptions are specified in Startup.ConfigureServices or directly to the extension method with UseForwardedHeaders, the default headers to forward are ForwardedHeaders.None. La propiedad ForwardedHeaders debe estar configurada con los encabezados que se van a reenviar.The ForwardedHeaders property must be configured with the headers to forward.

Configuración de NginxNginx configuration

Para reenviar los encabezados X-Forwarded-For y X-Forwarded-Proto, vea Hospedar ASP.NET Core en Linux con Nginx.To forward the X-Forwarded-For and X-Forwarded-Proto headers, see Hospedar ASP.NET Core en Linux con Nginx. Para obtener más información, consulte NGINX: Using the Forwarded header (NGINX: uso del encabezado Forwarded).For more information, see NGINX: Using the Forwarded header.

Configuración de ApacheApache configuration

X-Forwarded-For se agrega automáticamente. Consulte Apache Module mod_proxy: Reverse Proxy Request Headers (Módulo de Apache mod_proxy: Encabezados de solicitud de proxy inverso).X-Forwarded-For is added automatically (see Apache Module mod_proxy: Reverse Proxy Request Headers). Para obtener información sobre cómo reenviar el encabezado X-Forwarded-Proto, vea Hospedar ASP.NET Core en Linux con Apache.For information on how to forward the X-Forwarded-Proto header, see Hospedar ASP.NET Core en Linux con Apache.

Opciones del Middleware de encabezados reenviadosForwarded Headers Middleware options

ForwardedHeadersOptions controla el comportamiento del middleware de encabezados reenviados.ForwardedHeadersOptions control the behavior of the Forwarded Headers Middleware. En el ejemplo siguiente se cambian los valores predeterminados:The following example changes the default values:

  • Limite el número de entradas de los encabezados reenviados a 2.Limit the number of entries in the forwarded headers to 2.
  • Agregue una dirección de proxy conocida de 127.0.10.1.Add a known proxy address of 127.0.10.1.
  • Cambie el nombre del encabezado reenviado del valor predeterminado X-Forwarded-For a X-Forwarded-For-My-Custom-Header-Name.Change the forwarded header name from the default X-Forwarded-For to X-Forwarded-For-My-Custom-Header-Name.
services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardLimit = 2;
    options.KnownProxies.Add(IPAddress.Parse("127.0.10.1"));
    options.ForwardedForHeaderName = "X-Forwarded-For-My-Custom-Header-Name";
});
OpciónOption DescripciónDescription
AllowedHosts Restringe los hosts por el encabezado X-Forwarded-Host a los valores proporcionados.Restricts hosts by the X-Forwarded-Host header to the values provided.
  • Los valores se comparan mediante ordinal-ignore-case.Values are compared using ordinal-ignore-case.
  • Se deben excluir los números de puerto.Port numbers must be excluded.
  • Si la lista está vacía, se permiten todos los hosts.If the list is empty, all hosts are allowed.
  • Un carácter comodín de nivel superior * permite que todos los hosts que no están vacíos.A top-level wildcard * allows all non-empty hosts.
  • Se permiten caracteres comodín de subdominio, pero no coinciden con el dominio raíz.Subdomain wildcards are permitted but don't match the root domain. Por ejemplo, *.contoso.com coincide con el subdominio foo.contoso.com pero no con el dominio raíz contoso.com.For example, *.contoso.com matches the subdomain foo.contoso.com but not the root domain contoso.com.
  • Se permiten nombres de host Unicode, pero se convierten en Punycode para buscar la coincidencia.Unicode host names are allowed but are converted to Punycode for matching.
  • Las direcciones IPv6 deben incluir corchetes de enlace y estar en formato convencional (por ejemplo, [ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]).IPv6 addresses must include bounding brackets and be in conventional form (for example, [ABCD:EF01:2345:6789:ABCD:EF01:2345:6789]). Las direcciones IPv6 no usan mayúsculas y minúsculas de forma especial para buscar la igualdad lógica entre diferentes formatos, y no se realiza ninguna canonización.IPv6 addresses aren't special-cased to check for logical equality between different formats, and no canonicalization is performed.
  • Si no se restringen los hosts permitidos, un atacante podría suplantar los vínculos generados por el servicio.Failure to restrict the allowed hosts may allow an attacker to spoof links generated by the service.
El valor predeterminado es un IList<string> vacío.The default value is an empty IList<string>.
ForwardedForHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XForwardedForHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XForwardedForHeaderName. Esta opción se usa cuando el reenviador o proxy no emplea el encabezado X-Forwarded-For sino algún otro para reenviar la información.This option is used when the proxy/forwarder doesn't use the X-Forwarded-For header but uses some other header to forward the information.

De manera predeterminada, es X-Forwarded-For.The default is X-Forwarded-For.
ForwardedHeaders Identifica qué reenviadores se deben procesar.Identifies which forwarders should be processed. Consulte ForwardedHeaders Enum para obtener la lista de campos que se aplican.See the ForwardedHeaders Enum for the list of fields that apply. Los valores típicos que se asignan a esta propiedad son ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.Typical values assigned to this property are ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto.

El valor predeterminado es ForwardedHeaders.None.The default value is ForwardedHeaders.None.
ForwardedHostHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XForwardedHostHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XForwardedHostHeaderName. Esta opción se usa cuando el reenviador o proxy no emplea el encabezado X-Forwarded-Host sino algún otro para reenviar la información.This option is used when the proxy/forwarder doesn't use the X-Forwarded-Host header but uses some other header to forward the information.

De manera predeterminada, es X-Forwarded-Host.The default is X-Forwarded-Host.
ForwardedProtoHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XForwardedProtoHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XForwardedProtoHeaderName. Esta opción se usa cuando el reenviador o proxy no emplea el encabezado X-Forwarded-Proto sino algún otro para reenviar la información.This option is used when the proxy/forwarder doesn't use the X-Forwarded-Proto header but uses some other header to forward the information.

De manera predeterminada, es X-Forwarded-Proto.The default is X-Forwarded-Proto.
ForwardLimit Limita el número de entradas en los encabezados que se procesan.Limits the number of entries in the headers that are processed. Establézcalo en null para deshabilitar el límite, pero esto solo se debe realizar si están configurados KnownProxies o KnownNetworks.Set to null to disable the limit, but this should only be done if KnownProxies or KnownNetworks are configured. Establecerlo en un valor que no sea null es una medida de precaución (no una garantía) para protegerse contra los proxies mal configurados y las peticiones maliciosas que llegan desde los canales laterales de la red.Setting a non-null value is a precaution (but not a guarantee) to guard against misconfigured proxies and malicious requests arriving from side-channels on the network.

El middleware de encabezados reenviados procesa los encabezados en orden inverso, de derecha a izquierda.Forwarded Headers Middleware processes headers in reverse order from right to left. Si se usa el valor predeterminado (1), solo se procesa el valor más a la derecha de los encabezados, a menos que se aumente el valor de ForwardLimit.If the default value (1) is used, only the rightmost value from the headers is processed unless the value of ForwardLimit is increased.

De manera predeterminada, es 1.The default is 1.
KnownNetworks Intervalos de direcciones de redes conocidas de los que se aceptan encabezados reenviados.Address ranges of known networks to accept forwarded headers from. Proporcione intervalos de direcciones IP mediante la notación de Enrutamiento de interdominios sin clases (CIDR).Provide IP ranges using Classless Interdomain Routing (CIDR) notation.

Si el servidor usa sockets en modo dual, las direcciones IPv4 se suministran en formato IPv6 (por ejemplo, 10.0.0.1 en IPv4 se representa en IPv6 como ::ffff:10.0.0.1).If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format (for example, 10.0.0.1 in IPv4 represented in IPv6 as ::ffff:10.0.0.1). Consulte IPAddress.MapToIPv6.See IPAddress.MapToIPv6. Para determinar si este formato es necesario, examine HttpContext.Connection.RemoteIpAddress.Determine if this format is required by looking at the HttpContext.Connection.RemoteIpAddress. Para más información, consulte la sección Configuración de una dirección IPv4 representada como una dirección IPv6.For more information, see the Configuration for an IPv4 address represented as an IPv6 address section.

El valor predeterminado es un IList<IPNetwork> que contiene una única entrada para IPAddress.Loopback.The default is an IList<IPNetwork> containing a single entry for IPAddress.Loopback.
KnownProxies Direcciones de servidores proxy conocidos de los que se aceptan encabezados reenviados.Addresses of known proxies to accept forwarded headers from. Use KnownProxies para especificar las coincidencias exactas de direcciones IP.Use KnownProxies to specify exact IP address matches.

Si el servidor usa sockets en modo dual, las direcciones IPv4 se suministran en formato IPv6 (por ejemplo, 10.0.0.1 en IPv4 se representa en IPv6 como ::ffff:10.0.0.1).If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format (for example, 10.0.0.1 in IPv4 represented in IPv6 as ::ffff:10.0.0.1). Consulte IPAddress.MapToIPv6.See IPAddress.MapToIPv6. Para determinar si este formato es necesario, examine HttpContext.Connection.RemoteIpAddress.Determine if this format is required by looking at the HttpContext.Connection.RemoteIpAddress. Para más información, consulte la sección Configuración de una dirección IPv4 representada como una dirección IPv6.For more information, see the Configuration for an IPv4 address represented as an IPv6 address section.

El valor predeterminado es un IList<IPAddress> que contiene una única entrada para IPAddress.IPv6Loopback.The default is an IList<IPAddress> containing a single entry for IPAddress.IPv6Loopback.
OriginalForHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XOriginalForHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XOriginalForHeaderName.

De manera predeterminada, es X-Original-For.The default is X-Original-For.
OriginalHostHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XOriginalForHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XOriginalHostHeaderName.

De manera predeterminada, es X-Original-Host.The default is X-Original-Host.
OriginalProtoHeaderName Use el encabezado especificado por esta propiedad en lugar del especificado por ForwardedHeadersDefaults.XOriginalProtoHeaderName.Use the header specified by this property instead of the one specified by ForwardedHeadersDefaults.XOriginalProtoHeaderName.

De manera predeterminada, es X-Original-Proto.The default is X-Original-Proto.
RequireHeaderSymmetry Requiere que el número de valores de encabezado esté sincronizado entre los valores ForwardedHeadersOptions.ForwardedHeaders que se van a procesar.Require the number of header values to be in sync between the ForwardedHeadersOptions.ForwardedHeaders being processed.

El valor predeterminado en ASP.NET Core 1.x es true.The default in ASP.NET Core 1.x is true. El valor predeterminado en ASP.NET Core 2.0 o posterior es false.The default in ASP.NET Core 2.0 or later is false.

Escenarios y casos de usoScenarios and use cases

Cuando no es posible agregar encabezados reenviados y todas las solicitudes son segurasWhen it isn't possible to add forwarded headers and all requests are secure

En algunos casos, puede que no sea posible agregar encabezados reenviados a las solicitudes redirigidas mediante proxy a la aplicación.In some cases, it might not be possible to add forwarded headers to the requests proxied to the app. Si el proxy está forzando a que todas las solicitudes externas públicas sean HTTPS, el esquema se puede establecer manualmente en Startup.Configure antes de usar cualquier tipo de middleware:If the proxy is enforcing that all public external requests are HTTPS, the scheme can be manually set in Startup.Configure before using any type of middleware:

app.Use((context, next) =>
{
    context.Request.Scheme = "https";
    return next();
});

Este código puede deshabilitarse con una variable de entorno u otro valor de configuración en un entorno de desarrollo o ensayo.This code can be disabled with an environment variable or other configuration setting in a development or staging environment.

Tratar con la ruta de acceso base y los servidores proxy que cambian la ruta de acceso de la solicitudDeal with path base and proxies that change the request path

Algunos servidores proxy pasan la ruta de acceso sin cambios pero con una ruta de acceso base de aplicación que se debe quitar para que el enrutamiento funcione correctamente.Some proxies pass the path intact but with an app base path that should be removed so that routing works properly. El middleware UsePathBaseExtensions.UsePathBase divide la ruta de acceso en HttpRequest.Path y la ruta de acceso base de aplicación en HttpRequest.PathBase.UsePathBaseExtensions.UsePathBase middleware splits the path into HttpRequest.Path and the app base path into HttpRequest.PathBase.

Si /foo es la ruta de acceso base de aplicación para una ruta de acceso de proxy que se pasa como /foo/api/1, el middleware establece Request.PathBase en /foo y Request.Path en /api/1 con el siguiente comando:If /foo is the app base path for a proxy path passed as /foo/api/1, the middleware sets Request.PathBase to /foo and Request.Path to /api/1 with the following command:

app.UsePathBase("/foo");

La ruta de acceso base y la ruta de acceso original se vuelven a aplicar cuando se llama de nuevo al middleware en orden inverso.The original path and path base are reapplied when the middleware is called again in reverse. Para obtener más información sobre el procesamiento de pedidos del middleware, vea Middleware de ASP.NET Core.For more information on middleware order processing, see Middleware de ASP.NET Core.

Si el proxy recorta la ruta de acceso (por ejemplo, el reenvío /foo/api/1 a /api/1), corrija los redireccionamientos y los vínculos mediante el establecimiento de la propiedad PathBase de la solicitud:If the proxy trims the path (for example, forwarding /foo/api/1 to /api/1), fix redirects and links by setting the request's PathBase property:

app.Use((context, next) =>
{
    context.Request.PathBase = new PathString("/foo");
    return next();
});

Si el proxy va a agregar datos de ruta de acceso, descarte parte de esta ruta para corregir los redireccionamientos y los vínculos; para ello, use StartsWithSegments y asígnelo a la propiedad Path:If the proxy is adding path data, discard part of the path to fix redirects and links by using StartsWithSegments and assigning to the Path property:

app.Use((context, next) =>
{
    if (context.Request.Path.StartsWithSegments("/foo", out var remainder))
    {
        context.Request.Path = remainder;
    }

    return next();
});

Configuración de un proxy que usa otros nombres de encabezadoConfiguration for a proxy that uses different header names

Si el proxy no usa los encabezados denominados X-Forwarded-For y X-Forwarded-Proto para reenviar el puerto o la dirección de proxy y originar información de esquema, establezca las opciones ForwardedForHeaderName y ForwardedProtoHeaderName de modo que coincidan con los nombres de encabezado empleados por el proxy:If the proxy doesn't use headers named X-Forwarded-For and X-Forwarded-Proto to forward the proxy address/port and originating scheme information, set the ForwardedForHeaderName and ForwardedProtoHeaderName options to match the header names used by the proxy:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedForHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-For_Header";
    options.ForwardedProtoHeaderName = "Header_Name_Used_By_Proxy_For_X-Forwarded-Proto_Header";
});

Configuración de una dirección IPv4 representada como una dirección IPv6Configuration for an IPv4 address represented as an IPv6 address

Si el servidor usa sockets en modo dual, las direcciones IPv4 se suministran en formato IPv6 (por ejemplo, 10.0.0.1 en IPv4 se representa en IPv6 como ::ffff:10.0.0.1 o ::ffff:a00:1).If the server is using dual-mode sockets, IPv4 addresses are supplied in an IPv6 format (for example, 10.0.0.1 in IPv4 represented in IPv6 as ::ffff:10.0.0.1 or ::ffff:a00:1). Consulte IPAddress.MapToIPv6.See IPAddress.MapToIPv6. Para determinar si este formato es necesario, examine HttpContext.Connection.RemoteIpAddress.Determine if this format is required by looking at the HttpContext.Connection.RemoteIpAddress.

En el ejemplo siguiente, se agrega una dirección de red que proporciona encabezados reenviados a la lista KnownNetworks en formato IPv6.In the following example, a network address that supplies forwarded headers is added to the KnownNetworks list in IPv6 format.

Dirección IPv4: 10.11.12.1/8IPv4 address: 10.11.12.1/8

Dirección IPv6 convertida: ::ffff:10.11.12.1Converted IPv6 address: ::ffff:10.11.12.1
Longitud de prefijo convertida: 104Converted prefix length: 104

También puede proporcionar la dirección en formato hexadecimal (10.11.12.1 se representa en IPv6 como ::ffff:0a0b:0c01).You can also supply the address in hexadecimal format (10.11.12.1 represented in IPv6 as ::ffff:0a0b:0c01). Al convertir una dirección IPv4 en IPv6, agregue 96 a la longitud de prefijo de CIDR (8 en el ejemplo) para tener en cuenta el prefijo de IPv6 ::ffff: adicional (8 + 96 = 104).When converting an IPv4 address to IPv6, add 96 to the CIDR Prefix Length (8 in the example) to account for the additional ::ffff: IPv6 prefix (8 + 96 = 104).

// To access IPNetwork and IPAddress, add the following namespaces:
// using using System.Net;
// using Microsoft.AspNetCore.HttpOverrides;
services.Configure<ForwardedHeadersOptions>(options =>
{
    options.ForwardedHeaders =
        ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
    options.KnownNetworks.Add(new IPNetwork(
        IPAddress.Parse("::ffff:10.11.12.1"), 104));
});

Reenvío del esquema para servidores proxy inversos Linux y que no son de IISForward the scheme for Linux and non-IIS reverse proxies

Las aplicaciones que llaman a los métodos UseHttpsRedirection y UseHsts incluyen un sitio en un bucle infinito si se implementan en una instancia de Azure App Service de Linux, una máquina virtual Linux de Azure, o bien detrás de cualquier otro servidor proxy inverso, además de IIS.Apps that call UseHttpsRedirection and UseHsts put a site into an infinite loop if deployed to an Azure Linux App Service, Azure Linux virtual machine (VM), or behind any other reverse proxy besides IIS. El servidor proxy inverso termina TLS y Kestrel no es consciente del esquema de solicitud correcto.TLS is terminated by the reverse proxy, and Kestrel isn't made aware of the correct request scheme. En esta configuración también se produce un error de OAuth y OIDC, ya que generan redirecciones incorrectas.OAuth and OIDC also fail in this configuration because they generate incorrect redirects. UseIISIntegration agrega y configura middleware de encabezados reenviados cuando se ejecuta detrás de IIS, pero no hay ninguna configuración automática coincidente para Linux (integración de Apache o Nginx).UseIISIntegration adds and configures Forwarded Headers Middleware when running behind IIS, but there's no matching automatic configuration for Linux (Apache or Nginx integration).

Para reenviar el esquema desde el servidor proxy en escenarios que no sean de IIS, agregue y configure Middleware de encabezados reenviados.To forward the scheme from the proxy in non-IIS scenarios, add and configure Forwarded Headers Middleware. En Startup.ConfigureServices, use el código siguiente:In Startup.ConfigureServices, use the following code:

// using Microsoft.AspNetCore.HttpOverrides;

if (string.Equals(
    Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"), 
    "true", StringComparison.OrdinalIgnoreCase))
{
    services.Configure<ForwardedHeadersOptions>(options =>
    {
        options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | 
            ForwardedHeaders.XForwardedProto;
        // Only loopback proxies are allowed by default.
        // Clear that restriction because forwarders are enabled by explicit 
        // configuration.
        options.KnownNetworks.Clear();
        options.KnownProxies.Clear();
    });
}

Solucionar problemasTroubleshoot

Cuando no se reenvíen los encabezados como estaba previsto, habilite el registro.When headers aren't forwarded as expected, enable logging. Si los registros no proporcionan suficiente información para solucionar el problema, enumere los encabezados de solicitud recibidos por el servidor.If the logs don't provide sufficient information to troubleshoot the problem, enumerate the request headers received by the server. Use middleware insertado para escribir encabezados de solicitud en la respuesta de una aplicación o para registrar los encabezados.Use inline middleware to write request headers to an app response or log the headers.

Para escribir los encabezados en la respuesta de la aplicación, coloque el siguiente middleware insertado terminal inmediatamente después de la llamada a UseForwardedHeaders en Startup.Configure:To write the headers to the app's response, place the following terminal inline middleware immediately after the call to UseForwardedHeaders in Startup.Configure:

app.Run(async (context) =>
{
    context.Response.ContentType = "text/plain";

    // Request method, scheme, and path
    await context.Response.WriteAsync(
        $"Request Method: {context.Request.Method}{Environment.NewLine}");
    await context.Response.WriteAsync(
        $"Request Scheme: {context.Request.Scheme}{Environment.NewLine}");
    await context.Response.WriteAsync(
        $"Request Path: {context.Request.Path}{Environment.NewLine}");

    // Headers
    await context.Response.WriteAsync($"Request Headers:{Environment.NewLine}");

    foreach (var header in context.Request.Headers)
    {
        await context.Response.WriteAsync($"{header.Key}: " +
            $"{header.Value}{Environment.NewLine}");
    }

    await context.Response.WriteAsync(Environment.NewLine);

    // Connection: RemoteIp
    await context.Response.WriteAsync(
        $"Request RemoteIp: {context.Connection.RemoteIpAddress}");
});

Puede escribir en registros en lugar de en el cuerpo de respuesta.You can write to logs instead of the response body. Así el sitio funcionará con normalidad durante la depuración.Writing to logs allows the site to function normally while debugging.

Para ello, siga estos pasos:To write logs rather than to the response body:

app.Use(async (context, next) =>
{
    // Request method, scheme, and path
    _logger.LogDebug("Request Method: {Method}", context.Request.Method);
    _logger.LogDebug("Request Scheme: {Scheme}", context.Request.Scheme);
    _logger.LogDebug("Request Path: {Path}", context.Request.Path);

    // Headers
    foreach (var header in context.Request.Headers)
    {
        _logger.LogDebug("Header: {Key}: {Value}", header.Key, header.Value);
    }

    // Connection: RemoteIp
    _logger.LogDebug("Request RemoteIp: {RemoteIpAddress}", 
        context.Connection.RemoteIpAddress);

    await next();
});

Si se procesa, los valores X-Forwarded-{For|Proto|Host} se trasladan a X-Original-{For|Proto|Host}.When processed, X-Forwarded-{For|Proto|Host} values are moved to X-Original-{For|Proto|Host}. Si hay varios valores en un encabezado determinado, el middleware de encabezados reenviados procesa los encabezados en orden inverso, de derecha a izquierda.If there are multiple values in a given header, Forwarded Headers Middleware processes headers in reverse order from right to left. El valor predeterminado de ForwardLimit es 1 (uno), por lo que solo el valor más a la derecha de los encabezados se procesa, a menos que se aumente el valor de ForwardLimit.The default ForwardLimit is 1 (one), so only the rightmost value from the headers is processed unless the value of ForwardLimit is increased.

La dirección IP remota original de la solicitud debe coincidir con una entrada de las listas KnownProxies o KnownNetworks antes de procesar los encabezados reenviados.The request's original remote IP must match an entry in the KnownProxies or KnownNetworks lists before forwarded headers are processed. Esto limita la suplantación de encabezados al no aceptarse reenviadores de servidores proxy que no son de confianza.This limits header spoofing by not accepting forwarders from untrusted proxies. Cuando se detecta un servidor proxy desconocido, el registro indica la dirección de dicho proxy:When an unknown proxy is detected, logging indicates the address of the proxy:

September 20th 2018, 15:49:44.168 Unknown proxy: 10.0.0.100:54321

En el ejemplo anterior, 10.0.0.100 es un servidor proxy.In the preceding example, 10.0.0.100 is a proxy server. Si se trata de un servidor proxy de confianza, agregue la dirección IP del servidor a KnownProxies o agregue una red de confianza a KnownNetworks en Startup.ConfigureServices.If the server is a trusted proxy, add the server's IP address to KnownProxies (or add a trusted network to KnownNetworks) in Startup.ConfigureServices. Para más información, vea la sección Opciones del Middleware de encabezados reenviados.For more information, see the Forwarded Headers Middleware options section.

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

Importante

Admita solo las redes y los servidores proxy de confianza para reenviar encabezados.Only allow trusted proxies and networks to forward headers. De lo contrario, se pueden producir ataques de suplantación de IP.Otherwise, IP spoofing attacks are possible.

Recursos adicionalesAdditional resources