Debugging Akka.NET remote connections (Cant connect - Failed to bind) - c#

Using the example Chat Server/Client project available as part of the Akka.NET source code I have attempted to modify it such that it would successfully work over two computers on my network.
I have two systems that are connected via a router like this
192.168.0.29 (Server) <---------------| Router |---------------> 192.168.0.52 (Client)
I then have two actor systems that are configured like this:
Server:
akka {
actor {
provider = remote #Specify remote provider
}
remote {
dot-netty.tcp {
port = 666 #Akka server port number
hostname = 0.0.0.0 #Bind to all local network interfaces
public-hostname = 192.168.0.29 #Expose public IP to enable correct routing of public messages.
}
}
}
Client:
akka {
actor {
provider = remote
}
remote {
dot-netty.tcp {
port = 0 #Tell Akka that this is a client connection/use random port.
hostname = 192.168.0.29 #Tell Akka.NET which remote instance to connect to
}
}
}
Unfortunately, while I am able to successfully connect to the chat server locally, no matter how I configure my Hocon I cannot seem to get the remote instance to bind to my server actor located on the machine 192.168.0.29.
The specific error message that I receive
[ERROR][27/11/2019 4:58:36 PM][Thread 0004][Akka.Remote.Transport.DotNetty.TcpTransport] Failed to bind to 192.168.0.29:0; shutting down DotNetty transport.
Cause: System.Net.Sockets.SocketException (10049): The requested address is not valid in its context
at System.Net.Sockets.Socket.UpdateStatusAfterSocketErrorAndThrowException(SocketError error, String callerName)
This error message suggests to me that there is no available socket that Akka.NET can access.
Ironically enough, some time ago I asked a very similar question which at the time helped me resolve my connectivity issues but I never used Akka.NET till recently again.
I note that both machines have their firewalls turned off and can successfully ping each other, I have also played around with all various combinations of settings.
The original source code to the Akka.NET server/client application is located here, my current version of it is here.
Could anyone provide any insight into what I might be doing wrong and how I can improve my debugging of Akka.NET remote connections? For example is there a way that I can verify that the Actor system on server 192.168.0.29 is accessible from 192.168.0.52 externally?

Haha, and literally 5 minutes after posting my question I was finally able to determine the solution (although its not ideal).
The solution was the realisation that when you instantiate the ActorSystem on the client application you are NOT actually connecting the local actor system to the remote system BUT rather creating a local instance of an actor system which itself is listening on a random port.
The remote connection itself occurs when you create an ActorSelection() reference.
So all I needed to do was change my client hocon from
hostname = 192.168.0.29
TO
hostname = 192.168.0.52
However this creates one final (albeit rather small) problem. I now need a different hocon file for an instance running locally vs an instance running remotely. Admittedly this could probably be addressed through code....
I'd be happy to mark as the solution someone who might be able to propose something that addresses this issue.

Related

'No connection could be made because the target machine actively refused it'

