Ubuntu Weekly Recipe

第387回UbuntuでSSLを利用したサービスを構築する

SSLとは

インターネットは危険に満ちています。とはいえ、もはや我々のお仕事や生活はインターネットなしには成立しません。そんな危険なインターネット上で、安全に通信するためのプロトコルがSSL[1]です。SSLを利用することで「暗号化による通信の保護」「通信相手の真正性の確認」を行うことができます。逆に言えばSSLで保護されていない場合は、通信内容を盗み見られたり、偽のサイトに誘導されるといった攻撃に晒される危険があります。パスワードやクレジットカード情報などを入力するサイトはもちろんのこと、もはやインターネット上の通信はすべてSSLで保護すべき、といった意見もあるほどです。

今回のレシピではUbuntu 14.04 LTSのサーバーにSSL証明書をインストールし、セキュアなサービスを構築する方法を紹介します。

ApacheでHTTPSサーバーを立てる

まず手始めに、HTTPSで通信できるWebサーバーを構築してみましょう。Apache Webサーバーをインストールします。

Apache Webサーバーのインストール
$ sudo apt-get install apache2

次にApacheのSSLモジュールと、デフォルトのSSLのサイトを有効化し、Apacheを再起動します。

SSLモジュールとバーチャルホストの有効化
$ sudo a2enmod ssl
$ sudo a2ensite default-ssl
$ sudo service apache2 restart

これで、Apacheが443番ポートの待ち受けを開始します。

ポートの確認
$ ss -lnt
State      Recv-Q Send-Q        Local Address:Port          Peer Address:Port
LISTEN     0      128                      :::443                     :::*
LISTEN     0      128                      :::80                      :::*

SSLで通信を行うには、SSL証明書をサーバーにインストールしなければなりません。ですがUbuntuの場合、Apache Webサーバーをインストールした段階でサンプルのSSL証明書が自動的に作成され、利用可能になっています。Ubuntuのapache2パッケージは、Recommendsにssl-certパッケージが指定されています。そのため明示的に--no-install-recommendsオプションを指定しない限り、apache2のインストールと同時にこのパッケージもインストールされます。このパッケージのpostinstallスクリプト内で

make-ssl-cert generate-default-snakeoil

というコマンドが実行されているのです。make-ssl-certはその名の通り、SSL証明書を作成するためのラッパースクリプトです。これによって作成されたサンプル証明書の秘密鍵と公開鍵はそれぞれ

/etc/ssl/private/ssl-cert-snakeoil.key
/etc/ssl/certs/ssl-cert-snakeoil.pem

に配置されます。ApacheのデフォルトのSSLサイトの設定である/etc/apache2/sites-available/default-ssl.confでも、以下のようにこの証明書と秘密鍵が指定されています。

/etc/apache2/sites-available/default-ssl.conf
SSLEngine on
SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key

このような理由から、Ubuntuではapache2パッケージをインストールしてモジュールとサイトを有効化するだけで、⁠サンプルの証明書で)SSL通信を行うサイトを動かすことができるのです[2]⁠。

念の為opensslコマンドを使って、証明書の中身を確認しておきましょう。特にフィンガープリントは、自己署名証明書を使ううえで正しいサイトであることを確認する唯一の手段となりますので、控えておいてください。

SSL証明書の内容の確認
$ openssl x509 -in /etc/ssl/certs/ssl-cert-snakeoil.pem -noout -text -fingerprint -sha256
(……略……)
SHA256 Fingerprint=57:2A:35:91:05:9A:FE:62:11:EF:4F:54:6F:07:7C:39:7E:34:FB:F3:08:7C:CD:75:17:51:F0:D6:AE:79:AF:C8

Webブラウザーからhttps://(サーバーのIPアドレス)にアクセスしてください。画像のような警告が表示されているはずです。これはサーバーが(信頼できる認証局の署名のない)自己署名証明書を利用しているためです[3]⁠。

図1 証明書の警告画面
図1 証明書の警告画面
図2 セキュリティ例外の追加
図2 セキュリティ例外の追加
図3 証明書の詳細
図3 証明書の詳細

「例外を追加⁠⁠→⁠表示」をクリックして、証明書のフィンガープリントを確認してください。これが先ほど控えたフィンガープリントと一致していれば、意図したサイトに接続できているという証明になります。問題がないようであれば、⁠セキュリティ例外を承認」をクリックしてください。また、もしもこの方法で構築したサイトを自分以外の誰かに利用させる場合は、証明書のフィンガープリントを事前に連絡して、証明書の確認ができるようにしてあげてください。

