PerL SSL connect attempt failed because of handshake problems - perl

I'm hoping someone can help, I'm using the nagios plugin check_ilo2_health, the plugin works fine on our OpenSuSE systems but the new Ubuntu 14.04 system has issues, removing the nagios stuff and running perl, is basically this:
perl -e 'use IO::Socket::SSL qw(debug3);IO::Socket::SSL->new(SSL_hostname => "", PeerAddr=>"10.0.0.1:443", Proto=>"tcp",SSL_verify_mode => SSL_VERIFY_NONE)or die $!'
I'm connecting to an HP ILO2 with a self signed certificate and get a reply:
DEBUG: .../IO/Socket/SSL.pm:2503: new ctx 19182624
DEBUG: .../IO/Socket/SSL.pm:526: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:528: socket connected
DEBUG: .../IO/Socket/SSL.pm:550: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:586: not using SNI because hostname is unknown
DEBUG: .../IO/Socket/SSL.pm:647: Net::SSLeay::connect -> 0
DEBUG: .../IO/Socket/SSL.pm:695: connection failed - connect returned 0
DEBUG: .../IO/Socket/SSL.pm:1757: SSL connect attempt failed because of handshake problems
DEBUG: .../IO/Socket/SSL.pm:2537: free ctx 19182624 open=19182624
DEBUG: .../IO/Socket/SSL.pm:2549: OK free ctx 19182624
IO::Socket::SSL: SSL connect attempt failed because of handshake problems error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac ...propagated at -e line 1.
If I run it in curl:
curl "https://10.0.0.1" --insecure
It works returning the page from the ILO.
I want to tell perl or openSSL to ignore any certificate problems as this is a monitoring system and a lot of the servers use self signed certificates.
Any ideas of what can be done?
Versions:
Perl Version: This is perl 5, version 18, subversion 2 (v5.18.2) built for x86_64-linux-gnu-thread-multi
Crypt::SSLeay 0.72
IO::Socket::SSL 1.997
Net::SSLeay 1.66
Thanks in advance

I want to tell perl or openSSL to ignore any certificate problems as this is a monitoring system and a lot of the servers use self signed certificates.
You are doing it correctly, that is by using SSL_verify_mode of SSL_VERIFY_NONE.
IO::Socket::SSL: SSL connect attempt failed because of handshake problems error:140943FC:SSL routines:SSL3_READ_BYTES:sslv3 alert bad record mac ...propagated at -e line 1.
Strange, but I've seen other reports with "HP ILO2" and bad_record_mac.
Try to reduce the version to SSL 3.0, e.g. SSL_version => "SSLv3".
But because SSL 3.0 would not be a satisfactory solution because of POODLE I would be interested to have a look at the working SSL handshake from curl (upload to cloudshark.org).

The same error happens with Net::LDAP (which also uses IO::Socket::SSL) when connecting to a server that only supports SSLv2.
IO::Socket::SSL "auto-negotiates between SSLv2 and SSLv3" by default according to man page, so omitting SSL_version allows scripts to work with older servers.
Or, more optimistically, the script will still work when the administrator gets around to upgrading the server!

Related

Does perl-5.16.0-LWP-Protocol-Connect-6.09.tgz supports TLS 1.2?

I am kind of new to perl world but my script fails when loaded via SFTP with below error ,
IN SUBROUTINE: CSRF TOKEN DECODED CONTENT:
error while setting up ssl connection (SSL connect attempt failed with unknown error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure) at /home/rcc/perl5/lib/perl5/LWP/Protocol/https/connect/Socket.pm line 23.
Looping through csrf response array, param = [error while setting up ssl connection (SSL connect attempt failed with unknown error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure) at /home/rcc/perl5/lib/perl5/LWP/Protocol/https/connect/Socket.pm line 23.
]
Under the assumption its because of TLS depreciation , we upgraded SSL version but still doesn't work, can someone help us understand how to fix the issue ?
Or is there a latest version of perl LWP which by upgrade can fix the issue ? repacking the current package seems to be complex.
Thanks in advance.
The SSL handling is not done directly by LWP::Protocol::connect. Instead it uses IO::Socket::SSL which then uses Net::SSLeay which then uses the linked in OpenSSL library which is not necessarily the one used by the openssl binary. The general capability to use TLS 1.2 depends on the version of OpenSSL which should be at least 1.0.1.
To get the versions of the various parts use the following code
use strict;
use IO::Socket::SSL;
printf "IO::Socket::SSL %s\n", $IO::Socket::SSL::VERSION;
printf "Net::SSLeay %s\n", $Net::SSLeay::VERSION;
printf "OpenSSL compiled %x\n", Net::SSLeay::OPENSSL_VERSION_NUMBER();
printf "OpenSSL linked %x - %s\n", Net::SSLeay::SSLeay(),
Net::SSLeay::SSLeay_version(0);
... SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
Note that a TLS handshake problem can have lots of different reasons and an unsupported TLS protocol version is just one of many. No shared ciphers is another common problem at this stage of the connection.

