tags:

views:

33

answers:

2

I have a WCF service that provides access to some data. Our client has requested that this service be limited such that a given user can only make so many calls within a certain time period. My thinking was to establish a request rate limit and issue a temporary ban to that IP address once it exceeded that limit.

However, there appears to be only one way to get the caller's IP using WCF:

var context = OperationContext.Current;
var props = context.IncomingMessageProperties;
var endpoint = props[RemoteEndpointMessageProperty.Name];
return ((RemoteEndpointMessageProperty)endpoint).Address;

This is not useful to me at all because the RemoteEndpointMessageProperty is set using the Request.UserHostAddress property of the HttpContext under which it is being served. Normally, that'd be fine, except our web services are sitting behind a load balancer which causes Request.UserHostAddress to always show the IP of the load balancer, not the original caller.

I know about using X-Forwarded-For and such, and actually already have that configured on our load balancer, but there doesn't seem to be any way for me to hook into the http request to access the headers short of setting the WCF service to operate in ASP.NET compatibility mode. Is this REALLY my only option?

A: 

How do you reliably tie up an user with an IP address specially if the user is behind an ISP NAT (or Company NAT), you will only get the ISP's public IP Address. Instead how about identifying your user using an API Key (which many majors such as Google and Twitter are doing) or by other means (such as client certificate) and then track the usage in a persistence store for throttling.

Another option would be to introduce this sort of mechanism of restrictions by IP address at network layer using firewall rules (I am not experienced by assuming it is possible)

Pratik
The web service will be accessed directly via banner ads. There's no opportunity to assign a specific key for each user. I'm aware of the dangers of IP limiting, but it's all we have at this time.
Chris
Ok, so how about the feasibility of limiting requests by IP using some sort of firewall or intrusion detection system instead of at application layer.
Pratik
A: 

You can access HTTP headers in the same way. Instead of RemoteEndpointMessageProperty you have to use HttpRequestMessageProperty. This property contains Headers name value collection so you should be able to get any HTTP header from incoming request.

Ladislav Mrnka
Ultimately, this answer is valid, so I'm accepting it, but .NET 3.5 and greater added a WebOperationContext class to the System.ServiceModel.Web namespace which makes this a bit easier.
Chris
Yes, but this solution is general for all Http based bindings. WebOperationContext should work only for REST services (exposed on WebHttpBinding).
Ladislav Mrnka