本連載では過去にTinyTinyRSSやownCloudといったWebサービスの構築を紹介してきましたが、こういったサービスもSSLに対応して運用するのが望ましいでしょう。特にownCloudなどは、HTTPでアクセスしてきたら強制的にHTTPSにリダイレクトしてもよいくらいです[4]⁠。

コラム(自己署名証明書の利用について)

前述のように、自己署名証明書を利用しているサイトにアクセスすると、Webブラウザーが警告を発します。自己署名証明書を使うのは望ましくないのでしょうか?

筆者は場合によると考えています。自己署名証明書の問題は、認証局のサインがないため第三者が本当に正しいサイトなのか確認できないことです。たとえばOV(企業認証)証明書であれば、法務局や帝国データバンクの情報、あるいは登記簿謄本の提出などによる企業実在認証をパスしなければ証明書が発行されないため、通信している相手が実際に存在している企業であることは信用してよいでしょう[5]⁠。DV(ドメイン認証)証明書であっても、少なくともそのドメインを所有している相手ではあるわけです[6]⁠。しかし自己署名証明書ではそういったものが担保されていないため、偽のサイトに誘導されていても気づけないのです。

ですが自分自身から見れば(自分が作成した証明書とフィンガープリントが一致することによって)自分自身のサイトであることが確認できるわけですから、この点は問題になりません。自分一人、あるいは家庭、会社内など、閉じられた範囲で利用するのであれば、自己署名証明書でも暗号化という目的は達成できるため、証明書を購入しないで済ますという選択もあるでしょう[7]⁠。

ただしGmailのような外部サービスと連携する場合は注意が必要です。GmailのMail Fetcher機能を利用し、自分のメールサーバーに届いたすべてのメールをGmailに集める、というのは割とよくある運用です。しかしGmailは自己署名証明書を用いたSSL通信を拒否するため、このような場合は正規のSSL証明書が必要になります。第三者にサービスを公開したり、外部サービスと連携する場合には、SSL証明書を購入するようにしましょう。

(Gmailヘルプより引用)

SSLの要件 Gmailでは「厳格」なSSLセキュリティを使用します。このため、ご利用の他のプロバイダのリモートサーバーに有効なSSL証明書があるかどうかの確認が常に行われます。これにより高度なセキュリティを提供してユーザーの情報を保護します。

正規のSSL証明書を購入する

不特定多数に向けたサービスに、snakeoilをそのまま使うわけにはいきません。もしもサービスをインターネット上で公開するのであれば、正式なSSL証明書を購入しましょう[8]⁠。

本連載では過去にさくらのVPSでUbuntuサーバーを構築する方法を紹介しました。Ubuntuに対応した安価なVPSサービスということもあり、さくらでUbuntuサーバーを運用している方も多いのではないでしょうか[9]⁠。そのさくらがジオトラストブランドのRapidSSLの取り扱いを開始し、9月30日までの限定で1年分無料キャンペーンを行っています。ここでは(せっかくですのでこのキャンペーンを利用して)SSL証明書の購入方法を紹介します[10]⁠。

まずサーバー上でopensslコマンドを使い、秘密鍵を作成します。-des3オプションはトリプルDESで秘密鍵を暗号化するという意味で、引数の2048は、鍵長を2048bitにするということを意味します。セキュリティ上の理由から、1024bitのSSL証明書はすでに発行が禁止されているため、鍵長には気をつけてください。鍵に設定するパスフレーズを尋かれるので、4文字以上のパスフレーズを入力してください。

秘密鍵の作成
$ openssl genrsa -des3 -out server.key.secure 2048
Generating RSA private key, 2048 bit long modulus
...........................+++
...........+++
e is 65537 (0x10001)
Enter pass phrase for server.key:
Verifying - Enter pass phrase for server.key:

秘密鍵を暗号化したため、利用時にはパスフレーズを入力してロックを解除しなくてはなりません。サーバーの起動時もそれは例外ではないため、用途によっては非常に扱いづらいものになってしまいます。そこで以下のコマンドでパスフレーズのない秘密鍵も作成しておきましょう。server.key.secureがパスフレーズつき、server.keyがパスフレーズなしの鍵ファイルになります[11]⁠。

パスフレーズなしの秘密鍵の作成
$ openssl rsa -in server.key.secure -out server.key
Enter pass phrase for server.key:
writing RSA key

