原文 K8s中ASP.NET Core应用获取不到客户端真实IP地址解决办法
应用部署在 kubernets 集群中,请求是通过阿里云负载均衡+ nginx ingress 转发的,客户端 IP 是通过 X-Forwarded-For 请求头转发的,ASP.NET Core 应用是这么获取客户端 IP 的。
在 Startup.ConfigureServices 中的代码:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
options.KnownNetworks.Clear();
options.KnownProxies.Clear();
});
获取客户端 IP 地址的代码:
var ip = HttpContext.Connection.RemoteIpAddress.ToString();
之前部署在 docker swarm 集群上能正常获取,现在部署到 kubernetes 集群上却获取不到,而部署在同一个 k8s 集群上的其他 .net core 能正常获取。
排查过程:
确定排查目标:X-Forwarded-For 的值是 "116.62.124.68, 192.168.107.192",ForwardedHeadersMiddleware 是如何解析得到 192.168.107.192 的?
从 github 上签出 asp.net core 源代码 的 release/3.1 分支
运行 build.cmd 命令安装 build 环境(在 windows 系统上操作)
在 git bash 中运行 ./activate.sh 切换 .net core sdk 版本
修改 ForwardedHeadersMiddlewareTests 中的测试用例 XForwardedForDefaultSettingsChangeRemoteIpAndPort 重现问题。
[Fact]
public async Task XForwardedForDefaultSettingsChangeRemoteIpAndPort()
{
var builder = new WebHostBuilder()
.Configure(app =>
{
var options = new ForwardedHeadersOptions
{
ForwardedHeaders = ForwardedHeaders.XForwardedFor
};
app.UseForwardedHeaders(options);
});
var server = new TestServer(builder);
var context = await server.SendAsync(c =>
{
c.Request.Headers["X-Forwarded-For"] = "116.62.124.68, 192.168.107.192";
});
Assert.Equal("116.62.124.68", context.Connection.RemoteIpAddress.ToString());
}
在测试驱动+埋点打印的帮助下阅读 ForwardedHeadersMiddleware 的实现源码。
ForwardedHeadersMiddleware 是按从右到左的倒序读取 X-Forwarded-For 中的多个 IP 地址的。
if (checkFor && i < forwardedFor.Length)
{
set.IpAndPortText = forwardedFor[forwardedFor.Length - i - 1];
}
所以从 "116.62.124.68, 192.168.107.192" 得到 "192.168.107.192" 说明只读了1次。
找到控制读取次数的代码,发现 ForwardLimit 可以影响读取次数。
if (_options.ForwardLimit.HasValue && entryCount > _options.ForwardLimit)
{
entryCount = _options.ForwardLimit.Value;
}
于是找到解决方法,将 ForwardLimit 设置为 2 即可。
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
//...
});
先用tcpdump port 80 -A -s 0 -c 100(输出80端口接收的100个数据包,http数据包的ASCII部分会显示到stdout)确认一下进入到容器的HTTP请求是不是携带了X-Forwarded-For。
K8s中ASP.NET Core应用获取不到客户端真实IP地址解决办法
原文:https://www.cnblogs.com/lonelyxmas/p/13139842.html