スポンサーリンク

PHP5.6系PHP7.0系ではPDOにてSSHトンネリングとSSLは同時に使えない

Azure FunctionsにてPDO(MySQL)でSSLを使う」の続き記事になります。今回はAzure FunctionsではなくてDocker(Ubuntu16.04)で開発中に遭遇した事象を検証した結果です。

前回の記事でSSHトンネリングをしつつSSLを使ってMySQL(AWS RDS)に接続するという話を書きました。今回も同じこと(と言うか同じルーチンを利用)をしてぶつかった壁の話になります。結論にたどり着くまで眠れなく、結局徹夜してしまいました(笑)

Ubuntu16.04では標準で入るPHPは7.0系になります。それ自体は大した問題ではないし、むしろ積極的に7.0系を使いたいと思っているので全く問題なしなのですが、作成中のプログラムに於ては大問題が発生してしまいました。内容としては前回書いた通りで、今回は「AzureのVMに配置したDockerコンテナからAWS RDSに接続する」という構成になります。で、前回と同様に下図のエラーが出てデータベースに接続できないわけです。

接続できない理由が全く書かれていないので悩みに悩みまくったわけですが、遂に結論に辿り着きました!

PHP5.6以降ではサーバー証明書の検証がデフォルトで強化されていて、接続先ホスト名とサーバー証明書のコモンネームが不一致の場合エラーになり接続させないようになりました。具体的に書くとSSLコンテキストオプションの以下のオプションがデフォルトでtrueになったという事です。

'verify_peer' => true		// サーバー証明書の検証を行うか?

あと、オプションが追加になってデフォルト値が以下のようになっています。

'verify_peer_name' => true	// ピア名の検証を行うか?
'allow_self_signed' => false	// 自己署名証明書を許可するか?

その結果、SSHトンネリングでSSL接続を行う場合、接続先ホスト名(今回の場合はゲートウェイサーバーのホスト名)とサーバー証明書のコモンネーム(データベースサーバーのホスト名)が異なるため接続できなくなりました。じゃぁ、これらのオプションを全てひっくり返した設定をすれば良いのではないか?という事でやってみたのですが…

stream_context_set_default(array(
	'ssl' => array(
		'verify_peer_name' => false,
		'verify_peer' => false,
		'allow_self_signed' => true
	)
));

を設定し、PDOでデータベースへの接続を開こうとしても先のエラーになって接続できませんでした。調査を重ねた結果、昨年春にバグとしてレポートが上がっておりパッチも提案されているのですが、現段階では適用されていないためタイトルのような状況になっています。

ちなみにmysqliではMYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERTというオプションが用意されていて先の状況を解決できるようになっている模様ですが、PDOにはこのようなオプションが用意されていない(提案はされている)ため、PDOにてSSHトンネリングとSSLは同時に使えないという状況は未だに解決されていないというわけです。

困ったものです…

コメント

タイトルとURLをコピーしました