1

Software:

Homegrown Perl-5.34.1 (not perlbrew) Net-SSLeay 1.92 IO-Socket-SSL 2.074

[Apologies for lack of pastebin, no access from this location]

The "proxy tunnel" is HTTP, but the local firewall rules require that the connection be initiated with 'https'.

Making the connection via IO::Socket::INET and promoting it or sans handshake and performing it late don't seem to work around the proxy/tunnel issues, so I'm guessing this must require a separate socket.

Q: What is a working approach for handling the "http proxy tunnel" using IO::Socket::SSL, possibly with some other modules?

I'd prefer to avoid LWP::UserAgent if its possible, I just cannot find anything on CPAN that seems to deal with the issues.

Examples:

(1) curl --verbose

Attempting a connection from a RHEL6 platform through an intranet firewall to an HTTPS service. The service is a 'hello world' server intended to validate the SSL connection. It works from Firefox on an intranet host (not the same one as I'm using for IO::Socket:SSL). Using curl fails to connect, but shows the "proxy tunnel" (hosts and IP's munged).

curl --verbose 'https://foo.bar.net/bim/bam'
*   Trying 10.10.10.10...
* Connected to 10.10.10.10 (10.10.10.10) port 80 (#0)
* Establish HTTP proxy tunnel to foo.bar.net:443
> CONNECT foo.bar.net:443 HTTP/1.1
> Host: foo.bar.net:443
> User-Agent: curl/7.44.0
> Proxy-Connection: Keep-Alive
>
< HTTP/1.1 503 Service Unavailable
< Cache-Control: no-cache
< X-XSS-Protection: 1
< Connection: close
< Content-Type: text/html; charset=utf-8
< Content-Length: 750
< Pragma: no-cache
< Set-Cookie: frobnicate; path=/; Httponly
<
* Received HTTP code 503 from proxy after CONNECT
* Closing connection 0
curl: (56) Received HTTP code 503 from proxy after CONNECT

(2) IO:Socket::SSL alone

The tunnel doesn't appear to be transparent:

41:             $IO::Socket::SSL::DEBUG = 3;
42:             IO::Socket::SSL->new
43:             (
44:                 PeerAddr    => $auth
45:               , PeerPort    => 'https'
46:             )
  DB<1>
  DEBUG: .../IO/Socket/SSL.pm:2961: new ctx 54179840
  DEBUG: .../IO/Socket/SSL.pm:704: socket not yet connected
  DEBUG: .../IO/Socket/SSL.pm:706: socket connected
  DEBUG: .../IO/Socket/SSL.pm:729: ssl handshake not started
  DEBUG: .../IO/Socket/SSL.pm:771: using SNI with hostname foo.bar.com
  DEBUG: .../IO/Socket/SSL.pm:806: request OCSP stapling
  DEBUG: .../IO/Socket/SSL.pm:836: call Net::SSLeay::connect
  DEBUG: .../IO/Socket/SSL.pm:2852: did not get stapled OCSP response
  DEBUG: .../IO/Socket/SSL.pm:2805: ok=0 [0] /C=US/O=DigiCert Inc/CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1/C=US/ST=New York/L=Someplace/O=Foo Bar, Inc./CN=foo.bar.com
  DEBUG: .../IO/Socket/SSL.pm:839: done Net::SSLeay::connect -> -1
  DEBUG: .../IO/Socket/SSL.pm:842: SSL connect attempt failed

  DEBUG: .../IO/Socket/SSL.pm:842: local error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
  DEBUG: .../IO/Socket/SSL.pm:845: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
  DEBUG: ...inux/IO/Socket.pm:50: ignoring less severe local error 'IO::Socket::IP configuration failed', keep 'SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed'
  DEBUG: .../IO/Socket/SSL.pm:3010: free ctx 54179840 open=
  DEBUG: .../IO/Socket/SSL.pm:3014: free ctx 54179840 callback
  DEBUG: .../IO/Socket/SSL.pm:3021: OK free ctx 54179840
  not ok 1 - Direct: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed.

The POD for IO::Socket::SSL has two suggestions for possibly working around this situation:

(3) INET socket + Promotion:

    my $sock = IO::Socket::INET->new(...) or die $!;
    IO::Socket::SSL->start_SSL($sock,%sslargs) or die $SSL_ERROR;
    $sock->stop_SSL or die $SSL_ERROR;
41:             my $sock
42:             = IO::Socket::INET->new
43:             (
44:                 PeerAddr    => $auth
45:               , PeerPort    => 'https'
46:             )
47:             or die "INET: $IO::Socket::errstr\n";

49:             IO::Socket::SSL->start_SSL
50:             (
51:                 $sock
52:               , 'PeerPort'  => 'https'
53:             )
54:             or die "SSL: $SSL_ERROR\n";
  DB<1>
  DEBUG: .../IO/Socket/SSL.pm:2961: new ctx 58865232
  DEBUG: .../IO/Socket/SSL.pm:1561: start handshake
  DEBUG: .../IO/Socket/SSL.pm:729: ssl handshake not started
  DEBUG: .../IO/Socket/SSL.pm:774: not using SNI because hostname is unknown
  DEBUG: .../IO/Socket/SSL.pm:806: request OCSP stapling
  DEBUG: .../IO/Socket/SSL.pm:836: call Net::SSLeay::connect
  DEBUG: .../IO/Socket/SSL.pm:2852: did not get stapled OCSP response
  DEBUG: .../IO/Socket/SSL.pm:2805: ok=0 [0] /C=US/O=DigiCert Inc/CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1/C=US/ST=New York/L=Edgewood/O=Foo Bar, Inc./CN=foo.bar.com
  DEBUG: .../IO/Socket/SSL.pm:839: done Net::SSLeay::connect -> -1
  DEBUG: .../IO/Socket/SSL.pm:842: SSL connect attempt failed

  DEBUG: .../IO/Socket/SSL.pm:842: local error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
  DEBUG: .../IO/Socket/SSL.pm:845: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
  DEBUG: .../IO/Socket/SSL.pm:1984: downgrading SSL only, not closing socket
  DEBUG: .../IO/Socket/SSL.pm:3010: free ctx 58865232 open=
  DEBUG: .../IO/Socket/SSL.pm:3014: free ctx 58865232 callback
  DEBUG: .../IO/Socket/SSL.pm:3021: OK free ctx 58865232
  BRCC::FM::Test::(bin/socket-check:55):

(4) SSL socket with delayed handshake:

41:             my $sock
42:             = IO::Socket::SSL->new
43:             (
44:                 PeerAddr            => $auth
45:               , PeerPort            => 'https'
46:               , SSL_startHandshake  => 0
47:             )
48:             or die "SSL: $SSL_ERROR";
  DB<1>
DEBUG: .../IO/Socket/SSL.pm:2961: new ctx 43293280
DEBUG: .../IO/Socket/SSL.pm:704: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:706: socket connected
BRCC::FM::Test::(bin/socket-check:50):
50:             $sock->connect_SSL
51:             or die "Connect: $SSL_ERROR";
  DB<1>
DEBUG: .../IO/Socket/SSL.pm:729: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:771: using SNI with hostname foo.bar.com
DEBUG: .../IO/Socket/SSL.pm:806: request OCSP stapling
DEBUG: .../IO/Socket/SSL.pm:836: call Net::SSLeay::connect
DEBUG: .../IO/Socket/SSL.pm:2852: did not get stapled OCSP response
DEBUG: .../IO/Socket/SSL.pm:2805: ok=0 [0] /C=US/O=DigiCert Inc/CN=DigiCert Global G2 TLS RSA SHA256 2020 CA1/C=US/ST=New York/L=Edgewood/O=Foo Bar, Inc./CN=foo.bar.com
DEBUG: .../IO/Socket/SSL.pm:839: done Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:842: SSL connect attempt failed

DEBUG: .../IO/Socket/SSL.pm:842: local error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:845: fatal SSL error: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:3010: free ctx 43293280 open=
DEBUG: .../IO/Socket/SSL.pm:3014: free ctx 43293280 callback
DEBUG: .../IO/Socket/SSL.pm:3021: OK free ctx 43293280

(5) Disabling SSL_verify_mode didn't get much further with ssl_handshake turned on:

41:             my $sock
42:             = IO::Socket::SSL->new
43:             (
44:                 PeerAddr            => $auth
45:               , PeerPort            => 'https'
46:               , SSL_startHandshake  => 1
47:               , SSL_verify_mode     => 0
48:             )
49:             or die "SSL: $SSL_ERROR";
  DB<1>
  DEBUG: .../IO/Socket/SSL.pm:2537: new ctx 50291120
  DEBUG: .../IO/Socket/SSL.pm:529: socket not yet connected
  DEBUG: .../IO/Socket/SSL.pm:531: socket connected
  DEBUG: .../IO/Socket/SSL.pm:553: ssl handshake not started
  DEBUG: .../IO/Socket/SSL.pm:586: using SNI with hostname foo.bar.com
  DEBUG: .../IO/Socket/SSL.pm:653: Net::SSLeay::connect -> -1
  DEBUG: .../IO/Socket/SSL.pm:1769: SSL connect attempt failed

  DEBUG: .../IO/Socket/SSL.pm:1774: SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
  DEBUG: .../IO/Socket/SSL.pm:659: fatal SSL error: SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
  DEBUG: .../IO/Socket/SSL.pm:1758: IO::Socket::INET configuration failed
  DEBUG: .../IO/Socket/SSL.pm:2570: free ctx 50291120 open=50291120
  DEBUG: .../IO/Socket/SSL.pm:2582: OK free ctx 50291120

(6) Delaying the handshake gets the same result:

41:             my $sock
42:             = IO::Socket::SSL->new
43:             (
44:                 PeerAddr            => $auth
45:               , PeerPort            => 'https'
46:               , SSL_startHandshake  => 0
47:               , SSL_verify_mode     => 0
48:             )
49:             or die "SSL: $SSL_ERROR";
  DB<1>
  DEBUG: .../IO/Socket/SSL.pm:2537: new ctx 42963376
  DEBUG: .../IO/Socket/SSL.pm:529: socket not yet connected
  DEBUG: .../IO/Socket/SSL.pm:531: socket connected
  BRCC::FM::Test::(bin/socket-check:51):
  51:             $sock->connect_SSL
  52:             or die "Connect: $SSL_ERROR";
    DB<1>
    DEBUG: .../IO/Socket/SSL.pm:553: ssl handshake not started
    DEBUG: .../IO/Socket/SSL.pm:586: using SNI with hostname foo.bar.net
    DEBUG: .../IO/Socket/SSL.pm:653: Net::SSLeay::connect -> -1
    DEBUG: .../IO/Socket/SSL.pm:1769: SSL connect attempt failed

    DEBUG: .../IO/Socket/SSL.pm:1774: SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
    DEBUG: .../IO/Socket/SSL.pm:659: fatal SSL error: SSL connect attempt failed error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
    DEBUG: .../IO/Socket/SSL.pm:2570: free ctx 42963376 open=42963376
    DEBUG: .../IO/Socket/SSL.pm:2582: OK free ctx 42963376
3
  • I don't see how this has anything to do with a HTTP tunnel. The direct TLS handshake mostly succeeds with the remote server, only the server certificate cannot be validated: "SSL3_GET_SERVER_CERTIFICATE:certificate verify failed". It is not clear why it fails, but it might be a problem with misconfigured server or wrong/missing local trust store. Try to use SSL_verify_mode => 0 to disable certificate validation as a quick workaround. But this should not be done in production because it opens the connection up for man in the middle attacks. Commented Jun 16, 2022 at 19:02
  • Thank you for taking the time to look. #5 & #6 above: verify mode false, no improvement. Commented Jun 17, 2022 at 2:04
  • The server replies with a handshake failure but obviously after sending the certificate (otherwise certificate validation would not fail in previous tests). The exact reason for the handshake failure at this stage is unknown but it is often connected with the server expecting the client to authenticate itself with a client certificate, but the client not providing it. In any case it is hard to debug such a problem if it is not clear what the server expects - don't you have a working setup to access this server with a browser or other tool in order to compare the requirements? Commented Jun 17, 2022 at 4:10

1 Answer 1

1

After being sidelined for a few months and a certificate update on the affected servers I was able to connect. At this point the likely culprit was an expired or otherwise ineffective certificate being rejected by the Perl code.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.