SSLv3握手失败警告——Delphi Indy

5

我一直在使用:

  • Delphi XE8

  • Indy版本10.6.2.5263

  • 预编译的OpenSSL dll文件(Win 32位),版本为1.0.2.l

  • TIdSSLIOHandlerSocketOpenSSL,其中Method设置为sslvSSLv23

来向服务器提交POST请求。几个月来,它一直运行得很好。

突然间,一个错误出现了:

14094410 sslv3 alert handshake failure.

我的同事使用SOAP UI向同一台服务器提交请求,强制使用TLS 1.2,它可以工作。我尝试将TIdSSLIOHandlerSocketOpenSSL1Method设置为sslvTLSv1_2,并将Mode更改为sslmClient,但结果总是相同的。

我认为通过将Method设置为sslvTLSv1_2,不可能收到与SSLv3相关的错误。

我已经检查了以下这些stackoverflow帖子:

和其他一些主题,但我无法找到这个问题的根本原因。

也许我漏掉了什么。请给我一点提示好吗?


TLS是SSL 3.0的扩展,OpenSSL使用SSLv3功能来实现TLS,这就是为什么警报显示为SSLv3。但是如果没有关于警报的具体细节,特别是警报号码,就无法知道为什么OpenSSL会失败。此外,您的Indy版本有点旧,当前版本是10.6.2.5432,您应该考虑升级以获取最新的OpenSSL支持代码。 - Remy Lebeau
你好,Remy。具体错误为:error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure。我会尝试获取最新的Indy版本并再次尝试。 - Mr. Ajin
1
嗨,我已经更新了Indy组件,但现在显示的版本是10.6.2.0。 - Mr. Ajin
1
你好 Remy,我使用 Wireshark 和一些 Java 代码进行了一些测试。Wireshark 显示,无论我通过 SSLOptions.Method 或 SSLOptions.SSLVersions 进行什么选择,Indy 组件始终发送 TLSv1 请求。Java 代码请求使用 TLSv1.2,并且请求成功。因此,我的问题是,Indy 组件始终发送 TLSv1。 - Mr. Ajin
Indy 不是发送握手的一方,而是 OpenSSL。所使用的版本取决于 Indy 的 SSLOptions 如何配置。如果将其设置为仅 sslvTLSv1_2,则应该发送 TLS 1.2 hello,除非您正在使用已禁用 TLS 1.2 的 OpenSSL DLL,此时 Indy 将回退到 TLS 1.0。在 OpenSSL 加载到内存后,Indy 的 IsOpenSSL_TLSv1_2_Available() 函数返回 true 还是 false? - Remy Lebeau
显示剩余4条评论
3个回答

6

我曾经也遇到了同样的问题,以下源代码完美解决了问题。我从某个网站复制了这段代码,但是我找不到链接来表彰原始答案。请注意,源代码并不是我的。

TCustomIdHTTP = class(TIdHTTP)
  public
    constructor Create(AOwner: TComponent);
  private
    procedure OnStatusInfoEx(ASender: TObject; const AsslSocket: PSSL; const AWhere, Aret: TIdC_INT; const AType, AMsg: String);
  end;

constructor TCustomIdHTTP.Create(AOwner: TComponent);
begin
  IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
  with IOHandler as TIdSSLIOHandlerSocketOpenSSL do
  begin
    OnStatusInfoEx := Self.OnStatusInfoEx;
    SSLOptions.Method := sslvSSLv23;
    SSLOptions.SSLVersions := [sslvTLSv1_2, sslvTLSv1_1, sslvTLSv1];
  end;
  inherited Create(AOwner);
end;

procedure TCustomIdHTTP.OnStatusInfoEx(ASender: TObject; const AsslSocket: PSSL;
  const AWhere, Aret: TIdC_INT; const AType, AMsg: String);
begin
  SSL_set_tlsext_host_name(AsslSocket, Request.Host);
end;

1
请注意,您需要在uses部分中添加“IdCTypes”和“IdSSLOpenSSLHeaders”(我不得不挖掘它们)。 - Jerry Dodge

3

请确保您的应用程序文件夹中有最新的libeay32.dll和ssleay32.dll文件。


之前 - 我尝试了你发布的解决方案,它完美地运行了。 - user2005049

0

我自己在一些网站上也遇到了同样的问题。我通过使用TRESTClient而不是TIdHTTPOpenSSL来解决了这个问题。

  • TRESTClient
  • TRESTRequest
  • TRESTResponse

您可以在Delphi IDE的工具菜单中的REST Debugger中设置URL、身份验证和参数,并将组件复制到剪贴板,以便为您提供一个起点。


起初这是我的解决方案,但随后出现了获取二进制数据的部分,在这种情况下,TRESTClient不知道如何处理二进制数据... - Jerry Dodge

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