まだプログラマーですが何か?

プログラマーネタとアスリートネタ中心。たまに作成したウェブサービス関連の話も http://twitter.com/dotnsf

タグ:ssl

IBM Watson の API を使っていたら、ある日を境にこんなエラーが出るようになりました:
javax.net.ssl.SSLException: java.lang.ArrayIndexOutOfBoundsException: Array index out of range: 64

2016110901


エラーが出ているのは URL を指定して REST API を実行する瞬間の箇所です。GET でも POST でも発生しました。

原因を調べるために Watson API Explorer を使って、同じ API を実行してみたところ・・・今度はエラーなく実行できてしまいました:
2016110902


なんだこれは!? というわけで、エラーメッセージをググって調べてみたところ、こんな StackOverflow にこんなスレッドを見つけました:
Receiving “javax.net.ssl.SSLException: java.lang.ArrayIndexOutOfBoundsException” while connecting to “https:” site


ここに書かれている内容が原因であるとすると、暗号化アルゴリズムである TLS のバージョンの変更が原因らしいとのこと。またいくつかの対処方法があるが、クライアント側だけで対応するには JDK のバージョンを 1.8 にしろ、とのことらしいです。

確かに今回エラーが出るようになったシステムでは JDK 1.6 が使われているので、このエラーが発生する条件は満たしています。また Watson API Explorer 側では JDK 1.8 か、Java 以外のアプリケーションサーバーが使われていると仮定すればエラーなしに成功することになります。なので、今回のような結果になっても説明は付くことになります。
2016110903



原因が分かったところで、問題は対処方法です。今回はとあるシステム内からこの API を実行したかったという背景があります。そのシステムに組み込まれている JDK のバージョンが 1.6 である以上、ここを勝手に変更するわけにはいきません。 一方で、クライアントが JDK 1.8 未満である以上はこのエラーを回避するにはサーバー側を変更する必要があります。API 提供されているサーバー設定を変更してもらえる保証もありません。そもそもセキュリティ強化のためのサーバー設定変更が背景にあるわけですが、仮にセキュリティに一旦目をつぶるとして、JDK 1.6 のままでどうにかする方法はないでしょうか?


その方法の1つとして考えられるのが、下図のように JDK 1.8(または他のプラットフォームでもよい)など Watson API を実行できる環境でプロクシー的なものを作って、JDK 1.8 未満のシステムからはこのプロクシーを経由してリクエストを実行し、レスポンスを得る、という仕組みです:
2016110904

こうすると JDK 1.8 未満のシステムからはプロクシーまでアクセスできればよく、またプロクシー側の設定等にも自分である程度手を加えることも可能になります。そして Watson からは JDK 1.8 からのリクエストとして API を実行して結果を返す、という仕組みを作ればうまくいくのではないか、と考えました。まあ2つの仕組みを作ってメンテナンスしなければならない、という点はありますが、技術的にはクリアできる目処が立ちそうです。

近いうちに実際に作ってみた仕組みをまた紹介する予定です。


FireFox を使っていて https のサイトを訪れた時に「安全な接続ができませんでした」というエラーページに出くわすことがあります。それも選択肢が「再試行」と「報告」しかなくて、例外追加みたいな対応もできないケースです:
2015072501


よく見ると SSL が安全ではない、みたいなメッセージも書かれてます。この件に関する Mozzila としての見解はこちらです。昨年ですが、通称「プードルアタック」と呼ばれる脆弱性が SSL v3 に見つかり、SSL v3 は安全ではなくなってしまいました。その対策としてデフォルトでこのプロトコルを使ったサイトをブロックします、とのことです:
https://support.mozilla.org/ja/kb/enable-ssl-fix-cannot-connect-securely-error


まあ何もしないのはまずいと思うし、Mozzila の言いぶんはわかる。利用者には罪はなくて、サイトを提供する側に(安全ではない)SSL v3 を使わないでほしい、ということだと思っています。

とは言っても、すぐに対応できるとは限らないケースもあります。例えばサーバーイメージが仮想的に提供されているような場合は、その仮想イメージで SSL v3 を使っていることもあります。仮想イメージをすぐに更新してほしいと言われても困るし、仮に仮想イメージそのものは更新できたとしても既に仮想環境内で使われているイメージをどうやって更新するか、という問題だってあります。要はサイト提供側だけにこの問題の責任を追わせるのには無理があるのかな・・・と。

では諦めるしかないのか、というとそんなこともありません。ブラウザで利用するユーザーの自己責任にはなりますが、このような SSL v3 のサイトにアクセスするように FireFox の設定を変更することもできます。以下にその方法を紹介しますが、SSLv3 が安全ではないことに変わりはないので、社内の環境など、本当に安全が保証されているサイトでのみ、また目的のサイトへのアクセスが終わったらすぐに設定を元に戻るなど、自己責任で使ってください。