Certificate Signing Request(CSR)を作成します。後述の図「CSRの作成」に示すコマンドを実行してください。その際、署名アルゴリズムにSHA-2を利用するという意味の、-sha256オプションを忘れずにつけてください。これもセキュリティ上の理由により、SHA-1のSSL証明書はすでに非推奨となっているためです[12]

コマンドを実行すると、証明書のディスティングイッシュネーム(DN、サイトの運営者に関する情報)の入力を対話的に入力させられますが、RapidSSLはドメイン認証証明書なので、コモンネーム(CN、その証明書を利用するドメインのFQDN)以外は入力しなくても問題ありません。ただしCNを間違えるとその証明書は利用できなくなってしまうため、CNは絶対に間違わないように注意してください。

そのCNですが、特別な理由がないのであれば「www.ドメイン名」で申請することをお勧めします。前述の通り、SSL証明書はCNに書かれているドメイン名と、実際にアクセスに使われているドメイン名が一致しないと警告が表示されてしまいます。ですが「example.com」「www.example.com」の両方で同じサイトにアクセスさせたい、でもそのためにSSL証明書を2枚用意するのも嫌……ということはよくありますよね。そんな問題を解決するため、Subject Alternative Name(SAN)と呼ばれる仕組みが用意されています。このフィールドに複数のドメイン名を列挙することで、同一の証明書を複数のドメインで運用できるようになるのです。そしてRapidSSLは「www.ドメイン名」というCNで証明書を申請すると、自動的にSANにネイキッドドメイン(www.example.comであればexample.com)がセットされた、wwwあり/なし両方で利用できる証明書を発行してくれます。⁠メールサーバー用の証明書だから、サブドメインはmail.じゃないと困る」というような事情があるのであれば話は別ですが、そうでないなら「www.」で申し込んでおくのがお得でしょう。

最後に出力されたserver.csrがCSRファイルになります。秘密鍵とCSRの作成についてはUbuntu Server Guideも参考になるでしょう。

CSRの作成
$ openssl req -new -sha256 -key server.key -out 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]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:www.(自分のドメイン名)
Email Address []:

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

CSRが作成できたら、いよいよ証明書の発行手続きに移りましょう。さくらのSSLのサイトにログインし、RapidSSLを申し込みます。具体的な手順はさくらのサポート情報にある通りです。RapidSSLの1年[13]を選択し、支払い方法を選んで約款を確認したら、⁠CSRの入力へ進む」をクリックします。テキストボックスに先ほど生成したserver.csrの内容をコピー&ペーストして「>」ボタンをクリックすると、コモンネームや鍵長が表示されます。問題なければ「確認画面へ進む」をクリックします。最後にもう一度申し込み内容を確認し、間違いがなければ「この内容で申し込む」をクリックしてください。

しばらくすると「SSLサーバ証明書 認証ファイルのアップロードについて」というメールが届きます。このメールの指示に従って、認証用のファイルをサーバー上の指定されたURLへアップロードしてください。ジオトラストのプログラムがこのURLにHTTPでアクセスし、正しい認証用ファイルがアップロードされていると確認することで、自分がこのドメインの所有者であることが証明できるという仕組みです。

認証が完了すると、今度は「ジオトラスト SSLサーバ証明書発行のお知らせ」というメールが届きます。さくらの会員メニューにログインし、⁠契約情報」から発行されたSSL証明書をダウンロードしてください。最初に作成したパスフレーズなしの秘密鍵と、今ダウンロードした証明書をそれぞれ/etc/ssl/{private,certs}以下に移動してください。

証明書の配置
$ sudo chmod 600 server.key
$ sudo chown root:root server.key server.crt
$ sudo mv server.key /etc/ssl/private/
$ sudo mv server.crt /etc/ssl/certs/

