没有JKS的嵌入式Jetty上的TLS
问题描述:
我的目标:我正在研究Jetty Embedded的集成,这将使其易于使用。 interface将允许用于集成TLS证书的外部源,而不使用Java KeyStore。没有JKS的嵌入式Jetty上的TLS
这将允许建立分布式Web服务时更大的灵活性(在我的情况下是experimental, self-hosted CDN)。
但是,我在构建集成时遇到了问题。存根实现是in this repository。
我试过的东西:我试过更换key manager和trust manager,并为其中的每个函数设置断点。但是,当试图访问服务器时,这些断点永远不会被触发。相反,我遇到这个错误:
javax.net.ssl.SSLHandshakeException: no cipher suites in common
at sun.security.ssl.Handshaker.checkThrown(Handshaker.java:1478)
at sun.security.ssl.SSLEngineImpl.checkTaskThrown(SSLEngineImpl.java:535)
at sun.security.ssl.SSLEngineImpl.readNetRecord(SSLEngineImpl.java:813)
at sun.security.ssl.SSLEngineImpl.unwrap(SSLEngineImpl.java:781)
at javax.net.ssl.SSLEngine.unwrap(SSLEngine.java:624)
at org.eclipse.jetty.io.ssl.SslConnection$DecryptedEndPoint.fill(SslConnection.java:621)
at org.eclipse.jetty.server.HttpConnection.fillRequestBuffer(HttpConnection.java:322)
at org.eclipse.jetty.server.HttpConnection.onFillable(HttpConnection.java:231)
at org.eclipse.jetty.io.AbstractConnection$ReadCallback.succeeded(AbstractConnection.java:279)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112)
at org.eclipse.jetty.io.ssl.SslConnection.onFillable(SslConnection.java:261)
at org.eclipse.jetty.io.ssl.SslConnection$3.succeeded(SslConnection.java:150)
at org.eclipse.jetty.io.FillInterest.fillable(FillInterest.java:112)
at org.eclipse.jetty.io.ChannelEndPoint$2.run(ChannelEndPoint.java:124)
at org.eclipse.jetty.util.thread.QueuedThreadPool.runJob(QueuedThreadPool.java:672)
at org.eclipse.jetty.util.thread.QueuedThreadPool$2.run(QueuedThreadPool.java:590)
at java.lang.Thread.run(Thread.java:748)
我试图分析“标准”的码头设置,其中一个证书从密钥库,但没有多少运气。我无法找到Jetty获取我应该覆盖的密码/证书信息的地方。
我的问题:如何让Jetty使用my own certificate source代替Java KeyStore和TrustStore?
答
@EJP我指出了正确的方向,所以这里是如何做到这一点:
下面是它需要如何做。
首先,设置码头为TLS:
HttpConfiguration https = new HttpConfiguration();
https.addCustomizer(new SecureRequestCustomizer());
SslContextFactory sslContextFactory = new JettySslContextFactory(configuration.getSslProviders());
ServerConnector sslConnector = new ServerConnector(
server,
new SslConnectionFactory(sslContextFactory, "http/1.1"),
new HttpConnectionFactory(https)
);
sslConnector.setPort(httpsPort);
注意该类JettySslContextFactory。此类扩展内置X509ExtendedKeyManager,需要重写protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception
方法,以提供定制的KeyManager,像这样:
@Override
protected KeyManager[] getKeyManagers(KeyStore keyStore) throws Exception {
return new KeyManager[] {
new JettyX509ExtendedKeyManager(certificateProviders)
};
}
除此之外,下面的步骤在每个连接运行:
- SNI匹配器与SNI主机名进行协商。这似乎是SNI主机名甚至可用的唯一地方。
- 查询密钥管理器以获取特定密钥类型(EC或RSA)的别名(密钥ID的种类)。这里我们需要从SNI匹配器中获取主机名,否则我们不知道匹配哪个主机名。
- 根据别名(密钥ID),我们可以返回私钥和证书。
至少这是我从调试这个问题中收集到的。完整代码is online here。
这个异常通常意味着服务器找不到私钥和匹配的证书。显然你的'KeyManager'没有正确安装,或者它之前会被调用。 – EJP
谢谢,我将尝试追踪密钥管理器在“股票”版本与我自己的版本中的安装方式。 – Janoszen