DIRECT replacement of UserHostAddress in ASP.NET Core? - c#

We discovered that Request.UserHostAddress is not available in ASP.NET Core (1.0 RC1), as well as Request.ServerVariables["REMOTE_ADDR"], which returns essentially the same.
Now we found HttpContext.Connection.RemoteIpAddress or HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress to be the replacement, but is it really a 1:1 replacement for the functionality?
What I mean: Request.ServerVariables["REMOTE_ADDR"] only returns the direct IP address of a caller, not a forwarded client address (therefore you have to get "X-FORWARDED-FOR"). And that's what we need in our scenario: the direct caller address, not the forwarded one. But we couldn't find any info if HttpContext.Connection.RemoteIpAddress in ASP.NET Core is the right choice for us (and if not, what's the alternative?).

You only get X-Forwarded-For replacing it when you have plumbed that middleware into the pipeline. So to enable that use app.UseOverrideHeaders().
Without it RemoteIpAddress is going to be 127.0.0.1 in most configurations, because you will have IIS in front of Kestrel.

Related

Configure ASP.NET Core to work with proxy servers and load balancers

I have followed all steps explained on this Microsoft's documents page to be able to obtain remote client's IP address in an IIS-hosted app by calling HttpContext.Connection.RemoteIpAddress , but I keep getting the loopback IP address of ::1. There is only one weird scenario that gets me the remote client's IP address and that's by the service configuration code below where ForwardedForHeaderName is initialized by X-Forwarded-For-Custom-Header-Name which does not make any sense to me!
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardLimit = 2;
options.ForwardedForHeaderName = "X-Forwarded-For-Custom-Header-Name";
});
The full source code is found in this github repo and I'd like to know what exact change must be done to obtain the remote IP address successfully by removing "X-Forwarded-For-Custom-Header-Name" and why such a string gets me the IP address!
The idea is that X-Forwarded-For-Custom-Header-Name is meant to be replaced with a custom header name in case your proxy / load balancer doesn't use the standard X-Forwarded-For header but something different.
While X-Forwarded-For is the de-facto standard here, some proxies / load balancers use another header. In this case you would set it to the value used by your it, for examle X-Real-IP.
In your case, you will have to look at which headers are used in your setup and then configure your application accordingly.
When hosting in IIS using the default hosting model (dotnet publish should generate the appropriate web.config file), the forwarding is already set up and handled by the IIS middleware.
Unless you expect proxy to forward the original IP address in a header that is different from the usual X-Forwarded-For you don't have to specify ForwardedForHeaderName, instead configure it as:
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});

Servce Fabric Reverse Proxy Integration in ASP.NET Core 404 Response

I'm working on an implementation of ICommunicationClient and accompanying stuff for HTTP protocol communication which should be compatible with SF reverse proxy. The most subtle part for me is retry policy. According to Azure docs for 404 errors reverse proxy relies on X-Service-Fabric header to be returned from web service when deciding if it should retry.
ASP.NET Core provides middleware for integration with a reverse proxy which adds X-Service-Fabric header to every 404 response.
Assume we have the scenario when ServicePartitionClient cached the endpoint for a stateless service listening on port 3001. At some point, this service may be moved to another node. On the first node, the Service Fabric runtime allocates a different service with its own endpoints but using the same middleware and listening on the same 3001 port.
When a client tries to call the original service at its old (cached) address it will receive 404 response containing the X-Service-Fabric header. According to reverse proxy policies it shouldn't retry, but for me, it seems like the client will stay connected to the wrong service forever and won't attempt to re-resolve the endpoint.
I can't find any information about this case in the documentation, did I miss something here? Is it safe to rely on this standard middleware and don't do retry attempts on 404 errors with X-Service-Fabric: ResourceNotFound header?
In the described case the communication client will be invalidated by staying connected to the wrong service. It is recommended by Microsoft to use unique URL prefixes for services with dynamically-assigned port to handle those scenarios.
In ASP.NET Core programmers can leverage ServiceFabricMiddleware which checks URL prefixes and returns 410 Gone if they don't match. Then HTTP implementation of ICommunicationClient can retry with re-resolving endpoint only for 410 responses and don't perform any retries on 404 response with X-Service-Fabric: ResourceNotFound header if reverse proxy integration is enabled.
In your given scenario, when your Client encounters a 404, the X-Service-Fabric:ResourceNotFound header isn't the only attribute your code could examine when deciding whether or not to retry some operation.
To simplistically address your concern that your client won't be able to tell the difference between a "friendly" node and a "newly arrived" node, and since you're already working with http headers, you could add a custom HTTP header to outgoing responses to identify that a request comes from your application.
When the client receives a 404, you can simply check for the presence of your custom header to answer the question of whether or not it's a "legit" retry. Of course, adding a custom HTTP header just for the sake of this validation check may be more of a global solution to a local problem. Ed: goes without saying that this should not be used to make security decisions by the application
A more elegant and complex means of accomplishing the same would be to deduce the same result using a different combination of HTTP headers and response attributes (e.g., see if some other headers are expected/unexpected), but this could also be a hyper-local solution to the problem.

ASP.Net Core Detect real client IP

I've got an ASP.NET Core app hosting on IIS, the server with which is behind the router. I need to detect real clients IPs. From the local network context.HttpContext.Connection.RemoteIpAddress returns correct IP, but from the outside it is always 127.0.0.1.
Also I tried to look at X-Original-For header which locally gives 127.0.0.1 and nothing form the outside.
I tried UseForwardedHeaders (https://stackoverflow.com/a/41450563/4801505) middleware but as I got it the middleware is already used by UseIISIntegration (https://github.com/aspnet/Docs/issues/2384) so there is no sense using it twice.
So, can I achieve the thing at all in my circumstances? Maybe some IIS config required?
Use the external link to get ip address.
I end up using
var httpClient = new HttpClient();
var ip = await httpClient.GetStringAsync("https://api.ipify.org");
If you are using any language other than C# refer to website ipify

Equivalent for Request.UserHostName in OWIN/Nancy

I am trying to return the users host name (not address) in owin. I am running nancy on top of this. I know I can use this.Request.UserHostAddress to get the IP but I need the name. I have looked through the API's goggled and I ma struggling to find this information.
The only way I can determine to do this is use the ASP.NET HttpContext.Current.Request.UserHostName but this won't work when we self host owin and writing code to determine this information depending on how OWIN is hosted seems to defeat the object of OWIN.
From an IP address, you can use Dns.GetHostEntry (or moral equivalents) to get a IPHostEntry object that has a HostName property.
That's all that UserHostName was doing for you anyway (a DNS lookup):
Gets the DNS name of the remote client.

Request.IsLocal alternative?

As far as I understand, Request.IsLocal returns true in two scenarios. If the IP address of the request originator is 127.0.0.1, or if the IP address of the request is the same as the server's IP address.
I'm using this on a page which is regularly called by a cron task (using an absolute URL). Unfortunately this cron job is run on the same server as the page, meaning that IsLocal always returns true.
Ideally, I need a function which will just return true if I'm on localhost. How can I do this in a ASP.NET MVC environment?
You could look at the Request.Url property in MVC, but you need to check for 127.0.0.1, localhost and ::1 at least. There's also quite a lot you can do with UrlRewrite if all you want to do is request access. You don't say what you want to do if it returns true/false but assuming that's one of the things you want to do, have a look at UrlRewrite. There's a bunch of useful information in this post too;
How to limit page access only to localhost?

Categories

Resources