ではその設定方法を紹介します。まず FireFox を起動して、アドレス欄に about:config と入力します。「動作保証外である」という警告メッセージが表示されますが、「細心の注意を払って使用する」ボタンをクリックします:
2015072502


すると FireFox の挙動に関わる各種設定項目の一覧が表示されます。かなり大量にあるので、ここから目的の項目を探すのは大変なので、検索をします:
2015072503


「検索」と書かれたフィールドに "security.ssl3.dhe" と入力すると、少しずつ項目が絞られていきながら、ここまで入力した時点で2つの項目だけが表示されているはずです。またどちらも初期設定値の true が設定されているはずです:
2015072504


これら2行の項目の設定値を false に変更します。変更するには各行をダブルクリックすることで変更できます:
2015072505


この状態で先程エラーに成ったページに再度アクセスすると、ちゃんと見れるようになるはずです。



繰り返しになりますが、この設定状態は必ずしも安全ではないため、目的のページを見終わった後は、2箇所とも設定を元通りに戻しておくことを強くおすすめします:
2015072506


ちなみにプードルアタックとその対策についてはこちらで詳しく書かれていたので、是非参照してください:
SSLv3 の脆弱性 POODLE への対策を行う


以前に IBM Bluemix を独自ドメインで利用する方法について紹介しました:
IBM Bluemix を独自ドメインで運用する


本エントリでは、特に SSL を使って IBM Bluemix を独自ドメイン運用するための注意点と手順を紹介します。


まず独自ドメインを使わない場合、IBM Bluemix 上のウェブアプリケーションには米国リージョンの場合で****.mybluemix.net(英国リージョンであれば ****.eu-gb.mybluemix.net)というホスト名が割り当てられます。**** 部分はアプリケーション作成時に指定したものが使われます。 以下、説明をシンプルにするため、米国リージョンでの利用を前提として説明を続けます)。

このホスト名を SSL で利用する場合の SSL 証明書は mybluemix.net 側で(つまり IBM 側で)用意されていることになります。特に **** 部分にどのような文字列が来るか想定できない前提で SSL を使うので、その証明書はワイルドカード対応のものが用意されている、ということになります。


さて、独自ドメインで IBM Bluemix を使う場合の注意点として、そのドメインの SSL 証明書は利用者が用意する必要があり、加えて上記の理由からその証明書はワイルドカード対応のものを用意する必要がある、ということになります。

現在、SSL 証明書を発行してくれるサービスは国内外でいくつかあります。ただ IBM Bluemix で利用するドメインの SSL 証明書を発行してもらうためには、ワイルドカード対応のものを発行してもらう必要があるのですが、全ての業者がワイルドカード対応の証明書を発行してくれるわけではありませんワイルドカード対応の SSL 証明書を発行してくれる業者の中から選んで注文する、という点に注意が必要です。


ただ、特定の限られた用途での利用など、いわゆる「オレオレ証明書」でもいい、という場合は、自分でワイルドカードに対応した SSL 証明書を用意することでも対応は可能です。ワイルドカードに対応した SSL 証明書を自分で発行する場合の手順はこちらを参照してください:
ワイルドなオレの証明

以下はこの方法で用意した SSL 鍵および証明書を使った前提で紹介を続けます(手順そのものは正式な証明書を使った場合も同様です)。

まず冒頭で紹介した「IBM Bluemix を独自ドメインで運用する」の手順を進めて、「組織の管理」メニューからドメインの追加を行います:
2015030601


追加する独自ドメイン(この例では "yellomix.net")を指定して「保存」します:
2015030602


保存後、「SSL 証明書」と書かれた列に証明書アップロードのためのボタンが表示されるので、ここをクリックします:
2015030603


証明書ファイルと秘密鍵ファイルを指定してアップロードします。もし中間証明書ファイルをお持ちで、追加したい場合は中間証明書ファイルも指定します。最後に「アップロード」ボタンをクリックします:
2015030604


先ほどのボタンがグリーンに変わっていれば証明書ファイルのアップロードは完了です:
2015030605


では独自ドメインでアプリケーション・サーバーを1つ作成して、SSL でアクセスする、という動作確認を行ってみます。まずは Bluemix 上に(動作確認なので中身はあってもなくてもいいと思いますが)ランタイムまたはボイラープレートから作成したランタイムを作ります。その際にドメイン情報として、追加した独自ドメインを指定するようにします:
2015030606


ランタイムアプリケーションを作成すると、経路の情報としてホスト名が表示されます。先ほど独自ドメインを指定したので独自ドメインにアプリ名が付与されたホスト名になっているはずです:
2015030607


