Azure / DotNetty

DotNetty project – a port of netty, event-driven asynchronous network application framework
Other
4.09k stars 977 forks source link

Cannot connect to a TCP server using TLS 1.2 without SNI extension #165

Closed oacsed closed 7 years ago

oacsed commented 7 years ago

Hi,

We're currently trying to connect a physical device to a DotNetty TCP-based server we developed. The connection is achieved through a secured channel (TLS 1.2).

While everything works fine when connecting simulated devices (or even CURL-initiated requests), our physical devices can't connect. We've narrowed down the issue to the absence of the Server Name Indication (SNI) extension within the Client Hello message coming from our devices. From our understanding (see https://tools.ietf.org/html/rfc4366#section-3.1), this particular TLS extension is not mandatory ("clients MAY include an extension"...), so a TCP server should accept both messages with and within this extension.

How could I parameterize my DotNetty server to accept such TCP connections?

For reference, here's the relevant DotNetty server code we're using to reproduce the issue:

using System;
using System.Net;
using System.Security.Cryptography.X509Certificates;
using System.Threading.Tasks;
using DotNetty.Buffers;
using DotNetty.Handlers.Tls;
using DotNetty.Transport.Bootstrapping;
using DotNetty.Transport.Channels;
using DotNetty.Transport.Channels.Sockets;

namespace Server_Test
{
    internal class Program
    {
        private static X509Certificate2 tlsCertificate;
        private static IEventLoopGroup eventLoopGroup;
        private static IEventLoopGroup parentEventLoopGroup;

        private static ServerBootstrap SetupBootstrap()
        {
            return new ServerBootstrap()
                .Group(parentEventLoopGroup, eventLoopGroup)
                .Channel<TcpServerSocketChannel>()
                .Handler(new ExceptionCatchHandler(ex => ManageException(ex)))
                .ChildHandler(new ActionChannelInitializer<ISocketChannel>(channel =>
                {
                    if (tlsCertificate != null)
                    {
                        var settings = new ServerTlsSettings(
                            tlsCertificate,
                            false, 
                            true, 
                            System.Security.Authentication.SslProtocols.Tls 
                                | System.Security.Authentication.SslProtocols.Tls11
                                | System.Security.Authentication.SslProtocols.Tls12);
                        channel.Pipeline.AddLast("tls", new TlsHandler(settings));
                    }
                }))
                .ChildOption(ChannelOption.Allocator, PooledByteBufferAllocator.Default)
                .ChildOption(ChannelOption.TcpNodelay, true);
        }        
        private static void ManageException(Exception ex)
        {
            Console.WriteLine("ServerBootstrap: ex=" + ex.Message, ex);
        }
        private static void Main(string[] args)
        {
            tlsCertificate = new X509Certificate2("some_certificate.pfx", "some_password");
            parentEventLoopGroup = new MultithreadEventLoopGroup(1);
            eventLoopGroup = new MultithreadEventLoopGroup(4);

            ServerBootstrap server = SetupBootstrap();
            server.BindAsync(IPAddress.Any, 8883).Wait();

            Task.Delay(50000 * 1000).Wait();
            Console.WriteLine("Server stopped.");
        }
    }
}

Thanks for the help, Regards

nayato commented 7 years ago

@oacsed from working with devices I had learned that most of the time there’s something weird coming from device’s SSL stack. I’d recommend collecting traces with wireshark and analyzing them for validity. If anything, having SNI extension would actually hurt as SslStream (used internally in TlsHandler) does not support SNI.

nayato commented 7 years ago

closing due to lack of activity