しかし、これだけではまだ不充分です。SSL証明書は、サーバーの公開鍵に対して認証局が署名をし、Webブラウザーはその署名を検証することで正当性を確認しています。ルート認証局の証明書はWebブラウザーにプリインストールされているため、ルート認証局が直接署名をした証明書であれば問題なく検証することができます。しかしRapidSSLは「GeoTrust Global CA(ルート認証局⁠⁠→⁠RapidSSL CA⁠⁠→⁠自分のサーバーの証明書」という3階層構造となっているため、Webブラウザーによってはサーバーの証明書からルート認証局まで辿り着くことができず、証明書が検証できないのです。

図4 証明書の階層構造
図4 証明書の階層構造

この問題は、RapidSSL CAの「中間CA証明書」をサーバーにインストールすることで解決できます。ジオトラストのサイトからRSA SHA-2 RapidSSL用の中間証明書を入手してください。/etc/ssl/certs/rapidssl-sha2-intermediate.crtのようなファイルを作成し、証明書の中身をコピー&ペーストすればよいでしょう[14]⁠。

最終的に、/etc/apache2/sites-available/default-ssl.confは以下のようになるでしょう。Apacheを再起動したらWebブラウザーでサイトにアクセスし、警告が消えたか確認してみてください。

証明書の差し替えと中間証明書の追加
SSLCertificateFile    /etc/ssl/certs/server.crt
SSLCertificateKeyFile /etc/ssl/private/server.key
SSLCertificateChainFile /etc/ssl/certs/rapidssl-intermediate.crt

余談ですが、証明書は有効期限が切れる前に新しい証明書を(更新、購入して)発行してもらい、ファイルを差し替えるという作業が発生します。また有効期限内でも、なんらかの理由によって[15]新しい証明書を再発行してもらうようなケースも存在します。

そこで筆者は証明書の実ファイルを

(ドメイン名).(発行年).{crt,key}

のような名前にしておき、これに対して

(ドメイン名).{crt,key}

というシンボリックリンクを張っています。サーバーの設定ファイルではシンボリックリンクを指定することで、証明書更新時の手間を軽減することができるからです。

PostfixとDovecotでセキュアなメールサーバーを立てる

SSLというとショッピングサイトなどでのHTTPSの利用がまず思い浮かびますが、SSLは透過的なプロトコルのため、HTTP以外の様々なプロトコルをSSL上で動作させることができます。たとえばセキュアなFTPのFTPS[16]⁠、メール送受信のためのSMTPS、POP3S、IMAPSなどです。例としてSSLに対応した一般的なメールサーバーを、PostfixとDovecotで構築してみましょう。postfixパッケージと、dovecot-imapdをインストールします。

PostfixとDovecotのインストール
$ sudo apt-get install postfix dovecot-imapd

dovecot-imapdパッケージのインストール中に、自己署名証明書を作成するかどうか尋ねられます。既にRapidSSLの証明書を購入していますので、ここではNoを選択しましょう。

postfixパッケージのインストール中には、メールサーバーのタイプと名前を尋ねられます。タイプは「Internet Site⁠⁠、名前にはドメイン名を入力してください。これはメールアドレスのドメインパート(@以降の部分)のことで、Postfixはここで設定されたドメイン宛てのメールは、自分自身が最終配送先だと判断します。

図5 Dovecotのインストール
図5 Dovecotのインストール
図6 Postfixのインストールタイプ
図6 Postfixのインストールタイプ
図7 ドメイン名の入力
図7 ドメイン名の入力

パッケージのインストールが完了した状態で、サーバー自身からsendmailを利用したメールの送信は可能になっていますが、リモートのPCからメーラーを利用したメールの送受信はまだできません。外部からのメールのリレーができるよう、SMTPサーバーの認証と、SSLを有効にしましょう。ApacheではSSLCertificateChainFileを使って中間証明書を読み込ませましたが、Postfixではサーバー証明書と中間証明書を一つに結合したファイルを利用します。

サーバー証明書と中間証明書の結合
$ sudo bash -c 'cat /etc/ssl/certs/{server.crt,rapidssl-intermediate.crt} > /etc/ssl/certs/server-withintermediate.crt'

/etc/postfix/main.cfを編集し、⁠デフォルトでsnakeoilが指定されている)smtpd_tls_cert_fileとsmtpd_tls_key_fileに、それぞれ結合した証明書と秘密鍵を指定してください。

snakeoilから正規の証明書に変更する
smtpd_tls_cert_file = /etc/ssl/certs/server-withintermediate.crt
smtpd_tls_key_file = /etc/ssl/private/server.key

さらに以下の内容を追記します。

/etc/postfix/main.cfに以下を追記
smtpd_sasl_auth_enable = yes
smtpd_sasl_type = dovecot
smtpd_sasl_path = private/auth
smtpd_sasl_security_options = noanonymous
smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
smtpd_tls_protocols = !SSLv2, !SSLv3
smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
smtp_tls_protocols = !SSLv2, !SSLv3
smtpd_tls_security_level = may
home_mailbox = Maildir/