DNS 側でもこのホスト名の名前解決ができるような設定をしておきます。このランタイムに付けた名前(dotnsf-ibm-wordpress)の CNAME として、元々デフォルトで割り振られるはずだった名前(dotnsf-ibm-wordpress.mybluemix.net)を参照するように指定します。この部分は各々でお使いの DNS ツールの方法に従ってください:
2015030608


これで設定は完了しています。確認のため実際にブラウザを使って、作成したランタイムのホスト名に対して https:// でアクセスしてみましょう。オレオレ証明書を使った場合は、ブラウザの種類にもよりますが、「接続の安全性を確認できない」云々、といった確認画面になると思います。ある意味、正しく SSL が動いている証拠と言えます:
2015030609


理解した上で許可すれば SSL で(httpsで)見れるようになります。このホスト名を直接指定した形では SSL 証明書を作っていませんでしたが、ワイルドカード指定で作成した SSL 証明書が IBM Bluemix に正しくインポートされて動いていることが確認できました:
2015030610





















 

SSL のオレオレ自己署名証明書を、ワイルドカード対応で作成する手順です。CentOS 上での作業を前提で説明します。
ワイルドカード対応といっても、普通のオレオレ証明書(?)の時と比べてそんなに大きく変わるわけではありません。

CentOS のターミナルを開いて、以下を順次実行していきます。
なお、今回は "yellowmix.net" というドメイン向けのワイルドカード対応証明書を作る前提で説明します。

まずは普通に秘密鍵を作成:
# openssl genrsa -out server.key 2048

次に CSR (署名要求)ファイルを作成、ここでホスト名をワイルドカードで指定します:
# openssl req -new -key server.key -out server.csr
  :
  :
-----
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Chiba
Locality Name (eg, city) [Default City]:Funabashi
Organization Name (eg, company) [Default Company Ltd]:YellowMix Ltd
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server's hostname) []:*.yellowmix.net
Email Address []:

  :
  : (残りは全て Enter キーで)

最後に証明書を作成します。この例では約10年間(3653日)有効な証明書を作成しています:
# openssl x509 -days 3653 -in server.csr -out server.crt -req -signkey server.key

ここまでの作業で server.key, server.csr, server.crt の3ファイルができているはずです。

SSL を使ったウェブページの動作確認程度であればこれで充分です。
ワイルドカードで作ったので、ホスト名(****.yellowmix.net の **** 部分)が何であってもこの証明書1つで使えるはず。


次回は、作成したこのワイルドカード対応 SSL 証明書を IBM Bluemix 環境で使ってみます。


(2015/Feb/08 追記 続きはこちら)
IBM Bluemix を独自ドメインで使う(SSL編)

 

CentOS 環境設定備忘録シリーズ(?)、今回は Apache HTTPD の巻。
CentOS の導入は済んでいるものとします。詳しい手順はこちらを参照。

Apache HTTPD の導入自体は簡単すぎるので、今回は SSL アクセスを有効にするところまでを紹介、オレオレ SSL だけど。

まずはターミナルを開いて、 Apache HTTPD をサクっとインストール:
# yum install httpd

これで完了、簡単すぎ。後は実行すれば HTTPD サーバーとして使えるけど、その前に SSL の設定も紹介します。


SSL(Secure Sockets Layer) 情報を暗号化して送受信するプロトコル。これを HTTP で使う場合のプロトコルが HTTPS です。個人情報やクレジットカード情報を送受信する場合、その中身を暗号化して途中経路で読めなくする場合などに使います。利用者のレベルでは HTTP や HTTPS の違いをほとんど意識することはありません。

一方、サーバー側には SSL の鍵や証明書を使うことでこの暗号化を実現します。単にサーバーそのものを SSL 対応することに加え、この鍵や証明書を用意しておく必要があります。商用サイトであれば専門の機関から有償で発行してもらうもののですが、検証目的であれば OpenSSL を使って自分で(無償で)用意することもできます。

余談ですが、自分で用意した場合は自分の作った証明書で自分を信じこませて認証する、という意味で「オレオレ SSL」とか「オレオレ証明書」とか言われます。いずれこれらも「母さん、助けてSSL」とかって呼ばれるようになるんでしょうかね(笑)。

で、その自分で SSL を有効にするまでの手順も紹介します。まずは OpenSSL と、Apache HTTPD に SSL 機能を付けるための mod_ssl モジュールを導入します(既に導入済みかもしれません、その場合は気にせず先に進んでください):
# yum install openssl
# yum install mod_ssl

まずはオレオレ証明書を作ります。その前提として秘密鍵と公開鍵のペアが必要なので、順序としては (1)秘密鍵を作って、(2)公開鍵を作って、(3)証明書を作る という流れになります。この順に説明します。なお以下ではこれらのファイルを /etc/httpd/conf/ 以下に作成する前提で進めますが、別ディレクトリでも構いません。その場合は適宜読み替えてください。

