Network」カテゴリーアーカイブ

サーバの引越し(1)

固定IPを維持するのが経済的に負担になってきたので、レンタルサーバに引越しすることにした。

この文章を書いている時点で、引越し作業の大半は終わっているわけだが、今後同様の作業が必要になった場合、もしくは同様の作業を行うとしている人に、何らかの参考になるかもしれないので、これから数回に分けて、引越しにともなう作業とかをメモしておこうと思う。

ちなみに作業順に並べると、おおむね下のようになる。記事をこの順で書くかどうかは未定。

  1. メールサーバ。IMAPサーバの確保。既存メールの移動。
  2. Webサーバの引越し。レンタルサーバへ。
  3. DNSサーバ。プライマリをどこへ置くか。
  4. 自宅サーバ(動的IP割り当てになる予定)へのアクセス確保。Dynamic DNS。

OCSP

前回からの続きで、OCSP を試したメモ。

OpenSSL 1.0.0a の ocsp では、なぜか ::1 にしかバインドされないので、Apache のリバースプロキシを使って IPv4 アドレスにきたリクエストを ocsp に転送するようにした。

FireFox 3.6.3 の場合

OCSP によるサーバ証明書の検証は最初に行われる。オレオレ認証局による証明書の場合、最初に認証局が信頼できないというエラーが出る。そこで、証明書を受け入れるように指示すると、それ以上の検証は行われない。OCSPによる検証も行われない。

したがって、OCSPによる検証を有効にするには、サーバ証明書が信頼された認証局が発行したものでなければならない。つまり、オレオレ認証局の場合、あらかじめ認証局証明書をインストールしておく必要がある。

安全な接続ができませんでした

www.uconst.org への接続中にエラーが発生しました。
Peer’s Certificate has been revoked.
(エラーコード: sec_error_revoked_certificate)

* 受信したデータの真正性を検証できなかったため、このページは表示できませんでした。
* この問題を Web サイトの管理者に連絡してください。あるいは [ヘルプ] メニューの [不具合のあるサイトを報告] でこのサイトについて報告してください。

InternetExplorer 8 の場合

認証局証明書をインストールしても検証している気配なし。どこかでやり方を間違えているのかも。

結果まとめ

  • OpenSSL 1.0.0a を使えば OCSP による失効リストの確認は可能。
  • ただし、ポートを転送する必要がある。
  • 間違ったリクエストが届くと ocsp が終了するので、OpenSSL の ocsp を OCSP サーバとして使うのは実用的ではない
  • FireFox で OCSP が機能するためには、あらかじめ認証局が信頼されている必要がある。オレオレ認証局では機能しない。

Apache2.2 の SSL

Apache を 2.0 系列から 2.2 系列へ移行した。デフォルトの http.conf が機能別に分割されて、SSL 関連は httpd-ssl.conf で設定されるようになっている。以前の形式でも一部を修正すれば動くのだが、今後のメンテナンスを考慮して、新しい分割された記述に合わせるようにした。

デフォルトの http.conf では SSL 関連の設定を行う httpd-ssl.conf がコメントアウトされているので、コメントを外して有効にする。

# Secure (SSL/TLS) connections
Include etc/httpd/httpd-ssl.conf

http-ssl.conf で、サーバ証明書を SSLCertificate に、鍵を SSLCeritificateKeyFile に設定する。証明書の認証局が中間認証局であったりオレオレ認証局である場合には、認証局の証明書を SSLCertificateChainFile に設定する。

(略)
#   Server Certificate:
#   Point SSLCertificateFile at a PEM encoded certificate.  If
#   the certificate is encrypted, then you will be prompted for a
#   pass phrase.  Note that a kill -HUP will prompt again.  Keep
#   in mind that if you have both an RSA and a DSA certificate you
#   can configure both in parallel (to also allow the use of DSA
#   ciphers, etc.)
SSLCertificateFile "/usr/pkg/etc/httpd/server.crt"
#SSLCertificateFile "/usr/pkg/etc/httpd/server-dsa.crt"
#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
SSLCertificateKeyFile "/usr/pkg/etc/httpd/server.key"
#SSLCertificateKeyFile "/usr/pkg/etc/httpd/server-dsa.key"
#   Server Certificate Chain:
#   Point SSLCertificateChainFile at a file containing the
#   concatenation of PEM encoded CA certificates which form the
#   certificate chain for the server certificate. Alternatively
#   the referenced file can be the same as SSLCertificateFile
#   when the CA certificates are directly appended to the server
#   certificate for convinience.
SSLCertificateChainFile "/usr/pkg/etc/httpd/server-ca.crt"
(略)

