WSS?

Feb 28, 2012 at 8:03 AM
Edited Feb 28, 2012 at 8:05 AM

Hi - thanks again for all you great work on this and the other sockets components.

I read with interest the v1.5 check-in on SuperSockets to allow you to use a certificate from the servers certificate store, rather than load it from a file. Using from the store is our preference (in fact it's the only way we wish to load a certificate as we don't allow exporting). Any idea when you are going to be able to bring over the code to SuperWebSocket.

I've looked through the code used in the CertificateCreator.exe, and I don't understand why we have to run our issued certificate through the exe in order to use it to secure our socket server?

I tried changing the source of v1.4 supersocket to allow you to programatically set the certificate from the store by adding this to IAppServer<TAppSession>:

void SetupSecurity(X509Certificate certificate, SslProtocols basicSecurity);

And this to AppServerBase:

public void SetupSecurity(X509Certificate certificate, SslProtocols basicSecurity)
        {
            Certificate = certificate;
            BasicSecurity = basicSecurity;
        }

I then set it in the initialising of my server object like this:

X509Certificate certificate = CertificateHelper.GetCertificateByFriendlyName(StoreName.My, StoreLocation.LocalMachine, certificateFriendlyName);
_server.SetupSecurity(certificate, SslProtocols.Ssl3);

Where the certificate is a standard certificate which I havent' run through the CertificateCreator.exe

I also change the port number to 443, then spin up the server and everything looks to have started fine. I can see the server listening on the port by running netstat -ano.

