Obtener la dirección IP del cliente en AKS con .Net Core y NGNIX
- 3 minutes read - 457 wordsObtener la IP del cliente es algo imprescindible en muchas aplicaciones, para capturar ese valor en la telemetría, o para intentar saber desde qué país se está conectando el usuario. Sea como sea, si desplegáis una aplicación .Net Core en AKS y usáis un ingress NGINX, sin ninguna modificación, veréis que la dirección IP del cliente no es la que os esperábais.
Para resolver esto existe una cabecera que debería contener la IP original
llamada X-Forwarded-For
, pero para que funcione hay que realizar dos cambios.
Configuración del Ingress Controller
Cuando desplegamos un ingress controller en AKS se suele utilizar helm
para
instalarlo. En ese caso, necesitaremos añadir una opción que
está documentada pero no viene por defecto:
--set controller.service.externalTrafficPolicy=Local
Como yo suelo usar Flux para hacer GitOps en mi cluster, la forma de indicarlo la podéis ver aquí en la sección values (Flux no admite la forma abreviada):
apiVersion: helm.toolkit.fluxcd.io/v2beta1
kind: HelmRelease
metadata:
name: ingress-nginx
namespace: ingress-basic
spec:
chart:
spec:
chart: ingress-nginx
sourceRef:
kind: HelmRepository
name: ingress-nginx
values:
controller:
service:
externalTrafficPolicy: Local
interval: 1m0s
install:
remediation:
retries: 3
upgrade:
remediation:
retries: 3
Una vez configurado podremos ver que en la cabecera X-Forwarded-For
aparece ya
nuestra IP, pero si miramos en la propiedad
Request.HttpContext.Connection.LocalIpAddress
seguimos teniendo una IP (::ffff:10.240.0.14) que en este caso se corresponde con la IP asignada a mi Pod directamente porque estoy usando Azure CNI.
Cambios en el código
ASP.Net Core no usa la cabecera X-Forwarded-For
por defecto, para evitar
problemas de seguridad y porque si ejecutamos la aplicación sin un proxy,
no veremos la IP del cliente. Podemos configurar el middleware Forwarded Headers
para que sí se use esa información. Hay un detalle muy importante a configurar
para que funcione, y es configurar adecuadamente los
KnownProxies
y las KnownNetworks
. En el ejmplo oficial simplemente borran la
lista para que funcione:
using Microsoft.AspNetCore.HttpOverrides;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddRazorPages();
if (string.Equals(
Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"),
"true", StringComparison.OrdinalIgnoreCase))
{
builder.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();
});
}
var app = builder.Build();
app.UseForwardedHeaders();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseAuthorization();
app.MapRazorPages();
app.Run();
Aquí habría que poner en esa lista los valores de la red que tenemos en K8s, que podemos pasar por variable de entorno, pero es importante fijarse en cómo vienen esas direcciones pues a veces vendrán en formato IPv4 (10.240.0.1) y otras en IPv6 (::ffff:10.240.0.1). Es importante que pongamos la que está llegando a nuestra aplicación (en los pantallazos veréis que en mi caso están en formato IPv6).
Después de aplicar estos cambios en el código podremos finalmente recibir la IP del cliente dentro del :
Créditos
- Foto de portada por B Klug.