I am working on a 'Smart Device Project' using .Net Framework 3.5. I am trying to connect to some Java SOAP services on a remote server.
In order to do that, I added 'Web References' to my project.
When I try to call my web service I get a WebException 'Unable to connect to the remote server' with the inner exception being 'No connection could be made because the target machine actively refused it'.
I searched quite a lot on the Web and StackOverflow and found a lot of ASP configuration and 'Unavaliable port' answers, but as I have another application using the exact same Service successfully, I can't get why the new one isn't getting through (It did sometimes through my tests so I suppose my client implementation isn't that bad)
I tried to look if there was some connection issue on the port by using some TcpClient:
System.Net.Sockets.TcpClient client = new System.Net.Sockets.TcpClient();
try
{
client.Connect("myServerName", 8087);
MessageBox.Show("Success");
} catch (Exception ex)
{
MessageBox.Show("Failure");
}
finally
{
client.Close();
}
This connection succeed.
Here is a sample on how I call my WebService:
WSServiceExtended srv = new WSServiceExtended();
srv.Proxy = new System.Net.WebProxy();
ServeurWSI wsi = new ServeurWSI();
srv.Url = "http://myServerName:8087/myServerApp/services/myService";
wsr = srv.login(wsi);
The service is called 'Extended' because I overrided the auto-generated one in order to add Cookie managment since I am using the Compact Framework. Following the sample in this thread:
https://social.msdn.microsoft.com/Forums/en-US/34d88228-0b68-4fda-a8cd-58efe6b47958/no-cookies-sessionstate-in-compact-framework?forum=vssmartdevicesvbcs
EDIT:
I made some new tests with the Web references and got it to work.
When I add the Web Reference, I have to put some Url to the Web Service. When I set it with the actual hostname instead of the 'localhost' everything is fine.
But then, since I set it manually to the real address just before the call, it shouldn't matter
srv.Url = "http://myServerName:8087/myServerApp/services/myService";
EDIT2:
I might have forgotten some specifics about my environnement.
The Web Services are exposed on my computer on some Tomcat Server.
The application I am working on is also developped on this computer (That's why I can add Web References by putting 'localhost' in the address)
The application is then deployed on a distant device (Windows CE) that will make calls the Web Services through WIFI (There, localhost wouldn't work then)
I tried calling the Web services from other computers successfully.
I'm beginning to think that there might be some differential between the called Url and the one that is set, otherwise, how would I have a difference in behaviour such as the one described in the first edit?
EDIT3:
Well..Seems like it's not a network issue but a .Net compact framework (usage?) issue...
The Url property of the Web Service implementation is simply ignored and the one in the Reference.cs is used in place.
If someone had some idea on how I could troubleshot this, I would really appreciate it.
That error means that you reached a server and the server said "no way". So you're either hitting the wrong server or the wrong port.
I find the telnet client is useful for testing stuff like this. From the command line, you can do:
telnet [servername] [port]
So something like:
telnet myServerName 8087
If it goes to a blank screen, then it connected successfully. If it does not connect, it'll tell you.
The telnet client is no longer installed by default in Windows 7+, so you'll have to install it. See here for instructions: https://technet.microsoft.com/en-ca/library/cc771275
If the connection does open, you could paste in an actual HTTP request to see what happens. A simple GET would look something like this:
GET /myServerApp/services/myService HTTP/1.1
Host: myServerName:8087
One reason for this error can be that the service binds to only a certain IP address. It could well be that the service only listens on the IP that is assigned to the host name, but not on the localhost IP (127.0.0.1).
For example:
If the host myServerName has the public IP 192.168.0.1, your service can choose to listen on all IPs assigned to the host (sometimes specifying 0.0.0.0), or it can specifically listen on 192.168.0.1 only. In that case you will not be able to connect through 127.0.0.1, because the service simply doesn't listen on that IP.
You can "use" this inverse of this feature to make a service accessible only to local clients, not on the public IP-Address, by listening on 127.0.0.1 only, but not on the public IP. This is sometimes used on Linux for example to make MySQL only accessible on the host itself.
I was starting to forget this post but I finally found the problem that was messing things up and it has nothing to do with programmation.
I was doing the calls while the device was connected to the computer via the 'Windows Mobile Device Center' allowing to access the device from Windows.
While connected, the host provided is ignored and all calls on the specified port are handled by the connected computer.
Disconnecting the device allows to communicate properly...

No connection could be made because the target machine actively refused it when connecting to an Azure IP

When connecting to an Azure active directory service (see code below) I promptly receive the error:
No connection could be made because the target machine actively refused it 191.235.135.139:443
Having googled the IP it resolves to a Azure data centre based in Ireland. Though what's really odd is as the IPs change from time to time, yesterday the Azure IP of 191.235.195.38:443 worked without any issues?
public partial class Startup
{
public void ConfigureAuth(IAppBuilder app, HttpConfiguration config)
{
app.UseWindowsAzureActiveDirectoryBearerAuthentication(
new WindowsAzureActiveDirectoryBearerAuthenticationOptions
{
Audience = CloudConfigurationManager.GetSetting("AzureActiveDirectoryInstance"),
Tenant = CloudConfigurationManager.GetSetting("Tenant"),
Provider = new QueryStringOAuthBearerProvider("AUTHORIZATION")
});
app.UseWebApi(config);
}
}
I've searched high and low for answers, trying a whole range of suggestions such as checking nothing is using port 443 (the fact it tells me the target machine actively refused the connection leads me to believe that it's able to reach the machine).
I thought it could be to do with the Azure firewall but I have other colleagues that are able to connect to the service that are on the same public IP address.
Has anyone experienced this before when trying to connect to an Azure service?
After spending more time looking into this issue, it looked like the problem was because our internal network firewall was blocking access.

Renci ssh.net No connection could be made because the target machine actively refused it

We recently deployed a project into production and are now receiving this error message when we attempt to connect to the external sftp machine, "No connection could be made because the target machine actively refused it". When I was developing the application and testing it, we had no issues connecting to this server.
What would be different? I have administrative privileges and the app pool on the production server does not. I'm not sure if this could be what's causing the issue or if it may be something on the external client's server or their firewall blocking us.
If you are using localhost, specify 127.0.0.1 instead.
When I was using SSH.Net and the host was specified as localhost it threw the exception that the host actively refused the connection WSAECONNREFUSED - 10061. When I specified 127.0.0.1 instead, the connection could be made.
I think this is due to the implementation in SSH.Net:
internal static IPAddress GetIPAddress(this string host)
{
IPAddress ipAddress;
if (!IPAddress.TryParse(host, out ipAddress))
ipAddress = Dns.GetHostAddresses(host).First();
return ipAddress;
}
Which does not resolve a valid hostname for localhost, apparently. C# Interactive yields the following:
> Console.WriteLine(Dns.GetHostAddresses("localhost").First());
::1
The value ::1 does not seem to be a valid IP address for sockets to use.
This is a standard TCP error
WSAECONNREFUSED - 10061
From the Client's point of view it means 'there is no socket at that address listening to that port' (the "actively refused" is a red herring).
i) check the address
ii) check the port
iii) check firewall(s)
From our extensive experience (we offer own networking components) -- it's a firewall problem. The firewall doesn't let your requests pass. It's a common situation when you run say Putty, and it works, but your code doesn't. This is because many firewalls detect well-known applications and let them pass, while preventing other applications.