最近ではspamメールの送信を防ぐため、外部の25番ポートへの直接接続はプロバイダによってブロックされてしまうでしょう。そのためVPS上にメールサーバーを構築しても、自宅から25番ポートでメールを送信することができないかもしれません。そこでメール送信専用のSubmissionポートを利用できるようにします。/etc/postfix/master.cfを以下のように編集してください[17]⁠。

/etc/postfix/master.cfを以下のように変更する
#submission inet n       -       -       -       -       smtpd
#  -o syslog_name=postfix/submission
#  -o smtpd_tls_security_level=encrypt
#  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
#  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject



submission inet n       -       -       -       -       smtpd
  -o syslog_name=postfix/submission
  -o smtpd_tls_security_level=encrypt
  -o smtpd_sasl_auth_enable=yes
#  -o smtpd_reject_unlisted_recipient=no
#  -o smtpd_client_restrictions=$mua_client_restrictions
#  -o smtpd_helo_restrictions=$mua_helo_restrictions
#  -o smtpd_sender_restrictions=$mua_sender_restrictions
#  -o smtpd_recipient_restrictions=
  -o smtpd_relay_restrictions=permit_sasl_authenticated,reject

次はDovecotの設定です。/etc/dovecot/conf.d/10-master.confの119行目付近にPostfix smtp-authの設定がコメントアウトされていますので、このコメントを解除し、以下のよう編集します。

認証用のソケットを設定する
# Postfix smtp-auth
#unix_listener /var/spool/postfix/private/auth {
#  mode = 0666
#}



# Postfix smtp-auth
unix_listener /var/spool/postfix/private/auth {
  mode = 0660
  user = postfix
  group = postfix
}

Postfix側でメールボックスをMaildir形式に変更したので、/etc/dovecot/conf.d/10-mail.conf内のmail_locationを変更します。

mail_locationの変更
mail_location = mbox:~/mail:INBOX=/var/mail/%u



mail_location = maildir:~/Maildir

SSL証明書の設定は/etc/dovecot/conf.d/10-ssl.confにあります。ssl_certとssl_keyを、Postfixと同様に(結合した証明書に)設定します。またSSLv2およびv3を無効にするため、ssl_protocolsを設定しています。

/etc/dovecot/conf.d/10-ssl.conf
ssl_cert = </etc/ssl/certs/server-withintermediate.crt
ssl_key = </etc/ssl/private/server.key

(……略……)

# SSL protocols to use
ssl_protocols = !SSLv2 !SSLv3

ここまでできたら、PostfixとDovecotを再起動してください。

サービスの再起動
$ sudo service dovecot restart
$ sudo service postix restart

PCのメーラーからSubmission+STARTTLSでメール送信が可能なことと、IMAPSでメールボックスを読めることを確認してみましょう。

以上、駆け足でしたが、WebサーバーとメールサーバーでのSSLの利用方法を紹介しました。小規模でもインターネット上でサービスを立ち上げているのであれば、SSL証明書の導入を検討してみてはいかがでしょうか。

コラム(SSLとポート番号の関係について)

HTTPとSSLでは交換するメッセージが異なるため、通常のHTTPサーバー相手にはSSLで接続を確立することができません。そこでSSL専用のポートを用意し、SSL接続は別ポートで待ち受けることになっています。これがHTTP(80番)とHTTPS(443番)が存在する理由です。FTPやメールも同様で、FTP(21番)に対してFTPS(990番⁠⁠、SMTP(25番)に対してSMTPS(465番)といった専用のポートが使われます。これを暗黙的SSLと呼ぶことがあります。これに対し、最初は平文で通信を開始し、その後にSTARTTLSというコマンドを発行して暗号通信にアップグレードするという手段も用意されています。これを明示的SSLと呼ぶこともあります。STARTTLSを使えばSSL専用のポートを割り当てる必要がなく、平文通信とSSL通信で同じポートを共有することができます。

このように、SSLの通信方式とポート番号には密接な関係があります。たとえば、メール送信に465番ポートを使場合は暗黙的SSLの利用が必須ですし、587番ポートを使う場合はSSLは使用しないか[18]⁠、STARTTLSのどちらかになるでしょう。今回構築したサーバーで言えば、メール受信は993番ポートを使うのでSSL、メール送信は587番(Submission)ポートを使うのでSTARTTLSにしなければならないことがわかります。

図8 SylpheedのSSL設定画面
図8 SylpheedのSSL設定画面

おすすめ記事

記事・ニュース一覧