我试图通过使用TIdServerIOHandlerSSLOpenSSL
组件并设置其SSLOptions.Method
和SSLOptions.SSLVersions
属性(如this answer中所建议的)来控制与Web服务的HTTPS连接所支持的TLS / SSL协议。
默认值为方法sslvTLSv1
和SSLVersions [sslvTLSv1]
(有关方法和SSLVersions之间的关系,请参见this answer):
我将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 ))我看到sslvSSLv2
和sslvSSLv3
处于活动状态。但是我不希望支持SSL 2.0(RFC 6176在2011年弃用/禁止使用)和3.0(RFC 7568在2015年6月弃用了)(source)。
我不能从方法
sslvTLSv2
生成的集合中同时减去sslvTLSv3
和sslvSSLv23
:我们恢复为仅支持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_2
和SSLVersions
选项可用)。
请注意,如果我“仅”忽略了sslvTLSv2(方法是sslvSSLv23,而SSLVersions是[sslvSSLv3,sslvTLSv1]),nmap会告诉我:
当Method
为sslvSSLv23
时,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]
(在运行时或设计时)并继续。