設定が終わったら普通に再起動すると SSL が有効になる。以前と異なり startssl というものはない。

今回行った SSL 設定のディレクティブのまとめ。紛らわしいものに SSLCACertificateFile というものがある。こちらはクライアント認証を行うときに設定するもの。誤解して設定しても動くところがまた紛らわしい。

SSLCertificateFile
サーバ証明書のファイル名。
SSLCertificateKeyFile
サーバ秘密鍵のファイル名。
SSLCertificateChainFile
サーバ証明書を発行した中間認証局 (CA) の証明書のファイル名。
SSLCACertificateFile
クライアント認証を行う場合の、クライアント証明書を発行した CA の証明書のファイル名。誤解を恐れずにいえば、ブラウザにインストールされているルート証明書のようなもの。サーバ証明書を発行した中間認証局の証明書をここに置いても機能するが、中間証明書は SSLCertificateChainFile に置くのが正しい。Web で見られる事例も混同しているのが多いようだ。歴史的な経緯によるのかな?

自己 CA の証明書

自己 CA の証明書の形式に不具合があったので作りなおした。不具合とは、X509v3 Basic Constraints の値が CA:FALSE になっていたこと。この状態だと、自己 CA が認証局 (CA) として扱われない。Firefox などの証明書ビューアでは、Extensions – Certificate Basic Constraints の値が “Is a Certificate Authority” や ”Is not a Certificate Authority” などと表示される。キーチェインが正しく取り扱われるためには、もちろん “Is a Certificate Authority” である必要がある。

慌てて作業したので、CA の秘密鍵を上書きして消してしまった。バックアップから鍵を書き戻してやり直し。

まず、既存の鍵を指定して新しいリクエストを作成する。

$ openssl req -new -key private/cakey.pem -out careq.pem

次に、自分自身の鍵で署名する。

$ openssl req -x509 -key private/cakey.pem -in careq.pem -out cacert.pem -days 3650
(2010.6.10追記)

次のように -new と -x509 を同時に指定すれば、一回で自己署名した CA の証明書ができる。

$ openssl req -new -x509 -key private/cakey.pem -out cacert.pem -days 3650
(2010.6.10追記 ここまで)

ちなみに openssl ca -selfsign で作成した自己証明書では CA:TRUE にならなかった。openssl.cnf の中の全ての basicConstrains に CA:TRUE を指定してもダメ。うまくいった方が正しいのだろうけど、どう考えたらよいのか。

CA:TRUE であることを確認する。

$ openssl x509 -in cacert.pem -noout -text
Certificate:
Data:
Version: 3 (0x2)
Serial Number:
(略)
X509v3 extensions:
(略)
X509v3 Basic Constraints:
CA:TRUE
(略)

サーバにインストールしていた CA の証明書の部分を置き換えて完了。CA の秘密鍵は変更ないので、サーバ証明書は変更なし。

これで自己 CA の証明書が正しい形式になった。Firefox で「発行者の証明書が信頼されていないためこの証明書は信頼されません。」と正しい警告が表示される。

接続の安全性を確認できません

… に安全に接続するように求められましたが、接続の安全性が確認できませんでした。

安全に接続する場合は通常、あなたが適切な相手と通信することを確認できるように、信頼できる証明書を提供してきます。しかし、このサイトの証明書は信頼性を検証できません。

(略)

技術的詳細を表示

… は不正なセキュリティ証明書を使用しています。

発行者の証明書が信頼されていないためこの証明書は信頼されません。

(エラーコード: sec_error_untrusted_issuer)

(略)

SSL証明書の更新

いつものように Thunderbird でメールをチェックしようとしたら、SSL 証明書の有効期限が切れているとの警告が出た。メールサーバには imapd-uw を使って SSL 経由で接続している。自分で運用して自分でしか使っていないサーバなので、使っている証明書は、認証局 (CA) も自前の、いわゆるオレオレ証明書というものだ。

imapd で使う証明書を自己証明書にしても良いのだが、認証局の運用の仕組みを知りたかったので、自前サーバ上で OpenSSL による認証局を立ち上げ、imapd で使う証明書に署名をする形にしている。認証局の証明書は自己証明書で有効期限は10年とし、imapd の証明書の有効期限は 1 年としている。

自己認証局で、署名をする機会などそうそうあるものではなく、openssl を実行することは実際のところ、年に1度になっている。当然のように前にやったことなど忘れてしまっているので、今回もそうであるが、期限が切れてから慌てることになる。とはいえ、期限を短くすれば面倒なだけであるし、期限を3年とかにしたら、思い出すのが不可能になってしまうかもしれないので、1年に1度の混乱は我慢することにしている。

