18
votes

I'm trying with no luck to connect a device to a .Net (4.5.2) server. It's a TCP connection opened by the device, that uses TLS 1.2.

  • On the server side, I have a standard .Net implementation of a TCP Server: SslStream wrapped through DotNetty
  • I cannot change anything on the device

Any .Net client can successfully connect to my server using a secured TLS connection. It's working when trying with CURL too, so I've concluded my TCP server works fine.

So I've compared (using Wireshark) what was sent by a working client from what was sent by the device that cannot connect. The significant difference I found is the absence (for the device) of the Server Name Extension (SNI) inside the Client Hello TLS message.

Next thing I tried is to manually send data to my server using Pcap.Net, i.e. to manually send TCP SYN/TCP ACK/Client Hello messages using raw byte arrays (raw data I got (thanks to Wireshark) from the device trying to connect to my server). I confirmed that tweaking the non-working Client Hello raw byte array by adding the Server Name extension causes my TLS handshake to work.

So obviously I got an issue with clients that don't include the SNI extension and a server that refuses the handshake if this information is not present.

How could I change the way my TCP server behave to accept client that don't provide the Server Name extension? Is it possible in the first place using the standard .Net SslStream class?

AFAIK, the SNI extension is not mandatory, and it's up to the client to decide whether or not to use it, so the server should theoretically accept a Client Hello message without it.

Any pointer would be greatly appreciated.

1
I'm afraid .NET doesn't have any control over this - SslStream is just a managed wrapper for SChannel and isn't always up to date. Have you tried messing with the certificate validation callback? Does the Client Hello look fine to you? Can you cut it down further to make it work?Luaan
as an aside can your client device establish any TLS1.2 connections? e.g. via a browser to a given https website?wal
if you absolutely must get this working you could consider a different implementation of SSLStream eg a product like this eldos.com/sbb/desc-ssl-spec.php (i am not endorsing just the first alternative i found)wal
Have you tried to use the RemoteCertificateValidationCallback parameters of SslStream ctor or also ServicePointManager.ServerCertificateValidationCallback?Simon Mourier
Did you enable the TLS1.2 (by default it could be disabled) System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls; msdn.microsoft.com/en-us/library/…cristallo

1 Answers

1
votes

.Net 4.5.2 supports TLS1.2 but it is disabled by default.

For enabling it you have to explicitly define the security protocol set.

System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

for more information see the following link https://msdn.microsoft.com/en-us/library/system.net.servicepointmanager.securityprotocol%28v=vs.110%29.aspx