Mac OS XでSSL/TLSサーバ

'02.12.14 ('03.1.10更新)

Mac OS XのApache+mod_sslでSSL/TLSサーバを立ち上げる方法です。WebDAVとの相性もいいですね。ただし、固定IPアドレスか独自ドメインを持ってる必要があります。ダイナミックDNSでは危うい気もしますが可能です。

残念ながらFinderからはSSLのWebDAVが使えませんが、代わりにはGoliathがお勧め。WindowsのWebフォルダはSSLに対応しています。

(基本的にAppleのUsing mod_ssl on Mac OS Xに書いてある方法を踏襲してます)

(自己責任で行ってください。インターネットへ公開するには、セキュリティの知識とスキルが必要です)


OS XのSSL環境

OS XにはApacheとOpenSSLとmod_sslがインストール済みです。追加するのはsign.shスクリプトだけ。それのみのダウンロードはできないようなので、mod_sslのソースをダウンロードして解凍し、pkg.contribディレクトリの中から取り出します。ソースにはマニュアルも含まれています (英語ですが)。

ここから: mod_ssl: The Apache Interface to OpenSSL

SSLの設定

以下はTerminal (ターミナル) で操作します。

作業ディレクトリを作る

たとえば、SSLKeyという名でデスクトップ上にディレクトリを作成します。

% mkdir ~/Desktop/SSLKey

乱数の種になるデータを作成

乱数の種になる任意のデータを含むファイルを生成します。

% cd /
% openssl md5 * > ~/Desktop/SSLKey/rand.dat

rand.datの内容はこんな感じですね。

MD5(Applications)= d41d8cd98f00b204e9800998ecf8427e
MD5(Desktop DB)= 2176bbc2d9ba1838d396ab2ce84e58e7
MD5(Desktop DF)= 88a763db07a173b3c3b515706334c753
MD5(Desktop Folder)= d41d8cd98f00b204e9800998ecf8427e
MD5(Developer)= d41d8cd98f00b204e9800998ecf8427e
MD5(Library)= d41d8cd98f00b204e9800998ecf8427e
MD5(Network)= d41d8cd98f00b204e9800998ecf8427e
- 以下略 -

サーバの鍵およびCSRを生成する

ここからはSSLKeyディレクトリに移って作業します。

% cd ~/Desktop/SSLKey

RSA (RSA公開鍵方式) の秘密鍵 (実際は秘密鍵と公開鍵のペア) を作成します。パスフレーズ (パスワード) を要求されるので適当に入れます。あとで使うので忘れないように。

% openssl genrsa -des3 -out server.key -rand rand.dat 1024
1539 semi-random bytes loaded
Generating RSA private key, 1024 bit long modulus
..................++++++
........................................................++++++
e is 65537 (0x10001)
Enter PEM pass phrase: パスフレーズ入れる
Verifying password - Enter PEM pass phrase: パスフレーズ入れる

CSR (Certificate Signing Request, 証明書署名要求) を作成します。署名のためにCA (Certificate Authority = 認証局) へ送るものです。通常、買物サイトなどでは、ベリサイン等のパブリックCAに署名を依頼することになります。

% openssl req -new -key server.key -out server.csr

「Common Name」にはサーバ名を入れます。ここが違うとSSLが有効になりません。httpd.confの「ServerName」と同じでローカルテストなら127.0.0.1を入力。

Using configuration from /System/Library/OpenSSL/openssl.cnf
Enter PEM pass phrase: パスフレーズ入れる
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]:JA
State or Province Name (full name) [Some-State]:Kanagawa
Locality Name (eg, city) []:Yokohama
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TOM neko's company
Organizational Unit Name (eg, section) []:webmaster
Common Name (eg, YOUR name) []:127.0.0.1
Email Address []:BXE02022@nifty.ne.jp

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

SSLKeyディレクトリは以下のようになってるはず。

% ls -l
total 24
-rw-r--r--  1 tomneko  staff  1609 Dec 14 22:23 rand.dat
-rw-r--r--  1 tomneko  staff   725 Dec 14 22:27 server.csr
-rw-r--r--  1 tomneko  staff   951 Dec 14 22:25 server.key

CAの鍵およびCA証明書を生成する

パブリックCAに署名を依頼するなら必要ありません。テスト等では自分がCAになります。

秘密鍵 (実際は秘密鍵と公開鍵のペア) はserver.keyのときと同じですね。ここでもパスフレーズ (パスワード) を要求されるので、適当に入れて覚えておきます。

% openssl genrsa -des3 -out ca.key -rand rand.dat 1024
1539 semi-random bytes loaded
Generating RSA private key, 1024 bit long modulus
.......++++++
..++++++
e is 65537 (0x10001)
Enter PEM pass phrase: パスフレーズ入れる
Verifying password - Enter PEM pass phrase: パスフレーズ入れる

今作った秘密鍵を使って自己署名のCA証明書 (ルート証明書) を作成します。CSRのときとは少し違います。

