.NET 3.0 では当初クライアントのIPアドレスを調べる方法がありませんでしたが、.NET 3.0 SP1 以降は仕様できるようになったようです。
IPアドレスを取得できるのはTCPかHTTP通信を行っている場合に限ります。

実装することになった流れは以下のリンクを参照してください。

Nicholas Allenのブログ
その1 http://blogs.msdn.com/drnick/archive/2007/05/16/client-ip-address.aspx
その2 http://blogs.msdn.com/drnick/archive/2007/09/10/more-about-client-ip-addresses.aspx

Phil Henningのブログ
結果こうなりました http://blogs.msdn.com/phenning/archive/2007/08/08/remoteendpointmessageproperty-in-wcf-net-3-5.aspx

先に確認結果から記述すると、同一マシン上で、WCFホスト,WCFクライアント通信ではクライアントのポートアドレスは取得できましたが、IPアドレスはうまく取得できませんでした。
異なるPC上での通信の場合はクライアントのIPアドレスを取得できました。


確認環境は次のとおり(まいど思いつきで書いてます)

  • Windows Vista Enterprise(ホスト,クライアント)
  • .NET 3.5
  • Windows 2003 Server R2 Enterprise Edition(クライアント)
  • WCFの通信tプロトコルnet.tcp

1.サービスメソッド上で、クライアントのIPアドレスを取得する

サービスメソッド上でIPを取得するにはメソッドないで、次のように記述します。取得したRemoteEndpointMessagePropertyのAddressとPortプロパティで、クライアントのIPアドレスとポートアドレスを取得します。

なんらかのサービスメソッド内 ...
OperationContext.Current.IncomingMessageProperties[System.ServiceModel.Channels.RemoteEndpointMessageProperty.Name];
....

 1.1同一PC上でIPアドレスの取得を行った場合

私の環境では次のように取得されました。なんか値がおかしいのですが、間違っていたらだれか教えて下さい。
補足:enraさんの指摘で::1はIPv6のループバックアドレスということで、一応ただしく取れているという認識でよさそうです。

    Address: "::1"
    Port: 50464

1.2異なるPC上のクライアントからIPアドレスを取得した場合

私の環境では次のように取得されました。正しく取得できています。

    Address: "192.168.0.3
   Port: 50213

2.アクセスログを取得に応用してみる

IDispatchMessageInspectorを使用して、クライアントからリクエスト,クライアントへのリスポンス時にSOAPメッセージをフックして、アクセスログを残す方法を記載します。このときにクライアントのIPアドレスを取得機能を利用します。クラス、インタフェースなどの細かい説明はMSDNライブラリを参照してください。処理内容はなんとなくわかると思います。

まず、System.ServiceModel.DispatcherネームスペースのIDispatchServiceMessageInspectorを実装します。

class Interface1 : IDispatchMessageInspector
    {

        #region IDispatchMessageInspector Member

        object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            RemoteEndpointMessageProperty endpoint = request.Properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
            Console.WriteLine("Requested : {0}, from {1}\n body:{2}", request.Headers.Action, endpoint.Address, request.ToString())
           
            return null;
        }

        void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            throw new NotImplementedException();
        }

        #endregion
    }

System.ServiceModel.Description.IServiceBehaviorインタフェースをインプリメントします。AddBindingParameters内で、EndpointDispatcherにMessageInspectorを登録します。

class Class1 : IServiceBehavior
    {
        #region IServiceBehavior Members

        void IServiceBehavior.AddBindingParameters(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase, System.Collections.ObjectModel.Collection<ServiceEndpoint> endpoints, System.ServiceModel.Channels.BindingParameterCollection bindingParameters)
        {
        }

        void IServiceBehavior.ApplyDispatchBehavior(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
            foreach (ChannelDispatcher cd in serviceHostBase.ChannelDispatchers)
            {
                foreach (EndpointDispatcher ed in cd.Endpoints)
                {
                    ed.DispatchRuntime.MessageInspectors.Add(new Interface1());
                }
            }
        }

        void IServiceBehavior.Validate(ServiceDescription serviceDescription, System.ServiceModel.ServiceHostBase serviceHostBase)
        {
        }

        #endregion
    }

あとはサービスをホストするプログラム上で作成したServiceBehaviorを登録します。

 

host = new ServiceHost(typeof(WcfExample002.ProductService));
      host.Description.Behaviors.Add(new Class1());
      host.Open();