作業のメモは当然作るわけだが、理解しないまま作業した結果がたまたまうまくいったとか (しかも試行錯誤をしたうえで)、当時は普通だったけど今では時代遅れになっているとか、実行環境が変わって昔のやり方ではできないとか、以前はなかった要因が今回は増えているとかあって、作業の見直しはいつでも必要になる。

完全に理解した上で正しい記録を残すのが望ましいが、そうもいってられないので、せめて、後からの検証に耐えうるように、実際の作業の内容と結果、確認したことと、未確認なことが判別できるような記述を心がけたいと思う。

今回の証明書の更新では、有効期限が切れた証明書の失効手続きを行う、という作業が必要になった。更新は今回が初めてではないはずだが、1年前の作業を調べてみると、その時は CA を作り直している。何か思うところがあって、やり直したのだろうが、そこのところはメモしていなかった。我ながら困ったものである。たぶんそれまでの CA の運営方法が間違っていると判断したのだろう。今回は、CA はそのままで、imapd 用の証明書の更新のみを行うことにする。

はじめに証明書の失効手続きを行う。期限切れの証明書と、新たに更新する証明書は、特に理由がない限りその識別名 (DN) は同じにすると思う。私もそうする。ところが、 CA で署名する際に、DN が同じだと署名に失敗してしまう。有効な証明書は DN 1つに付き1つしか存在できないらしい。当然といえば当然かもしれない。ただ、期限切れの証明書と失効した証明書は別物というのは注意が必要なのかもしれない。また、OpenSSL の署名時のエラーメッセージも適切でないと思う。’failed to update database’ では失敗の原因を誤解するではないか。

証明書の失効手続きが初めての時は、crlnumber というファイルがおそらく存在しない。そのときは、あらかじめ次のように crlnumber というファイルを作成しておかなければならない。このファイル名は openssl.conf の crlnumber で定義されていて、サンプルでは $dir/crlnumber となっている。たぶん、ファイルの中身は失効した証明書の個数を表しているのだろう。

$ echo "00" > crlnumber

crlnumber ができたら、証明書の失効手続きをおこなう。失効手続きは CA.sh でサポートされていないようなので、openssl コマンドを直接実行しなければならない。また、失効させる証明書の現物が必要である。通常の環境であれば index.txt に CA が署名した DN とシリアル番号の一覧がある (行頭が V となっているのが現在有効な証明書) ので、ここで失効させたいシリアル番号を確認しておく。例えばシリアル番号 01 の証明書を失効させたい場合、newcerts/01.pem というように過去に署名した証明書の控えが保存されているはずなので、このファイルを指定して次のように失効手続きを行う。

$ openssl ca -revoke newcerts/01.pem
Using configuration from /etc/openssl/openssl.cnf
Enter pass phrase for /home/moriko/Config/CA/private/cakey.pem:
Revoking Certificate 01.
Data Base Updated

失効すると、index.txt の該当箇所には R (Revoked) の印がつけられる(他の情報も記録される)。crlnumber の中の数字がインクリメントされる。

また、次のようにして失効した証明書のリストを更新する。imap-uw で失効した証明書を調べてくれるのかどうかは知らない。

$ openssl ca -gencrl -out crl.pem

これで新しい証明書を作成する準備ができたので、CA.sh を使って新しいリクエストを作成する。この手順はよく知られている。ただし、CA.sh を使った場合、作成される鍵 (newkey.pem) にはパスフレーズが要求されてしまう。これが都合が悪い場合は後述するように、後からパスフレーズを不要にした鍵に変換すれば良い。CA.pl だと -newreq-nodes オプションで、はじめからパスフレーズ不要の鍵とすることができる、らしい。

$ ./CA.sh -newreq
Generating a 1024 bit RSA private key
(略)
writing new private key to 'newkey.pem'
Enter PEM pass phrase:(パスフレーズの入力)
Verifying - Enter PEM pass phrase:(パスフレーズの入力)
(略)

OpenSSH で SOCKS サーバ(NetBSD)

前回は Thunderbird が Gmail に接続するためにファイアウォールを超えるための要件について書いた。

ファイアウォールを越えるためには SOCKS サーバをたてなければならない(もちろん SOCKS サーバ自身は外部へ 993 のポートが空いている必要がある)。が、調べてみると、ssh(1) が -D オプションで SOCKS サーバになるらしいということがわかったので、(追加のアプリケーションのインストールが不要な)NetBSD 5.0.1 付属の ssh で SOCKS サーバをたててみることにした。

$ ssh -f -N -D :1080 localhost

