I'm looking for a way to enable or disable certain IPs from accessing and adding my WCF service as service reference.
Currently it's possible to add our Webservice publicly, how can I add an IP filter?
Or is there any other setting I could use?
I've seen Can I setup an IP filter for a WCF Service? about adding <IPFilter /> to web.config, but the essential part in code is missing thus unusable.
Note; The webservices are part of a bigger project and cannot be separated as individual project which is available via HTTPS (a website).
Since I don't think there is an automatic way to do it in WCF, you have two main options:
If you want something secured, don't want to implement anything but your environment uses firewalls, you can configure the firewall in order to refuse the connections coming from specific IP addresses.
Otherwise, you can implement an IP filter as in the article you mentionned (i.e. as a serviceBeharvior, not described here) or simpler as a single private method called by all your public webservice methods that throw an error code if the IP of the client is not allowed (based on white or black lists of IPs in a file or a database).
/// <summary>
/// Get the client IP address.
/// </summary>
private string GetClientIpAddress()
{
string result = string.Empty;
try
{
OperationContext context = OperationContext.Current;
MessageProperties messageProperties = context.IncomingMessageProperties;
RemoteEndpointMessageProperty endpointProperty = messageProperties[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
result = endpointProperty.Address;
}
catch (Exception ex)
{
logger.Error(ex);
}
return result;
}
/// <summary>
/// Returns <code>true</code> if the current IP address is allowed
/// to access the webservice method, <code>false</code> otherwise.
/// </summary>
private bool CheckIPAccessRestriction()
{
bool result = false;
List<string> allowed = GetAllowedIpAddressesList();
if (allowed.Count() == 0)
{
result = true;
}
else
{
var ip = GetClientIpAddress();
result = allowed.Contains(ip);
}
return result;
}
If you Web service is hosted in IIS you can restrict IP addresses there:
Related
I am building an app in XAMARIN, that has to connect to a custom device via wifi and that device does not have internet connection. So my app always wants to work on mobile data and there for never communicating with the device. Is there anyway to force the app to use only WIFI and never mobile data? I guess I'm not the only one with that problem as I've seen a few posts about this, but none in xamarin specific.
EDIT:
I found that if I let the application run for about 50 seconds, then it will use the wifi insted of mobile data. Is this due to some timeout? If so, then can I shorten the timeout?
After a lot of sweating I have found the solution. Make a class with this code:
using Android.Content;
using Android.Net;
namespace Project.Communication
{
class ForceNetworkType
{
public static Context _context = Android.App.Application.Context;
/// <summary>
/// Forces the wifi over cellular
/// </summary>
public static void ForceWifiOverCellular()
{
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.AddTransportType(TransportType.Wifi);
var callback = new ConnectivityManager.NetworkCallback();
connection_manager.RegisterNetworkCallback(request.Build(), new CustomNetworkAvailableCallBack());
}
/// <summary>
/// Forces the cellular over wifi.
/// </summary>
public static void ForceCellularOverWifi()
{
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
NetworkRequest.Builder request = new NetworkRequest.Builder();
request.AddTransportType(TransportType.Cellular);
connection_manager.RegisterNetworkCallback(request.Build(), new CustomNetworkAvailableCallBack());
}
}
/// <summary>
/// Custom network available call back.
/// </summary>
public class CustomNetworkAvailableCallBack : ConnectivityManager.NetworkCallback
{
public static Context _context = Android.App.Application.Context;
ConnectivityManager connection_manager = (ConnectivityManager)_context.GetSystemService(Context.ConnectivityService);
public override void OnAvailable(Network network)
{
//ConnectivityManager.SetProcessDefaultNetwork(network); //deprecated (but works even in Android P)
connection_manager.BindProcessToNetwork(network); //this works in Android P
}
}
}
And Then you just use where you need to force certain Network:
ForceNetworkType.ForceWifiOverCellular();
to force the wifi over mobile data.
Using Xamarin.Essentials.
Like this:
>
var profiles = Connectivity.ConnectionProfiles;
if (profiles.Contains(ConnectionProfile.WiFi))
{
// Active Wi-Fi connection.
}
You can change this check to block users that without a wifi connection.
reference:
https://learn.microsoft.com/en-us/dotnet/api/xamarin.essentials.connectionprofile?view=xamarin-essentials
I believe the best you can actually do is set the preference of what you want the device to use. With both OS, it will prefer a Wifi connection over a cellular connection unless it times out on the request.
However you can use the Reachability class in iOS to say something like:
//PseudoCode
if(ReachabilityStatus == ReachableViaWifi)
{
//Only do things when WIFI is on
}
else
{
//Only do things when WIFI is not on
}
Within Android, you can do the following with ConnectivityManager:
//PseudoCode again
ConnectivityManager connectivityManager = (ConnectivityManager)GetSystemService(Context.ConnectivityService);
NetworkInfo wifi = connectivityManager.GetNetworkInfo(ConnectivityType.Wifi);
if (wifi.IsConnected)
{
//Pretty fly for a wifi
}
else
{
//No wifi here!
}
I am developing a microservice architecture application where I am using a Redis Cache to cache frequently used information. The issue is that the number of connected clients is constantly increasing and I don't know why.
I am accessing the Redis Cache from an ASP.NET Web API and a Web Job. The NuGet package used for connection is "StackExchange.Redis" (https://github.com/StackExchange/StackExchange.Redis).
The way I am connecting to Redis in code is as follows:
connection = ConnectionMultiplexer.Connect(configurationOptions);
connection.ConnectionFailed += ConnectionFailed;
connection.ConnectionRestored += ConnectionRestored;
connection.InternalError += InternalError;
if (!connection.IsConnected)
{
//_traceSource.TraceWarning($"Connection to REDIS '{_endpointAddress}' was not established.");
}
database = connection.GetDatabase();
return database;
In addition, I have implemented the Dispose() method to make sure that connections are disconnected properly:
public void Dispose()
{
connection?.Close(true);
}
Implement a static Helper class like this.
/// <summary>
/// Helper class for connection with Redis Server.
/// </summary>
public static class Helper
{
/// <summary>
/// Configuration option to connect with Redis Database.
/// </summary>
private static Lazy<ConfigurationOptions> configOptions = new Lazy<ConfigurationOptions>(() =>
{
var configOptions = new ConfigurationOptions();
configOptions.EndPoints.Add("Your Redis sever name");
configOptions.AbortOnConnectFail = false;
configOptions.AllowAdmin = true;
configOptions.KeepAlive = 4;
configOptions.Password = "Redis server password";
return configOptions;
});
private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => ConnectionMultiplexer.Connect(configOptions.Value));
/// <summary>
/// Connection property to connect Redis Database.
/// </summary>
public static ConnectionMultiplexer Connection
{
get
{
return lazyConnection.Value;
}
}
}
After that use it like this wherever you need it.
var RedisDatabase = Helper.Connection.GetDatabase(Database Number);
This will maintain the connections automatically. Hope this will help.
I'd take the following 3 steps :
Add shutdown hook which calls connection.close().
Refer : How to call event before Environment.Exit()?
But it's not guaranteed to be called always. Hence, #2:
Configure Redis with client timeout to close connections idle > some threshold
https://redis.io/topics/clients
Ensure duplicate connections aren't created unnecessarily. Ex: a new connection is created per call to Redis. #Keyur Ramoliya 's answer seems to address this.
I am trying to find out when the TCP connection has been established while using HttpWebRequest, how these connections have been pooled and reused using ServicePoint.
I have looked at the system.dll, and tried to browse through the code using ILSpy and Reflector, somehow didn't see any references to sockets, establishing tcp connection etc.
Below I have pasted the decompiled code - can any please give me tips or redirect me so that I can understand:
When the TCP connection has been created?
How these connections are kept alive, pooled and reused using ServicePoint?
Code snippet from HttpWebRequest of System.dll:
public override Stream GetRequestStream()
{
TransportContext context;
return this.GetRequestStream(out context);
}
public Stream GetRequestStream(out TransportContext context)
{
if (Logging.On)
{
Logging.Enter(Logging.Web, this, "GetRequestStream", "");
}
context = null;
this.CheckProtocol(true);
if ((this._WriteAResult == null) || !this._WriteAResult.InternalPeekCompleted)
{
lock (this)
{
if (this._WriteAResult != null)
{
throw new InvalidOperationException(SR.GetString("net_repcall"));
}
if (this.SetRequestSubmitted())
{
throw new InvalidOperationException(SR.GetString("net_reqsubmitted"));
}
if (this._ReadAResult != null)
{
throw ((Exception) this._ReadAResult.Result);
}
this._WriteAResult = new LazyAsyncResult(this, null, null);
this.Async = false;
}
this.CurrentMethod = this._OriginVerb;
while (this.m_Retry && !this._WriteAResult.InternalPeekCompleted)
{
this._OldSubmitWriteStream = null;
this._SubmitWriteStream = null;
this.BeginSubmitRequest();
}
while (this.Aborted && !this._WriteAResult.InternalPeekCompleted)
{
if (!(this._CoreResponse is Exception))
{
Thread.SpinWait(1);
}
else
{
this.CheckWriteSideResponseProcessing();
}
}
}
ConnectStream connectStream = this._WriteAResult.InternalWaitForCompletion() as ConnectStream;
this._WriteAResult.EndCalled = true;
if (connectStream == null)
{
if (Logging.On)
{
Logging.Exception(Logging.Web, this, "EndGetRequestStream", this._WriteAResult.Result as Exception);
}
throw ((Exception) this._WriteAResult.Result);
}
context = new ConnectStreamContext(connectStream);
if (Logging.On)
{
Logging.Exit(Logging.Web, this, "GetRequestStream", connectStream);
}
return connectStream;
}
K, after browsing through code some time I think I kind of understood the abstractions. Basically servicepoint, servicepoint manager, how the tcp connection has been created, connections have been pooled, queued etc. always confused me. Below information kind of helped me - hopefully this is useful for others who are curious or tried to understand these details:
ServicePoint: High level abstraction of 'connection' to a particular host (destination Host Ip:port)
(that's why for ex, function static ServicePoint FindServicePoint(string host, int port) is defined in servicePointManger.
ServicePointManager: as the name indicates its the global (static) class which manages service points.
Connection (internal class): Basically this is the one I think that represents TCP connection. it basically derives from System.Net.PoolStream (internal class - it has the definitions of the sockets its using) which derives from stream.
ConnectionGroup (internal class): Each HttpWebRequest is associated with a connection group.
(basically based on connectionLimit it creates at most connectionLimit (can be configured globally through ServicePointManager, and also per httpwebrequest using its servicePoint property) number of connection objects per httpwebrequest)
If the connection limit is reached, its simply queued and passed to the wire (most likely - but still didn't get the code which does this).
And if you are connecting to service on the local machine, the servicepoint.connectionlimit no longer equal to servicepointmanager.defaultconnectionlimit. it defaults to; int.Maxvalue (2147483647 or 7FFFFFFF) ( you may refer to: http://blogs.microsoft.co.il/idof/2011/06/20/servicepointmanagerdefaultconnectionlimit-2-depends/ )
Update:
Looks like following two links are useful too:
System.Net.ServicePointManager.DefaultConnectionLimit and .MaxServicePointIdleTime
http://blogs.msdn.com/b/jpsanders/archive/2009/05/20/understanding-maxservicepointidletime-and-defaultconnectionlimit.aspx
Best Regards!
Using the code from this answer - Async two-way communication with Windows Named Pipes (.Net) - I'm finding the maximum number of connections/clients at any one time is 10.
In the crude example below (this uses multiple threads - same thing happens if multiple processes are used) clients 1 to 10 will start and run as normal. However clients 11 and 12 will block when 'ProcessData' is called, eventually throwing a TimeoutException.
public static void Start()
{
// Start Server
new Thread(new ThreadStart(Server.MainRun)).Start();
// Start Clients
for (int i = 1; i <= 12; i++)
{
Thread.Sleep(500);
Client c = new Client(i.ToString());
new Thread(new ThreadStart(c.Run)).Start();
}
}
// Create a contract that can be used as a callback
public interface IMyCallbackService
{
[OperationContract(IsOneWay = true)]
void NotifyClient();
}
// Define your service contract and specify the callback contract
[ServiceContract(CallbackContract = typeof(IMyCallbackService))]
public interface ISimpleService
{
[OperationContract]
string ProcessData();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class SimpleService : ISimpleService
{
public string ProcessData()
{
// Get a handle to the call back channel
var callback = OperationContext.Current.GetCallbackChannel<IMyCallbackService>();
callback.NotifyClient();
return DateTime.Now.ToString();
}
}
class Server
{
public static void MainRun()
{
// Create a service host with an named pipe endpoint
using (var host = new ServiceHost(typeof(SimpleService), new Uri("net.pipe://localhost")))
{
host.AddServiceEndpoint(typeof(ISimpleService), new NetNamedPipeBinding(), "SimpleService");
host.Open();
Console.WriteLine("Simple Service Running...");
Console.ReadLine();
host.Close();
}
}
}
class Client : IMyCallbackService
{
string _id;
public Client(string ID)
{
_id = ID;
}
public void Run()
{
Console.WriteLine("Starting client : " + _id);
// Consume the service
var factory = new DuplexChannelFactory<ISimpleService>(new InstanceContext(this), new NetNamedPipeBinding(), new EndpointAddress("net.pipe://localhost/SimpleService"));
var proxy = factory.CreateChannel();
Console.WriteLine(proxy.ProcessData());
Console.WriteLine("Client finished : " + _id);
}
public void NotifyClient()
{
Console.WriteLine("Notification from Server");
}
}
If the client closes the channel when done (factory.Close()) then all clients will be able to run.
I understand this question - Number of Clients that can connect to a Named Pipe - is very similar but suggests there is no low limit.
This suggests the limit is 10 on Windows XP and 2000 machines - http://msdn.microsoft.com/en-us/library/system.io.pipes.namedpipeclientstream.aspx - except this is happening on a Windows 8 machine and Windows 2008 server.
Is there a way to change this limit? Am I missing something obvious?
Google brought me here a year after this question was asked. I figure I may as well post to help anyone else who ends up here. I think I know why the limit of 10.
Are you aware of the NetNamedPipeBinding.MaxConnections property?
Gets or sets the maximum number of connections, both inbound and outbound, that are allowed to endpoints configured with the named pipe binding. ... The maximum number of named pipe connections that are allowed with this binding. The default value is 10.
"guest" is correct and an old blog post from MSDN corroborates this as still being applicable in current .net releases.
It also suggests that the default setting was defined for use with development environments and "small" deployments.
From the other settings (eg, the buffer size) I'd suggest that >8kb per connection overhead would be expected.
I have not yet found any information on what issues may arise if the value is tuned for larger values (eg, >1000): the API appears tuned for shorter, burstier requests and I suspect for large values it may simply be inefficient (not so much for memory but just internal implementation) -
I'd welcome evidence either way on performance/issues (or success) with significant numbers of clients attaching to an endpoint.
At this line of code i am getting the error as i mentioned
I declared MSMQ_NAME as string as follows
private const string MSMQ_NAME = ".\\private$\\ASPNETService";
private void DoSomeMSMQStuff()
{
using (MessageQueue queue = new MessageQueue(MSMQ_NAME))
{
queue.Send(DateTime.Now); //Exception raises
queue.Close();
}
}
Can you first verify the queue is existing with the name 'ASPNETService' at below location?
Computer Management -> Services and Applications -> Message Queuing -> Private Queues
I had a similar problem. I was confused because my code worked on my local development machine, but not in production. Even stranger, the queues were created the exact same way.
It turns out that IIS doesn't have access to them by default. I just opened up the permissions.
Computer Management -> Private Queues -> right-click queue name -> Properties -> Security Tab -> click "Everyone" user -> click Full Control/Allow checkbox -> click OK
This fixed it for me, and in my case it's not an issue, but you may want to think about the ramifications of just opening it up for all users.
Also, I had to do this across all queues on all servers. There doesn't seem to be a way to multi-select queues or folders in order to set permissions for multiple queues simultaneously.
I was having the same problem.
I had created a new private queue and gave Full Permission to Everyone.
But I was still catching a "Queue does not exist or you do not have sufficient permissions to perform the operation" when trying to Send() to the queue. And I was able to verify that MessageQueue.Exists(".\\private$\\myqueue") was returning true.
Restarting the Message Queuing Service resolved my the problem for me.
I had same problem and I did like below where I check whether queue exists or not. If yes send message else create queue and then send message
MessageQueue msgQueue = null;
string queuePath = ".\\Private$\\billpay";
Payment newPayment = new Payment()
{
Payee = txtPayee.Text,
Payor = txtPayor.Text,
Amount = Convert.ToInt32(txtAmount.Text),
DueDate = dpDueDate.SelectedDate.Value.ToShortDateString()
};
Message msg = new Message();
msg.Body = newPayment;
msg.Label = "Gopala - Learning Message Queue";
if (MessageQueue.Exists(queuePath) == false)
{
//Queue doesnot exist so create it
msgQueue = MessageQueue.Create(queuePath);
}
else
{
msgQueue = new MessageQueue(queuePath);
}
msgQueue.Send(msg);
I was facing the same problem, I had resolved it using the following class to create queue
private MessageQueue messageQueue;
public const string DEFAULT_QUEUE_NAME = "newQueue";
public const string QUEUENAME_PREFIX = ".\\Private$\\";
public static string QueueName
{
get
{
string result = string.Format("{0}{1}", QUEUENAME_PREFIX, DEFAULT_QUEUE_NAME);
return result;
}
}
public void SendMessage()
{
string queuePath = QueueName;
MessageQueue messageQueue = MessageQueue.Create(queuePath);
messageQueue.Send("msg");
}
Create message queue in same manner for receiving the message.
For others struggling with this and pulling their hair out like I have been, I finally found something that works when all of the upvoted suggestions failed.
Even if you think the host name of your target queue's hosting system is being resolved correctly, don't believe it. Try replacing the host name with an IP address and see if it works. It does for me. I can WRITE to a public queue using a host name on my remote server without problems, but trying to READ from it produces exactly the error listed for this question.
For example, if I declare the following:
private static string QueueName = #"FormatName:DIRECT=TCP:SOMEHOST\MyQueue";
private static System.Messaging.MessageQueue Queue = new System.Messaging.MessageQueue(QueueName);
Where "MyQueue" is a public queue on server SOMEHOST, the following code will successfully insert messages to the queue, but always fails on the Receive():
Queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(String) });
// The Receive() call here is a blocking call. We'll wait if there is no message in the queue, and processing
// is halted until there IS a message in the queue.
//
try
{
Queue.Send("hello world", System.Messaging.MessageQueueTransactionType.Single);
var msg = Queue.Receive(MessageQueueTransactionType.Single);
}
catch (Exception ex)
{
// todo error handling
}
One simple change in how I specify the queue location is all that's needed to make the Receive() stop failing with the dreaded "queue does not exist or you do not have sufficient permissions" error:
private static string QueueName = #"FormatName:DIRECT=TCP:192.168.1.100\MyQueue";
(Obviously I've obfuscated IP addresses and other sensitive info). Using the IP address is not obviously a production-worthy scenario, but it did point me to some type of name resolution problem as being the possible cause of the error. I cannot explain why Send() works but Receive() does not when I am using a host name instead of IP, but I can reproduce these results consistently. Until I can figure out what's going on with the name resolution, I'm no longer wasting a day trying to read messages from a queue.