如何使Indy OpenSSL与大多数服务器兼容

11

我使用以下代码来为POP3/SMTP发送/接收应用程序设置SSLHandler:

IdSSLHandler->SSLOptions->Mode        = sslmClient;
IdSSLHandler->SSLOptions->Method      = slvSSLv23;
IdSSLHandler->SSLOptions->SSLVersions = TIdSSLVersions() << sslvSSLv3 << sslvTLSv1 << sslvTLSv1_1 << sslvTLSv1_2;

因此,上面的代码应自动支持SSL 3、TLS 1、TLS 1.1和TLS 1.2。但实际上它不能正常工作,并报告“错误版本”错误。当移除SSLVersions行时,它可以工作,但默认情况下包括sslvSSLv2,而我不想支持它。这就像:
IdSSLHandler->SSLOptions->Mode        = sslmClient;
IdSSLHandler->SSLOptions->Method      = slvSSLv23;
IdSSLHandler->SSLOptions->SSLVersions = TIdSSLVersions() << sslvSSLv2 << sslvSSLv3 << sslvTLSv1 << sslvTLSv1_1 << sslvTLSv1_2;

由于某种原因,下面的代码在同一台服务器上能够正常工作,但上面的代码不能。我知道slvSSLv23是一种“使用任何可用版本”的值。那么为什么它在上述代码中不起作用,而其中版本2不存在呢?
另外,我可以使用广泛部署的TLS1,但如果服务器支持1.1或1.2,则我的代码将不会使用更新的版本,除非像上面那样使用。
我希望进行以下初始化:
- 兼容所有服务器,无论它们使用v3、tls1、tls1.1还是tls1.2。 - 自动使用最新版本,并在服务器上不可用时使用较低版本,但不低于版本3——如果版本低于3,则失败/异常。 - 我认为第一个代码版本会实现这一目标,但它报告了版本错误。是否可能实现上述目标,或者必须提供用户设置来选择要使用的SSL版本?

当你说“邮件”时,你指的是哪些协议?即使使用SSLv2,带有STARTTLS的SMTP也比没有加密更好,因为机会主义加密比没有加密更好(我不赞成SSLv2)。然而,IMAPS或POP3S应该使用TLSv1及以上版本,因为客户端将使用这些协议来检查电子邮件和管理邮箱。 - jww
我理解,但由于SSL v2已经过时,而且不多有服务器在使用它(我希望如此),我仍然想避免它。我已经更新了问题 - 它是POP3和SMTP。问题是上面的代码似乎不允许我避免使用v2。 - Coder12345
1个回答

11

SSLVersions设置为单个值会自动将Method设置为相应的单个版本。将SSLVersions设置为多个值会自动将Method设置为slvSSLv23

Method设置为单个版本会自动将SSLVersions设置为相应的单个值。将Method设置为slvSSLv23会自动将SSLVersions设置为所有支持的值。

根据MethodSSLVersions的值,Indy会在OpenSSL中激活/停用适当的SSL_OP_NO_SSL_v#SSL_OP_NO_TLS_v#标志。

我建议采用以下方法,这种方法在添加新的TLS版本时略具未来性:

IdSSLHandler->SSLOptions->Method      = sslvSSLv23;
IdSSLHandler->SSLOptions->SSLVersions = IdSSLHandler->SSLOptions->SSLVersions >> sslvSSLv2;
无论如何,Indy都将使用SSLv23,仅激活SSL_OP_NO_SSL_v2标志。
在这种配置中,“错误版本”通常意味着服务器使用不支持版本协商(使用SSLv2兼容的客户端hello)的特定版本。换句话说,连接到TLSv1服务器的SSLv23客户端将失败。服务器必须使用SSLv23以支持版本协商。在服务器上使用SSLv23允许其接受任何版本的客户端,因为客户端启动握手,所以服务器可以看到正在使用哪个版本头。但是,在客户端上使用SSLv23并不允许它连接到任何除了SSLv23服务器之外的服务器。只有SSLv2服务器可以接受SSLv2客户端,只有SSLv3服务器可以接受SSLv3客户端,只有TLSv1服务器可以接受TLSv1客户端,依此类推。
要真正连接到“任何”服务器,你必须检测“错误版本”错误并使用不同的Method/SSLVersions配置重试。不幸的是,“错误版本”回复不包括服务器的实际版本,因此您必须使用试错法。如果SSLv23失败,请尝试TLSv1_2。如果失败,请尝试TLSv1_1。如果失败,请尝试TLSv1。如果失败,请尝试SSLv3。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接