General Electric
General Electric

Reputation: 1226

Getting user's IP address through Cloudflare and Azure

I have a website in Azure, the website is routed through Cloudflare for extra protection.

Cloudflare adds a header CF-Connecting-IP which is supposed to be the client's IP address, however sometimes this gives a real IP address but most of the time I'm getting reserved IP addresses instead of the client's IP.

I tested it going to the website through my office internet and cloudflare returns a reserved IP address, however when I go to whatsmyip.org I get my real office IP address.

How can I make sure to always obtained the client's IP address unless of course they are behind a proxy or VPN.

Upvotes: 5

Views: 8668

Answers (5)

Sha
Sha

Reputation: 2397

Based on masoud ch's answer, a .NET Core version could look like this using IHttpContextAccessor instead of 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();
        }
    }
}

To use the extension in your controller do the following:

HomeController.cs

 private readonly IHttpContextAccessor _accessor; 

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

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

Upvotes: 8

Dmitry
Dmitry

Reputation: 322

Use ForwardedHeadersExtensions, cloudflare and azure also send ​​X-Forwarded-For header. Btw almost all proxy send that

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

If there is no X-Forwarded-For header you can specify any header you want

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

After that u can just resolve ip regular way,

var ip = context.Connection.RemoteIpAddress;

Upvotes: 0

masoud ch
masoud ch

Reputation: 91

X-Forwarded-For is a list of IP address, where the last one is most likely user's IP address.

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

Example:

X-Forwarded-For: 198.51.100.101,198.51.100.102,203.0.113.1

In the examples above, 203.0.113.1 is the original visitor IP address and 198.51.100.101 and 198.51.100.102 are proxy server IP addresses provided to Cloudflare via the X-Forwarded-For header

We have to grab it, if it is present in the list, if not default to UserHostAddress. As a bonus, Cloudflare defines its own header for client IP address called CF-Connecting-IP. If you use Cloudflare look for it. If use some other cloud providers check for specific headers they might define. Example below should give you good general idea how to get user's IP address.

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;
    }
}

Upvotes: 2

Guy
Guy

Reputation: 67280

If you read the link that Terry Carmen posted in the only other answer (at the time of writing this) then you'll see that there are 2 headers that you can use to get the IP:

X-Forwarded-For and CF-Connecting-IP

I believe that X-Forwarded-For is the better one to use. Cloudflare will set this to the same value as CF-Connecting-IP if it isn't already present, otherwise they will maintain its value through to your server.

Consider this scenario:

User => SomeCloudProvider => Cloudflare => YourServer

In this scenario CF-Connecting-IP will be SomeCloudProvider because that's what's connecting to Cloudflare. But if SomeCloudProvider had added the User IP address in X-Forwarded-For then Cloudflare will preserve this and send it on to you (in the headers) so you can get the real IP address of the User.

X-Forwarded-For is a quasi-standard that all cloud providers, routers, switches etc. (that I've seen) will add or maintain.

Upvotes: 2

Terry Carmen
Terry Carmen

Reputation: 3886

They provide CF-Connecting-IP, which is supposed to be correct.

I'm not sure what would be in CF-Connection-IP

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

Upvotes: 1

Related Questions