chronoxor / NetCoreServer

Ultra fast and low latency asynchronous socket server & client C# .NET Core library with support TCP, SSL, UDP, HTTP, HTTPS, WebSocket protocols and 10K connections problem solution
https://chronoxor.github.io/NetCoreServer
MIT License
2.63k stars 550 forks source link

Question on SSLContext usage #274

Open AllonisDave opened 9 months ago

AllonisDave commented 9 months ago

I have a need to connect to a Lutron RA3 hub. This requires a SSL connection using a hub generated device cert file and private key along with an intermediate CA cert file. These all have to be chained together to make the connection.

I have created a new SSL class based on the SSLChat client example. I cannot figure out the proper way to build the SSLContext when creating the client.

The problem is that when I issue the connect() I get the connect event but then it is immediately followed by a error event and a disconnect event.

The reported error is - disconnected.

I suspect I am not packaging the certificates correctly. If anyone has done something similar to this any insights you can provide will be greatly appreciated.

This is what I have tried. The paths to the files are valid and I do end up with 2 certificates in the collection.

string deviceCertFilePath = ServerPath + "\data\lutron\192.168.0.140.crt"; string deviceKeyFilePath = ServerPath + "\data\lutron\192.168.0.140.key"; string intermediateCertFilePath = ServerPath + "\data\lutron\192.168.0.140-bridge.crt";

X509Certificate2Collection certificates = new();

var certificate = X509Certificate2.CreateFromPemFile(deviceCertFilePath, deviceKeyFilePath); certificates.Add(certificate); certificates.Add(new X509Certificate2(File.ReadAllBytes(intermediateCertFilePath)));

var context = new SslContext(SslProtocols.Tls12, certificates, ValidateServerCertificate) { ClientCertificateRequired = true };

controller.wrkClient = new NetSslClient(context, deviceHost, devicePort);

controller.wrkClient.NetConnected += (sender, e) => { NetSslClient rTCP = (NetSslClient)sender; LogDebug("Pair", "Device has connected."); }; controller.wrkClient.NetDisconnected += (sender, e) => { NetSslClient rTCP = (NetSslClient)sender; LogDebug("Pair", "Device has disconnected."); }; controller.wrkClient.NetError += (sender, error) => { LogDebug("Pair", "Error " + error.ToString()); }; controller.wrkClient.NetHandshake += (sender, e) => { LogDebug("Pair", "Handshake"); };

controller.wrkClient.DataReceived += (sender, msg) => { NetSslClient rTCP = (NetSslClient)sender; LogDebug("Pair RX", msg); }; controller.wrkClient.Connect();

...

and my NetSslClient is as follows (essentially the SSLChatClient)

public class NetSslClient: SslClient { public event EventHandler NetConnected; public event EventHandler NetDisconnected; public event EventHandler NetHandshake; public event EventHandler NetError; public event EventHandler DataReceived;

public NetSslClient(SslContext context, string address, int port) : base(context, address, port) { }
private bool _stop;
public string tag { get; set; }
public byte Delimiter { get; set; }

public void DisconnectAndStop() {
    _stop = true;
    DisconnectAsync();
    while (IsConnected)
        Thread.Yield();
}

protected override void OnConnected() {
    NetConnected?.Invoke(this, true);
}

protected override void OnDisconnected() {
    NetDisconnected?.Invoke(this, true);
    _stop = true;
    if (!_stop) {
        Thread.Sleep(1000);
        ConnectAsync();
    }
}

protected override void OnHandshaked() {
    NetHandshake?.Invoke(this, true);
}

protected override void OnReceived(byte[] buffer, long offset, long size) {
    Console.WriteLine(Encoding.UTF8.GetString(buffer, (int)offset, (int)size));
    if (DataReceived != null) {
        string msg = Encoding.UTF8.GetString(buffer, (int)offset, (int)size);
        DataReceived(this, msg);
    }
}

protected override void OnError(SocketError error) {
    NetError?.Invoke(this, error);
}

}