Search code examples
c#wcf

Retrieve destination IP address from OperationContext MessageProperties


I've seen posts on how to retrieve the caller's IP address (RemoteEndpointMessageProperty within MessageProperties within OperationContext) but can't find anything that shows the local IP address involved in the exchange.

For the source IP (i.e. the caller) I've seen this: WCF 4 Rest Getting IP of Request?

What about getting the destination IP address? Yes, I recognize that it's my IP address, but I want to know which one they used.


Solution

  • I know it's an old question, but it is possible to get the server's/host's IP address for which the request is coming in on by using reflection. The answer given by Igor Tkachenko will only give the URI used by the client. That could contain an IP address, a fully qualified DNS name, or just a NetBIOS host name. That is not sufficient for my needs.

    As was hinted at by joelc, we know that the HttpListenerContext has and exposes a LocalEndPoint property that contains the information we need. Fortunately, under the hood, the WCF does use the HttpListenerContext. So we just need to find it and access it via reflection. That can be done with the following code:

    // The HttpListenerContext we need is in a private field of an internal WCF class.
    // Use reflection to get the value of the field.
    var fieldInfo = OperationContext.Current.RequestContext.GetType().GetField("listenerContext", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
    var listenerContext = (System.Net.HttpListenerContext)fieldInfo.GetValue(OperationContext.Current.RequestContext);
    var serverIP = listenerContext.Request.LocalEndPoint.Address;
    
    Debug.WriteLine(serverIP);
    
    // For comparison, if you just use the .Via or Header.To properties, you will
    // only get what the client used in their URL.
    var url = OperationContext.Current.IncomingMessageProperties.Via;
    
    Debug.WriteLine(url);
    
    var to = OperationContext.Current.RequestContext.RequestMessage.Headers.To;
    
    Debug.WriteLine(to);
    

    So, for example, if a client makes the following request:

    GET https://sg4.kevdev.local/RSTS/page HTTP/1.1
    Host: sg4.kevdev.local
    

    The output of the above code, when running on my server, will be:

    172.21.21.4
    https://sg4.kevdev.local/RSTS/page
    https://sg4.kevdev.local/RSTS/page
    

    From that, you can tell the difference between the result of the LocalEndPoint versus the other properties.

    In my use case, I need the server's IP address to be able to make another request to the server when running in a clustered environment. I would not be able to rely upon or use the value passed in the URI by the client because my server may not be able to resolve the DNS name, or the server may be behind a load balancer and I don't want the request that is made by the server to go through the load balancer again.