ひさびさに Perl の話。結構前のことだけど、OS のバージョンを Debian 10 (Buster) にしたら LWP で一部のサイトにアクセスできなくなってしまった。
500 Can't connect to ***.com:443 (SSL connect attempt failed error:141A318A:SSL routines:tls_process_ske_dhe:dh key too small) at ...
こんな感じ。
OpenSSL のグローバルな設定を変更するとこのへんの挙動は変えられるとのことだけど、当然そんなことをしたいわけではないので、Perl (LWP) 側から設定したかった。結局このようになった。
my $ua = LWP::UserAgent->new( ssl_opts => { SSL_create_ctx_callback => sub { my $ctx = shift; Net::SSLeay::CTX_set_security_level($ctx, 1); }, } );
ネストが深いが、こういう流れ。
LWP::UserAgent->new
に渡す ssl_opts
の値が IO::Socket::SSL に渡されるので、ここでディープな設定を仕込むことができる。
SSL_create_ctx_callback というフックで、Net::SSLeay によって作成された ctx という値を受け取れる。この ctx は OpenSSL 由来のもので、これに対して Net::SSLeay の 低レイヤの API を使って OpenSSL を直接触ることができるようになる。ここでおもむろに SSL_CTX_get_security_level を呼ぶことで、冒頭の問題を解決することができるのです。
ところで SSLeay ってなんやねん! ってずっと思ってたけど OpenSSL の前身がこういう名前だったらしい。なるほどなー。いや eay ってなんなん?