However, when I configure my client to connect on the new port and use wss:\\ instead (I'm using the MS DesktopClient.dll) it fails with an NotSupportedException with a description "Secure web sockets are not supported. Specify 'ws' scheme instead of 'wss' on the client.Open() line.

I can't tell if this is the client declaring that it doesn't support wss yet or whether it can tell that the server doesn't actually support wss and my configuration is wrong on the server side.

Coordinator
Feb 28, 2012 at 8:16 AM

Actually, I created a new branch for SuperWebSocket which base on SuperSocket 1.5, the branch's name is "future".

You can use it for testing instead of production, I am not sure when it can be used as production because there are lots of works to do for SuperSocket 1.5.

 

I am wondering whether I should release a SuperSocket 1.4 SP4 to support the feature you wanted. How about your idea?

CertificateCreator.exe is used for creating a self-signed certificate for testing if you don't have a legal one.

If the client reported you  "Secure web sockets are not supported.", then the websocket client you are using really cannot support "wss://...".

You can use WebSocket4Net to verify the secure websocket connection, it supports wss.

Feb 28, 2012 at 10:08 AM

Hi Kerry - thanks for the prompt reply - much appreciated.

I understand the role of the CertificateCreator.exe better now - so we should be able to load a valid certificate from the store and use it.

I've implemented by hacks in SuperSocket to get the certificate in and changes my client to using WebSockets4Net. Changing the uri to wss:\\ still doesn't work. However, I can change to connect with ws:\\ and the client connects fine.

As the client can still connect on ws:\\ that indicates that the ssl isn't working quite right. This points to a problem with my hacks, so a SuperSockets 1.4 SP4 would be very useful to get the certificate load features into SuperWebSockets.

How can I verify that the server is indeed only listening on ssl?

Thanks Kerry

Coordinator
Feb 28, 2012 at 10:22 AM
Try specify secure port in Uri.

Sent from my Windows Phone

From: ChubbyArse
Sent: 2/28/2012 6:09 PM
To: kerry-jiang@hotmail.com
Subject: Re: WSS? [SuperWebSocket:346522]

From: ChubbyArse

Hi Kerry - thanks for the prompt reply - much appreciated.

I understand the role of the CertificateCreator.exe better now - so we should be able to load a valid certificate from the store and use it.

I've implemented by hacks in SuperSocket to get the certificate in and changes my client to using WebSockets4Net. Changing the uri to wss:\\ still doesn't work. However, I can change to connect with ws:\\ and the client connects fine.

As the client can still connect on ws:\\ that indicates that the ssl isn't working quite right. This points to a problem with my hacks, so a SuperSockets 1.4 SP4 would be very useful to get the certificate load features into SuperWebSockets.

How can I verify that the server is indeed only listening on ssl?

Thanks Kerry

Feb 28, 2012 at 10:49 AM

Hmmm, I don't think I'd be able to use a SP4 version of SuperWebSockets as I have changed the code in SuperSockets to remove the dependencies on Log4Net - and would lose those if I took a new version of SuperWebSockets.

Would you be able to point me to the code changes I need to make in SuperSocket to allow me to load a certificate from the certificate store? Below is how I currently configure and start the server:

                X509Certificate certificate = CertificateHelper.GetCertificateByFriendlyName(StoreName.My, StoreLocation.LocalMachine, certificateFriendlyName);

                _server = new WebSocketServer();

                _serverConfig = new ServerConfig()
                {
                    Ip = "Any",
                    MaxConnectionNumber = 1000,
                    Mode = SocketMode.Async,
                    Port = 80,
                    ClearIdleSession = false,
                    ClearIdleSessionInterval = 86400,
                    ListenBacklog = 1000,
                    ReceiveBufferSize = 1024,
                    SendBufferSize = 1024,
                    KeepAliveInterval = 1,
                    KeepAliveTime = 55,
                };

                _rootConfig = new RootConfig() { LoggingMode = LoggingMode.Root };

                _server.Setup(_rootConfig, _serverConfig, SocketServerFactory.Instance);
                //This is where I invoke my hack - which obviously doesn't work
                _server.SetupSecurity(certificate, SslProtocols.Ssl3);
                
                //Hook up to the events to react to the connections and data received
                _server.NewDataReceived += ServerOnNewDataReceived;
                _server.NewMessageReceived += ServerOnNewMessageReceived;
                _server.NewSessionConnected += ServerOnNewSessionConnected;
                _server.SessionClosed += ServerOnSessionClosed; 

                //Finally start the server
                _server.Start();

Thanks Kerry.

 

Coordinator
Feb 28, 2012 at 11:00 AM

Oh

_serverConfig = new ServerConfig()
                {
                    Ip = "Any",
                    MaxConnectionNumber = 1000,
                    Mode = SocketMode.Async,
                    Port = 80,
                    ClearIdleSession = false,
                    ClearIdleSessionInterval = 86400,
                    ListenBacklog = 1000,
                    ReceiveBufferSize = 1024,
                    SendBufferSize = 1024,
                    KeepAliveInterval = 1,
                    KeepAliveTime = 55,
		    Security = "Tls"
                };

 

Please add the security property.

Feb 29, 2012 at 10:36 AM

OK - I've made some progress on the server side getting the wss running and it looks like the server is ok now. I'll post the changes I needed to make to get the certificate store cert into the server config later today.

However, now I am using both your client and the MS one to connect, I am getting the same failure for both clients now when connecting. The server logs the following error in both instances:

[9732] DI.Wiz - ManagedThread: 7 :: DeviceCommsChannelLogger: Exception occured [9732] The handshake failed due to an unexpected packet format. [9732] System.IO.IOException: The handshake failed due to an unexpected packet format. [9732]    at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result) [9732]    at SuperSocket.SocketEngine.AsyncStreamSocketSession`2.OnBeginInitStream(IAsyncResult result) 

Can you let me know what else you need to diagnose this issue? How can I inspect the packet being sent over and let you have it?

I am not specifying any protocols when I configure the server or the client:

		_server = new WebSocketServer();
                _server.Setup(_rootConfig, _serverConfig, SuperSocket.SocketEngine.SocketServerFactory.Instance);
                
                //Hook up to the events to react to the connections and data received
                _server.NewDataReceived += ServerOnNewDataReceived;
                _server.NewMessageReceived += ServerOnNewMessageReceived;
                _server.NewSessionConnected += ServerOnNewSessionConnected;
                _server.SessionClosed += ServerOnSessionClosed; 

                //Finally start the server
                _server.Start();

Thanks Kerry

Alex

Coordinator
Feb 29, 2012 at 11:01 AM
How are you using the client?

Sent from my Windows Phone

From: ChubbyArse
Sent: 2/29/2012 6:36 PM
To: kerry-jiang@hotmail.com
Subject: Re: WSS? [SuperWebSocket:346522]

From: ChubbyArse

OK - I've made some progress on the server side getting the wss running and it looks like the server is ok now. I'll post the changes I needed to make to get the certificate store cert into the server config later today.

However, now I am using both your client and the MS one to connect, I am getting the same failure for both clients now when connecting. The server logs the following error in both instances:

[9732] DI.Wiz - ManagedThread: 7 :: DeviceCommsChannelLogger: Exception occured [9732] The handshake failed due to an unexpected packet format. [9732] System.IO.IOException: The handshake failed due to an unexpected packet format. [9732] at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result) [9732] at SuperSocket.SocketEngine.AsyncStreamSocketSession`2.OnBeginInitStream(IAsyncResult result)

