locked
Secure WCF Services with IP Address RRS feed

  • Question

  • Does anyone know the easiest way to secure WCF services to only allow certian IP ranges to hit it (whitelisting)? I looked into ipSecurity, but there is a lot of server configuration to make it work. I would really like to NOT get out IS deepartment involved.

    Thanks,
    David McCarter


    Microsoft MVP

    Thursday, July 12, 2012 4:33 PM

Answers

  • One easy way would be to use a message inspector, and check the RemoteEndpointMessageProperty for the client IP address. If it falls outside your whitelist, then throw an exception on the inspector, and the service won't be hit.

        public class Post_3ecb563f_7785_4e01_81a4_00c58216c343
        {
            [ServiceContract]
            public interface ITest
            {
                [OperationContract]
                string Echo(string text);
            }
            public class Service : ITest
            {
                public string Echo(string text)
                {
                    return text;
                }
            }
            public class MyIpRangeFilterInspector : IEndpointBehavior, IDispatchMessageInspector
            {
                public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
                {
                }
                public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
                {
                }
                public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
                {
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
                }
                public void Validate(ServiceEndpoint endpoint)
                {
                }
                public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
                {
                    RemoteEndpointMessageProperty prop = request.Properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
                    if (!IsValidClientAddress(prop.Address))
                    {
                        throw new FaultException(new FaultReason("Invalid client address"));
                    }
                    return null;
                }
                public void BeforeSendReply(ref Message reply, object correlationState)
                {
                }
                private bool IsValidClientAddress(string address)
                {
                    // implement your custom logic here
                    return true;
                }
            }
            public static void Test()
            {
                string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
                ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
                ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new WSHttpBinding(), "");
                endpoint.Behaviors.Add(new MyIpRangeFilterInspector());
                host.Open();
                Console.WriteLine("Host opened");
                ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new WSHttpBinding(), new EndpointAddress(baseAddress));
                ITest proxy = factory.CreateChannel();
                Console.WriteLine(proxy.Echo("Hello"));
                ((IClientChannel)proxy).Close();
                factory.Close();
                Console.Write("Press ENTER to close the host");
                Console.ReadLine();
                host.Close();
            }
        }


    Carlos Figueira

    • Marked as answer by Yi-Lun Luo Thursday, July 19, 2012 9:22 AM
    Thursday, July 12, 2012 5:57 PM

All replies

  • One easy way would be to use a message inspector, and check the RemoteEndpointMessageProperty for the client IP address. If it falls outside your whitelist, then throw an exception on the inspector, and the service won't be hit.

        public class Post_3ecb563f_7785_4e01_81a4_00c58216c343
        {
            [ServiceContract]
            public interface ITest
            {
                [OperationContract]
                string Echo(string text);
            }
            public class Service : ITest
            {
                public string Echo(string text)
                {
                    return text;
                }
            }
            public class MyIpRangeFilterInspector : IEndpointBehavior, IDispatchMessageInspector
            {
                public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
                {
                }
                public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
                {
                }
                public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
                {
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
                }
                public void Validate(ServiceEndpoint endpoint)
                {
                }
                public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
                {
                    RemoteEndpointMessageProperty prop = request.Properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
                    if (!IsValidClientAddress(prop.Address))
                    {
                        throw new FaultException(new FaultReason("Invalid client address"));
                    }
                    return null;
                }
                public void BeforeSendReply(ref Message reply, object correlationState)
                {
                }
                private bool IsValidClientAddress(string address)
                {
                    // implement your custom logic here
                    return true;
                }
            }
            public static void Test()
            {
                string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
                ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
                ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new WSHttpBinding(), "");
                endpoint.Behaviors.Add(new MyIpRangeFilterInspector());
                host.Open();
                Console.WriteLine("Host opened");
                ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new WSHttpBinding(), new EndpointAddress(baseAddress));
                ITest proxy = factory.CreateChannel();
                Console.WriteLine(proxy.Echo("Hello"));
                ((IClientChannel)proxy).Close();
                factory.Close();
                Console.Write("Press ENTER to close the host");
                Console.ReadLine();
                host.Close();
            }
        }


    Carlos Figueira

    • Marked as answer by Yi-Lun Luo Thursday, July 19, 2012 9:22 AM
    Thursday, July 12, 2012 5:57 PM
  • One easy way would be to use a message inspector, and check the RemoteEndpointMessageProperty for the client IP address. If it falls outside your whitelist, then throw an exception on the inspector, and the service won't be hit.

        public class Post_3ecb563f_7785_4e01_81a4_00c58216c343
        {
            [ServiceContract]
            public interface ITest
            {
                [OperationContract]
                string Echo(string text);
            }
            public class Service : ITest
            {
                public string Echo(string text)
                {
                    return text;
                }
            }
            public class MyIpRangeFilterInspector : IEndpointBehavior, IDispatchMessageInspector
            {
                public void AddBindingParameters(ServiceEndpoint endpoint, BindingParameterCollection bindingParameters)
                {
                }
                public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
                {
                }
                public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
                {
                    endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
                }
                public void Validate(ServiceEndpoint endpoint)
                {
                }
                public object AfterReceiveRequest(ref Message request, IClientChannel channel, InstanceContext instanceContext)
                {
                    RemoteEndpointMessageProperty prop = request.Properties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
                    if (!IsValidClientAddress(prop.Address))
                    {
                        throw new FaultException(new FaultReason("Invalid client address"));
                    }
                    return null;
                }
                public void BeforeSendReply(ref Message reply, object correlationState)
                {
                }
                private bool IsValidClientAddress(string address)
                {
                    // implement your custom logic here
                    return true;
                }
            }
            public static void Test()
            {
                string baseAddress = "http://" + Environment.MachineName + ":8000/Service";
                ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
                ServiceEndpoint endpoint = host.AddServiceEndpoint(typeof(ITest), new WSHttpBinding(), "");
                endpoint.Behaviors.Add(new MyIpRangeFilterInspector());
                host.Open();
                Console.WriteLine("Host opened");
                ChannelFactory<ITest> factory = new ChannelFactory<ITest>(new WSHttpBinding(), new EndpointAddress(baseAddress));
                ITest proxy = factory.CreateChannel();
                Console.WriteLine(proxy.Echo("Hello"));
                ((IClientChannel)proxy).Close();
                factory.Close();
                Console.Write("Press ENTER to close the host");
                Console.ReadLine();
                host.Close();
            }
        }


    Carlos Figueira

    thank for this
    Sunday, December 16, 2012 8:12 AM