RubyにおけるHTTPS通信
HTTPS (SSL)のお勉強
- http://www005.upp.so-net.ne.jp/nakagami/Memo/SSL/
- まとめると安全に通信を行うにはルートCAの証明書が必要と理解
Ruby (OpenSSL)におけるルートCA証明書
- ruby-listのアーカイブによると以下のコマンドでデフォルトの証明書の置き場所を取得できる
- Debian (lenny)における結果
% ruby -r openssl -e 'p OpenSSL::X509::DEFAULT_CERT_FILE' "/usr/lib/ssl/cert.pem" % ls /usr/lib/ssl/cert.pem ls: cannot access /usr/lib/ssl/cert.pem: そのようなファイルやディレクトリはありません % ruby -r openssl -e 'p OpenSSL::X509::DEFAULT_CERT_DIR' "/usr/lib/ssl/certs" % ls /usr/lib/ssl/certs/ 02b73561.0@ 0481cb65.0@ 052e396b.0@ 06d75f4b.0@ 0c364b2d.0@ 0dbd0096.0@ 0e82f83a.0@ 10d149a2.0@ 11a09b38.0@ 11f154d6.0@ (ry
net/httpsを使ったHTTPS通信
- net/httpsのマニュアルを見て作ったサンプルが以下
#!/usr/bin/ruby require 'net/https' https = Net::HTTP.new('secure.nicovideo.jp', 443) https.use_ssl = true https.ca_file = 'GTE_CyberTrust_Global_Root.pem' https.verify_mode = OpenSSL::SSL::VERIFY_PEER https.verify_depth = 5 https.start {|w| response = w.get('/') puts response.body }
- ca_fileは絶対パスで指定する必要があるようだ
- OpenSSL::X509::DEFAULT_CERT_DIRに同名のファイルが存在しても読んでくれないようだ
- ソース読んで確認したわけではないので間違っているかも
- OpenSSL::X509::DEFAULT_CERT_DIRに同名のファイルが存在しても読んでくれないようだ
- GTE_CyberTrust_Global_Root.pemはDebianの上記のディレクトリ(/usr/lib/ssl/certs)からコピーしてきたもの
- あるいはFirefox3.6からも取得可能
- https://secure.nicovideo.jp/にアクセス
- URLの左隣の緑の部分をクリック
- 「詳細を表示」をクリック
- 「証明書を表示」をクリック
- 「詳細」タブを開く
- 証明書の階層から「GTE Cyber Trust Global Root」を選択
- 「エクスポート」をクリック
- ファイルの種類「X509 証明書 (PEM)」で保存
- IE8の場合・・・がうまくいかない
- 似たような感じでファイルのエクスポートができるようだがそのファイルを使うとうまくアクセスできない
- 基本が分かってないのでこういうとこで躓いちゃうなあ
- あるいはFirefox3.6からも取得可能
- うまく行くと下記のような出力が得られる
<HTML> <HEAD> </HEAD> <BODY> <A HREF="payment">payment</A> </BODY> </HTML>
- 失敗した場合は以下のようなエラーが出力される
/usr/lib/ruby/1.8/net/http.rb:586:in `connect': SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (OpenSSL::SSL::SSLError) from /usr/lib/ruby/1.8/net/http.rb:586:in `connect' from /usr/lib/ruby/1.8/net/http.rb:553:in `do_start' from /usr/lib/ruby/1.8/net/http.rb:542:in `start' from ./hoge.rb:12
- 証明書なしでも以下のようにすると接続できてしまう
#!/usr/bin/ruby require 'net/https' https = Net::HTTP.new('secure.nicovideo.jp', 443) https.use_ssl = true https.verify_mode = OpenSSL::SSL::VERIFY_NONE # ←ここをPEERからNONEに変更 https.verify_depth = 5 https.start {|w| response = w.get('/') puts response.body }
-
- ブラウザでいうところの安全ではない接続に相当するか
Mechanizeを用いたHTTPS接続
- MechanizeのSSL周りのデフォルトの設定を確認
#!/usr/bin/ruby require 'rubygems' require 'mechanize' agent = WWW::Mechanize.new puts agent.ca_file puts agent.cert puts agent.key puts agent.pass puts agent.verify_callback
-
- 結果は全部nil
nil nil nil nil nil
- こちらのドキュメントによるMechanizeではこれらの値がnilの場合以下の通りであるとのこと
どれも設定されてない https アクセスである場合は、検証されないアクセスである OpenSSL::SSL::VERIFY_NONE による通信が行われます。
- つまり以下の例は検証されないアクセスになっているらしい
#!/usr/bin/ruby require 'rubygems' require 'mechanize' agent = WWW::Mechanize.new puts agent.get('https://secure.nicovideo.jp/').body
- 安全なアクセスを行うには以下のように証明書を指定する必要があるらしい
#!/usr/bin/ruby require 'rubygems' require 'mechanize' agent = WWW::Mechanize.new agent.ca_file = 'GTE_CyberTrust_Global_Root.pem' puts agent.get('https://secure.nicovideo.jp/').body
- Rubyのマニュアルによればきちんと調べるには以下の通り
-
- [TODO] まだ関数の使い方が分からず未調査