Can you let me know what else you need to diagnose this issue? How can I inspect the packet being sent over and let you have it?

I am not specifying any protocols when I configure the server or the client:

		_server = new WebSocketServer();
                _server.Setup(_rootConfig, _serverConfig, SuperSocket.SocketEngine.SocketServerFactory.Instance);
                
                //Hook up to the events to react to the connections and data received
                _server.NewDataReceived += ServerOnNewDataReceived;
                _server.NewMessageReceived += ServerOnNewMessageReceived;
                _server.NewSessionConnected += ServerOnNewSessionConnected;
                _server.SessionClosed += ServerOnSessionClosed; 

                //Finally start the server
                _server.Start();

Thanks Kerry

Alex

Feb 29, 2012 at 11:11 AM

Ignore the message above - my client was still trying to connect using ws:\\ - Apologies.

However, I am now connecting (using only the WebSocket4Net client and wss:\\) and on the server side an event is raised to indicate that session was accepted:

[4460] DI.Wiz - ManagedThread: 8 :: DeviceCommsChannelLogger: Session: 19c12473-aecf-460a-b1d6-4750ed01b7d4/127.0.0.1:9312
[4460] New SocketSession was accepted! 

But in the client, the Opened event is not raised...

I can switch back to non-secure server and ws:\\ from the client and it works fine - the Opened event is raised OK.

Again like I mentioned before I don't specifcy an protocols or sub protocols on either the server or client side. My Client code:

     _socket = new WebSocket(uri);
            _socket.Opened += (sender, args) => OpenedSignal.Set();
            _socket.DataReceived += (sender, args) => OnDataReceived(Encoding.UTF8.GetString(args.Data));
            _socket.Closed += (sender, args) => OnStatusUpdate("Client closed");
            _socket.Open();

            if (!OpenedSignal.WaitOne(2000))
            {
                OnStatusUpdate("Failed to open a client");
            }
            else
            {
                if (_socket.State == WebSocketState.Open)
                {
                    //Send Data
                }
            }

Any ideas?

Thanks

Coordinator
Feb 29, 2012 at 11:19 AM
Check err.log

Sent from my Windows Phone

From: ChubbyArse
Sent: 2/29/2012 7:12 PM
To: kerry-jiang@hotmail.com
Subject: Re: WSS? [SuperWebSocket:346522]

From: ChubbyArse

Ignore the message above - my client was still trying to connect using ws:\\ - Apologies.

However, I am now connecting (using only the WebSocket4Net client and wss:\\) and on the server side an event is raised to indicate that session was accepted:

[4460] DI.Wiz - ManagedThread: 8 :: DeviceCommsChannelLogger: Session: 19c12473-aecf-460a-b1d6-4750ed01b7d4/127.0.0.1:9312
[4460] New SocketSession was accepted!

But in the client, the Opened event is not raised...

I can switch back to non-secure server and ws:\\ from the client and it works fine - the Opened event is raised OK.

Again like I mentioned before I don't specifcy an protocols or sub protocols on either the server or client side. My Client code:

     _socket = new WebSocket(uri);
            _socket.Opened += (sender, args) => OpenedSignal.Set();
            _socket.DataReceived += (sender, args) => OnDataReceived(Encoding.UTF8.GetString(args.Data));
            _socket.Closed += (sender, args) => OnStatusUpdate("Client closed");
            _socket.Open();

            if (!OpenedSignal.WaitOne(2000))
            {
                OnStatusUpdate("Failed to open a client");
            }
            else
            {
                if (_socket.State == WebSocketState.Open)
                {
                    //Send Data
                }
            }

