I am writing an Azure Function to ping a particular host to check response times using the System.Net.NetworkInformation.Ping class. I get a generic exception when calling Ping.Send, however this works fine locally.
Are there restrictions on network calls made outbound from Azure Functions?
The exception I get is simply:
Could not ping: An exception occurred during a Ping request.
at System.Net.NetworkInformation.Ping.Send(IPAddress address, Int32 timeout, Byte[] buffer, PingOptions options)
at System.Net.NetworkInformation.Ping.Send(String hostNameOrAddress, Int32 timeout, Byte[] buffer, PingOptions options
As ICMP protocol is not permitted through the Azure, you will not be able to ping an Azure VM from the internet, and from within the Azure VM, you are unable to ping internet locations.
To test connectivity, it is recommended to do a port ping. While Ping.exe uses ICMP, other tools such as PsPing, Nmap, or Telnet which allows you to test connectivity to a specific TCP port.
It is nicely explained in this post - https://blogs.msdn.microsoft.com/mast/2014/06/22/use-port-pings-instead-of-icmp-to-test-azure-vm-connectivity/
Related
I am new to Amazon Web Services Lambda functions, and I decided to write a small function to ping a website. We have a VPC subnet and security group already set up, which I applied to my function when I published it.
When I run this small function in debug mode through Visual Studio it works okay, but once I publish it to AWS Lambda it fails and I get an exception:
System.Net.NetworkInformation.PingException: An exception occurred during a Ping request. ---> System.PlatformNotSupportedException: The system's ping utility could not be found.\n at System.Net.NetworkInformation.Ping.SendWithPingUtility(IPAddress address, Byte[] buffer, Int32 timeout, PingOptions options)\n at System.Net.NetworkInformation.Ping.SendPingAsyncCore(IPAddress address, Byte[] buffer, Int32 timeout, PingOptions options)\n at System.Net.NetworkInformation.Ping.GetAddressAndSendAsync(String hostNameOrAddress, Int32 timeout, Byte[] buffer, PingOptions options)\n --- End of inner exception stack trace ---\n at System.Net.NetworkInformation.Ping.GetAddressAndSendAsync(String hostNameOrAddress, Int32 timeout, Byte[] buffer, PingOptions options)\n at TestPingWebsite.Function.FunctionHandler(String input, ILambdaContext context) in C:\Users\GWhite\source\TestingWebsite\TestPingWebsite\TestPingWebsite\Function.cs:line 26
Can anybody help me understand why this error occurs please?
AWS lambda does not support outbound ICMP (the protocol that drives ping) traffic. In addition to this, the underlying infrastructure to create the ping messages isnt supported either.
From the AWS docs (https://aws.amazon.com/lambda/faqs/):
Q: What restrictions apply to AWS Lambda function code?
Lambda attempts to impose as few restrictions as possible on normal
language and operating system activities, but there are a few
activities that are disabled: Inbound network connections are blocked
by AWS Lambda, and for outbound connections only TCP/IP and UDP/IP
sockets are supported, and ptrace (debugging) system calls are
blocked. TCP port 25 traffic is also blocked as an anti-spam measure.
We have 11 windows webapp machines running IIS. These send messages to rabbitMQ server for tasks. We are using rabbit for basic work queue functionality. For each message publish a new connection and a channel is created. Pretty much like in the tutorial here - https://www.rabbitmq.com/tutorials/tutorial-two-dotnet.html
This is working great most of the time, but in production, sporadically from a different machine every time once or twice a day, we start getting this exception on ConnectionFactory.CreateConnection.
[BrokerUnreachableException: None of the specified endpoints were reachable]
RabbitMQ.Client.ConnectionFactory.CreateConnection():56
[TimeoutException: Connection to amqp://machinename.domain.net:5672 timed out]
RabbitMQ.Client.Impl.SocketFrameHandler.Connect(TcpClient socket, AmqpTcpEndpoint endpoint, Int32 timeout):65
RabbitMQ.Client.Impl.SocketFrameHandler..ctor(AmqpTcpEndpoint endpoint, Func2 socketFactory, Int32 timeout):52
RabbitMQ.Client.Framing.Impl.ProtocolBase.CreateFrameHandler(AmqpTcpEndpoint endpoint, Func`2 socketFactory, Int32 timeout):8
RabbitMQ.Client.ConnectionFactory.CreateConnection():45
Which is causing message loss. I have been investigating max concurrent connections for each machine setting - but did not lead me anywhere. This does not coincide with our peak traffic either. The most interesting clue i have is that it happens in bursts and when it happens it is ONLY happening to one out of the 11 machines publishing messages to the queue at a time.
I am using rabbitmq dot net client.
Any ideas or pointers on what could be the possible cause?
Probably some sort of packet loss? Why not Try...Catch..Retry?
Do a ping RabbitServerHostName -t (where RabbitServerHostName is the server where you have Rabbit installed) in a command window and see after couple of days how many packet losses you have.
Because of all the packet drops and network instability issues, it is almost always a recommended approach to retry your connection creation. EasyNetQ library does it really well. It is however not very complex to implement your own timer based retry when you get this exception until connection is established.
Consider the situation where some client calls WebMethod and after connection was established the host process crashes and connection becomes half-open. Will ASP.NET WebMethod proxy automatically detect it?
We assume that WebMethod timeout settled to the infinity or some big amount of time. Will connectivity error be detected only on TCP keep-alive packet sending (after 2 hours of idle on Windows by default)?
[WebService(Namespace = "http://www.example.com/TestService/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
public class TestService : System.Web.Services.WebService
{
[WebMethod]
public void DoLongWork()
{
// long work here
}
}
Web Reference proxy call:
public void ServiceClient()
{
var serviceProxy = new MyNamespace.TestService();
// serviceProxy.Url = ...
serviceProxy.Timeout = -1; // do not use timeout
// will it wait for 2 hours (when TCP keep-alive will be sent) if connection was lost after handshake?
serviceProxy.DoLongWork();
}
UPDATE.
I've tried multiple scenarios and here the results that I got using Wireshark to see what is going on under the hood.
Stopping hosting Web Server (IIS) through the IIS Manager or killing host process (w3wp.exe):
In both cases client notified via sending TCP RST flag. Seems Windows takes care of closing sockets for crashed/killed processes. In .NET the System.Net.WebException will be thrown:
Unhandled Exception: System.Net.WebException: The underlying connection was closed: An unexpected error occurred on a receive. ---> System.IO.IOException: Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host. ---> System.Net.Sockets.SocketException: An existing connection was forcibly closed by the remote host
at System.Net.Sockets.Socket.Receive(Byte[] buffer, Int32 offset, Int32 size, SocketFlags socketFlags)
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
--- End of inner exception stack trace ---
at System.Net.Sockets.NetworkStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.PooledStream.Read(Byte[] buffer, Int32 offset, Int32 size)
at System.Net.Connection.SyncRead(HttpWebRequest request, Boolean userRetrievedStream, Boolean probeRead)
--- End of inner exception stack trace ---
at System.Web.Services.Protocols.WebClientProtocol.GetWebResponse(WebRequest request)
at System.Web.Services.Protocols.HttpWebClientProtocol.GetWebResponse(WebRequest request)
at System.Web.Services.Protocols.SoapHttpClientProtocol.Invoke(String methodName, Object[] parameters)
at WebMethodAndTCPHalfOpenTest.TestWebReference.TestService.DoLongWork(Int32 sec)
at WebMethodAndTCPHalfOpenTest.Program.Main(String[] args)
Killed the host process after connectivity (to the host) loss, so TCP RST can not reach client:
Results here is very tangling for me, because after 2.5 hours the broken connection (half-open) is not detected and client still thinks that underlying TCP connection is alive (the same situation after 6 hours). Here the output from Sysinternals TCPView:
TCPView v3.01 - TCP/UDP endpoint viewer Copyright (C) 1998-2010
Mark Russinovich and Bryce Cogswell Sysinternals -
www.sysinternals.com
[TCP] WebMethodAndTCPHalfOpenTest.exe
PID: 8180
State: ESTABLISHED
Local: 192.168.1.2
Remote: 5.167.159.81
Windows Version: Microsoft Windows [Version 6.1.7601]
Wireshark output:
I've checked KeepAliveTime registry setting on my system here: HKLM\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters and it was missing, so the default 2 hours should be used (?).
Can anybody explain the result described in the second point? Why TCP keepalive was not sent? Is proxy explicitly settled up different keepalive behavior for underlying socket (https://msdn.microsoft.com/en-us/library/windows/desktop/ee470551(v=vs.85).aspx)?
It looks like the keep alive is not garanteed because things might muck with that setting in windows (no the registry value isn't the end all).
According to this:
Windows TCP socket has SO_KEEPALIVE enabled by default?
It looks like you should not rely on this behavior and set a timeout. If you are using a soap request, you could always invoke an async request, and then wait on the request based on a client configurable value, and have a nice logic handling for timeouts.
If the host process crashes the connection will close. It won't wait for the TCP keep-alive to kick. You can easily test this scenario by spinning your WebService and making it crash voluntary.
I am using Moonapns asp.net library to send push notifications to apple device.
it works fine on my local machine which is 64bit OS but when i am trying to deploy it to client's server with 64bit OS it gives following error , any one guide me what could be the problem?
Event log:
System.InvalidOperationException: The operation is not allowed on non-connected sockets.
at System.Net.Sockets.TcpClient.GetStream()
at MoonAPNS.PushNotification.OpenSslStream(String host, X509CertificateCollection certificates)
at MoonAPNS.PushNotification.Connect(String host, Int32 port, X509CertificateCollection certificates)
at MoonAPNS.PushNotification.SendQueueToapple(IEnumerable`1 queue)
at MoonAPNS.PushNotification.SendToApple(List`1 queue)
at NeoFaceWatchMobileClient.watchservice.Timer_Elapsed(Object sender, EventArgs e)
any help would be appreciated.
I guess it was due to server's restriction on that port that was being used by MoonAPNS, i asked network administrator and he removed the restriction and it worked, so it was not relevant to me or programming but server.
I am sending an email from a WPF application. When sending as a domain user on the network, the emails sends as expected. However, when I attempt to send email over a VPN connection, I get the following exception:
Exception:
System.Net.Mail.SmtpException: Failure sending mail. ---> System.IO.IOException: Unable to read data from the transport connection: net_io_connectionclosed.
at System.Net.Mail.SmtpReplyReaderFactory.ProcessRead(Byte[] buffer, Int32 offset, Int32 read, Boolean readLine)
at System.Net.Mail.SmtpReplyReaderFactory.ReadLines(SmtpReplyReader caller, Boolean oneLine)
at System.Net.Mail.SmtpReplyReaderFactory.ReadLine(SmtpReplyReader caller)
at System.Net.Mail.SmtpConnection.GetConnection(String host, Int32 port)
at System.Net.Mail.SmtpTransport.GetConnection(String host, Int32 port)
at System.Net.Mail.SmtpClient.GetConnection()
at System.Net.Mail.SmtpClient.Send(MailMessage message)
I have tried using impersonation as well as setting the Credentials on the SmtpClient. Neither seem to work:
using (new ImpersonateUser("myUser", "MYDOMAIN", "myPass"))
{
var client = new SmtpClient("myhost.com");
client.UseDefaultCredentials = true;
client.Credentials = new NetworkCredential("myUser", "myPass", "MYDOMAIN");
client.Send(mailMessage);
}
I've also tried using Wireshark to view the message over the wire, but I don't know enough about SMTP to know what I'm looking for.
One other variable is that the machine I'm using on the VPN is Vista Business and the machine on the network is Win7. I don't think it's related, but then I wouldn't be asking if I knew the issue! :)
Any ideas?
I solved this by connecting outlook on a VPN machine to the Exchange server. The IP address automatically resolved to a different server name than the one I was trying. Evidently the exchange server was only available over VPN through the other URL.