Example usage for io.netty.handler.ssl SslContextBuilder forServer

List of usage examples for io.netty.handler.ssl SslContextBuilder forServer

Introduction

In this page you can find the example usage for io.netty.handler.ssl SslContextBuilder forServer.

Prototype

boolean forServer

To view the source code for io.netty.handler.ssl SslContextBuilder forServer.

Click Source Link

Usage

From source file:com.crystal.chat.SecureChatServer.java

License:Apache License

public static void main(String[] args) throws Exception {
    SelfSignedCertificate ssc = new SelfSignedCertificate();
    SslContext sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();

    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {//from   ww  w.  jav  a2s  . c  om
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup)

                .channel(NioServerSocketChannel.class).option(ChannelType.op, ChannelType.TYPE_TCP)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new SecureChatServerInitializer(sslCtx));

        ChannelFuture future = b.bind("127.0.0.1", Port.PORT).sync().channel().closeFuture().sync();

    } catch (Exception ex) {
        ex.printStackTrace();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

From source file:com.ctrip.xpipe.redis.console.health.netty.EchoServer.java

License:Apache License

public static void main(String[] args) throws Exception {
    // Configure SSL.
    final SslContext sslCtx;
    if (SSL) {/* w  w w.  ja v  a2s .c  om*/
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
    } else {
        sslCtx = null;
    }

    // Configure the server.
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 100).option(ChannelOption.TCP_NODELAY, true)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline p = ch.pipeline();
                        if (sslCtx != null) {
                            p.addLast(sslCtx.newHandler(ch.alloc()));
                        }
                        //p.addLast(new LoggingHandler(LogLevel.INFO));
                        p.addLast(new EchoServerHandler());
                    }
                });

        // Start the server.
        ChannelFuture f = b.bind(PORT).sync();

        // Wait until the server socket is closed.
        f.channel().closeFuture().sync();
    } finally {
        // Shut down all event loops to terminate all threads.
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

From source file:com.demo.netty.echo.EchoServer.java

License:Apache License

public static void main(String[] args) throws Exception {
    // Configure SSL.
    final SslContext sslCtx;
    if (SSL) {//  ww w . j  a  v a2s  . c  o  m
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
    } else {
        sslCtx = null;
    }

    //EventLoopGroup is  abstraction of Notification and Thread loop
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup) //
                .channel(NioServerSocketChannel.class) //
                .option(ChannelOption.SO_BACKLOG, 100).handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline p = ch.pipeline();
                        if (sslCtx != null) {
                            p.addLast(sslCtx.newHandler(ch.alloc()));
                        }
                        //p.addLast(new LoggingHandler(LogLevel.INFO));
                        p.addLast(new EchoServerHandler());
                    }
                });

        // Start the server.
        ChannelFuture f = b.bind(PORT).sync();

        // Wait until the server socket is closed.
        f.channel().closeFuture().sync();
    } finally {
        // Shut down all event loops to terminate all threads.
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

From source file:com.floragunn.searchguard.ssl.DefaultSearchGuardKeyStore.java

License:Apache License

private SslContext buildSSLServerContext(final PrivateKey _key, final X509Certificate[] _cert,
        final X509Certificate[] _trustedCerts, final Iterable<String> ciphers, final SslProvider sslProvider,
        final ClientAuth authMode) throws SSLException {

    final SslContextBuilder _sslContextBuilder = SslContextBuilder.forServer(_key, _cert).ciphers(ciphers)
            .applicationProtocolConfig(ApplicationProtocolConfig.DISABLED)
            .clientAuth(Objects.requireNonNull(authMode)) // https://github.com/netty/netty/issues/4722
            .sessionCacheSize(0).sessionTimeout(0).sslProvider(sslProvider);

    if (_trustedCerts != null && _trustedCerts.length > 0) {
        _sslContextBuilder.trustManager(_trustedCerts);
    }/*from   w  w  w . j  a  v  a 2  s.c o m*/

    return buildSSLContext0(_sslContextBuilder);
}

From source file:com.floragunn.searchguard.ssl.DefaultSearchGuardKeyStore.java

License:Apache License

private SslContext buildSSLServerContext(final File _key, final File _cert, final File _trustedCerts,
        final String pwd, final Iterable<String> ciphers, final SslProvider sslProvider,
        final ClientAuth authMode) throws SSLException {

    final SslContextBuilder _sslContextBuilder = SslContextBuilder.forServer(_cert, _key, pwd).ciphers(ciphers)
            .applicationProtocolConfig(ApplicationProtocolConfig.DISABLED)
            .clientAuth(Objects.requireNonNull(authMode)) // https://github.com/netty/netty/issues/4722
            .sessionCacheSize(0).sessionTimeout(0).sslProvider(sslProvider);

    if (_trustedCerts != null) {
        _sslContextBuilder.trustManager(_trustedCerts);
    }/* w ww  .j  a va  2s.  c  o m*/

    return buildSSLContext0(_sslContextBuilder);
}

From source file:com.floragunn.searchguard.ssl.SearchGuardKeyStore.java

License:Apache License

private void initSSLConfig() {

    final Environment env = new Environment(settings);
    log.info("Config directory is {}/, from there the key- and truststore files are resolved relatively",
            env.configFile().toAbsolutePath());

    if (transportSSLEnabled) {

        final String keystoreFilePath = env.configFile()
                .resolve(settings.get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_KEYSTORE_FILEPATH, ""))
                .toAbsolutePath().toString();
        final String keystoreType = settings.get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_KEYSTORE_TYPE,
                DEFAULT_STORE_TYPE);/*from  ww  w  .  ja v  a2 s . c  o m*/
        final String keystorePassword = settings
                .get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_KEYSTORE_PASSWORD, DEFAULT_STORE_PASSWORD);
        final String keystoreAlias = settings.get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_KEYSTORE_ALIAS,
                null);

        final String truststoreFilePath = env.configFile()
                .resolve(settings.get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, ""))
                .toAbsolutePath().toString();

        if (settings.get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_KEYSTORE_FILEPATH, null) == null) {
            throw new ElasticsearchException(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_KEYSTORE_FILEPATH
                    + " must be set if transport ssl is reqested.");
        }

        checkStorePath(keystoreFilePath);

        if (settings.get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_TRUSTSTORE_FILEPATH, null) == null) {
            throw new ElasticsearchException(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_TRUSTSTORE_FILEPATH
                    + " must be set if transport ssl is reqested.");
        }

        checkStorePath(truststoreFilePath);

        final String truststoreType = settings.get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_TRUSTSTORE_TYPE,
                DEFAULT_STORE_TYPE);
        final String truststorePassword = settings
                .get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_TRUSTSTORE_PASSWORD, DEFAULT_STORE_PASSWORD);
        final String truststoreAlias = settings
                .get(SSLConfigConstants.SEARCHGUARD_SSL_TRANSPORT_TRUSTSTORE_ALIAS, null);

        try {

            final KeyStore ks = KeyStore.getInstance(keystoreType);
            ks.load(new FileInputStream(new File(keystoreFilePath)),
                    (keystorePassword == null || keystorePassword.length() == 0) ? null
                            : keystorePassword.toCharArray());

            transportKeystoreCert = SSLCertificateHelper.exportCertificateChain(ks, keystoreAlias);
            transportKeystoreKey = SSLCertificateHelper.exportDecryptedKey(ks, keystoreAlias,
                    (keystorePassword == null || keystorePassword.length() == 0) ? null
                            : keystorePassword.toCharArray());

            if (transportKeystoreKey == null) {
                throw new ElasticsearchException(
                        "No key found in " + keystoreFilePath + " with alias " + keystoreAlias);
            }

            if (transportKeystoreCert != null && transportKeystoreCert.length > 0) {

                //TODO create sensitive log property
                /*for (int i = 0; i < transportKeystoreCert.length; i++) {
                X509Certificate x509Certificate = transportKeystoreCert[i];
                        
                if(x509Certificate != null) {
                    log.info("Transport keystore subject DN no. {} {}",i,x509Certificate.getSubjectX500Principal());
                }
                }*/
            } else {
                throw new ElasticsearchException(
                        "No certificates found in " + keystoreFilePath + " with alias " + keystoreAlias);
            }

            final KeyStore ts = KeyStore.getInstance(truststoreType);
            ts.load(new FileInputStream(new File(truststoreFilePath)),
                    (truststorePassword == null || truststorePassword.length() == 0) ? null
                            : truststorePassword.toCharArray());

            trustedTransportCertificates = SSLCertificateHelper.exportCertificateChain(ts, truststoreAlias);

            if (trustedTransportCertificates == null) {
                throw new ElasticsearchException("No truststore configured for server");
            }

            final SslContextBuilder sslServerContextBuilder = SslContextBuilder
                    .forServer(transportKeystoreKey, transportKeystoreCert)
                    .ciphers(getEnabledSSLCiphers(this.sslTransportServerProvider, false))
                    .applicationProtocolConfig(ApplicationProtocolConfig.DISABLED)
                    .clientAuth(ClientAuth.REQUIRE)
                    // https://github.com/netty/netty/issues/4722
                    .sessionCacheSize(0).sessionTimeout(0).sslProvider(this.sslTransportServerProvider)
                    .trustManager(trustedTransportCertificates);

            transportServerSslContext = buildSSLContext(sslServerContextBuilder);

            if (trustedTransportCertificates == null) {
                throw new ElasticsearchException("No truststore configured for client");
            }

            final SslContextBuilder sslClientContextBuilder = SslContextBuilder.forClient()
                    .ciphers(getEnabledSSLCiphers(sslTransportClientProvider, false))
                    .applicationProtocolConfig(ApplicationProtocolConfig.DISABLED).sessionCacheSize(0)
                    .sessionTimeout(0).sslProvider(sslTransportClientProvider)
                    .trustManager(trustedTransportCertificates)
                    .keyManager(transportKeystoreKey, transportKeystoreCert);

            transportClientSslContext = buildSSLContext(sslClientContextBuilder);

        } catch (final Exception e) {
            throw new ElasticsearchSecurityException(
                    "Error while initializing transport SSL layer: " + e.toString(), e);
        }

    }

    final boolean client = !"node".equals(this.settings.get(SearchGuardSSLPlugin.CLIENT_TYPE));

    if (!client && httpSSLEnabled) {
        final String keystoreFilePath = env.configFile()
                .resolve(settings.get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_KEYSTORE_FILEPATH, ""))
                .toAbsolutePath().toString();
        final String keystoreType = settings.get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_KEYSTORE_TYPE,
                DEFAULT_STORE_TYPE);
        final String keystorePassword = settings.get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_KEYSTORE_PASSWORD,
                DEFAULT_STORE_PASSWORD);
        final String keystoreAlias = settings.get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_KEYSTORE_ALIAS, null);
        httpClientAuthMode = ClientAuth.valueOf(settings
                .get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_CLIENTAUTH_MODE, ClientAuth.OPTIONAL.toString()));

        //TODO remove with next version
        String _enforceHTTPClientAuth = settings.get("searchguard.ssl.http.enforce_clientauth");

        if (_enforceHTTPClientAuth != null) {
            log.error("{} is deprecated and replaced by {}", "searchguard.ssl.http.enforce_clientauth",
                    SSLConfigConstants.SEARCHGUARD_SSL_HTTP_CLIENTAUTH_MODE);
            throw new RuntimeException("searchguard.ssl.http.enforce_clientauth is deprecated");
        }

        log.info("HTTPS client auth mode {}", httpClientAuthMode);

        final String truststoreFilePath = env.configFile()
                .resolve(settings.get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_TRUSTSTORE_FILEPATH, ""))
                .toAbsolutePath().toString();

        if (settings.get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_KEYSTORE_FILEPATH, null) == null) {
            throw new ElasticsearchException(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_KEYSTORE_FILEPATH
                    + " must be set if https is reqested.");
        }

        checkStorePath(keystoreFilePath);

        if (httpClientAuthMode == ClientAuth.REQUIRE) {

            if (settings.get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_TRUSTSTORE_FILEPATH, null) == null) {
                throw new ElasticsearchException(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_TRUSTSTORE_FILEPATH
                        + " must be set if http ssl and client auth is reqested.");
            }

        }

        try {

            final KeyStore ks = KeyStore.getInstance(keystoreType);
            ks.load(new FileInputStream(new File(keystoreFilePath)),
                    (keystorePassword == null || keystorePassword.length() == 0) ? null
                            : keystorePassword.toCharArray());

            httpKeystoreCert = SSLCertificateHelper.exportCertificateChain(ks, keystoreAlias);
            httpKeystoreKey = SSLCertificateHelper.exportDecryptedKey(ks, keystoreAlias,
                    (keystorePassword == null || keystorePassword.length() == 0) ? null
                            : keystorePassword.toCharArray());

            if (httpKeystoreKey == null) {
                throw new ElasticsearchException(
                        "No key found in " + keystoreFilePath + " with alias " + keystoreAlias);
            }

            if (httpKeystoreCert != null && httpKeystoreCert.length > 0) {

                //TODO create sensitive log property
                /*for (int i = 0; i < httpKeystoreCert.length; i++) {
                X509Certificate x509Certificate = httpKeystoreCert[i];
                        
                if(x509Certificate != null) {
                    log.info("HTTP keystore subject DN no. {} {}",i,x509Certificate.getSubjectX500Principal());
                }
                }*/
            } else {
                throw new ElasticsearchException(
                        "No certificates found in " + keystoreFilePath + " with alias " + keystoreAlias);
            }

            if (settings.get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_TRUSTSTORE_FILEPATH, null) != null) {

                checkStorePath(truststoreFilePath);

                final String truststoreType = settings
                        .get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_TRUSTSTORE_TYPE, DEFAULT_STORE_TYPE);
                final String truststorePassword = settings.get(
                        SSLConfigConstants.SEARCHGUARD_SSL_HTTP_TRUSTSTORE_PASSWORD, DEFAULT_STORE_PASSWORD);
                final String truststoreAlias = settings
                        .get(SSLConfigConstants.SEARCHGUARD_SSL_HTTP_TRUSTSTORE_ALIAS, null);

                final KeyStore ts = KeyStore.getInstance(truststoreType);
                ts.load(new FileInputStream(new File(truststoreFilePath)),
                        (truststorePassword == null || truststorePassword.length() == 0) ? null
                                : truststorePassword.toCharArray());

                trustedHTTPCertificates = SSLCertificateHelper.exportCertificateChain(ts, truststoreAlias);
            }

            final SslContextBuilder sslContextBuilder = SslContextBuilder
                    .forServer(httpKeystoreKey, httpKeystoreCert)
                    .ciphers(getEnabledSSLCiphers(this.sslHTTPProvider, true))
                    .applicationProtocolConfig(ApplicationProtocolConfig.DISABLED)
                    .clientAuth(Objects.requireNonNull(httpClientAuthMode)) // https://github.com/netty/netty/issues/4722
                    .sessionCacheSize(0).sessionTimeout(0).sslProvider(this.sslHTTPProvider);

            if (trustedHTTPCertificates != null && trustedHTTPCertificates.length > 0) {
                sslContextBuilder.trustManager(trustedHTTPCertificates);
            }

            httpSslContext = buildSSLContext(sslContextBuilder);

        } catch (final Exception e) {
            throw new ElasticsearchSecurityException("Error while initializing HTTP SSL layer: " + e.toString(),
                    e);
        }
    }
}