Override DNS For Specific Domains Like A Hosts File, But Without Using Hosts file

I need to issue a series of parallelized web requests from the same server to a specific domain, but control what IP address these requests actually go to. Originally, I came up with a scheme where I would request the IP I wanted specifically, and then manually set the Host: www.example.com header on the request, and use a series of handlers to make sure that redirects issued followed the same pattern.
This seemed to work for some time, but lately I've been having trouble with redirects to HTTPS. The handshake will fail, and the request in turn. I have tried disabling SSL verification in a variety of ways, including:
local $ENV{ PERL_LWP_SSL_VERIFY_HOSTNAME } = 0;
local $ENV{ HTTPS_DEBUG } = 1;
$ua->ssl_opts(
SSL_ca_file => Mozilla::CA::SSL_ca_file(),
verify_hostname => 0,
SSL_verify_mode => 0x00,
);
IO::Socket::SSL::set_ctx_defaults(
SSL_verifycn_scheme => 'www',
SSL_verify_mode => 0,
);
I have also tried using LWP::UserAgent::DNS::Hosts to solve the problem, but it persists.
<edit>I should note that the reason why turning off peer validation for SSL is not solving the problem is likely because for some reason requesting this way is actually causing the handshake to fail, not failing on a validation point.</edit>
One thing that works is making an entry in /etc/hosts to point the domain at the appropriate IP, however this is not practical, because I may need to run tens, or hundreds, of tests, in parallel, on the same domain.
Is there a way to emulate the functionality of adding an entry to /etc/hosts that does not involve requesting the IP specifically and overriding the Host: ... HTTP header?
EDIT: SSL Debug Info
DEBUG: .../IO/Socket/SSL.pm:1914: new ctx 140288835318480
DEBUG: .../IO/Socket/SSL.pm:402: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:404: socket connected
DEBUG: .../IO/Socket/SSL.pm:422: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:455: not using SNI because hostname is unknown
DEBUG: .../IO/Socket/SSL.pm:478: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:491: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:501: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:511: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:531: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:491: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1388: SSL connect attempt failed with unknown error
DEBUG: .../IO/Socket/SSL.pm:497: fatal SSL error: SSL connect attempt failed with unknown error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure
DEBUG: .../IO/Socket/SSL.pm:1948: free ctx 140288835318480 open=140288835318480
DEBUG: .../IO/Socket/SSL.pm:1953: free ctx 140288835318480 callback
DEBUG: .../IO/Socket/SSL.pm:1956: OK free ctx 140288835318480
And in the response I get:
Can't connect to redacted.org:443
SSL connect attempt failed with unknown error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure at /System/Library/Perl/Extras/5.18/LWP/Protocol/http.pm line 51.
It fails equally well on our server (using an older legacy version of Perl, which I will not disclose here as it seems irrelevant).
The server initially responds to a non-HTTPS request with a 301 redirect to the HTTPS site. Then the failure occurs. I will post reproducing code with the specific details of my request removed, but any site which redirects non-HTTPS traffic to HTTPS should suffice.
use IO::Socket::SSL qw/ debug4 /;
use LWP::UserAgent;
use LWP::UserAgent::DNS::Hosts;
use HTTP::Request;
use Mozilla::CA;
use Data::Dumper;
LWP::UserAgent::DNS::Hosts->register_hosts(
'recacted.org' => '127.0.0.1', # no I am not redirecting to loopback in reality, this is anonymized
'www.redacted.org' => '127.0.0.1',
);
LWP::UserAgent::DNS::Hosts->enable_override;
my $ua = LWP::UserAgent->new;
$ua->ssl_opts( SSL_ca_file => Mozilla::CA::SSL_ca_file() );
my $request = HTTP::Request->new(GET => 'http://redacted.org/');
my $response = $ua->request($request);
print $response->content; #Dumper ( $response->is_success ? $response->headers : $response );
Again, that is not the production code, just enough code to reproduce the issue. It doesn't seem to have anything to do with SSL verification, but moreover an inability to negotiate the request, presumably because LWP::UserAgent::DNS::Hosts is doing exactly what I was doing: changing the request target to the desired IP, and then writing the Host: ... header manually. Why this causes the SSL handshake to fail, I do not know.
On my local machine debugging
openssl version -a: 1.0.2j 26 Sep 2016
IO::Socket::SSL->VERSION == 1.966
Net::SSLeay->VERSION == 1.72
On a server of ours
openssl version -a: 1.0.1t 3 May 2016
IO::Socket::SSL->VERSION == 1.76
Net::SSLeay->VERSION == 1.48
Given that it works with an explicit /etc/hosts file but not with just replacing PeerAddr or using LWP::UserAgent::DNS::Hosts this looks like a problem with the SNI extension. This TLS extension is used to provide the TLS server with the requested hostname (similar to the HTTP Host header) so that it can choose the appropriate certificate. If this SNI extension is missing some servers return a default certificate while others throw an error, like in this case.
The fix is to provide the hostname using SSL_hostname in ssl_opts. Such fix could probably also help with LWP::UserAgent::DNS::Hosts, i.e in LWP/Protocol/https/hosts.pm:
12 if (my $peer_addr = LWP::UserAgent::DNS::Hosts->_registered_peer_addr($host)) {
13 push #opts, (
14 PeerAddr => $peer_addr,
15 Host => $host,
16 SSL_verifycn_name => $host,
NEW SSL_hostname => $host, # for SNI
17 );
18 }

