如何使Indy OpenSSL与大多数服务器兼容
我使用以下代码为POP3/SMTP发送/接收应用程序设置SSLHandler:
I use the following code to setup SSLHandler for POP3/SMTP sending/receiving app:
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
.就像这样:
So, the above code is supposed to support SSL 3, TLS 1, TLS 1.1 and TLS 1.2 automatically. This does not work well and reports "wrong version" error. When the SSLVersions
line is removed then it works but by defaults it includes sslvSSLv2
which I don't want to support. It is the same like:
IdSSLHandler->SSLOptions->Mode = sslmClient;
IdSSLHandler->SSLOptions->Method = slvSSLv23;
IdSSLHandler->SSLOptions->SSLVersions = TIdSSLVersions() << sslvSSLv2 << sslvSSLv3 << sslvTLSv1 << sslvTLSv1_1 << sslvTLSv1_2;
由于某种原因,这可行,并且以上内容不在同一服务器上.我知道slvSSLv23
是一种使用任何可用版本"的值.那么为什么它不能与上面没有版本2的代码一起使用呢?
For some reason, this works and the above does not on same server. I know that slvSSLv23
is a kind of "use any available version" value. So why does it not work with above code where version 2 is not present?
此外,我可以使用似乎已广泛部署的TSL1,但如果服务器支持1.1或1.2,则除非使用了类似上述内容,否则我的代码将不会使用较新的版本,但将强制使用1.0版.
Additionally, I can use TSL1 which seems to be widely deployed, but if the server supports 1.1 or 1.2 then my code won't be using more recent versions but will force 1.0 version unless something like above is used.
我要进行初始化,其目标如下:
I would like to make an initialization with the following goals:
- 与所有服务器兼容,无论它们使用的是v3,tls1,tls1.1还是tls1.2
- 自动使用最新版本,如果服务器上没有较新版本但不低于3,则使用较低版本-如果版本低于3,则失败/异常.
我认为该代码的第一个版本将提供该功能,但是它报告版本错误.是否可以实现上述目标,或者必须提供用户设置来选择要使用的SSL版本?
I thought the first version of the code would provide that but it reports version error. Are the above goals possible or a user-setting must be provided to select SSL version to use?
将SSLVersions
设置为单个值会自动将Method
设置为相应的单个版本.将SSLVersions
设置为多个值会自动将Method
设置为slvSSLv23
.
Setting the SSLVersions
to a single value automatically sets the Method
to the corresponding single version. Setting the SSLVersions
to multiple values automatically sets the Method
to slvSSLv23
.
将Method
设置为单个版本会自动将SSLVersions
设置为相应的单个值.将Method
设置为slvSSLv23
会自动将SSLVersions
设置为所有受支持的值.
Setting the Method
to a single version automatically sets the SSLVersions
to the corresponding single value. Setting the Method
to slvSSLv23
automatically sets the SSLVersions
to all supported values.
Indy根据Method
和SSLVersions
的值来激活/停用OpenSSL中相应的SSL_OP_NO_SSL_v#
和SSL_OP_NO_TLS_v#
标志.
Indy activates/deactivates the appropriate SSL_OP_NO_SSL_v#
and SSL_OP_NO_TLS_v#
flags in OpenSSL depending on the values of Method
and SSLVersions
.
我建议采用以下方法,随着添加新的TLS版本,该方法在将来会稍作证明:
I would suggest the following approach, which is a slightly more future proof as new TLS versions are added:
IdSSLHandler->SSLOptions->Method = sslvSSLv23;
IdSSLHandler->SSLOptions->SSLVersions = IdSSLHandler->SSLOptions->SSLVersions >> sslvSSLv2;
无论哪种方式,Indy都将使用仅激活SSL_OP_NO_SSL_v2
标志的SSLv23.
Either way, Indy would be using SSLv23 with only the SSL_OP_NO_SSL_v2
flag activated.
在该配置中,错误版本"错误通常表示服务器使用的是不支持版本协商的特定版本(该版本使用SSLv2兼容的客户端问候).换句话说,连接到TLSv1服务器的SSLv23客户端将失败.服务器必须使用SSLv23才能支持版本协商.在服务器上使用SSLv23可以使其接受任何版本的客户端,因为客户端会发起握手,以便服务器可以查看正在使用哪个版本头.但是在客户端上使用SSLv23不允许其连接到SSLv23服务器以外的任何服务器. SSLv2服务器只能接受SSLv2客户端,SSLv3服务器只能接受SSLv3客户端,TLSv1服务器只能接受TLSv1客户端,依此类推.
In that configuration, a "wrong version" error typically means the server is using a specific version that does not support version negotiation (which uses an SSLv2-compatible client hello). In other words, an SSLv23 client connecting to a TLSv1 server will fail. The server must use SSLv23 in order to support version negotiation. Using SSLv23 on the server allows it to accept any version client, as the client initiates the handshake so the server can see which version header is being used. But using SSLv23 on the client DOES NOT allow it to connect to any server OTHER THAN an SSLv23 server. An SSLv2 server can only accept SSLv2 clients, an SSLv3 server can only accept SSLv3 clients, a TLSv1 server can only accept TLSv1 clients, and so on.
要真正连接到任何"服务器,您必须检测到错误版本"错误,然后使用其他特定的Method
/SSLVersions
配置重试.不幸的是,错误版本"答复不包括服务器的实际版本,因此您必须使用反复试验.如果SSLv23失败,请尝试TLSv1_2.如果失败,请尝试TLSv1_1.如果失败,请尝试TLSv1.如果失败,请尝试SSLv3.
To truly connect to "any" server, you would have to detect a "wrong version" error and retry with a different specific Method
/SSLVersions
configuration. Unfortunately, the "wrong version" reply does not include the server's actual version, so you have to use trial-and-error. If SSLv23 fails, try TLSv1_2. If that fails, try TLSv1_1. If that fails, try TLSv1. If that fails, try SSLv3.