Всем доброе утро,
На прошлой неделе я решил запустить команды для обновления пакетов на моем сервере 14.04, чтобы убедиться, что я пропатчен для недавно обнаруженных уязвимостей Bash. Согласно информации здесь (http://www.ubuntu.com/usn/usn-2362-1/) Я запустил apt-get dist-upgrade. Для справки, я запустил apt-get update, apt-get dist-upgrade и затем apt-get upgrade, чтобы попытаться убедиться, что у меня все обновлено до последних версий (хотя я обычно запускаю apt-get upgrade).
После успешного выполнения этого я обнаружил, что ряд моих скриптов Perl больше не функционируют. Для справки, я использую этот сервер для Nagios, чтобы контролировать все мои другие серверы. Все скрипты, о которых идет речь, которые сейчас выходят из строя, подключаются к системе через https, входят в хост и запрашивают различные биты информации.
До обновления мне удавалось добавлять строку в каждый из моих скриптов Perl, чтобы заставить их игнорировать SSL:
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0 }
Однако после обновления это, похоже, не оказывает никакого эффекта, и все скрипты завершаются ошибкой, поскольку они не могут проверить сертификаты SSL (все самоподписанные).
Вот некоторые фрагменты того, что я вижу:
выполнение скрипта:
nagios@nagios:/usr/local/nagios/libexec$ ./check_esx.pl -H 192.168.22.18 -u root -p password -l cpu
CHECK_ESX.PL CRITICAL - Can't connect to 192.168.22.18:443 (certificate verify failed)
LWP::Protocol::https::Socket: SSL connect attempt failed error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed at /usr/share/perl5/LWP/Protocol/http.pm line 41.
Этот конкретный скрипт Perl использует "VMware Infrastructure (VI) Perl Toolkit" для работы. Скрипт, который я вызываю, check_esx.pl доступенздесь
Вот фрагмент файла http.pm вокруг строки, на которую ссылается ошибка выше; строка 41 — это строка «die».
sub _new_socket
{
my($self, $host, $port, $timeout) = @_;
local($^W) = 0; # IO::Socket::INET can be noisy
my $sock = $self->socket_class->new(PeerAddr => $host,
PeerPort => $port,
LocalAddr => $self->{ua}{local_address},
Proto => 'tcp',
Timeout => $timeout,
KeepAlive => !!$self->{ua}{conn_cache},
SendTE => 1,
$self->_extra_sock_opts($host, $port),
);
unless ($sock) {
# IO::Socket::INET leaves additional error messages in $@
my $status = "Can't connect to $host:$port";
if ($@ =~ /\bconnect: (.*)/ ||
$@ =~ /\b(Bad hostname)\b/ ||
$@ =~ /\b(certificate verify failed)\b/ ||
$@ =~ /\b(Crypt-SSLeay can't verify hostnames)\b/
) {
$status .= " ($1)";
}
die "$status\n\n$@";
}
# perl 5.005's IO::Socket does not have the blocking method.
eval { $sock->blocking(0); };
$sock;
}
Так что, я думаю, я ищу здесь одну из двух вещей:
Либо: (A) Есть ли новый/лучший/более правильный способ заставить Perl игнорировать сертификаты SSL? или (B) Есть ли способ импортировать самоподписанный сертификат SSL с другого хоста в Ubuntu, чтобы скрипт Perl распознал его и доверял ему? Либо: (B-2) Есть ли способ заставить Ubuntu распознавать мой центр сертификации Windows Active Directory, чтобы я мог выдавать сертификаты SSL из своего CA для соответствующих систем и чтобы скрипты Perl распознавали его?
Заранее спасибо всем!
решение1
$ENV{PERL_LWP_SSL_VERIFY_HOSTNAME} = 0
Это была ошибка в LWP (CVE-2014-3230), которая была исправлена в новых версиях. PERL_LWP_SSL_VERIFY_HOSTNAME используется только для пропуска проверки имени хоста в сертификате, а не цепочки сертификатов. Но поскольку вы используете самоподписанную цепочку сертификатов, проверка не будет выполнена.
Эта опция была введена только для миграции со старого бэкэнда Crypt::SSLeay на новый бэкэнд IO::Socket::SSL. Crypt::SSLeay не поддерживает проверку имени хоста (и, таким образом, открыт для атак типа «человек посередине»), тогда как IO::Socket::SSL поддерживает. В LWP версии 6 бэкэнд по умолчанию — IO::Socket::SSL.
Чтобы полностью отключить проверку набора сертификатов SSL_verify_mode => SSL_VERIFY_NONE
(нужно use IO::Socket::SSL
иметь доступ к константе SSL_VERIFY_NONE или просто использовать 0) в ssl_opts LWP. Переменной среды для этого нет.
Пример:
use LWP::UserAgent;
use IO::Socket::SSL;
my $ua = LWP::UserAgent->new(..., ssl_opts => { SSL_verify_mode => SSL_VERIFY_NONE });
$ua->get(...); # or $ua->post(...) or $ua->request(...)
К сожалению, я не вижу использования LWP в скрипте, на который вы ссылаетесь, поэтому не вижу, где это можно исправить.
Что касается вашего варианта Б:
(B) Есть ли способ импортировать самоподписанный SSL-сертификат с другого хоста в Ubuntu, чтобы скрипт Perl распознал его и доверял ему? Альтернативный вариант: (B-2) Есть ли способ заставить Ubuntu распознавать мой центр сертификации Windows Active Directory, чтобы я мог выдавать SSL-сертификаты из своего CA для соответствующих систем и чтобы скрипты Perl распознавали их?
Вы должны иметь возможность использовать переменную среды PERL_LWP_SSL_CA_FILE, чтобы указать файл, какие центры сертификации или самозаверяющие сертификаты вы принимаете в качестве доверенных.
решение2
Я думаю, что это проблема версии Perl. Проверьте, какую версию Perl вы использовали ранее для запуска этого скрипта.
В чем я уверен, так это в том, что Ubuntu устанавливает последнюю стабильную версию каждого программного обеспечения. Возьмем, к примеру, если у вас есть скрипт python3, который работает на ubuntu 12.04, он может не работать на ubuntu 14.04, и причина этого в том, что у первого python 3.2, а у второго — python 3.4.
Я предполагаю, что то же самое произойдет и с вашим скриптом Perl, проверьте версию Perl и примечание к выпуску новой версии.