Net::LDAPS throws unknown error during SSL connect

I am trying to connect to an LDAP server using the Net::LDAPS module. I am passing the right username, password and capath to it. The same code with all the modules in the same version works on one of my other machines. But on this particular machine I see this error.
The sample code I am working with :
my $ad_host = 'XYZ';
my $ad_port = 636;
my $ad_user = 'ABC';
my $ad_pass = '****';
my $ca_path = '<path to ca cert>';
my $ldap = Net::LDAPS->new(
$ad_host,
port => $ad_port,
verify => 'require',
capath => $ca_path
);
Is it a known bug in the LDAPS module? Or am I missing out something apparent.
The debug logs:
DEBUG: .../IO/Socket/SSL.pm:179: set domain to 2
DEBUG: .../IO/Socket/SSL.pm:1427: new ctx 21295632
DEBUG: .../IO/Socket/SSL.pm:309: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:311: socket connected
DEBUG: .../IO/Socket/SSL.pm:324: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:354: set socket to non-blocking to enforce timeout=120
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:377: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:387: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:407: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:377: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:387: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:407: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:367: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1175: SSL connect attempt failed with unknown error..error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:373: fatal SSL error: SSL connect attempt failed with unknown error..error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
DEBUG: .../IO/Socket/SSL.pm:1462: free ctx 21295632 open=21295632
DEBUG: .../IO/Socket/SSL.pm:1465: OK free ctx 21295632
DEBUG: .../IO/Socket/SSL.pm:1175: IO::Socket::INET6 configuration failederror:00000000:lib(0):func(0):reason(0)
Versions of the modules I am using :
...:~/test_perl$ perlmodver Net::LDAPS
0.05
...:~/test_perl$ perlmodver Net::LDAP
0.39
...:~/test_perl$ perlmodver IO::Socket::SSL
1.18
If you look at the error you can see that certificate verification failed.
SSL connect attempt failed with unknown error..error:14090086:SSL
routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed
You can either correct the certificate or ignore certificate verification by passing
verify => 'none'
On a sidenote, you can also use Net::LDAP if you pass ldaps:// as a prefix to $ad_host.
$ldaps = Net::LDAP->new('ldaps://myhost.example.com:10000',
verify => 'require',
capath => $ca_path);
Oops just noticed that you said
The same code with all the modules in the same version works on one of
my other machines. But on this particular machine I see this error.
Then this looks like a configuration issue. Can you connect to your server using ldapsearch?
This issue is resolved.
There are 2 ways to solve this :
Bypass the verification (Not recommended)
If you are using the "verify" attribute like the one in my code, you just have to comment it out. It will bypass the cert verification.
Add a soft link to the certificates
Maybe it is a behavior specific to trusty, because on lucid it was working fine. So, you need to create a soft link to all your pem files and place it in the CA Path. You can do this by running
ln -s cacert.pem `openssl x509 -hash -noout < cacert.pem`.0

