【问题标题】:EIdOSSLUnderlyingCryptoError ExceptionEIdOSSLUnderlyingCryptoError 异常
【发布时间】:2015-04-26 09:01:27
【问题描述】:

我正在使用 Indy(IdHTTP、OpenSSL)。我使用这个简单的代码来下载一个页面

var
  IdHTTP: TIdHTTP;
begin
  IdHTTP:=TIdHTTP.Create;
  try
    IdHTTP.Get('https://ezfile.ch/?m=help&a=tos');
  finally
    IdHTTP.Free;
  end;
end;

返回:

EIdOSSLUnderlyingCryptoError exception "Error connecting with SSL.
    error:14094438:SSL routines:SSL3_READ_BYTES:tlsv1 alert internal error"

该站点使用 TLS 1.1、AES_128_CBC_SHA1、ECDHE-ECDSA。 它应该很容易重现。

尝试了各种 Delphi 版本、Indy 10.6.2、各种 OpenSSL 版本。更改 SSLVersion 选项没有帮助。

可能是什么问题?

【问题讨论】:

  • 该站点支持 TLS 1.2、1.1 和 1.0。
  • 这是可能的。结果是一样的。 PS:您不应该删除该注释代码(在旧的 Indy 版本中是必需的)。
  • 我刚刚尝试使用原始 OpenSSL 可执行文件来测试连接。命令:“openssl.exe s_client -connect ezfile.ch:443”,它返回几乎相同的“:error:14077438:SSLroutines:SSL23_GET_SERVER_HELLO:tlsv1 alert internal error”
  • 如果预建的 OpenSSL 应用程序无法连接,那么服务器可能配置错误。联系服务器管理员。
  • 使用可能相同的 OpenSSL 1.0.2 的 curl 可以正常工作,这很神秘。

标签: delphi http openssl indy indy10


【解决方案1】:

这是关于如何使用SSL_set_tlsext_host_name 解决此问题的示例代码

这是通过创建一个继承自 TIdHTTP 的自定义类,并通过使用 TIdSSLIOHandlerSocketOpenSSLOnStatusInfoEx 事件以正确的参数调用 SSL_set_tlsext_host_name 来完成的

大约一个月前,这个问题开始出现在所有 Cloudflare 启用 SSL 的网站上。

program Project1;

{$APPTYPE CONSOLE}

uses
  System.Classes, IdHTTP, IdSSL, IdSSLOpenSSL, IdSSLOpenSSLHeaders, IdCTypes;

type
  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;

{ TCustomIdHTTP }

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;
//////////////////

var
  MyHTTP: TCustomIdHTTP;
begin
  MyHTTP := TCustomIdHTTP.Create(nil);
  // Your normal Indy HTTP code here
  MyHTTP.Free;
end.

【讨论】:

  • 是的,我在使用 CloudFlare 证书的服务器上遇到了这个问题。正确答案评论中已经提到了这个解决方案;)
  • @smooty86 我知道,但代码比 API 名称要好 :)
  • 太棒了!谢谢尼克C。
  • 仅供参考,当前版本的 Indy supports client-side SNI,它现在为您调用 SSL_set_tlsext_host_name()
  • 此解决方法修复了 Windows 上的问题,但问题仍然出现在 MacOS 上。我正在使用 XE8 火猴。有什么建议吗?
【解决方案2】:

可能是什么问题?

该网站对我来说似乎可以运行。我什至可以连接 TLS 1.2。

但是,我在尝试连接 SSLv3 时失败了。这是一件好事。

这可能是库中的错误。也就是说,它试图与 SSLv3 连接,或者它做错了其他事情,比如用 SNI 省略了服务器名称。或者,您在运行时加载了错误版本的 OpenSSL。也就是说,您针对 OpenSSL 1.0.2 进行了编译,但您在运行时加载了系统低级别版本,例如 0.9.8。

您可以通过获取 CA 并通过 -CAfile 将其传递给 s_client 来清除下面的 verify error:num=20

