2012-03-05 16 views
9

クライアントとサーバーの両方が証明書を提示して確認する双方向SSLハンドシェイクでNettyを設定しようとしています。双方向SSL Handsake(クライアントとサーバー証明書)でNettyを設定する

これはSslHandlerでは実装されていないようです。誰もこれをしていますか?私はそれがSslHandler.handshakeオペレーションに入り、javax.net.ssl.SSLEngineに委譲されると思いますか?

ヒント/ヒント/既存の実装はありますか?

ありがとうございます!


ANSWER(stackoverflowのは、私はそれを通常の方法を掲載させません)私は私のSslHandlerを設定する前に、SSLEngineのオブジェクトにneedClientAuthフラグを設定した場合、それが問題の世話をことがわかりました!

答えて

10

ここでは、nettyプロジェクトのHttpSnoopサーバーの例に基づいて解決策を示します。クライアント側のパイプラインを設定するときは、次のように、SSLエンジンが設定されている必要があり

public ChannelPipeline getPipeline() throws Exception { 
    // Create a default pipeline implementation. 
    ChannelPipeline pipeline = pipeline(); 

    // Uncomment the following line if you want HTTPS 
    SSLEngine engine = SecureChatSslContextFactory.getServerContext().createSSLEngine(); 
    engine.setUseClientMode(false); 
    engine.setNeedClientAuth(true); 
    pipeline.addLast("ssl", new SslHandler(engine)); 

    pipeline.addLast("decoder", new HttpRequestDecoder()); 
    pipeline.addLast("logger", new RequestAuditLogger()); 
    // Uncomment the following line if you don't want to handle HttpChunks. 
    pipeline.addLast("aggregator", new HttpChunkAggregator(1048576)); 
    pipeline.addLast("outputLogger", new ResponseAuditLogger()); 
    pipeline.addLast("encoder", new HttpResponseEncoder()); 
    // Remove the following line if you don't want automatic content compression. 
    pipeline.addLast("deflater", new HttpContentCompressor()); 
    pipeline.addLast("handler", new HttpSnoopServerHandler()); 
    return pipeline; 
} 
} 

次のように次に、あなたのSSLContextは、キーストア(SecureChatSslContextFactory)に加えて、信頼ストアを設定するように変更する必要があります:

public final class SecureChatSslContextFactory { 


private static Logger logger = LoggerFactory.getLogger(SecureChatSslContextFactory.class); 

private static final String PROTOCOL = "TLS"; 
private static final SSLContext SERVER_CONTEXT; 
private static final SSLContext CLIENT_CONTEXT; 

static { 

    SSLContext serverContext = null; 
    SSLContext clientContext = null; 

     // get keystore and trustore locations and passwords 
    String keyStoreLocation = System.getProperty("javax.net.ssl.keyStore"); 
    String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword"); 
    String trustStoreLocation = System.getProperty("javax.net.ssl.trustStore"); 
    String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword"); 
    try { 

     KeyStore ks = KeyStore.getInstance("JKS"); 
     ks.load(KeyStoreStreamManager.asInputStream(keyStoreLocation), 
       keyStorePassword.toCharArray()); 

     // Set up key manager factory to use our key store 
     KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm()); 
     kmf.init(ks, keyStorePassword.toCharArray()); 

      // truststore 
     KeyStore ts = KeyStore.getInstance("JKS"); 
     ts.load(KeyStoreStreamManager.asInputStream(trustStoreLocation), 
       trustStorePassword.toCharArray()); 

     // set up trust manager factory to use our trust store 
     TrustManagerFactory tmf = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); 
     tmf.init(ts); 

     // Initialize the SSLContext to work with our key managers. 
     serverContext = SSLContext.getInstance(PROTOCOL); 
     serverContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null); 

    } catch (Exception e) { 
     throw new Error(
       "Failed to initialize the server-side SSLContext", e); 
    } 

    try { 
     clientContext = SSLContext.getInstance(PROTOCOL); 
     clientContext.init(null, SecureChatTrustManagerFactory.getTrustManagers(), null); 
    } catch (Exception e) { 
     throw new Error(
       "Failed to initialize the client-side SSLContext", e); 
    } 

    SERVER_CONTEXT = serverContext; 
    CLIENT_CONTEXT = clientContext; 
} 

public static SSLContext getServerContext() { 
    return SERVER_CONTEXT; 
} 

public static SSLContext getClientContext() { 
    return CLIENT_CONTEXT; 
} 

private SecureChatSslContextFactory() { 
    // Unused 
} 
} 
+1

私はCStepnitzの答えにコメントしました。 SslEngineドキュメントから: クライアント認証を要求するようにエンジンを設定します。このオプションは、サーバーモードのエンジンでのみ有効です。彼が指摘したようにクライアント側ではありません。 – user1792307

+0

@CStepnitz:TrustManagerがどのような種類の証明書を受け入れるか知っていますか?私は非常に似たアーキテクチャを持っていますが、クライアントはECC証明書を送信しています(証明書のカーブが認識されないため、ハンドシェークが失敗します)がRSA証明書が受け入れられます。 – favicon

4

相互認証は、今(現在は単にJDKプロバイダのために、しかし、OpenSSLはサポートがすぐに来て提供)SslContextによってサポートされています。 newClientContextnewServerContextを参照してください。両方とも、TrustManagerFactoryとKeyManagerFactoryの取得をサポートしています。これらの静的ファクトリメソッドは、証明書、キー、および証明書チェーンファイルを直接取得して、TrustManagerFactoryおよびKeyManagerFactoryを構築することもサポートしています。

(JDKプロバイダの)クライアント認証を要求する方法の例については、JdkSslEngineTestを参照してください。

+0

OpenSSLエンジンは相互認証をサポートするようになりました。 OpenSSLエンジンは、基本的にJDKのSSLエンジンとの機能パリティを備えています。[SSLEngineTest](https://github.com/netty/netty/blob/4.1/handler/src/test/java/io/netty/handler/ssl/SSLEngineTest.java)を参照してください。見つからない機能がある場合は[file問題](https://github.com/netty/netty/issues)。 –

6

SSLEngineの代わりにnettys SslContextを使用して、新しいSslHandlerを作成します。基本的には次のようにKeyManagerFactoryを渡すことによって、新しいSslContextを作成

のSSLContextのSSLContext = SslContextBuilder.forServer(のKeyManagerFactory).build()することができます。

のハンドラーを取得するには、を作成してください。

ChannelPipeline.addLast( "ssl"、sslContext.newHandler(socketChannel.alloc()));

関連する問題