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は、さらに下位の認証局に証明書を発行します。

ということだった。

リンク

SSL 証明書の購入と設定

暗号化して通信するだけなら 「第三者認証局がドメイン登録情報のみを確認したうえで発行される証明書」 で十分。一年、千円くらいで取得できる。

NameCheap

http://www.namecheap.com/ssl-certificates/geotrust-ssl-certificates.aspx の一番安いものにした。 該当のドメインのメールをきちんと受信できるようにしておく必要がある。

のページの通りにすると証明書を購入することができた。

適当なディレクトリに鍵を作る。

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;
        }

リンク

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" }))

のようにしている。

リンク

Tags of current page

, , ,