$ echo -e "GET /?m=help&a=tos HTTP/1.1\r\nHost: ezfile.ch\r\n\r\n" | \
    openssl s_client -connect ezfile.ch:443 -tls1_1 -servername ezfile.ch -ign_eof
CONNECTED(00000003)
depth=2 C = GB, ST = Greater Manchester, L = Salford, O = COMODO CA Limited, CN = COMODO ECC Certification Authority
verify error:num=20:unable to get local issuer certificate
---
Certificate chain
 0 s:/OU=Domain Control Validated/OU=PositiveSSL Multi-Domain/CN=sni42046.cloudflaressl.com
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Domain Validation Secure Server CA 2
 1 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Domain Validation Secure Server CA 2
   i:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Certification Authority
 2 s:/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Certification Authority
   i:/C=SE/O=AddTrust AB/OU=AddTrust External TTP Network/CN=AddTrust External CA Root
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIGtjCCBlugAwIBAgIRAPpZe3LxW3syzgKsuUmSJqEwCgYIKoZIzj0EAwIwgZIx
CzAJBgNVBAYTAkdCMRswGQYDVQQIExJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAOBgNV
BAcTB1NhbGZvcmQxGjAYBgNVBAoTEUNPTU9ETyBDQSBMaW1pdGVkMTgwNgYDVQQD
Ey9DT01PRE8gRUNDIERvbWFpbiBWYWxpZGF0aW9uIFNlY3VyZSBTZXJ2ZXIgQ0Eg
MjAeFw0xNTAzMjUwMDAwMDBaFw0xNTA5MzAyMzU5NTlaMGsxITAfBgNVBAsTGERv
bWFpbiBDb250cm9sIFZhbGlkYXRlZDEhMB8GA1UECxMYUG9zaXRpdmVTU0wgTXVs
dGktRG9tYWluMSMwIQYDVQQDExpzbmk0MjA0Ni5jbG91ZGZsYXJlc3NsLmNvbTBZ
MBMGByqGSM49AgEGCCqGSM49AwEHA0IABGtNNuTz7vtNt80pyh8FgGuPH78FQb1D
FsR0tBKe+ygNLGysmcTkhekQeupBYMFsfHdjUy51iabkf1a2m75iqM6jggS2MIIE
sjAfBgNVHSMEGDAWgBRACWFn8LyDcU/eEggsb9TUK3Y9ljAdBgNVHQ4EFgQUo9+D
XFOnVv7lgCtpOyO+2vbluvswDgYDVR0PAQH/BAQDAgeAMAwGA1UdEwEB/wQCMAAw
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCME8GA1UdIARIMEYwOgYLKwYB
BAGyMQECAgcwKzApBggrBgEFBQcCARYdaHR0cHM6Ly9zZWN1cmUuY29tb2RvLmNv
bS9DUFMwCAYGZ4EMAQIBMFYGA1UdHwRPME0wS6BJoEeGRWh0dHA6Ly9jcmwuY29t
b2RvY2E0LmNvbS9DT01PRE9FQ0NEb21haW5WYWxpZGF0aW9uU2VjdXJlU2VydmVy
Q0EyLmNybDCBiAYIKwYBBQUHAQEEfDB6MFEGCCsGAQUFBzAChkVodHRwOi8vY3J0
LmNvbW9kb2NhNC5jb20vQ09NT0RPRUNDRG9tYWluVmFsaWRhdGlvblNlY3VyZVNl
cnZlckNBMi5jcnQwJQYIKwYBBQUHMAGGGWh0dHA6Ly9vY3NwLmNvbW9kb2NhNC5j
b20wggL9BgNVHREEggL0MIIC8IIac25pNDIwNDYuY2xvdWRmbGFyZXNzbC5jb22C
ECouYm90aXNrYWNhZmUucnOCFCouZGVlZm9yZGVzaWduLmNvLnVrgg0qLmRvcmVn
YW1hLnR2gg8qLmR1dGNocG9ybi5vcmeCCyouZXpmaWxlLmNoggwqLmZhaGFtdS5u
ZXSCDCouZmFoYW11Lm9yZ4IPKi5ncmVlbmhhYml0LnVzgg8qLmp1ZGlrYXJ0dS5j
b22CFCouanVtcGZyb21yb29mLnRvZGF5ggwqLm1vYml1cy54eXqCDioubXV0aHJv
bmUubmV0ghEqLm15YWxwaGFob3N0LmNvbYIOKi5uZXdzYmVkcy5jb22CDyoucGF1
bGRpYXouYXNpYYINKi5wYXVsZGlhei5tZYIVKi5wb2thenktY2hlbWljem5lLnBs
ghMqLnNpeHR5c2l4c291bmQuY29tggsqLnNvYXdyLm9yZ4ISKi5zdGV2aWVjcmlw
cHMuY29tghoqLnN3aW5nc2V0cHJpY2Vjb21wYXJlLmNvbYILKi50dWJ5bG8ucGyC
DmJvdGlza2FjYWZlLnJzghJkZWVmb3JkZXNpZ24uY28udWuCC2RvcmVnYW1hLnR2
gg1kdXRjaHBvcm4ub3JnggllemZpbGUuY2iCCmZhaGFtdS5uZXSCCmZhaGFtdS5v
cmeCDWdyZWVuaGFiaXQudXOCDWp1ZGlrYXJ0dS5jb22CEmp1bXBmcm9tcm9vZi50
b2RheYIKbW9iaXVzLnh5eoIMbXV0aHJvbmUubmV0gg9teWFscGhhaG9zdC5jb22C
DG5ld3NiZWRzLmNvbYINcGF1bGRpYXouYXNpYYILcGF1bGRpYXoubWWCE3Bva2F6
eS1jaGVtaWN6bmUucGyCEXNpeHR5c2l4c291bmQuY29tgglzb2F3ci5vcmeCEHN0
ZXZpZWNyaXBwcy5jb22CGHN3aW5nc2V0cHJpY2Vjb21wYXJlLmNvbYIJdHVieWxv
LnBsMAoGCCqGSM49BAMCA0kAMEYCIQCdDfGZutuJWSUn3ytumOYCbpeRjkuHN5ZN
7L0AganZGQIhANpKjy+PNLTWCOzGCcva3fEbCLzpCmu2PUatE9xBl+Ck
-----END CERTIFICATE-----
subject=/OU=Domain Control Validated/OU=PositiveSSL Multi-Domain/CN=sni42046.cloudflaressl.com
issuer=/C=GB/ST=Greater Manchester/L=Salford/O=COMODO CA Limited/CN=COMODO ECC Domain Validation Secure Server CA 2
---
No client certificate CA names sent
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 4166 bytes and written 408 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-ECDSA-AES128-SHA
Server public key is 256 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
SSL-Session:
    Protocol  : TLSv1.1
    Cipher    : ECDHE-ECDSA-AES128-SHA
    Session-ID: ACB2C0516C9F57EE6AA973463849A53B07CAF99A6A78EE6C12AC0CDF99CC9C50
    Session-ID-ctx: 
    Master-Key: 0DCCE2B3E57E034B271296C716CFBDC4039AE4E6697A8EF560FD7423A9090ACEC3F924D331C2B8FD0FAE5631C9D8219A
    Key-Arg   : None
    PSK identity: None
    PSK identity hint: None
    SRP username: None
    TLS session ticket lifetime hint: 64800 (seconds)
    TLS session ticket:
    0000 - 03 30 b1 f4 75 9a 14 f7-d5 97 03 b3 4e 4d 5e ab   .0..u.......NM^.
    0010 - d1 15 d5 09 4a 7e 88 8b-d1 ba ed 9d 20 b5 bb f4   ....J~...... ...
    0020 - 33 c0 14 44 b3 d7 1d 78-f5 f0 f5 06 dd 57 cb 58   3..D...x.....W.X
    0030 - 51 6d 0a 18 a7 97 1b d6-36 ea bd ab a3 5a bc 1e   Qm......6....Z..
    0040 - 35 47 31 4b 19 cb c5 94-ac c5 41 f1 65 6a 76 d3   5G1K......A.ejv.
    0050 - 9e b2 45 e1 3c 5d dd 4d-49 6f 2f f2 18 1b 88 45   ..E.<].MIo/....E
    0060 - 9b 9d 50 1e 66 e2 ec c9-e5 87 a1 5a b7 80 d3 60   ..P.f......Z...`
    0070 - 6d fe 3e b6 77 0b c2 ba-f9 f9 12 49 f3 55 72 02   m.>.w......I.Ur.
    0080 - b1 da 2b 4c a6 74 50 df-11 12 c9 6b 1d 2f da a8   ..+L.tP....k./..
    0090 - 4f bc c5 9e ff f1 ff 5d-9a 28 ad e9 4d 43 09 ed   O......].(..MC..
    00a0 - bb 7d d6 1d fc 39 75 1e-e2 6e 2f f4 a6 69 7e 6c   .}...9u..n/..i~l
    00b0 - 97 cd 9c 1a 77 0d 14 c7-61 f8 87 cf 24 52 60 3e   ....w...a...$R`>

    Start Time: 1430097932
    Timeout   : 7200 (sec)
    Verify return code: 20 (unable to get local issuer certificate)
