LWP で 500 Can't verify SSL peers without knowning which Certificate Authorities to trust が出た時の対処方法
久々に perl でプログラム書いてたのですが、https な URI に LWP でアクセスをしたら下記のエラーに遭遇しました。LWP で https なページヘのアクセスは実に数年ぶり。
プログラムは極めて簡単。昔はこれでイケたはずなんだけど・・・。
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 の環境はこれでエラーは解消されました。
sudo cpanm Crypt::SSLeay Scalar::Util IO::Socket::SSL
さて、では挙動は何時頃から変わったのか・・・改めてマニュアルを見てみます。
LWP::UserAgent の changes をみたら 2011-03-08 Release 6.00 からの変更の模様。もう2年以上前でした。どんだけよ!www
対処方法もドキュメントにサラッと書いてありますね。わかりづらいけど。www
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.
というわけで、これで対処できるかと思います。備忘録でした。
コメントやシェアをお願いします!