My sendmail log get TLS setup failed

I setup my nagios in docker container,and It working.and sendmail can send mail to me.
I find it can't send message to me one day,and I see the Log of sendmail,I get this error
nagios sendEmail.pl[15471]: ERROR => TLS setup failed: SSL connect attempt failed because of handshake problems error:14094410:SSL routines:SSL3_READ_BYTES:sslv3 alert handshake failure
during this time,I just stop and restart my nagios container
the packages of libio-socket-ssl-perl and libnet-ssleay-perl perl also have installed.
How can I slove this problem??
Thanks very much
If you mean with sendEmail.pl this script with the last update from 2009 then you are using unsupported and broken software. It might work if you change the following line in the script:
- if (! IO::Socket::SSL->start_SSL($SERVER, SSL_version => 'SSLv3 TLSv1')) {
+ if (! IO::Socket::SSL->start_SSL($SERVER)) {
Reason for this change is that the setting of SSL_version in the code was wrong from the beginning, only that 7 years ago IO::Socket::SSL did not complain about it but simply used the first setting SSLv3. But since 4 years IO::Socket::SSL is stricter and complains about the wrong usage. Apart from that SSLv3 would not work in many cases anyway today because the protocol is disabled for security reasons.

Error: 500 Can't connect to foo.com:443 ( unknown errorerror:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3)

I am using LWP::UserAgent version 6.03 to fetch the status of website.
my $ua = LWP::UserAgent->new(ssl_opts => {verify_hostname => 0},);
$ua->cookie_jar({});
$ua->agent('Mozilla/5.0');
push #{$ua->requests_redirectable}, 'POST';
push #{$ua->requests_redirectable}, 'GET';
my $url = 'https://foo.com'
$page = $ua->get($url);
print "Error ".$page->status_line."\n";
When I am running this code on my unix machine it giving the following status and the error message for LWP module.
#status
500 Can't connect to foo.com:443
#error
LWP::Protocol::https::Socket: SSL connect attempt failed with unknown
errorerror:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert
unexpected message at /usr/local/lib/perl5/site_perl/5.8.9/LWP/Protocol/http.pm line 51.
I tried to make use of answer given to similar question but it did not worked out. Need your valuable advice.
ran the debug
DEBUG: .../IO/Socket/SSL.pm:193: set domain to 2
DEBUG: .../IO/Socket/SSL.pm:1545: new ctx 74489552
DEBUG: .../IO/Socket/SSL.pm:334: socket not yet connected
DEBUG: .../IO/Socket/SSL.pm:336: socket connected
DEBUG: .../IO/Socket/SSL.pm:349: ssl handshake not started
DEBUG: .../IO/Socket/SSL.pm:379: set socket to non-blocking to enforce timeout=180
DEBUG: .../IO/Socket/SSL.pm:392: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:402: ssl handshake in progress
DEBUG: .../IO/Socket/SSL.pm:412: waiting for fd to become ready: SSL wants a read first
DEBUG: .../IO/Socket/SSL.pm:432: socket ready, retrying connect
DEBUG: .../IO/Socket/SSL.pm:392: Net::SSLeay::connect -> -1
DEBUG: .../IO/Socket/SSL.pm:1276: SSL connect attempt failed with unknown errorerror:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert unexpected message
DEBUG: .../IO/Socket/SSL.pm:398: fatal SSL error: SSL connect attempt failed with unknown errorerror:140773F2:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert unexpected message
DEBUG: .../IO/Socket/SSL.pm:1276: IO::Socket::INET6 configuration failederror:00000000:lib(0):func(0):reason(0)
DEBUG: .../IO/Socket/SSL.pm:1582: free ctx 74489552 open=74489552
DEBUG: .../IO/Socket/SSL.pm:1590: OK free ctx 74489552`
Yeah... This sort of thing happens when some services account for the Poodle vulnerability. I haven't done the research to find the exact cause. It just appears the in some cases the client and server don't properly negotiate the protocol. We've gotten around it by adding 'SSL_version' => 'tlsv1' to the "ssl_opts". I don't really like it though since next protocol upgrade it will need fixing again. I'd far rather let the libraries do the negotiation on their own.