読者です 読者をやめる 読者になる 読者になる

無題の備忘録

よく知らない技術や試したこと記録するブログです。情報セキュリティ、ネットワーク、Linux関係で消化したことを記録します。すぐ詳細を忘れるので、優れた外部記憶装置にしたいです。

opensslコマンドで認証局(CA)を構築してサーバ証明書を発行する

セキュリティ

opensslコマンドとは

OpenSSLはSecure Sockets Layer (SSL v2/v3) and Transport Layer Security (TLS v1) のプロトコルとそれに関係する標準的暗号を実装したツールキットです。 OpenSSLの暗号ライブラリの様々な暗号機能をシェルから使うためのコマンドラインです。 次のような機能があります。

  • プライベート鍵と公開鍵とそのパラメータの作成と管理
  • 公開鍵の暗号化操作
  • X.509証明書、認証局(CA)に提出する証明書発行要求ファイル(CSR)、無効となった証明書のリスト(CRL)の作成
  • メッセージダイジェストの計算
  • 暗号化と暗号文の復号
  • SSL/TLSクライアントとサーバのテスト
  • S/MIMEサインと暗号化メールの取り扱い
  • タイムスタンプの要求、生成と検証

今回は認証局(CA)を構築して、サーバ証明書を発行してみます。

準備

opensslをインストールします。

$ sudo apt-get install openssl

apacheをインストールします。

$ sudo apt-get install apache2

SSL設定の有効化します。

$ sudo a2enmod ssl
$ sudo a2ensite default-ssl
$ sudo /etc/init.d/apache2 restart

認証局(CA)の事前設定

認証局(CA)用のディレクトリを作成して、そのディレクトリを設定ファイルに記述します。 認証局に必要な情報をここに配置します。

$ sudo mkdir /etc/ssl/myCA
$ vi /etc/ssl/openssl.conf
dir = /etc/ssl/myCA

作成したmyCA配下に次のディレクトリを作成します。

$ sudo mkdir -p /etc/ssl/myCA/certs
$ sudo mkdir -p /etc/ssl/myCA/private
$ sudo mkdir -p /etc/ssl/myCA/crl
$ sudo mkdir -p /etc/ssl/myCA/newcerts

privaeteディレクトリには秘密鍵が置かれるのでアクセス制限をかけます。

$ sudo chmod 700 /etc/ssl/myCA/private

認証局が発行する証明書にシリアル番号が付与されますが、それに使われる番号が保存されます。最初に01で初期化します。

# sudo echo “01” > /etc/ssl/myCA/serial

証明書のデータベースを初期化します。newcertsディレクトリ内に保管される証明書の番号(nn)と識別名DN(Distinguished Name)との対応表らしいです。

$ sudo tocuh /etc/ssl/myCA/index.txt

自己署名証明書/秘密鍵生成

認証局自己署名証明書秘密鍵を生成します。-daysは有効期限です。365日を設定しています。

$ cd /etc/ssl/myCA
$ sudo openssl req -new -x509 -newkey rsa:2048 -out cacert.pem -keyout private/cakey.pem -days 365

パスフレーズを2度聞かれます。

Enter PEM pass phrase: stacktrace

その後に証明書情報を聞かれます。

Country Name (2 letter code) [AU]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) []:City1
Organization Name (eg, company) []:Company1
Organizational Unit Name (eg, section) []:Section1
Common Name (eg, YOUR name) []:myCA
Email Address []: (Enter)

証明書情報の入力が終わると以下のファイルがされます。

念の為、自己署名証明書秘密鍵のアクセスを次のように制限しておきます。

$ chown root:root /etc/ssl/myCA/private/cakey.pem
$ chmod 600 /etc/ssl/myCA/private/cakey.pem

証明書が正しくできたかを確かめるには次のコマンドを実行することで、証明書情報で入力した値を確認することができます。

$ openssl x509 -in /etc/ssl/myCA/cacert.pem -text

認証局のポリシー[ policy_match ]のorganizationNameをmatchからoptionalに変更します。 これで証明書情報の"Organization Name"が認証局と一致していなくても署名できるようになります。

$ sudo vi /etc/ssl/openssl.cnf
organizationName        = match
↓
organizationName        = optional

サーバ認証とサーバ証明書

サーバ証明書とは

サーバを識別するための証明書です。サーバが証明書の所有者になります。 サーバ証明書は、Webサイトの所有者の情報やSSL/TLS通信における暗号化に必要な公開鍵などを含みます。 これらの情報は、先ほど作成した認証局によって署名をします。 一般的にはWebサーバとWebブラウザとのHTTPS通信において、Webサーバは証明書に記された所有者の公開鍵であることを保証します。 つまり、サーバを認証していることになります。

  • WebサーバでCSR(Certificate Signing Request)証明書署名要求を作成する
  • 認証局で署名する
  • Webサーバに秘密鍵を組み込む