From source file:com.flysoloing.learning.network.netty.factorial.FactorialServer.java

License:Apache License

public static void main(String[] args) throws Exception {
    // Configure SSL.
    final SslContext sslCtx;
    if (SSL) {//from   w w w. ja  v  a 2 s. c o m
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
    } else {
        sslCtx = null;
    }

    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new FactorialServerInitializer(sslCtx));

        b.bind(PORT).sync().channel().closeFuture().sync();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

From source file:com.flysoloing.learning.network.netty.file.FileServer.java

License:Apache License

public static void main(String[] args) throws Exception {
    // Configure SSL.
    final SslContext sslCtx;
    if (SSL) {/*from   w  w w  .  ja va 2 s. c om*/
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
    } else {
        sslCtx = null;
    }

    // Configure the server.
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .option(ChannelOption.SO_BACKLOG, 100).handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    public void initChannel(SocketChannel ch) throws Exception {
                        ChannelPipeline p = ch.pipeline();
                        if (sslCtx != null) {
                            p.addLast(sslCtx.newHandler(ch.alloc()));
                        }
                        p.addLast(new StringEncoder(CharsetUtil.UTF_8), new LineBasedFrameDecoder(8192),
                                new StringDecoder(CharsetUtil.UTF_8), new ChunkedWriteHandler(),
                                new FileServerHandler());
                    }
                });

        // Start the server.
        ChannelFuture f = b.bind(PORT).sync();

        // Wait until the server socket is closed.
        f.channel().closeFuture().sync();
    } finally {
        // Shut down all event loops to terminate all threads.
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

From source file:com.flysoloing.learning.network.netty.http.helloworld.HttpHelloWorldServer.java

License:Apache License

public static void main(String[] args) throws Exception {
    // Configure SSL.
    final SslContext sslCtx;
    if (SSL) {//w w  w .  j a  v a 2 s.  c  om
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).build();
    } else {
        sslCtx = null;
    }

    // Configure the server.
    EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    EventLoopGroup workerGroup = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.option(ChannelOption.SO_BACKLOG, 1024);
        b.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new HttpHelloWorldServerInitializer(sslCtx));

        Channel ch = b.bind(PORT).sync().channel();

        System.err.println("Open your web browser and navigate to " + (SSL ? "https" : "http") + "://127.0.0.1:"
                + PORT + '/');

        ch.closeFuture().sync();
    } finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}