Any ideas?

Thanks

Feb 29, 2012 at 11:19 AM

In the meantime, here's the hacks that I made to specify a certificate from the store:

Added this to SuperSocket.SocketBase.Config.ICertificateConfig:

 

X509Certificate Certificate { get; }

 

Implmented the new property in SuperSocket.SocketBase.Config.CertificateConfig:

 

public X509Certificate Certificate { get; set; }

 

Also implmented the new property in SuperSocket.SocketEngine.Configuration.CertificateConfig:

 

        [ConfigurationProperty("isEnabled", IsRequired = false, DefaultValue = false)]
        public X509Certificate Certificate
        {
            get
            {
                return (X509Certificate)this["Certificate"];
            }
        }

And finally, changed the SuperSocket.SocketBase.Security.CertficiateManager.Initialize() method to this:

       X509Certificate cert;

            //Handle a certificate from the store first
            if (cerConfig.Certificate == null)
            {
                //To keep compatible with website hosting
                string filePath;

                if (Path.IsPathRooted(cerConfig.FilePath))
                    filePath = cerConfig.FilePath;
                else
                {
                    filePath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, cerConfig.FilePath);
                }

                cert = new X509Certificate2(filePath, cerConfig.Password);
                
            }
            else
            {
                cert=  cerConfig.Certificate;
            }

            return cert;

Hope this helps whilst Kerry works on implementing SuperSockets v1.5

Alex

 

Feb 29, 2012 at 11:23 AM

I've implemented my own logger and injected that at run time. All the logs should come out through that - and there are no logs server side other than:

[4460] DI.Wiz - ManagedThread: 8 :: DeviceCommsChannelLogger: Session: 19c12473-aecf-460a-b1d6-4750ed01b7d4/127.0.0.1:9312
[4460] New SocketSession was accepted!

I can't see any logging in the client?

Feb 29, 2012 at 11:29 AM

I should add that it is an implementation of ILogger injected using.

            //Inject our log factory
            LogUtil.Setup(new DeviceCommsChannelLogger());

