通过 Cloudflare 和 Azure 获取用户的 IP 地址

4
我在Azure上有一个网站,该网站通过Cloudflare进行路由以获得额外的保护。
Cloudflare添加了一个头文件CF-Connecting-IP,该文件应该是客户端的IP地址,但是大多数情况下,我得到的是保留的IP地址,而不是客户端的IP地址。
我通过我的办公室互联网测试访问该网站时,Cloudflare返回了一个保留的IP地址,但是当我去了whatsmyip.org后,我得到了真正的办公室IP地址。
除非他们在代理或VPN后面,否则如何确保始终获取客户端的IP地址?

IP地址不是访问您的网站的客户端请求头的一部分吗?您能否提供获取IP地址所使用的代码? - boateng
现在我只获取带有cf-connecting-ip索引的标头,该索引提供IP地址,如果未设置,则返回null。问题是它总是返回某些内容,即使是那些保留的IP地址。 - General Electric
有趣的平台,但你觉得它不会过滤掉一半的访问者吗?他们似乎有很棒的社区和论坛,可以试着在那里询问。 - boateng
5个回答

5

基于上面 masoud ch 的回答,.NET Core 版本可以使用 IHttpContextAccessor 替代 HttpRequestBase 实现如下:

using Microsoft.AspNetCore.Http;
using System.Linq;

namespace myproject.Extensions
{
    public static class HttpContextAccessorExtensions
    {
        public static string GetIpAddress(this IHttpContextAccessor accessor)
        {
            if (!string.IsNullOrEmpty(accessor.HttpContext.Request.Headers["CF-CONNECTING-IP"]))
                return accessor.HttpContext.Request.Headers["CF-CONNECTING-IP"];

            var ipAddress = accessor.HttpContext.GetServerVariable("HTTP_X_FORWARDED_FOR");

            if (!string.IsNullOrEmpty(ipAddress))
            {
                var addresses = ipAddress.Split(',');
                if (addresses.Length != 0)
                    return addresses.Last();
            }

            return accessor.HttpContext.Connection.RemoteIpAddress.ToString();
        }
    }
}

要在控制器中使用扩展功能,请按照以下步骤操作:

HomeController.cs

 private readonly IHttpContextAccessor _accessor; 

 public HomeController(IHttpContextAccessor httpContextAccessor)
 {
     _accessor = httpContextAccessor; // Dependency Injection:
 }

 public IActionResult Index()
 {
     var IP = _accessor.GetIpAddress());
     return View();
 }

如何到达港口? - undefined
@sunnamed 这是一个完全不同的问题,与原帖无关。无论如何,我不确定你对端口的需求是什么。请参考CF支持的头部信息(端口不在其中)https://developers.cloudflare.com/fundamentals/reference/http-request-headers/REMOTE_PORT可以在你的服务器上获取。 - undefined

3

X-Forwarded-For是一串IP地址列表,其中最后一个通常是用户的IP地址。

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

例如:

X-Forwarded-For: 198.51.100.101,198.51.100.102,203.0.113.1

在上面的示例中,203.0.113.1是原始访问者IP地址,198.51.100.101和198.51.100.102是通过X-Forwarded-For标题提供给Cloudflare的代理服务器IP地址。

如果X-Forwarded-For在列表中存在,我们需要获取它;否则,默认使用UserHostAddress。作为额外奖励,Cloudflare为客户端IP地址定义了自己的头部CF-Connecting-IP。如果你使用Cloudflare,请查找它。如果使用其他云服务提供商,则需检查他们可能定义的特定标题。下面的示例应该能够给您一个很好的概念如何获取用户的IP地址。

public static class RequestExtensions
{
    public static string GetIpAddress(this HttpRequestBase request)
    {
        if (request.Headers["CF-CONNECTING-IP"] != null)
            return request.Headers["CF-CONNECTING-IP"];

        var ipAddress = request.ServerVariables["HTTP_X_FORWARDED_FOR"];

        if (!string.IsNullOrEmpty(ipAddress))
        {
            var addresses = ipAddress.Split(',');
            if (addresses.Length != 0)
                return addresses.Last();
        }

        return request.UserHostAddress;
    }
}

1

这里有几个保留的IP地址,Cloudflare正在返回241.7.216.18、248.245.44.54、240.31.14.8和241.43.18.136。这些显然是错误的。我在Cloudflare上读到可以向服务器设置添加一些条目,但我无法在Azure应用服务计划上托管我的应用程序来执行此操作。 - General Electric
241网段是保留地址,但不像本地网段地址(10、192、172等)那样无效。它用于多播。https://tools.ietf.org/html/rfc1112 - Terry Carmen
我知道这些IP地址是有效的,问题在于即使我可以通过whatsmyip.com验证它,cloudflare也没有给我真实的IP地址。 - General Electric
CF表示他们在该标头中传递IP。如果不正确,除了联系Cloudflare之外,您无法做任何事情。可能是他们看到了您和他们之间的其他下游路由器或设备。仅因为whatsmyip获取您的真实IP并不意味着CF总是能够获取它。 - Terry Carmen

1
如果您阅读Terry Carmen在唯一其他答案中发布的链接(在撰写本文时),那么您将看到有两个标题可用于获取IP地址:X-Forwarded-For和CF-Connecting-IP。我认为X-Forwarded-For是更好的选择。如果不存在,Cloudflare将把它设置为与CF-Connecting-IP相同的值,否则,他们将保留其值传递到您的服务器。考虑这种情况:用户=> SomeCloudProvider => Cloudflare => YourServer,在这种情况下,CF-Connecting-IP将是SomeCloudProvider,因为这是连接到Cloudflare的内容提供商,但是如果SomeCloudProvider在X-Forwarded-For中添加了用户IP地址,则Cloudflare将保留此地址并将其发送给您(在标头中),以便您可以获取用户的真实IP地址。 X-Forwarded-For是一种准标准,所有云提供商、路由器、交换机等(我见过的)都会添加或维护。

0

使用ForwardedHeadersExtensions,Cloudflare和Azure也会发送X-Forwarded-For头。顺便说一下,几乎所有的代理都会发送这个头。

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

如果没有 X-Forwarded-For 头部,你可以指定任何你想要的头部。

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedForHeaderName = "custom-x-forwarded-for",
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

之后您可以按照常规方式解析IP地址。

var ip = context.Connection.RemoteIpAddress;

对我来说不起作用 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接