From source file:com.flysoloing.learning.network.netty.http2.helloworld.multiplex.server.Http2Server.java

License:Apache License

public static void main(String[] args) throws Exception {
    // Configure SSL.
    final SslContext sslCtx;
    if (SSL) {/*from   ww w  .  jav a2  s .  c o  m*/
        SslProvider provider = OpenSsl.isAlpnSupported() ? SslProvider.OPENSSL : SslProvider.JDK;
        SelfSignedCertificate ssc = new SelfSignedCertificate();
        sslCtx = SslContextBuilder.forServer(ssc.certificate(), ssc.privateKey()).sslProvider(provider)
                /* NOTE: the cipher filter may not include all ciphers required by the HTTP/2 specification.
                 * Please refer to the HTTP/2 specification for cipher requirements. */
                .ciphers(Http2SecurityUtil.CIPHERS, SupportedCipherSuiteFilter.INSTANCE)
                .applicationProtocolConfig(new ApplicationProtocolConfig(Protocol.ALPN,
                        // NO_ADVERTISE is currently the only mode supported by both OpenSsl and JDK providers.
                        SelectorFailureBehavior.NO_ADVERTISE,
                        // ACCEPT is currently the only mode supported by both OpenSsl and JDK providers.
                        SelectedListenerFailureBehavior.ACCEPT, ApplicationProtocolNames.HTTP_2,
                        ApplicationProtocolNames.HTTP_1_1))
                .build();
    } else {
        sslCtx = null;
    }
    // Configure the server.
    EventLoopGroup group = new NioEventLoopGroup();
    try {
        ServerBootstrap b = new ServerBootstrap();
        b.option(ChannelOption.SO_BACKLOG, 1024);
        b.group(group).channel(NioServerSocketChannel.class).handler(new LoggingHandler(LogLevel.INFO))
                .childHandler(new Http2ServerInitializer(sslCtx));

        Channel ch = b.bind(PORT).sync().channel();

        System.err.println("Open your HTTP/2-enabled web browser and navigate to " + (SSL ? "https" : "http")
                + "://127.0.0.1:" + PORT + '/');

        ch.closeFuture().sync();
    } finally {
        group.shutdownGracefully();
    }
}