最初に /etc/httpd/conf に移って、(1)秘密鍵を server.key というファイル名で作成します:
# cd /etc/httpd/conf
# openssl genrsa -aes128 1024 > server.key

Generating RSA private key, 1024 bit long modulus
..................++++++
..........................................++++++
e is 65537 (0x10001)
Enter pass phrase:(パスフレーズ)
Verifying - Enter pass phrase:(同じパスフレーズ)

この例では 128 ビットの AES 方式で暗号化した 1024 ビットの秘密鍵を作っています。途中でパスフレーズ(パスワード)を聞かれるので適当なパスワードを指定し、直後に確認のため同じパスワードを入力します。これで秘密鍵が完成です。

次にこの秘密鍵ファイルとペアになる (2)公開鍵ファイルを server.csr というファイル名で作成します:
# openssl req -new -key server.key > server.csr
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Chiba
Locality Name (eg, city) []:Funabashi
Organization Name (eg, company) [Internet Widgits Pty Ltd]:空白
Organizational Unit Name (eg, section) []:空白
Common Name (eg, YOUR name) []:192.168.XXX.XXX
Email Address []:空白

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:空白
An optional company name []:空白

2文字の国識別コードには JP を指定、都道府県、市区町村を指定、それ以外は Common Name 欄以外は空白のままで大丈夫です。
注意点として、Common Name には実際に HTTPS として運用する際にブラウザから指定するアドレスを入力することになります。 https://www.xxx.com/ といったサーバー名でアクセスするのであれば xxx.com を、https://192.168.XXX.XXX/ といった IP アドレスでアクセスするのであれば IP アドレスを指定してください。

最後にこの秘密鍵と公開鍵を使って (3)証明書ファイルを server.crt というファイル名で作成します:
# openssl x509 -in server.csr -days 36500 -req -signkey server.key > server.crt
Signature ok
subject=/C=JP/ST=Chiba/L=Funabashi/O=Default Company Ltd/CN=192.168.XXX.XXX
Getting Private key
Enter pass phrase for server.key:(上記で指定したパスフレーズ)


この場合では X.509 形式の証明書ファイルを、有効期間36500日(約100年)の指定で作成しています。これだけ指定しておけば自分の開発期間中はまあ大丈夫でしょうw。


これでデジタル証明書の作成までできましたが、このまま使うと Apache HTTPD の起動時にパスフレーズの入力を求められることになります。開発期間中はそれでもいいのかもしれませんが、実際の運用はサーバーの起動と同時に HTTPD サーバーも起動させたりするので、ここまでの作業が完了していればパスフレーズは不要と言えます。パスフレーズは以下のコマンドで解除することができるので、一応紹介しておきます:
# mv server.key server.key.bak
# openssl rsa -in server.key.bak > server.key
Enter pass phrase for server.key.back:パスフレーズ
writing RSA key

デジタル鍵/証明書が用意できたので、実際にこれを使って HTTPS を構築します。mod_ssl をインストールしたタイミングで /etc/httpd/conf.d/ssl.conf が作られているはずなので、このファイルを編集して今作成したこれらのファイルを指定します:
# vi /etc/httpd/conf.d/ssl.conf

  :
<VirtualHost _default_:443>
  ErrorLog logs/ssl_error_log
  TransferLog logs/ssl_access_log
  LogLevel warn
  SSLEngine on
  SSLProtocol all -SSLv2
  SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
  SSLCertificateFile /etc/httpd/conf/server.crt
  SSLCertificateKeyFile /etc/httpd/conf/server.key
  <Files ~ "\.(cgi|shtml|phtml|php3?)$">
    :
  </Files>
</VirtualHost>

これで準備は整いました。では HTTP(S) サーバーを起動します:
# /etc/init.d/httpd start

起動後、ウェブブラウザを使ってこのサーバーにアクセスしてみます。まずは普通に http://XXX.XXX.XXX.XXX でアクセス。特に何もしていなければ Apache HTTPD のデフォルトページが表示されるはずです:
2014020801


次に同じアドレスに対して https://XXX.XXX.XXX.XXX でアクセスを試みます。SSL でのアクセスになります。証明書がオレオレなので、「信頼できないよ(第三者が保証するものではないよ)」と警告されます。
2014020802


ブラウザによってこの後の承認方法が異なりますが、Chrome であれば「このまま続行」ボタン、FireFox であれば「危険性を理解した上で接続するには」 - 「例外を追加」 - 「セキュリティ例外を承認」 を順に選択することで先に進むことができて、本来のトップページが HTTPS プロトコルで見ることができます。
2014020803












このページのトップヘ