LWP で 500 Can't verify SSL peers without knowning which Certificate Authorities to trust が出た時の対処方法

久々に perl でプログラム書いてたのですが、https な URI に LWP でアクセスをしたら下記のエラーに遭遇しました。LWP で https なページヘのアクセスは実に数年ぶり。

500 Can't verify SSL peers without knowing which Certificate Authorities to trust at t.pl line 6.

プログラムは極めて簡単。昔はこれでイケたはずなんだけど・・・。

use LWP::UserAgent;
 
my $ua = LWP::UserAgent->new;
my $res = $ua->get('https://github.com/');
unless ($res->is_success) {
  die $res->status_line;
}
print $res->content;

ソースを見てみると、エラーをはいている箇所は LWP::Protocol::https でした。

- スポンサーリンク -

sub _extra_sock_opts
{
    my $self = shift;
    my %ssl_opts = %{$self->{ua}{ssl_opts} || {}};
    if (delete $ssl_opts{verify_hostname}) {
	$ssl_opts{SSL_verify_mode} ||= 1;
	$ssl_opts{SSL_verifycn_scheme} = 'www';
    }
    else {
	$ssl_opts{SSL_verify_mode} = 0;
    }
    if ($ssl_opts{SSL_verify_mode}) {
	unless (exists $ssl_opts{SSL_ca_file} || exists $ssl_opts{SSL_ca_path}) {
	    eval {
		require Mozilla::CA;
	    };
	    if ($@) {
		if ($@ =! /^Can't locate Mozilla\/CA\.pm/) {
		    $@ = <<'EOT';
Can't verify SSL peers without knowing which Certificate Authorities to trust

This problem can be fixed by either setting the PERL_LWP_SSL_CA_FILE
envirionment variable or by installing the Mozilla::CA module.

To disable verification of SSL peers set the PERL_LWP_SSL_VERIFY_HOSTNAME
envirionment variable to 0.  If you do this you can't be sure that you
communicate with the expected peer.
EOT
		}
		die $@;
	    }
	    $ssl_opts{SSL_ca_file} = Mozilla::CA::SSL_ca_file();
	}
    }
    $self->{ssl_opts} = \%ssl_opts;
    return (%ssl_opts, $self->SUPER::_extra_sock_opts);
}

500 Can't verify SSL の対処方法はコードを見る限り2通りあるようです。

対処方法1. ホスト名の検証をしない

  • $ENV{'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;
  • $ua->ssl_opts( verify_hostname => 0 );

対処方法2. Mozilla::CA モジュールをインストールしてホスト名の検証をする

  • コード的には Mozilla::CA::SSL_ca_file() にお任せしているようです

とりあえず正攻法は対処方法2でしょう。cpanm でさくっとできます。

sudo  cpanm  Mozilla::CA

インストールしたらもう一度、テストスクリプトを実行してみましょう。もしこんなエラーが出たら更にモジュールをインストールします。この情報はこちらを参考にしました。とりあえずウチの sakura vps の環境はこれでエラーは解消されました。

'_content' => 'Can't connect to github.com:443 (Crypt-SSLeay can't verify hostnames)
sudo  cpanm  Crypt::SSLeay  Scalar::Util  IO::Socket::SSL

さて、では挙動は何時頃から変わったのか・・・改めてマニュアルを見てみます。
LWP::UserAgent の changes をみたら 2011-03-08 Release 6.00 からの変更の模様。もう2年以上前でした。どんだけよ!www

For https://... default to verified connections with require IO::Socket::SSL and Mozilla::CA modules to be installed. Old behaviour can be requested by setting the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable to 0. The LWP::UserAgent got new ssl_opts method to control this as well.

対処方法もドキュメントにサラッと書いてありますね。わかりづらいけど。www

verify_hostname => $bool
When TRUE LWP will for secure protocol schemes ensure it connects to servers that have a valid certificate matching the expected hostname. If FALSE no checks are made and you can't be sure that you communicate with the expected peer. The no checks behaviour was the default for libwww-perl-5.837 and earlier releases.

This option is initialized from the PERL_LWP_SSL_VERIFY_HOSTNAME environment variable. If this environment variable isn't set; then verify_hostname defaults to 1.

というわけで、これで対処できるかと思います。備忘録でした。

- スポンサーリンク -