SSL の証明書を取得と nginx、rails、devise の設定
SSL の証明書について
証明書は SSL で暗号化して通信するのに必要というくらいの認識だったので調べてみた。
「SSL 証明書」で検索したときに上位にきた http://www.atmarkit.co.jp/fsecurity/special/133evssl/evssl00.html を読んだ。EV (Extended Validation) SSL 証明書について書かれている。
証明書の機能は
SSLサーバ証明書は、「通信データの暗号化」と、「通信相手の認証」という2つの主な機能を持っています。
で「通信相手の認証」の方で証明書の種類があるようだ。
EV とつく証明書は、認証の方法が厳格ということらしい。
SSL サーバ証明書自体については、「SSL サーバ証明書は、大きく分けると3種類」と書いてあって、次の3つ。
- 第三者認証局がドメインの使用権、企業の実在性、Webサーバの結び付きを確認したうえで発行される証明書
- 第三者認証局がドメイン登録情報のみを確認したうえで発行される証明書
- 独自に認証局を立てて発行される証明書
認証に関係する組織がいくつもあってややこしいのは、
認証局 (CA) ベンダから発行される証明書は、認証局を階層型に構成する「階層型モデル」を取っています。 階層型モデルの頂点に位置する認証局を「ルートCA」といい、ルートCAによって証明される認証局を下位CA(下位認証局)といいます。 ルートCAは、下位CA(中間認証局)の証明書を発行し、下位CAは、さらに下位の認証局に証明書を発行します。
ということだった。
リンク
- http://e-words.jp/w/E383ABE383BCE38388E8A8BCE6988EE69BB8.html
- http://ja.wikipedia.org/wiki/ルート証明書
- http://www.atmarkit.co.jp/fsecurity/index.html
- http://www.ssloff.com/ssl
- http://www005.upp.so-net.ne.jp/nakagami/Memo/SSL/
SSL 証明書の購入と設定
暗号化して通信するだけなら 「第三者認証局がドメイン登録情報のみを確認したうえで発行される証明書」 で十分。一年、千円くらいで取得できる。
NameCheap
http://www.namecheap.com/ssl-certificates/geotrust-ssl-certificates.aspx の一番安いものにした。 該当のドメインのメールをきちんと受信できるようにしておく必要がある。
- http://www.myhome-server.com/service/ssl.html
- http://blog.wensheng.com/2012/03/using-namecheap-ssl-with-nginx.html
のページの通りにすると証明書を購入することができた。
適当なディレクトリに鍵を作る。
mkdir -p ssl/crt ssl/csr ssl/key
openssl genrsa -out ssl/key/yourdomain.key 2048
openssl req -new -key ssl/key/yourdomain.key -out ssl/csr/yourdomain.csr
NameCheap で証明書を購入して、メールに記載されている証明書を次の二つのファイルを作って記入する。
vi ssl/crt/yourdomain.crt
vi ssl/crt/intermediate.crt
nginx で使う場合はこれらを一つのファイルに記入する。
cat ssl/crt/yourdomain.crt ssl/crt/intermediate.crt > yourdomain_nginx.crt
nginx
nginx をリバースプロキシにして rails の unicorn に接続させる。 SSL については ssl/crt/yourdomain_nginx.crt と ssl/key/yourdomain.key を使うように設定する。
設定
設定は次のようにした。unicorn に関する設定は別途おこなっておく。 これは /some_path と /assets 以外の URL に対しては http に転送するようにしてある。 ブラウザと nginx の間は https で nginx と rails の間は http。 ブラウザと nginx の間は https で通信したということを rails に知らせるために、 忘れずに nginx でヘッダで X-Forwarded-Proto https とする。
server {
listen 443;
server_name yourdomain.net;
ssl on;
ssl_certificate /path/to/ssl/crt/yourdomain_nginx.crt;
ssl_certificate_key /path/to/ssl/key/yourdomain.key;
ssl_session_timeout 5m;
ssl_protocols SSLv2 SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
error_log /var/log/nginx/yourdomain.ssl.error.log;
access_log /var/log/nginx/yourdomain.ssl.access.log;
root /var/www/rails/public;
add_header X-XSS-Protection "1; mode=block";
add_header X-Frame-Options DENY;
add_header X-Content-Type-Options nosniff;
gzip on;
gzip_http_version 1.1;
gzip_types text/plain
text/xml
text/css
application/xml
application/xhtml+xml
application/rss+xml
application/javascript
application/x-javascript;
gzip_buffers 4 8k;
gzip_min_length 1000;
gzip_comp_level 1;
gzip_proxied off;
gzip_disable "MSIE [1-6]\." "Mozilla/4";
gzip_vary off;
if ($uri !~ ^/[some_path|assets]) {
rewrite ^(.*)?$ http://$host$uri last;
}
location ~* ^.+.(jpg|jpeg|gif|css|png|js|ico)$ {
expires 7d;
}
location / {
try_files $uri $uri.html $uri/index.html @unicorn;
}
location @unicorn {
proxy_http_version 1.1;
proxy_set_header X-Forwarded-Ssl on;
proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_max_temp_file_size 0;
proxy_pass http://unicorn_server;
}
リンク
- http://labs.unoh.net/2009/08/tips_for_nginx.html
- http://www.fraction.jp/log/archives/2012/01/26/nginx-ssl-rails
- http://blog.livedoor.jp/enjoy_baseball-advanced/archives/51447967.html
- http://reciente-naga.blogspot.jp/2010/12/nginx-redmine-https.html
rails & devise
設定
https を使いたい部分はユーザ認証の devise の部分なので config/application.rb に
config.to_prepare do
Devise::SessionsController.force_ssl
Devise::SessionsController.layout "for_ssl"
Devise::RegistrationsController.force_ssl
Devise::RegistrationsController.layout "for_ssl"
Devise::PasswordsController.force_ssl
Devise::PasswordsController.layout "for_ssl"
Devise::ConfirmationsController.force_ssl
Devise::ConfirmationsController.layout "for_ssl"
end
を追加した。SSL を使わなければならないコントローラに force_ssl をつける。 私の環境ではレイアウトを http のページと別にする必要があったので for_ssl というレイアウトを使用することにしている。
他のサービス
https でないリンクからダウンロードすると鍵マークがつかない。
- google analytics
- twitter のボタン
- facebook のいいねボタン
は https なので問題なかったが
- amazon のアフィリエイト
- google adsense
- はてなブックマーク
- addclips
は http なので https のページでは外さないと鍵マークがつかない。
https のページへのリンク
nginx で特定の URL を http から https にしていたのだが、 それだけだと鍵マークがつかなかった。 (リダイレクトでうまくやる方法があるのかもしれないが、) link_to などのリンクを https にする必要があった。
link_to("title", :controller => "contact", :action => "index", :only_path => false, :protocol => 'https://')
のように only_path と protocol オプションを加えた。 ただ、これだと production 環境で devise のページから controller が認識されなかった。
link_to("title", :controller => "/contact", :action => "index", :only_path => false, :protocol => 'https://')
とすることで回避した。
実際には、production 環境以外では、https にしないように、 あまりきれいではないけれど
module ApplicationHelper
def https_url_args(*args)
if Rails.env.production?
args[0] = { :protocol => "https://", :only_path => false }.merge(args[0])
end
args
end
end
というメソッドを定義して
link_to("title", *https_url_args({ :controller => "/contact", :action => "index" }))
のようにしている。