openssl でオレオレ認証局で証明書を発行する
ubuntuバージョン
$ cat /etc/os-release | grep PRETTY_NAME
PRETTY_NAME="Ubuntu 18.04.4 LTS"
openssl バージョン
$ openssl version
OpenSSL 1.1.1 11 Sep 2018
概要
2020/05/31
ちょー簡単に証明書を発行してくれる mkcert という開発環境用の証明書発行ツールが存在しています。
https://github.com/FiloSottile/mkcert
何らかの理由でLetsEncryptなど無料の証明書が使えない場合とにかく開発環境でSSLを使いたい。
ルート認証局を作成し、ルートCA証明書(ルート認証局の証明書)とサーバ証明書を発行する。
ルートCA証明書は、クライアントのブラウザにインポートする。
サーバ証明書は、Webサーバにインポートする。
ルート認証局から発行したルートCA証明書とサーバ証明書を使用することでクライアント(ブラウザ)とサーバ(WEBサーバ)でSSL通信ができる。
シェルを作った。けど mkcert の方を使った方がいいと思う。
https://github.com/yutakachi/createCertificates
ルート認証局(オレオレ認証局)を作成する
ルート証明局用のディレクトリを作成する
$ cd ~
$ mkdir -p ./rootCA/private
$ mkdir -p ./rootCA/newcerts
$ mkdir -p ./rootCA/testDomain.jp
$ mkdir -p ./rootCA/testDomain.jp/certs
$ mkdir -p ./rootCA/testDomain.jp/private
秘密鍵を作る
$ openssl genrsa -aes256 -out ./rootCA/private/cakey.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...................+++++
..........................................................+++++
e is 65537 (0x010001)
Enter pass phrase for ./rootCA/private/cakey.pem:任意のパスフレーズ
Verifying - Enter pass phrase for ./rootCA/private/cakey.pem:確認用のパスフレーズ
CSRを作る
秘密鍵に対する公開鍵を作るための情報を作成する
(Can't load /home/a_user/.rnd into RNG のエラーがでたら。。後述)
$ openssl req -new -key ./rootCA/private/cakey.pem -subj "/C=JP/ST=Tokyo/L=edogawa/O=testCompany/OU=software/CN=my_rootCA/" -out ./rootCA/cacert.csr
Enter pass phrase for ./rootCA/private/cakey.pem:秘密鍵のパスフレーズ
-subj オプションの補足
-subj無しの場合、対話形式で入力を求められる
/C Country Name(2 letter code)
/ST State or Province Name (full name)
/L Locality Name(eg, company)
/O Organization Name (eg, company)
/OU Organization Unit Name (eg, section)
/CN Common Name (eg, your name or your server's hostname)
※ /CN はサーバ証明書の作成時にはドメイン名を指定する必要がある。
https://ドメイン名/xxx 一致しないとSSLのエラーとなる。
以下、注意すべきオプション。
/O Organization (認証局の組織名) 会社名とか。。 例) testCompany
ルートCA証明書をブラウザにインポートした後、確認するのでわかりやすい名前がいい。
/CN Common Name (コモンネーム) ルート認証局の名前 例) my_rootCA
ルートCA証明書用なのでmy_rootCA としているが、サーバ証明書を作成(後述)する際は、ドメイン名にする。
Can't load /home/a_user/.rnd into RNG のエラーがでたら。。
Can't load /home/a_user/.rnd into RNG
140491206660544:error:2406F079:random number generator:RAND_load_file:Cannot open file:../crypto/rand/randfile.c:88:Filename=/home/a_user/.rnd
以下の対応をする。
$ sudo vim /etc/ssl/openssl.cnf
コメントアウトする
RANDFILE = $ENV::HOME/.rnd
↓
# RANDFILE = $ENV::HOME/.rnd
ルートCA証明書(自己証明書)認証局自信が自分を証明する
自己署名(openssl x509)することで証明する。
$ openssl x509 -days 825 -in ./rootCA/cacert.csr -req -signkey ./rootCA/private/cakey.pem -out ./rootCA/cacert.pem
Signature ok
subject=C = JP, ST = Tokyo, L = edogawa, O = testCompany, OU = software, CN = my_rootCA
Getting Private key
Enter pass phrase for ./rootCA/private/cakey.pem:秘密鍵のパスフレーズ
補足 -days 有効期限の最長(上限)で 825日。
認証局に必要なファイル
証明書発行を記録していくファイルを作成する
$ touch ./rootCA/index.txt
$ touch ./rootCA/index.txt.attr
$ echo 00 > ./rootCA/serial
ここまででルート証明局は完了。
ブラウザにルートCA証明書をインポート
ルートCA証明書(./rootCA/cacert.pem)をインポートすることで、my_rootCAで発行されたサーバ証明書は有効なものになる。
Chrome
ブラウザ右上点3つ > 設定 > 左メニューのプライバシーとセキュリティ > もっと見る > 証明書の管理 > インポート
windows 信用さえた認証期間タブ
Linux 認証局タブ
org-testCompany で一覧に登録されていることを確認する。
org-は接頭語 testCompanyは、opensslの/Oオプションで設定した Organization name
Firefox
ブラウザの右上三本線 > 設定 > プライバシーとセキュリティ > 証明書(一番下)> 証明書を表示 > 認証局証明書 > インポート
testCompany で一覧に登録されていることを確認する
Webサーバ用証明書作成
ルート認証局からWebサーバで使用する鍵や証明書を発行する
openssl.cnf を修正する
$ sudo cp /etc/ssl/openssl.cnf /etc/ssl/openssl.cnf.org
$ sudo vim /etc/ssl/openssl.cnf
[CA_default]
dir = ./rootCA
[usr_cert]
subjectAltName = @alt_names
SANs拡張を使用する (subjectAltName = Subject Alternative Names)
subjectAltNameを設定しないとブラウザで不正な証明書と認識されてしまう。
サーバ証明書に登録するドメインをtestDomain.jpとする。
今回はサブドメインにも対応できるように設定する。
san.ext を作成する。san.extは証明書を発行する際のオプション-extfileで読み込む
vim ./rootCA/san.ext
subjectAltName=DNS:*.testDomain.jp, DNS:testDomain.jp
秘密鍵を作成
openssl genrsa -aes256 -out ./rootCA/testDomain.jp/private/privkey.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
...............................+++++
.+++++
e is 65537 (0x010001)
Enter pass phrase for ./rootCA/testDomain.jp/private/privkey.pem:任意のパスフレーズ
Verifying - Enter pass phrase for ./rootCA/testDomain.jp/private/privkey.pem:確認用パスフレーズ
CSR作成
$ openssl req -new -key ./rootCA/testDomain.jp/private/privkey.pem -subj "/C=JP/ST=Tokyo/L=edogawa/O=testCompany/OU=software/CN=testDomain.jp/" -out ./rootCA/testDomain.jp/certs/testDomain.csr
Enter pass phrase for ./rootCA/testDomain.jp/private/privkey.pem:秘密鍵のパスフレーズを入力
証明書発行
ルート(オレオレ)認証局(openssl ca)で署名する。
$ openssl ca -keyfile ./rootCA/private/cakey.pem -cert ./rootCA/cacert.pem -in ./rootCA/testDomain.jp/certs/testDomain.csr -out ./rootCA/testDomain.jp/certs/testDomain.crt.pem -days 825 -outdir ./rootCA/newcerts -extfile ./rootCA/san.ext
Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./rootCA/private/cakey.pem: cakey.pemの秘密鍵のパスフレーズを入力
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 0 (0x0)
Validity
Not Before: Apr 15 07:51:59 2020 GMT
Not After : Jul 19 07:51:59 2022 GMT
Subject:
countryName = JP
stateOrProvinceName = Tokyo
organizationName = testCompany
organizationalUnitName = software
commonName = testDomain.jp
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:*.testDomain.jp, DNS:testDomain.jp
Certificate is to be certified until Jul 19 07:51:59 2022 GMT (825 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
ここまででサーバ証明書の作成、発行は完了
Webサーバへの適用
Apacheの場合
Apache2.4
apache ssl 設定ファイルを編集
vim /etc/apache2/sites-available/default-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
# ServerAdmin webmaster@localhost
DocumentRoot /home/a_user/testDomain.jp
ServerName gitproject
ErrorLog ${APACHE_LOG_DIR}/error-ssl.log
CustomLog ${APACHE_LOG_DIR}/access-ssl.log combined
SSLEngine on
SSLCertificateFile "/home/a_user/rootCA/testDomain.jp/certs/testDomain.crt.pem"
SSLCertificateKeyFile "/home/a_user/rootCA/testDomain.jp/private/privkey.pem"
<FilesMatch "\.(cgi|shtml|phtml|php)$">
SSLOptions +StdEnvVars
</FilesMatch>
<Directory /usr/lib/cgi-bin>
SSLOptions +StdEnvVars
</Directory>
</VirtualHost>
</IfModule>
ssl の有効化
$ sudo a2enmod ssl
Considering dependency setenvif for ssl:
Module setenvif already enabled
Considering dependency mime for ssl:
Module mime already enabled
Considering dependency socache_shmcb for ssl:
Enabling module socache_shmcb.
Enabling module ssl.
See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
To activate the new configuration, you need to run:
systemctl restart apache2
$ sudo systemctl restart apache2
Enter passphrase for SSL/TLS keys for testDomain.jp:443 (RSA): *********
サーバ証明書を作成した際の秘密鍵のパスフレーズを入力する ↑
サーバ秘密鍵のパスフレーズを確認したい場合
$ openssl rsa -in ./rootCA/testDomain.jp/private/privkey.pem
Enter pass phrase for ./rootCA/testDomain.jp/private/privkey.pem:確認するパスフレーズをいれる
パスフレーズが正しければ以下のように表示される。間違っている場合、エラーとなる。
※パスフレーズが設定されていない場合は、Enter pass phrase は表示されない。
writing RSA key
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEA1lD1H2Z8HIZihM/VGqCkAXNLuTCxJvGX7jduajypN+t6gAYB
RX+pWNPjkVE1G69k0RlplxF+951x1+54QZ9CuYQNbKuamfEQg5VKnn8jyhZgWfPn
QoPnQiMdUwurlBsjUE24XusdU24aXXXXXXXXXXXXXXXXXXXXX
省略。。。
-----END RSA PRIVATE KEY-----
nginxの場合
/etc/nginx/nginx.conf は直接いじらない。
sslの鍵のパスフレーズを記載したファイルを用意しておく必要がある。
Apacheの場合は、起動時に入力を求められるが、nginxの場合はエラーになる。
Job for nginx.service failed because the control process exited with error code.
See "systemctl status nginx.service" and "journalctl -xe" for details.
パスフレーズを記載した任意のファイルを用意する。ここでは pwf とした。
vim /home/a_user/rootCA/testDomain.jp/pwf
記述内容は、SSLのパスフレーズを記述する
password01
default.conf の ssl_password_file に設定する
sudo vim /etc/nginx/conf.d/default.conf
server {
listen 80;
listen 443 ssl;
ssl on;
ssl_certificate /home/a_user/rootCA/testDomain.jp/certs/testDomain.crt.pem;
ssl_password_file /home/a_user/rootCA/testDomain.jp/pwf;
ssl_certificate_key /home/a_user/rootCA/testDomain.jp/private/privkey.pem;
server_name testDomain.jp;
access_log /home/a_user/testDomain/log/testDomain.access.log;
location / {
root /home/a_user/testDomain;
index index.html;
}
}
https 接続確認
ブラウザで確認
https://testDomain.jp/index.html
curlで確認
$ curl --cacert /home/a_user/rootCA/cacert.pem https://testDomain.jp/index.html
以上。