java - 为基于 netty 的 EPPServer 添加 SSL 支持时,客户端 socket.startHandshake() 失败。

标签 java sockets ssl netty

我正在开发一个支持 EPP 服务器 SSL 的程序,这里是基于 netty 官方示例的代码:

public void start(final int port, final String type) {
    try {
        ServerBootstrap boot = new ServerBootstrap();
        boot.group(bossGroup, workerGroup)
                .channel(NioServerSocketChannel.class)
                .childHandler(new ChannelInitializer<SocketChannel>() {

                    @Override
                    protected void initChannel(SocketChannel ch) throws Exception {
                        if (type.equals("EPP/SSL")) {
                            SslHandler sslHandler = new SslHandler(sslEngine);
                            ch.pipeline().addFirst(sslHandler);
                        }
                        ch.pipeline().addLast(new EppDecoder(),new EppHandler(service));
                    }

                })
                .option(ChannelOption.SO_BACKLOG, 128)
                .childOption(ChannelOption.SO_KEEPALIVE, true);

        this.port = port;
        boot.bind(this.port).sync();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
}

这就是我获取 keystore 和初始化 channel 的方式:

String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm");
    if (null == algorithm) {
        algorithm = "SunX509";
    }
    try {
        KeyStore ks = KeyStore.getInstance("JKS");
        String file = FileLocator.getPath(this.keystorePath);
        FileInputStream fileInputStream = new FileInputStream(file);
        ks.load(fileInputStream, this.keystorePassword.toCharArray());
        KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm);
        kmf.init(ks, this.keystorePassword.toCharArray());
        SSLContext serverContext = SSLContext.getInstance("TLS");
        serverContext.init(kmf.getKeyManagers(), null, null);
        this.sslEngine = serverContext.createSSLEngine();
        this.sslEngine.setUseClientMode(false);
    } catch (Exception e) {
        throw new Error("Failed to initialize the server-side SSLContext", e);
    }

在此之后,我使用 verisign epp 工具对其进行调试。不幸的是,使用epp工具的源代码,我发现它失败了:

    public static Socket createSocket ( String aHost, int aPort, int aTimeout,
        SSLSocketFactory aSslSocketFactory ) throws UnknownHostException,
        IOException, Exception {
    if ( aHost == null || aHost.trim().length() == 0 ) {
        throw new IllegalArgumentException(
                "SecureSocket.createSocket(): host name is invalid" );
    }
    if ( aPort < 0 || aPort > 65535 ) {
        throw new IllegalArgumentException( "Invlaid argument: aPort" );
    }
    if ( aTimeout < 0 ) {
        aTimeout = 0;
    }
    SSLSocket socket =
            (SSLSocket) aSslSocketFactory.createSocket( aHost, aPort );
    if ( aTimeout > 0 ) {
        socket.setSoTimeout( aTimeout );
    }
    socket.startHandshake();//failed here
    return socket;
}

我使用 keytool 创建了认证文件并将其导入到 epp 客户端 keystore 中,但它似乎不起作用。当类型不是“EPP/SSL”时,源代码仍然有效。为什么 SSL 套接字握手失败?

最佳答案

您必须为每个连接创建一个新的 SSLEngine。看起来您的代码创建了一个 SSLEngine 实例,然后将其用于所有 SSL 连接。它永远不会起作用。

初始化 SSL 连接的推荐方法是在 io.netty.handler.ssl 中使用 SslContext:

public static void main(String[] args) throws Exception {
    final SslContext sslCtx = SslContext.newServerContext(...);
    ServerBootstrap b = ...;

    b.childHandler(new ChannelInitializer<SocketChannel>() {
        @Override
        protected void initChannel(SocketChannel ch) throws Exception {
            if (type.equals("EPP/SSL")) {
                SslHandler sslHandler = sslCtx.newHandler(ch.alloc());
                ch.pipeline().addFirst(sslHandler);
            }
            ...
        }
    });
    ...
}

关于java - 为基于 netty 的 EPPServer 添加 SSL 支持时,客户端 socket.startHandshake() 失败。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28341458/

相关文章:

C# Socket 服务器 - Flash 客户端 - 数据库访问和性能

用于本地 HTTPS 的 Docker WSL2 SSL 证书

ssl - ServletRequest.getAttribute ("javax.servlet.request.X509Certificate") 返回 null

ssl - 下载 DoD 证书颁发机构 (CA) 证书的链接

java - 使用 Java 删除 BOM 字符

c - pipe2(...) vs pipe() + fcntl(...),为什么不同?

Java访问Queue<Map>中的Map

python - 检查python套接字中的数据是否可用

java - ArrayList 获取数组索引

java - 比较已实现可比较的类的对象