我试图通过使用TIdServerIOHandlerSSLOpenSSL组件并设置其SSLOptions.MethodSSLOptions.SSLVersions属性(如this answer中所建议的)来控制与Web服务的HTTPS连接所支持的TLS / SSL协议。

默认值为方法sslvTLSv1和SSLVersions [sslvTLSv1](有关方法和SSLVersions之间的关系,请参见this answer):

delphi - 我如何仅支持TLS 1.x(在我的Web服务中)?-LMLPHP

我将nmap与this answer中的ssl-enum-ciphers.nse脚本一起使用,以检查实际可用的内容,并获得以下脚本输出:

| ssl-enum-ciphers:
|   TLSv1.0:
|     ciphers:
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: client
|     warnings:
|       Ciphersuite uses MD5 for message integrity
|       Weak certificate signature: SHA1
|_  least strength: C


但是缺少TLS 1.1和TLS 1.2。

如果我将Method设置为sslvSSLv23(“在客户端和服务器支持不同的SSL / TLS版本的情况下,允许动态版本协商的通配符。它允许他们找出并使用双方通用的最高版本”(source ))我看到sslvSSLv2sslvSSLv3处于活动状态。
但是我不希望支持SSL 2.0(RF​​C 6176在2011年弃用/禁止使用)和3.0(RF​​C 7568在2015年6月弃用了)(source)。
我不能从方法sslvTLSv2生成的集合中同时减去sslvTLSv3sslvSSLv23:我们恢复为仅支持TLS 1.0的默认配置。

请注意,如果我仅“忽略” sslvTLSv2(方法为sslvSSLv23,SSLVersions为[sslvSSLv3,sslvTLSv1]),nmap会告诉我:

| ssl-enum-ciphers:
|   SSLv3:
|     ciphers:
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: client
|     warnings:
|       CBC-mode cipher in SSLv3 (CVE-2014-3566)
|       Ciphersuite uses MD5 for message integrity
|       Weak certificate signature: SHA1
|   TLSv1.0:
|     ciphers:
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: client
|     warnings:
|       Ciphersuite uses MD5 for message integrity
|       Weak certificate signature: SHA1
|   TLSv1.1:
|     ciphers:
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: client
|     warnings:
|       Ciphersuite uses MD5 for message integrity
|       Weak certificate signature: SHA1
|       Weak cipher RC4 in TLSv1.1 or newer not needed for BEAST mitigation
|   TLSv1.2:
|     ciphers:
|       TLS_RSA_WITH_3DES_EDE_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_AES_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_128_GCM_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_CBC_SHA256 (rsa 2048) - A
|       TLS_RSA_WITH_AES_256_GCM_SHA384 (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_128_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_CAMELLIA_256_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_DES_CBC_SHA (rsa 2048) - C
|       TLS_RSA_WITH_IDEA_CBC_SHA (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_MD5 (rsa 2048) - A
|       TLS_RSA_WITH_RC4_128_SHA (rsa 2048) - A
|       TLS_RSA_WITH_SEED_CBC_SHA (rsa 2048) - A
|     compressors:
|       NULL
|     cipher preference: client
|     warnings:
|       Ciphersuite uses MD5 for message integrity
|       Weak certificate signature: SHA1
|       Weak cipher RC4 in TLSv1.1 or newer not needed for BEAST mitigation
|_  least strength: C


我该怎么做才能仅支持所有TLS 1.x版本?

这是运行于Win7的带有Indy 10.5.8.0的Delphi XE2,已通过OpenSSL 1.02f进行了测试。使用OpenSSL 1.02g,我得到this issue,我们还没有准备好更新到Delphi Seattle(更新1),在Indy代码中解决了该问题。

补充说明:


我也应该放弃TLS 1.0支持吗?
SSLOptions.Mode仍为默认的sslmUnassigned,我想稍后再看。
请注意,nmap脚本仅测试SSLv3 / TLS版本,而不测试SSLv2。我还使用了SSLScan,这表明如果仅省略sslvTLSv3,则确实仍启用SSL2 ;-(
忘记有关弱密码的信息,这是接下来要解决的问题;-)
如果我在Delphi IDE中运行Web服务,我实际上无法进行nmap测试,这会产生各种运行时错误(如果运行可执行文件则不会出现)。也许是因为nmap脚本触发了各种测试而发生了这些?


    EIdOSSLAcceptError'接受SSL连接时出错。观察到EOF违反了协议。
    ssl3_get_client_hello中的EIdOSSLUnderlyingCryptoError:无共享密码
    ssl3_get_client_hello中的EIdOSSLUnderlyingCryptoError:版本号错误

最佳答案

但是缺少TLS 1.1和TLS 1.2。


正确,因为如果将Method设置为sslvTLSv1,Indy将仅专门使用TLS 1.0。

对象检查器的屏幕快照清楚地表明您正在使用不支持TLS 1.1+的Indy版本(如果使用的话,在sslvTLSv1_1属性中将有sslvTLSv1_2SSLVersions选项可用)。


  请注意,如果我“仅”忽略了sslvTLSv2(方法是sslvSSLv23,而SSLVersions是[sslvSSLv3,sslvTLSv1]),nmap会告诉我:


MethodsslvSSLv23时,Indy仅禁用不需要的SSL / TLS版本,在这种情况下为SSLv2。显然,您正在使用支持TLS 1.1+的OpenSSL库版本。因此,由于您的Indy版本不支持TLS 1.1+,因此不会禁用它们。默认情况下启用它们。由于您没有禁用TLS 1.0,因此OpenSSL本身隐式启用了TLS 1.1+。


  我该怎么做才能仅支持所有TLS 1.x版本?


这是一个奇怪的解决方法,但是您可以将SSLVersions设置为[sslvSSLv23,sslvTLSv1]。这会将Method设置为sslvSSLv23,并从sslvSSLv23中删除​​SSLVersions。这样,Indy将使用SSLv23通配符并禁用SSLv2和SSLv3,从而启用TLS 1.0+。

不幸的是,您在设计时无法真正在Object Inspector中进行此配置。好吧,您可以(先启用sslvTLSv1,然后再启用ssvSSLv23),但是不会正确地将其保存在DFM中(由于SSLVersions是默认值,因此将省略[sslvTLSv1]),因此最终将在运行时重新启用SSLv2和SSLv3。为避免这种情况,必须在运行时在激活服务器之前在代码中分配SSLVersions

IdServerIOHandlerSSLOpenSSL1.SSLOptions.SSLVersions := [sslvSSLv23,sslvTLSv1];


否则,替代方法是升级到本地支持TLS 1.1+的Indy的最新版本,然后可以将SSLVersions设置为[sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2](在运行时或设计时)并继续。

07-26 09:40