% openssl req -new -x509 -days 365 -key ca.key -out ca.crt

「Common Name」はここでは自分の名前を入れます。

Using configuration from /System/Library/OpenSSL/openssl.cnf
Enter PEM pass phrase: パスフレーズ入れる
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]:JA
State or Province Name (full name) [Some-State]:Kanagawa
Locality Name (eg, city) []:Yokohama
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TOM neko's company
Organizational Unit Name (eg, section) []:gatekeeper
Common Name (eg, YOUR name) []:TOM neko
Email Address []:BXE02022@nifty.ne.jp

ここまででSSLKeyディレクトリに5ファイルですね。

% ls -l
total 40
-rw-r--r--  1 tomneko  staff  1338 Dec 14 22:29 ca.crt
-rw-r--r--  1 tomneko  staff   951 Dec 14 22:27 ca.key
-rw-r--r--  1 tomneko  staff  1609 Dec 14 22:23 rand.dat
-rw-r--r--  1 tomneko  staff   725 Dec 14 22:27 server.csr
-rw-r--r--  1 tomneko  staff   951 Dec 14 22:25 server.key

CAとして署名しサーバ証明書を作る

プライベートCAとして署名しサーバ証明書を作ります。パブリックCAへ頼んだ場合は、署名済みサーバ証明書が送られてきます。

作業ディレクトリにmod_sslのソースからsign.shをコピーしてきて実行します。

% ./sign.sh server.csr
CA signing: server.csr -> server.crt:
Using configuration from ca.config
Enter PEM pass phrase: パスフレーズ入れる
Check that the request matches the signature
Signature ok
The Subjects Distinguished Name is as follows
countryName           :PRINTABLE:'JA'
stateOrProvinceName   :PRINTABLE:'Kanagawa'
localityName          :PRINTABLE:'Yokohama'
organizationName      :PRINTABLE:'TOM neko's company'
organizationalUnitName:PRINTABLE:'webmaster'
commonName            :PRINTABLE:'127.0.0.1'
emailAddress          :IA5STRING:'BXE02022@nifty.ne.jp'
Certificate is to be certified until Dec 14 13:30:48 2003 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
CA verifying: server.crt <-> CA cert
server.crt: OK

SSLKeyディレクトリはこうなってるはず。

% ls -l
total 72
-rw-r--r--  1 tomneko  staff  1338 Dec 14 22:29 ca.crt
drwxr-xr-x  3 tomneko  staff   102 Dec 14 22:30 ca.db.certs
-rw-r--r--  1 tomneko  staff   131 Dec 14 22:30 ca.db.index
-rw-r--r--  1 tomneko  staff     3 Dec 14 22:30 ca.db.serial
-rw-r--r--  1 tomneko  staff   951 Dec 14 22:27 ca.key
-rw-r--r--  1 tomneko  staff  1609 Dec 14 22:23 rand.dat
-rw-r--r--  1 tomneko  staff  2750 Dec 14 22:30 server.crt
-rw-r--r--  1 tomneko  staff   725 Dec 14 22:27 server.csr
-rw-r--r--  1 tomneko  staff   951 Dec 14 22:25 server.key
-rwxr-xr-x  1 tomneko  staff  1784 Jan  1  2001 sign.sh

/etc/httpdへ設置

/etc/httpdにssl.keyディレクトリを作り、作業ディレクトリの内容をすべてコピーします。

% sudo mkdir /etc/httpd/ssl.key
% sudo cp -r * /etc/httpd/ssl.key

安全のためには秘密鍵ファイルは複数無いほうがいいので、テストでないなら作業ディレクトリは消します。コピーでなく移動してファイルのオーナーをrootに変更しても同じですね。

パブリックCAに頼んだ場合は、送られてきたサーバ証明書のファイル名をserver.keyとしてssl.keyディレクトリに入れます。

起動時のパスフレーズ要求をなくす

server.key (サーバの秘密鍵) の暗号化を解除してパスフレーズ要求をなくすと、自動起動できるようになり、システム環境設定からも起動できるようになります。あくまでテストサーバでの便宜で、実用サーバの設定で行うのは危険です。解除したらアクセス権の変更を必ず行うこと (次項目)。

OS X 10.2は問題ないですが、10.1では、パーソナルWeb共有をオンのままシャットダウンした場合、システム起動時にhttpdを起動しようとしてパスフレーズ待ちで止まってしまう (未確認)。そんなときにはcommand+Vキーを押したままverboseモードで立ち上げればいいらしいのですが、上記のパスフレーズ要求をなくせば止まることもなくなります。

% cd /etc/httpd/ssl.key
% sudo cp server.key server.key.original
% sudo openssl rsa -in server.key.original -out server.key
read RSA key
Enter PEM pass phrase: パスフレーズ入れる
writing RSA key

アクセス権の変更

安全のため、特にパスフレーズを解除した場合は、一連のファイルへのアクセスはrootのみに制限します。

