I have some SSL client code (C#) which looks like:
X509Certificate2 cert = new X509Certificate2(#"client.pfx");
X509Certificate2Collection x09s = new X509Certificate2Collection();
x09s.Add(cert);
TcpClient client = new TcpClient(controllerIP, port);
sslStream = new SslStream(client.GetStream(), false, OnCertificateValidation,
new LocalCertificateSelectionCallback(SelectLocalCertificate));
sslStream.AuthenticateAsClient("", x09s, SslProtocols.Default, false);
This is communicating with a linux server running with openssl. It all works great when the client is Windows 7. When I try on a Windows 8 client however, the AuthenticateAsClient always get an exception with the message: "Unable to read data from the transport connection. 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."
The LocalCertificateSelectionCallback function is called and returns properly.
What changed in Windows 8?
Thanks...
I know this is an old thread, but still, I got same answer form AuthenticateAsClient in Windows 10.
AuthenticateAsClient was successful when I increased response time in client (TcpClient) and streams (NetworkStream, SslSteram).
But for some weird reason in Windows 10, after I dispose of connection objects (SslStream and TcpClient) and try to go through connection steps again, AuthenticateAsClient is successful each second time. (success, fail, success, fail ...).
For Windows 7 everything works perfectly.
Related
I have looked at
unable to read data from the transport connection the connection was closed
Unable to read data from the transport connection : An existing connection was forcibly closed by the remote host
Unable to read data from the transport connections
I am new to this and I have been told the issue is not the server. Is there anyway the issue can be client side or the client is causing an issue that forces the server to disconnect?
I make my connection
_client.BeginConnect(host, port, ConnectCallback, null);
and then in ConnectCallback
_client.EndConnect(result);`
_client.NoDelay = true;`
_client.ReceiveBufferSize = 65535;`
NetworkStream ns = _client.GetStream();`
byte[] buffer = new byte[_client.ReceiveBufferSize];`
ns.BeginRead(buffer, 0, buffer.Length, ReadCallback, buffer);`
and then in ReadCallback
ns = _client.GetStream();`
read = ns.EndRead(result);`
Which is where it sometimes fails. There are other connections in the app and they have no problems. One of the connections is to the same server that I am having issues, but on a different port.
All the machines are on the same network. This is the only client connecting to this particular server/port. We run the app for about 3 hours and this error happens anytime.
Edit
I appreciate the comments and input. Being new to programming and networking, etc, I still have the question: Is it possible the client is causing the issue?
The remote endpoint or a device on the network is closing the TCP connection.
You always need to test that the TCP connection is available and connected before reading from it.
You have no control over when the remote endpoint closes the connection. Even if you wrote the code on the remote endpoint it could still close due to a power outage.
The ReadCallback will be fired when the connection is closed, as well as when data is available. Your code is responsible for detecting that the connection has been closed and taking the necessary action in your code to deal with this scenario.
The easiest way to deal with this is to catch the exception, stop reading/writing from/to the socket, do any clean up tasks and reconnect if necessary etc etc..
When I use WebSocket server in C#, and access it in local PC, it works normally. But when I try to access with another PC, it doesn't work.
I'm using WebSocket library from Fleck.
Code in C# WebSocket Server:
_server = new Fleck.WebSocketServer("wss://127.0.0.1:8181");
_server.Certificate = new X509Certificate2(#"C:\test.com.pfx", "123");
Code in HTML/Javascript:
websocket = new WebSocket('wss://192.168.1.37:8181');
When I work with insecure WebSocket "ws://127.0.0.1:8181" when I try to access the local IP "ws://192.168.1.37:8181", it the Chrome Console sends the error:
The page at 'https://www.websocket.org/echo.html' was loaded over HTTPS, but attempted to connect to the insecure WebSocket endpoint 'ws://192.168.1.37:8181/?encoding=text'. This request has been blocked; this endpoint must be available over WSS.
When I work with Secure WebSocket "wss://127.0.0.1:8181"
it sends the error:
WebSocket connection to 'wss://192.168.1.37:8181/?encoding=text' failed: Error in connection establishment: net::ERR_CONNECTION_REFUSED
It only works when I type "wss://127.0.0.1:8181" in WebSocket client, but I want to work with the standard IP, to be accessed by other PC.
I found the solution, here the steps if someone needs:
You need to start the Fleck WebSocket server as bellow:
_server = new Fleck.WebSocketServer("wss://0.0.0.0:8181");
_server.Certificate = new X509Certificate2(#"C:\test.com.pfx", "123");
Then in the PC that you want to access though WebSocket client, you need to access first with the browser:
https://192.168.1.37:8181
Then you allow the access. (It'll let the Certification of an Unknown User)
After that you WebSocket Client will work.
Little Background
I have a Windows service (written in C# .NET) that listens on several different ports using TcpListener. some of the ports are (8090, 8091, 554, 25100, 25101).
Each port listener performs different tasks which I'm not going to mention in detail here in this question.
The service keeps on running OK for weeks without any trouble and then all of sudden one of the port 8091 stops receiving new client connections. However other ports remain functioning OK and so as the windows service.
How this port (8091) is being used
User can access the Windows service port from the browser using a secure HTTPS URL. For example look at this URL.
https://XYZServer.net:8091/ABC/?access=123
In the Windows Service I am opening this port using TCPListner. Some sample code is written below.
m_listener = new TcpListener(IPAddress.Any, 8091);
m_listener.Start();
m_listener.BeginAcceptTcpClient(DoAcceptWebTcpClientCallback, m_listener);
And then when a new client connection request comes in. See some sample code.
private void DoAcceptWebTcpClientCallback(IAsyncResult ar)
{
try
{
var client = m_listener.EndAcceptTcpClient(ar);
var webConnection = CreateConnection(client, m_waitForDeviceTimeout);
webConnection.Start();
}
catch (Exception ex)
{
s_log.Error(ex, "{0}: Exception", m_serverName);
}
try
{
BeginAccept();
}
catch (Exception ex)
{
s_log.Error(ex, "{0}: Exception", m_serverName);
}
}
I am associating the sslStream with the client connection. Also I am authenticating the Server using a certificate without authenticating the client. Sample code below
protected override WebConnection CreateConnection(TcpClient client, int waitForFb4Timeout)
{
return new HttpsConnection(SERVER_NAME, client, m_serverCertificate, waitForFb4Timeout); // Create an ssl/tls connection using the configured certificate
}
public HttpsConnection(string serverName, TcpClient client, X509Certificate serverCertificate, int waitForFb4Timeout) :
base (serverName, client, GetStream(client, serverCertificate), DeviceConnection.ProtocolEnum.HTTP, waitForFb4Timeout)
{
}
private static Stream GetStream(TcpClient client, X509Certificate serverCertificate)
{
// Create the SslStream using the client's network stream.
var sslStream = new SslStream(client.GetStream(), false);
// Authenticate the server but don't require the client to authenticate.
sslStream.AuthenticateAsServer(serverCertificate, false, SslProtocols.Tls, true);
return sslStream;
}
Windows service relays all the messages coming on this port to another destination (a WebSocker Server) and relays the response back to the browser. User can then see the page on the screen. This keeps on working fine for weeks and then all of sudden users can't browse the page and new client connection requests on the port 8091 stops coming.
When this happens, no exceptions are raised. It is really annoying and hard to understand whats really going wrong here..
One more thing I would like to mention that in the same windows service we are making lots of outbound connections which is using ephemperal port range (49000-65535). I can see all of these ports beings used and then reused again and again. However there are no evidence of all the ports being used at once. I know that there are ways to increase the port range but I have not tried this yet as I'm not convinced that we are reaching to the limit.
I can see several exceptions in the code related to authentication on this port.
2018-08-11 01:39:43.8952|ERROR|Fb4RelayServerLib.WebConnections.WebServer.DoAcceptWebTcpClientCallback: HTTPS: Exception System.IO.IOException: Authentication failed because the remote party has closed the transport stream.
People have suggested on different forums about using
SecurityProtocolType.Ssl3 | SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12
Whereas I am only using the SslProtocols.Tls only (see code). I have not tried above as in my case I am getting this exception rarely and for the same client IP which is also working fine.
I'm really stuck and don't know how to troubleshoot and further investigate this issue. Any help in this regard will be very helpful. Many thanks in advance and sorry for a lengthy question.
Thank You
Right, after a lot of struggle I finally resolve the issue.
I did two things mainly to address the problem.
1- Add the support for tls1.1 and tls1.2 which my product was lacking originally. (As I posted in my question as well)
2- Replace AuthenticateAsServer with AuthenticateAsserverAsync.
Actually for some unknown reason the AuthenticateAsServer function was hanging and not allowing the application to accept any new client connections.
Doing above changes, it seems to be working fine so far. Keeping my fingers crossed :)
I have been working on a C# Websocket Server for some time now and there has been one issue that I have worked around but never resolved or found a proper reason for its existence.
My environments that I have tested have been using Google's Chrome browser over the series of versions over the past year or so on Windows XP and Windows 7. My server has been tested on both OS as well.
The problem I notice only occurs when the browser is running under Windows XP. Upon completion of the Websocket Handshake, the browser/client cannot send data to the server unless a message is sent from the server to the client first.
What I have done, is simply tagged on a Ping frame to the end of the server Handshake and all functions as expected. I have tested with other frames as well, so long as the server sends a message, the client will proceed as normal.
The message from the server does not need to be instant either. If the client attempts to send a message, it can wait indefinitely. As soon as the server sends a message to the client, the client proceeds.
Now, I figured I was doing something incorrectly on my Websocket Server, but if this was the case, then why does everything work as expected when the browser is running under Windows 7. I do not need to send a message to the client before the client will release a message to the server.
As a very basic example, here is server code that will never complete if Chrome connects from an XP machine;
byte[] textPound = {0x81, 0x01, 0x23};
Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.IP);
IPEndPoint ip = new IPEndPoint(IPAddress.Any, 56100);
server.Bind(ip);
server.Listen(100);
byte[] buffer = new byte[1000];
Socket client = server.Accept();
int rec = client.Receive(buffer);
Handshake(buffer, ref rec);//custom function returns the handshake to the buffer
client.Send(buffer, rec, SocketFlags.None);
//client.Send(textPound);
rec = client.Receive(b);
client.Close();
So long as the .Send() is commented out .Receive() will never complete if Chrome is ran from an XP machine, no matter how you send a message from the browser. If you were to start a thread before .Receive() that would issue a .Send() after x amount of time, the process completes once that happens.
Has anyone experienced this, or know why this may be?
EDIT -- For those who do not know what the WebSocket Protocol is;
Protocol Documentation
API Documentation
If you are writing a new WebSocket implementation, you might have a look at AutobahnTestsuite.
AutobahnTestsuite provides a fully automated test suite to verify client and server implementations of The WebSocket Protocol for specification conformance and implementation robustness.
It's used by dozens of projects and is some kind of "defacto standard" for testing.
Disclosure: I am original author of Autobahn and work for Tavendo.
I am trying to create a simple xmpp client that connects to Gtalk.
The first part of the handshake seems to work.
Ror the TLS handshake I created a client SslStream, connected to the intended server (talk.google.com) and successfully got authenticated .
The first SSlStream.Read is to receive the greeting reply, it went fine . I do a SslStream.write to send my first command, but when i do my Sslstream.Read() to get the reply , i get this error."System.IO.IOException: Unable to read data from the transport connection: An established connection was aborted by the software in your host machine."
Can anyone point me to the right direction?
I am using code very similar to the example on msdn http://msdn.microsoft.com/en-us/library/system.net.security.sslstream.aspx
except that I switch from a Network stream to a Sslstream when TLS is negotiated.
netStream.Flush();
sslStream = new SslStream(netStream,
true,
new RemoteCertificateValidationCallback(ValidateServerCertificate),
null
);
sslStream.AuthenticateAsClient("talk.google.com");
I'd try using one of the existing XMPP libraries for .Net:
Jabber-Net: http://code.google.com/p/jabber-net/
agsXMPP: http://www.ag-software.de/agsxmpp-sdk/
Even if you don't use of these libs, you'll get some good ideas from looking at the code.
In this case, you probably want:
sslStream.AuthenticateAsClient("gmail.com");
where gmail.com is the domain name from the JID you're trying to log in as.