TCP Connect to Azure Fails

I recently deployed an Azure app to the staging environment which is supposed to accept TCP packets in port 2993. When run in the Azure emulator, it does this very well, and performs exactly as it should.
However, now that it is on Azure's staging servers, whenever I try to connect to the TCP port, i get the following SocketException:
A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond.
My web app has two instances, one is a worker role (it has 2993 configured in its endpoints) and a web role (only for port 80). Port 80, by the way, functions perfectly. The web app was created with Visual Studio in C#. Why is this happening and how can I fix it?
All help is greatly appreciated.
I would like to explain what was the issue and why adding above code solve this problem for others benefit.
In your worker role, you configure any TCP endpoint along with any port number. When this VM starts the VM is provisioned to use this port and firewall is included an exception to provide access to this port. By the time your is ready to start your Azure VM already have TCP/IP address and configured port is enabled.
Now when your role starts and if you have any service or application required access this port you really need to l
For example If I have Tomcat/Java configured in my worker role, I must have to create a TCP listener on my configured port. This can be done when my worker role starts as below:
Get the IP address and Port number of the current role instance
Create a TCP Listener and start on this IP address and Port
Add the code to perform step 1) and 2) in my worker role OnStart() function.
The code will look like as below:
TcpListener TomcatPortListener = new TcpListener(RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["TomcatWeb80"].IPEndpoint);
TomcatPortListener.Start();
In your case you you did exactly the same you got the IP address and Port number from and then created an endpoint from a socket address using IP/Port:
RoleInstanceEndpoint externalEndPoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["TCPin"];
IPEndPoint localEndPoint = new IPEndPoint(externalEndPoint.IPEndpoint.Address, externalEndPoint.IPEndpoint.Port);
localEndPoint.Create();
It is a must setting for any web or worker role which create TCP endpoint.
It seems the problem had something to do with the program's detection of the server's IP address. By using the following server code instead, I managed to fix the problem:
RoleInstanceEndpoint externalEndPoint = RoleEnvironment.CurrentRoleInstance.InstanceEndpoints["TCPin"];
IPEndPoint localEndPoint = new IPEndPoint(externalEndPoint.IPEndpoint.Address, externalEndPoint.IPEndpoint.Port);
The IPEndpoint can then be used with the tcpListener socket.