---
HTTP/1.1 200 OK
Server: cloudflare-nginx
Date: Mon, 27 Apr 2015 01:18:45 GMT
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
Set-Cookie: __cfduid=dc202f5845fd4246ec401ee26196a7e831430097524; expires=Tue, 26-Apr-16 01:18:44 GMT; path=/; domain=.ezfile.ch; HttpOnly
Expires: Mon, 26 Jul 1997 05:00:00 GMT
Last-Modified: Mon, 27 Apr 2015 01:18:45 GMT
Cache-Control: no-store, no-cache, must-revalidate
Cache-Control: post-check=0, pre-check=0
Pragma: no-cache
X-Frame-Options: sameorigin
Access-Control-Allow-Origin: *
CF-RAY: 1dd6b1fac4350874-IAD
...

【讨论】:

  • 标志“-servername”是关键。我收到相同的结果。没有它我会出错。它是 SNI(服务器名称指示)获取正确证书的一个选项。回到 Indy - 我已经能够通过提供 SNI 来解决问题(默认情况下不使用/实现)。此命令有帮助:“SSL_set_tlsext_host_name”。看来 Indy 正在等待更改。
  • @smooty86 - Wireshark 跟踪可能是一个危险信号,但您需要知道要查找的内容。现在,您将永远不会忘记在跟踪中查找 SNI 扩展 :)
  • @smooty86:Indy 的当前版本supports client-side SNI