% cd /etc/httpd/ssl.key
% sudo chmod -R 400 server.* ca.* rand.dat

httpd.confの設定

/etc/httpd/httpd.confを編集します。最初にファイルのバックアップ。

% cd /etc/httpd
% sudo cp httpd.conf httpd.conf.backup

httpd.confファイルを編集。GUIのmiでもできますね。

  1. 下記2つを探して頭の#を消して読み込まれるようにします。

    #LoadModule ssl_module         libexec/httpd/libssl.so
    
    #AddModule mod_ssl.c
  2. #を付けて「Port 80」をコメントアウトします。

    #Port 80

    そのわかりこちらを追加。<IfModule>で囲うならLoadModuleより下に書かないと読み込まれないので注意。

    <IfModule mod_ssl.c>
        Listen 443
        Listen 80
    </IfModule>
  3. 「ServerName」はローカルテストなら127.0.0.1

    ServerName 127.0.0.1
  4. httpd.confの最後に以下をまるごと追加。この設定ではhttpもhttpsも同じディレクトリで使えます。127.0.0.1はテスト用ですから、実際に使うサーバ名に置き換えます。

    下記をコピーして使う場合、Unicodeの問題で「\」が全角の「¥」に化けることがあります。Syntax errorが出るときは怪しいです。
    <IfModule mod_ssl.c>
        # 証明書ダウンロード用のMIMEタイプ
        AddType application/x-x509-ca-cert .crt
        AddType application/x-pkcs7-crl .crl
        # SSLの基本設定
        # SSLProtocol all -SSLv3
        SSLPassPhraseDialog builtin
        SSLSessionCache dbm:/var/run/ssl_scache
        SSLSessionCacheTimeout 300
        SSLMutex file:/var/run/ssl_mutex
        SSLRandomSeed startup builtin
        SSLLog /var/log/httpd/ssl_engine_log 
        SSLLogLevel info
        #
        # バーチャルホストでSSLとそうでないアクセスを分ける
        #
        <VirtualHost 127.0.0.1:80>
            # こちらは通常設定
            DocumentRoot /Library/WebServer/Documents
            ServerName 127.0.0.1
            # ServerAdmin メールアドレス
            # SSLオフ
            SSLEngine off
        </VirtualHost>
        <VirtualHost 127.0.0.1:443>
            # バーチャルホストの基本設定
            DocumentRoot /Library/WebServer/Documents
            # ServerNameはCSR作成時に書いたのと同じ名前にすること
            ServerName 127.0.0.1
            # ServerAdmin メールアドレス
            ErrorLog /var/log/httpd/error_log
            TransferLog /var/log/httpd/access_log
            # SSLを有効にする
            SSLEngine on
            # EXPORT56はIE用に無効になっている
            SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
            # サーバ証明書と秘密鍵のパス
            SSLCertificateFile /etc/httpd/ssl.key/server.crt
            SSLCertificateKeyFile /etc/httpd/ssl.key/server.key
            # CGI等の環境変数にSSL標準のセットを追加
            <Files ~ "\.(cgi|shtml|php)$">
                SSLOptions +StdEnvVars
            </Files>
            <Directory /Library/WebServer/CGI-Executables>
                SSLOptions +StdEnvVars
            </Directory>
            # SSL接続がうまくないブラウザ用
            SetEnvIf User-Agent ".*MSIE.*" \
            nokeepalive ssl-unclean-shutdown \
            downgrade-1.0 force-response-1.0
            # カスタムSSLログファイル
            # SSLのコンパクトなエラーでないログファイルなら
            CustomLog /var/log/httpd/ssl_request_log \
            "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
        </VirtualHost>
    </IfModule>

「SSLProtocol all -SSLv3」は、たぶんいらないです。IE5.0のWebフォルダでもMac版IE 5.2.2でも無くても問題ありませんでした。下記のWin版IEの問題で必要になるかもしれませんが。記述するとSSLv3の128bit暗号が使えなくなるので、安全度はかなり下がってしまいます。

mod_ssl: F.A.Q. (MS IEの問題)

以上で設定はおしまいです。

Apacheの起動

一旦止めて、

% sudo apachectl stop

以下のどちらかで起動。パスフレーズ要求を外してあればシステム環境設定からも起動できます。

% sudo httpd -D SSL

% sudo apachectl start
server_setup: entered
folder_setup: entered
server_setup: entered
Processing config directory: /private/etc/httpd/users
 Processing config file: /private/etc/httpd/users/tomneko.conf
Apache/1.3.26 mod_ssl/2.8.10 (Pass Phrase Dialog)
Some of your private key files are encrypted for security reasons.
In order to read them you have to provide us with the pass phrases.

Server 127.0.0.1:443 (RSA)
Enter pass phrase: パスフレーズ入れる

Ok: Pass Phrase Dialog successful.

参考文献

謝辞

お世話になりました。ありがとうございます。