UDP Hole Punching help

I'm trying to add networking over the internet to my game, using Peer to Peer.
I have already implemented a LAN only version, which uses .NET's peer to peer classes to connect within the local network.
I realized I need to use UDP hole punching in order to establish a connection to other clients that are behind a firewall.
This is how I have started to implement it:
The server is a HTTP server using very simple PHP scripts to get the job done.
register name on server, sending the private ip address and port as a GET variable
when the server gets a registration request, it will save the public endpoint and the private endpoint
request to connect to another client.
the server will return the private and public endpoints of the client
every two seconds, the second client will check in with the server, and if there is another client attempting to connect with it, it will get its endpoints too
both clients start spamming each others public endpoints until they get a valid response
Now I have a bunch of questions
Can the server be a HTTP server?
When I make a request to an HTTP server, the client port changes each time a request is made. Is a private endpoint always matched to the same public endpoint?
Does the request to the server have to have the same source endpoint as the UDP messages to the client?
Is there a way to connect to an HTTP server in C# using a specified source endpoint?
Are there any problems with my implementation?
Thanks!
UDP hole punching is a complex topic, and many attempts have been made to find a solution that works. The problem is that there are so many different NAT routers out there, and there is no standard way of implementing NAT, so all routers behave a bit different.
Some attempts have been standardized, e.g. STUN, ICE. They still work only in most cases, not all, but they accumulate a lot of knowledge and address many concerns -- more than your attempt will ever be able to, simply because you can't test your solution with every NAT router under the sun. Skype, for example, spent years of perfecting its NAT traversal mechanism.
I recommend you have a look at STUN or preferably ICE. Try to implement one of them or look for existing implementations.
Another option might be to simply create a port forward at the router, e.g. using UPnP or NAT-PMP.
That said, I wouldn't be surprised if the .NET peer to peer classes came with a NAT traversal mechanism, but I'm not familiar with them.
STUN is a best solution for the problem. it works for most of the scenarios.here is a simple example(C#) that gives you the NAT type,Local IP:Port and Public IP:Port.
try
{
Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.Bind(new IPEndPoint(IPAddress.Any, 0));
STUN_Result result = STUN_Client.Query("stunserver.org", 3478, socket);
Console.WriteLine("Net Type : " + result.NetType.ToString());
Console.WriteLine("Local IP : " + socket.LocalEndPoint.ToString());
if (result.NetType != STUN_NetType.UdpBlocked)
{
Console.WriteLine("Public IP : " + result.PublicEndPoint.ToString());
}
else
{
Console.WriteLine("");
}
}
catch (Exception x)
{
Console.WriteLine(x.StackTrace.ToString());
}
You can just add some breakpoints and check the behaviour of the code.
also you can traverse NAT using vs2010 onwords (.net4.0 < ) . there is a method AllowNATTraversal (bool value). set the value true for NAT Traverse. It uses Ipv6 address for connectivity. You can get Ipv6 global address from "Teredo" server by writing some commands in command prompt. Actually IPV6 is the technology that is used to avoid this problem.

Categories