WebサーバでCSRを作成する

一般的にはこのWebサーバは認証局を構築したサーバとは別です。 準備と同じ手順で別のマシンにapache2のWebサーバを用意して試します。

まず、Webアプリケーション用のディレクトリを作成して、そこに鍵などを作成します。

$ sudo mkdir /etc/ssl/www.app.com

次のコマンドで鍵ペアとCSRファイルを作成します。

$ cd /etc/ssl/www.app.com
$ sudo openssl req -x509 -new -keyout appkey.pem -out appcsr.pem

パスフレーズを聞かれるので入力します。

Enter PEM pass phrase: application

次は、証明書情報を入力します。 Common Nameはサーバ証明書を導入してHTTPS通信を行うサイトのURLのことです。 Common NameはWebブラウザにアドレスとして指定するURLと一致している必要があります。 実験なので、ここではマシンのIPアドレスを指定します。

Country Name (2 letter code) [AU]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) []:City2
Organization Name (eg, company) []:Company2
Organizational Unit Name (eg, section) []:Section2
Common Name (eg, YOUR name) []:192.168.0.1
Email Address []: (Enter)
A challenge password: appcsr
An optional company name []:  (Enter)

作成が終わると以下のファイルができあがります。

  • /etc/ssl/www.app.com/appcsr.pem : 証明書署名要求(CSR)です。認証局で使います。
  • /etc/ssl/www.app.com/appkey.pem : サーバ秘密鍵です。大切に保管します。

認証局での署名

ここのでの操作はWebサーバのマシンではなく、認証局を構築したマシンで行います。 上記で作成した証明書署名要求(CSR)を認証局のマシンにコピーして、認証局で次のコマンドを実施し署名します。

$sudo openssl ca -in appcsr.pem -out appcert.pem 

認証局パスフレーズが聞かれるので入力します。

Enter PEM pass phrase: stacktrace

署名するかどうか聞かれるので、"y"を入力します。

Certificate is to be certified until Dec 11 00:38:12 2016 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 Update

次のファイルができます。

証明書が正しく出来たかを確認するには、以下のコマンドで確認できます。 入力した証明書情報が表示されれば正しくサーバ証明書ができています。

$ openssl x509 -in appcert.pem -text

サーバ証明書秘密鍵をWebサーバに組み込む

認証局で署名したサーバ証明書(appcert.pem)をWebサーバに組み込みます。 認証局で作成した証明書(appcert.pem)をWebサーバの/etc/ssl/www.app.com/コピーします。 そして、apache2のsslの設定ファイルで、証明書ファイルと秘密鍵をこれまでで作成したファイルに変更します。

$ sudo vi /etc/apache2/sites-available/default-ssl.conf

SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
↓
SSLCertificateFile /etc/ssl/www.app.com/appcert.pem

SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
↓
SSLCertificateKeyFile /etc/ssl/www.app.com/appkey.pem

設定ファイルの変更が終わったら、apache2を再起動します。

$ sudo /etc/init.d/apache2 restart

これでWebサーバに証明書の設定ができました。

Webブラウザに証明書を組み込む

Webブラウザの方に証明書をインストールします。 このとき、サーバ証明書をインストールすることもできたはずですが、証明書チェーンの意味がないので認証局の証明書をインストールします。 認証局の証明書をインストールすることで、インストールした認証局が署名したサーバ証明書を設定しているサーバであることを確認でき、サーバとの通信が暗号化されます。 その前に、Webブラウザ用に証明書をpem形式から、der形式に変換します。 pem形式はテキストでder形式はバイナリです。 認証局サーバで次のコマンドを実行してcacert.derを生成します。

$ sudo openssl x509 -inform PEM -outform DER -in /etc/ssl/myCA/cacert.pem -out /etc/ssl/myCA/cacert.der

WebブラウザとWebサーバの接続

cacert.derをWebブザウザにインストールする前は、httpsでWebサーバに接続すると下記のメッセージが表示されます。

"この接続ではプライバシーが保護されません"

cacert.derをWebブラウザにインストールした後は、httpsでアクセスできるようになります。 また、Webブラウザでサーバ証明書の情報を表示できると思います。 Chromeで証明書情報を確認した場合、次のような内容が表示されます。 証明書を作成した時に入力した値が表示されています。

発行先
一般名(CN)   192.168.0.1
組織(O)   Company2
組織単位(OU)    Section2
シリアル番号  01

発行元
一般名(CN)   myCA
組織(O)   Company1
組織単位(OU)    Section1

例えば、Wireshakのようなパケットキャプチャーのツールでパケットを見るとTLSプロトコルで通信していることがわかります。