あーかいぶすハイディフィニション

ここはもう更新しとらんのじゃ

Pound + Nginx ( + Rails ) 環境で SSL 通信

勤めている会社のテストサーバ群は、

  1. ゲートウェイに配置された Cisco ASA
  2. ASA からグローバル IP を付与された Pound サーバ
  3. 更に下位ローカルネットワークに配置された仮想サーバ

このような構成にしています。んでこの環境下だと必ず Pound を通るため、http は複数列挙して名前解決すればいいけど、「証明書が必要な SSL 通信をする場合どうすんの?」となります。

ワイルドカード SSL 証明書を用意する

Pound の下にぶら下げるサーバが一台ならドメインと一致した単一の証明書で問題ないのですが、今回は複数ホストの場合です。Pound は自身にぶら下げたサーバへの誘導に、当然ですがドメインを利用します。SSLドメインの正当性を証明します。なので、複数のサーバをぶら下げた環境下で SSL を利用しようとすれば、複数のドメインに対応した証明書が必要ですね。という訳で前置きが長かったですが、ワイルドカード証明書です。これは簡単に言っちゃうと、所属するサブドメインを全て認める SSL 証明書、となります。
例えば、*.example.com というワイルドカード SSL 証明書を取得した場合、

このように、サブドメイン部に相違があっても、example.com ドメインであれば汎用的に利用することが可能です。

※気をつけなければ行けないのは、例えば stg.example.comstg.local.example.comサブドメインの階層が違うため、*.example.com というワイルドカード証明書一枚で対応出来ない、ということです。これのお陰で僕は数万円勉強代を払いました(半ギレ)。

という訳でワイルドカード SSL 証明書を素直に用意しましょう。僕はよく、Rapid-SSL で購入しています(ドメインの公開連絡窓口に紐付いたメールアドレスが受信可能なら、購入から発行まで 5 〜 10 分位で取得できる)が、別にこれはどこのでもいいです。中間証明書 ( CA ) がどこにあるのかちゃんと教えてくれる業者で買うことぐらいが注意点でしょう!

Pound に SSL 設定を記述する

たぶんこんなん。

User        "pound"
Group       "pound"
LogLevel    1
Alive       10
Daemon      1
LogFacility local1

ListenHTTPS
    Address    0.0.0.0
    Port       443
    xHTTP      2
    #Err414     "/var/www/pound/err414.html"
    #Err500     "/var/www/pound/err500.html"
    #Err501     "/var/www/pound/err501.html"
    #Err503     "/var/www/pound/err503.html"
    Cert       "/usr/local/etc/ssl_certificate/YYYY/wairudoka-do_syoumeisyo.pem"
    AddHeader  "X-Forwarded-Proto: https"
    HeadRemove "X-Forwarded-Proto"

  ### SSL ( dev.example.com )  ###
  Service
    HeadRequire "Host: dev.example.com"
    BackEnd
        Address 192.168.10.1
        Port    80
        TimeOut 60
    End
  End

  ### SSL ( stg.example.com )  ###
  Service
    HeadRequire "Host: stg.example.com"
    BackEnd
        Address 192.168.10.10
        Port    80
        TimeOut 60
    End
  End

  ### SSL ( vip.example.com )  ###
  Service
    HeadRequire "Host: vip.example.com"
    BackEnd
        Address 192.168.10.100
        Port    80
        TimeOut 60
    End
  End

End

http 側の設定も一杯書いてあるけど、今回の記事には関係ないので省きます。修正すべきところは、

  • ListenHTTPS
    • Cert "/usr/local/etc/ssl_certificate/YYYY/wairudoka-do_syoumeisyo.pem"
  • Service
    • HeadRequire "Host: vip.example.com"
    • Address 192.168.10.100

このあたりす。

ListenHTTPS の Cert が参照するファイルの中には、

  • crt ( 発行された SSL 証明書の中身。安いやつは大体メールでくる )
  • key ( csr 作る時に使った鍵ファイル。パスワードを含ませてパスフレーズ入力なしで使えるようにしたもの )
  • ca ( 中間証明書。有名な所だったらブラウザがなんとかしてくれるけど慢心せず設定、しよう! )

これらを順に書き込みます。起動失敗した時は、多分中身を書く順番が間違ってるので、入れ替えてやれば動くはず。

Service の HeadRequire には、対象のサブドメインを含めたドメイン名を(ちゃんと DNS に登録するか、自分の hosts に書いて確認できるようにしとけよしとけー)、Address には、Pound から参照出来るそのサーバのアドレスを( Pound のサーバから lynxwgetw3mcurl なんかで、http アクセスできるアドレスならおk)それぞれ記述します。

Pound を起動する
[root@localhost ~]# cd Pound のバイナリがあるとこ
[root@localhost ~]# pound -vc
starting...
Config file /path/to/config/pound.cfg is OK
[root@localhost ~]# pound

さらっと -vc でチェックしてるし、なんで root でうごかしてんねん、みたいなツッコミはやめろ、やめろォ!

アクセスする

バックエンドのサーバと通信できてれば、https:// から始まるアドレスでドメインアクセスできるはずです、やったね。

んで、この構成というかリバースプロキシの設定というか、実際にアクセスするときの https プロトコルの通信は Pound までです。Pound が自身にぶら下げてるサーバとの通信は http を利用します。なので、本番は Nginx 単体で SSL 通信を用い、テスト用のサーバ群では Pound が SSL 通信をする、などという場合は、アプリケーションによっては、というか大体は設定が変わると思います。純粋な意味でのテストをしたい場合は、このような環境を用いるべきではないですね!とはいえこの環境だと、機能のテスト程度では十分なはずなのです!

例として Rails アプリケーションと通信する場合

Nginx に https 対応の server 句 ( listen 443 ) を書いて、SSL 証明書のファイルとか設置して、なおかつ rails アプリケーションの config/enviroments/production.rb あたりに「config.force_ssl = true」をかく必要があります。
逆に Pound に https 通信をさせる場合はこのへんはいりません、http で動作させるのと同じ Nginx の server 句 ( listen 80 ) を書いて、逆に config/enviroments/production.rb あたりに「config.force_ssl = false」もしくは「そもそも記述しない(デフォルト値が false だったはず)」とします。

よくやらかす例

https と http 両方設定する必要があって、https は見れるのに http で無限リダイレクトが発生する!もしくはその逆のパターン。大体上記 config.force_ssl あたりの記述ミスがあるので、あわてず騒がず確認しましょう。