Here is the code for it, so I shouldn't miss any thing:

 /// <summary>
    /// LoggingManager-aware implementation of ILogger - to link up the logging from SuperWebSocket to our centralised logging.
    /// </summary>
    public class DeviceCommsChannelLogger: ILogger //ILog
    {
        #region Implementation of ILogger

        public void LogError(Exception e)
        {
            LoggingManager.LogError(e, "DeviceCommsChannelLogger: Exception occured");
        }

        public void LogError(string title, Exception e)
        {
            LoggingManager.LogError(e, "DeviceCommsChannelLogger: Exception occured - {0}", title);
        }

        public void LogError(string message)
        {
            LoggingManager.LogError("DeviceCommsChannelLogger: {0}", message);
        }

        public void LogDebug(string message)
        {
            LoggingManager.LogVerbose("DeviceCommsChannelLogger: {0}", message);
        }

        public void LogInfo(string message)
        {
            LoggingManager.LogInformation("DeviceCommsChannelLogger: {0}", message);
        }

        public void LogPerf(string message)
        {
            LoggingManager.LogVerbose("DeviceCommsChannelLogger: {0}", message);
        }

        public string Name
        {
            get { return "DeviceCommsChannelLogger"; }
        }

        #endregion

Thanks for all your help with this so far Kerry - much appreciated. I'm being as verbose as possible so that should anyone encounter this thread with the same issues - it may help them.

Alex

Coordinator
Feb 29, 2012 at 11:51 AM
Could show me your client code? I also met this exception when the Uri to ws instead of was or set a wrong port by mistake!

Sent from my Windows Phone

From: ChubbyArse
Sent: 2/29/2012 7:29 PM
To: kerry-jiang@hotmail.com
Subject: Re: WSS? [SuperWebSocket:346522]

From: ChubbyArse

I should add that it is an implementation of ILogger injected using.

            //Inject our log factory
            LogUtil.Setup(new DeviceCommsChannelLogger());

Here is the code for it, so I shouldn't miss any thing:

 /// <summary>
    /// LoggingManager-aware implementation of ILogger - to link up the logging from SuperWebSocket to our centralised logging.
    /// </summary>
    public class DeviceCommsChannelLogger: ILogger //ILog
    {
        #region Implementation of ILogger

        public void LogError(Exception e)
        {
            LoggingManager.LogError(e, "DeviceCommsChannelLogger: Exception occured");
        }

        public void LogError(string title, Exception e)
        {
            LoggingManager.LogError(e, "DeviceCommsChannelLogger: Exception occured - {0}", title);
        }

        public void LogError(string message)
        {
            LoggingManager.LogError("DeviceCommsChannelLogger: {0}", message);
        }

        public void LogDebug(string message)
        {
            LoggingManager.LogVerbose("DeviceCommsChannelLogger: {0}", message);
        }

        public void LogInfo(string message)
        {
            LoggingManager.LogInformation("DeviceCommsChannelLogger: {0}", message);
        }

        public void LogPerf(string message)
        {
            LoggingManager.LogVerbose("DeviceCommsChannelLogger: {0}", message);
        }

        public string Name
        {
            get { return "DeviceCommsChannelLogger"; }
        }

        #endregion

Thanks for all your help with this so far Kerry - much appreciated. I'm being as verbose as possible so that should anyone encounter this thread with the same issues - it may help them.

Alex

Feb 29, 2012 at 11:58 AM

I've just had a thought.....

Could the client be failing to accept my connection because the certificate is a wildcard certificate issued by verisign... but I am using it on a local machine and connecting to a URL of ws:\\localhost:8030\websocket instead of a URL that matches the certificate?

That would explain why the server is completing OK - but the client doesn't accept the response because it can't verify the certificate?

I'm going to deploy the server configured as it is and attempt to connect to it in it's deployed environment. Will report back my findings.

Alex

Coordinator
Feb 29, 2012 at 12:14 PM
Please use "wss" and secure port to connect a secure we socket server.

Did you subscribe Error event of the client? And did you get any error from that event?

Sent from my Windows Phone

From: ChubbyArse
Sent: 2/29/2012 7:58 PM
To: kerry-jiang@hotmail.com
Subject: Re: WSS? [SuperWebSocket:346522]

From: ChubbyArse

I've just had a thought.....

Could the client be failing to accept my connection because the certificate is a wildcard certificate issued by verisign... but I am using it on a local machine and connecting to a URL of ws:\\localhost:8030\websocket instead of a URL that matches the certificate?

That would explain why the server is completing OK - but the client doesn't accept the response because it can't verify the certificate?

I'm going to deploy the server configured as it is and attempt to connect to it in it's deployed environment. Will report back my findings.

Alex

Feb 29, 2012 at 12:50 PM

Thanks for the prompt replies Kerry.

Bingo! I rigged up the OnError event in the client (why I hadn't done this already I don't know) and this was raised:

12:46:03.156: System.Exception: RemoteCertificateNameMismatch
12:46:03.202: System.Security.Authentication.AuthenticationException: The remote certificate is invalid according to the validation procedure.   at System.Net.Security.SslState.InternalEndProcessAuthentication(LazyAsyncResult lazyResult)   at System.Net.Security.SslState.EndProcessAuthentication(IAsyncResult result)
   at System.Net.Security.SslStream.EndAuthenticateAsClient(IAsyncResult asyncResult)   at SuperSocket.ClientEngine.SslStreamTcpSession.OnAuthenticated(IAsyncResultresult)

So it would seem that localhost testing with a secure signed certificate for a domain name doesn't work..... and why would it!!

I'll get a self issued cert running (using the CertificateCreator.exe) and test again. I'll also get this deployed to our test server - as I'm confident if we connect on the correct url - it will be fine. I'll report back my findings.

Thanks again Kerry

Alex

Coordinator
Feb 29, 2012 at 12:55 PM

Well done, Alex!

Feb 29, 2012 at 3:08 PM

Deployed to our test servers (Azure) and everything looks good. We are running a secure wss channel on azure hosts.

Thanks for you help today Kerry.