【解决方案3】:

此代码适用于 5273 修订版和 OpenSSL 1.0.2 / 1.0.2a:

program HttpsGetExample;

{$APPTYPE CONSOLE}

uses
  IdHTTP, IdGlobal, SysUtils, Classes;

var
  HTTP: TIdHTTP;
  ResponseBody: string;
begin
  HTTP := TIdHTTP.Create;
  try
    try
      ResponseBody := HTTP.Get('https://ezfile.ch');
      WriteLn(ResponseBody);
      WriteLn(HTTP.ResponseText);
    except
      on E: EIdHTTPProtocolException do
      begin
        WriteLn(E.Message);
        WriteLn(E.ErrorMessage);
      end;
      on E: Exception do
      begin
        WriteLn(E.Message);
      end;
    end;
  finally
    HTTP.Free;
  end;
  ReadLn;
  ReportMemoryLeaksOnShutdown := True;
end.

【讨论】:

  • 不适合我。代码是一样的。我也在另一台电脑上测试过,结果相同。
【解决方案4】:

上述方法 SSL_set_tlsext_host_name 对我有用,只是我必须在添加的析构函数中释放 IOHandler。否则会引发异常。

【讨论】:

    猜你喜欢
    • 2023-03-17
    • 1970-01-01
    • 2016-09-11
    • 2021-12-05
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多