-D オプションの引数の 1080 は SOCKS サーバを動かすポート番号で、任意のポートが指定できるが、ここでは /etc/services で ‘socks 1080/tcp’ となっていたのに合わせてみた。ポート番号の前の ‘:’ は、待ち受けポートを ‘*:1080’ にするのに必要。単に ‘-D 1080’ としたら待ち受けポートが ‘127.0.0.1:1080’ になってしまい、外部のクライアントから接続できない。

また、事前にパスフレーズなしのキーペアを作り、公開鍵を authorized_keys に登録するなど、ssh の実行の際に入力が不要となるよう準備をしておいた。

で、Thunderbird から接続してみると、一見うまく接続できているようだが、データの転送量?が多くなると、下記のエラーが ssh を実行している端末に表示されて、先に進まなくなってしまう。

channel X: rcvd too much data XXXX, win XXX

ネットで検索してみると、ssh のバージョンによってはこのあたりにバグがあるらしいということがわかった。どのバージョンが大丈夫だとかの詳細は不明だったので、とりあえず pkgsrc から OpenSSH-5.2 をインストールして試してみると、sshd は NetBSD 5.0.1 のもの (OpenSSH_5.0) で問題なく、ssh のほうだけ pkgsrc の方 (OpenSSH_5.2.p1) を使えばよいことがわかった。

動作が確認できたので、次は、サーバを起動したときに ssh が実行されるようにする。

何の疑いもなく /etc/rc.local の中に記述したら、なんと sshd が実行されるよりも先に ssh が実行されてしまった(そしてもちろん失敗した)。

今の NetBSD では /etc/rc.local は /etc/rc.d/local から呼び出されるようになっているのだが、rcorder(8) で確認してみると、ssh などの daemon 群が /etc/rc.d/local の後になっている。

ううむ、rc.local は最後に実行されるようになってないといろいろと具合が悪いような気もするのだが……。

/etc/rc.d/local を書き換えて実行順が最後になるようにすることも考えたが、NetBSD の UPDATE 時に忘れてハマることを考えて、以下の rc.d スクリプトを書き起こすことにした。

/etc/rc.d/ssh_socks

#!/bin/sh
#
# $Id$
#
# PROVIDE: ssh_socks
# REQUIRE: sshd
$_rc_subr_loaded . /etc/rc.subr
name="ssh_socks"
rcvar=$name
command="/usr/pkg/bin/ssh"
pidfile="/var/run/${name}.pid"
identityfile="/var/chroot/sshd/.ssh/id_rsa"
start_postcmd="ssh_socks_postcmd"
command_args="-f -N -i ${identityfile} -D :1080 localhost"
required_files="${identityfile}"
ssh_socks_user="sshd"
ssh_socks_postcmd()
{
ps axw | grep "${command}" | awk '!/grep/{print $1}' > ${pidfile}
}
load_rc_config $name
run_rc_command "$1"

いまのところは順調に動いている。

ファイアウォールの内側の Thunderbird

Thunderbird で Gmail に IMAP で接続する人は多いだろう。この場合、IMAP over SSL(ポート番号 993)で通信が行われる。
ここで Thunderbird がファイアウオールの内側にいて、993 が外部に対して空いていない場合、プロキシを介して imap サーバに接続する必要がある。
Thunderbird 3.0.1 (おそらくそれ以前のバージョンでも)のオプションで、「インターネット接続」というのがあるが、ここに、「HTTP プロキシ」、「SSL プロキシ」、「SOCKSホスト」の3つの設定項目がある。ここで「IMAP over SSL だから SSL プロキシを設定すればいいんじゃないの?」と早がってんすると(私のように)ハマることになる。
SSL プロキシを設定しても Thunderbird の IMAP over SSL の接続には使用されない。無視されるだけである。この設定は https のために使用される設定であって、IMAP over SSL のためではない。IMAP over SSL がファイアウォールを越えるためには SOCKS サーバを用意しなければならない。
世の中のどこかに IMAP over SSL に対応した SSL プロキシなるものがあるのではないかと探し回り、時間を無駄にしてしまった。実際は、そんな汎用 SSL プロキシがあったとしても、Thunderbird で使えるようになるわけではなかったのだ。正直、Thunderbird のあの設定画面のレイアウトは不親切にも程があると思う。
ネットでずいぶん検索してわかったことは、世界中に私と同様の無駄足を踏まされた人がたくさんいるということだった。Squid ではできない、という回答はネットから得られたが、そもそも SSL プロキシは使ってくれない、という回答は得られなかったので、後続の人のためにここに書いておく(日本語だけど)。
次は OpenSSH を使ってSOCKS サーバをたてる話を書く予定。