Java客户端中具有SNI的TLS

时间:2010-05-10 16:48:09

标签: java client-side ssl

正在讨论security and trust working group for NHIN Direct regarding the IP-to-domain mapping problem that is created with traditional SSL。如果HISP(由NHIN Direct定义)想要为提供商托管数以千计的NHIN Direct“健康域名”,那么必须为这些域中的每个域购买IP都是“人为膨胀的成本”。

由于Apache和OpenSSL最近发布了支持SNI扩展的TLS,因此可以使用SNI作为此问题的解决方案在服务器端。但是,如果我们决定允许 NHINDirect传输层的服务器实现来支持TLS + SNI,那么我们必须要求所有客户端也支持SNI。默认情况下,基于OpenSSL的客户端应该这样做,如果您的给定编程语言SSL实现不支持SNI,我们总是可以实现TLS + SNI感知客户端代理。看来使用OpenJDK的本机Java应用程序还不支持SNI,但我无法从该项目中得到直接的答案。我知道有OpenSSL Java库可用,但我不知道这是否可行。

你能否给我一个关于TLS + SNI支持Java客户端的“最新技术”总结?我需要一个Java实现者的观点。

3 个答案:

答案 0 :(得分:8)

答案 1 :(得分:6)

也可以使用某些行修补SUN JDK(bootclasspath)以使服务器SNI正常工作。

类:sun.security.ssl.ServerHandshaker

添加字段

    /** Use for SNI */
    private ServerNameExtension serverNameExtension = null;

补丁方法clientHello(添加这些行)

    /* Use for SNI */
    this.serverNameExtension = (ServerNameExtension)mesg.extensions.get(ExtensionType.EXT_SERVER_NAME);

补丁方法setupPrivateKeyAndChain(更改)

    if (this.conn != null) { alias = km.chooseServerAlias(algorithm      , null, this.conn);
    } else                 { alias = km.chooseEngineServerAlias(algorithm, null, this.engine); }

to

    final Principal[] principals = (this.serverNameExtension == null) ? null : this.serverNameExtension.getHostnamePrincipals();
    if (this.conn != null) { alias = km.chooseServerAlias(algorithm      , principals, this.conn);
    } else                 { alias = km.chooseEngineServerAlias(algorithm, principals, this.engine); }

添加到类sun.security.ssl.ServerNameExtension

static final class ServerNamePrincipal implements Principal {
    private final String name;
    ServerNamePrincipal(final String name) { this.name = name; }
    @Override public String getName() { return this.name; }
    @Override public String toString() { return this.name; }
}

public Principal[] getHostnamePrincipals() {
    final List<Principal> principals = new LinkedList<>();
    for(final ServerName name : this.names) {
        if(name.type == NAME_HOST_NAME) { principals.add(new ServerNamePrincipal(name.hostname)); }
    }
    return principals.toArray(new Principal[principals.size()]);
}

答案 2 :(得分:3)

我正在和ftrotter一样从事同一个项目。

请注意支持域的要求。我不认为SAN会因为两个原因而削减芥末。首先,证书的大小将变得巨大,这可能会导致性能问题至少。其次,这些领域将频繁出现,特别是在NHIN Direct的早期阶段。恕我直言,每当一个域出现或进入时必须更新证书的操作负担将是不可接受的。

根据ftrotter的要求,我做了一些关于java,TLS和SNI主题的谷歌搜索,以及实现相当于基于命名的虚拟主机情况的其他方法,每个虚拟主机只有一个证书。以下是我的想法:

  • JSSE(Java安全套接字扩展)支持TLS,并且对TLS + SNI具有“部分支持”。我不知道在这种情况下部分支持意味着什么。我看到的评论表明,存在的支持不足以完成基于命名的虚拟主机,这基本上就是我们所需要的。

  • 我发现有一篇文章声称JDSE7版本的JSSE 支持TLS + SNI(日期为2008年11月20日),我发现一篇声称它赢了(2009年2月27日)。两者都没有特别的权威性。

  • 在OpenJDK 7上工作的一些人讨论了在2009年2月至3月期间向JSSE添加SNI支持的问题,包括发布源补丁。 (线程从这里开始: http://www.mail-archive.com/security-dev@openjdk.java.net/msg00612.html)。 OpenJDK7将不会在2010年9月之前的任何时间发布。我不知道何时会发布Java 7平台。

  • java.sun.com上没有任何实质内容,所以我真的不知道Sun的计划是什么。

  • 显然有一种不同的方法来完成基于名称的虚拟主机,它显然是广泛兼容的,每个托管服务器使用一个证书,其中包含多个通用名称和多个主题备用名称。请参阅http://wiki.cacert.org/VhostTaskForceServe different certs for same Tomcat application via connectors?

如果您拥有大量虚拟主机,这种方法将创建非常大的证书(由于所有这些CN和SAN)。 NHIN Direct最近面对面会议的其中一位成员正在讨论想要支持数千个的虚拟主机。我的猜测是,这会破坏很多实现。此外,每次添加或删除虚拟主机时都必须更新证书听起来像是一个荒谬的操作负担。

总之,基于名称的虚拟主机的当前Java技术水平,每个虚拟主机具有单独的证书,似乎是“不能做”。此外,还不清楚何时或是否会被添加。

有没有人同意或不同意?有谁知道OpenJDK项目是否有意“反向移植”对Java 6的SNI支持?