Get client IP address for WCF, post operation

Wayne Lo picture Wayne Lo · Aug 27, 2010 · Viewed 9k times · Source

I am trying to determine the client's IP address following this link: http://www.danrigsby.com/blog/index.php/2008/05/21/get-the-clients-address-in-wcf/

In .Net 3.0 there was not a reliable way to obtain the address of the client connecting to a WCF service. In .Net 3.5 a new property was introduced called RemoteEndpointMessageProperty. This property gives you the IP address and port that the client connection came into the service on. Obtaining the this information is pretty straight forward. Just pull it from the IncomingMessageProperties of the current OperationContext by the RemoteEndpointMessageProperty.Name and access the Address and Port properties.

> [ServiceContract] public interface IMyService {
>     [OperationContract]
>     string GetAddressAsString(); }
> 
> public class MyService : IMyService {
>     public string GetAddressAsString()
>     {
>         RemoteEndpointMessageProperty clientEndpoint =
>             OperationContext.Current.IncomingMessageProperties[
>             RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
> 
>         return String.Format(
>             "{0}:{1}",
>             clientEndpoint.Address, clientEndpoint.Port);
>     } } 

Things to note:

  1. This property only works on http and tcp transports. On all other transports such as MSMQ and NamedPipes, this property will not be available.
  2. The address and port are reported by the socket or http.sys of the service’s machine. So if the client came in over a VPN or some other proxy that modified the address, that new address will be represented instead of the client’s local address. This is desirable and important because this is the address and port that the service sees the client as, not as the client sees itself as. This also means that there could be some spoofing going on. A client or something in between the client and server could spoof an address. So, do not use the address or port for any security decisions unless you add in some other custom checking mechanisms.
  3. If you are using duplexing on your service, then not only will the service have this property populated for the client, but the client will also have this property populated for the service for each call from that service.

I have operationContracts of WebInvoke/Post and WebGet. The code works when the client request is a WebGet. But when the client request is a WebInvoke, I will get the WCF host IP. Any solution? Thanks.

Here is the interface

[OperationContract]
[WebGet(UriTemplate = RestTemplate.hello_get)]
Stream hello_get();

[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = RestTemplate.hello_post)]
Stream hello_post();

// Code for getting IP
private string getClientIP()
{
    //WebOperationContext webContext = WebOperationContext.Current;

    OperationContext context = OperationContext.Current;

    MessageProperties messageProperties = context.IncomingMessageProperties;

    RemoteEndpointMessageProperty endpointProperty =

    messageProperties[RemoteEndpointMessageProperty.Name]

    as RemoteEndpointMessageProperty;
    return endpointProperty.Address;
}

public Stream hello_get()
{
    string ip = getClientIP();
    ...
}

public Stream hello_post()
{
    string ip = getClientIP();
    ...
} 

Answer

Pierrick picture Pierrick · Aug 17, 2014

Have you tried using the HttpContext? It's not available in all WCF modes but this could work depending on your environment:

if (HttpContext.Current != null)
            {
                Trace.WriteLine(
                    "Who's calling? IP address: '{0}', Name: '{1}', User Agent: '{2}', URL: '{3}'.",
                    HttpContext.Current.Request.UserHostAddress, HttpContext.Current.Request.UserHostName,
                    HttpContext.Current.Request.UserAgent, HttpContext.Current.Request.Url);
            }