Vagrant上のUbuntu20.04サーバーにオレオレ証明書の発行局を開設

開発環境

前にアップした記事
オレオレ認証局(CA)を作ってオレオレ証明書を発行
これはCenoOS7で行ったものですが、今回はUbuntuでやってみます。
まあ大差ないですが(笑)、ディレクトリ構成がちょっと違う(sslと、あとapacheも)のと、今回はやり方を少し変えてフォルダを新しく作ってやったのと、あとは証明書の有効期間が前回記事の時より大幅に短縮されて「398日未満」になった点、ここらあたりが前回記事との違いになります。

では、相変わらず雑ですが、Let's Go!!!!

準備

確認事項 openssl、mod_sslがあるか確認

openSSLはあるか?

$ openssl version
OpenSSL 1.1.1f  31 Mar 2020

ある。

mod_sslを確認する。

$ ll /etc/apache2/mods-available | grep ssl
-rw-r--r-- 1 root root  3110 Apr 14  2020 ssl.conf
-rw-r--r-- 1 root root    97 Apr 14  2020 ssl.load

で、mods_enabledの方にちゃんとシンボリックリンクが張ってある。
OK!!!

※ ない場合はインストールして有効化しておく

※ a2enmodコマンドってのもあるらしい。

# a2enmodは、availableなモジュールの中から指定したモジュールの読み込みをenableにするコマンドらしい。

$ 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:
Module socache_shmcb already enabled
Module ssl already enabled

mod_sslが既に入っている。

opensslの設定ファイルの編集

ubuntu版の場所は /etc/ssl/openssl.cnf
この /etc/ssl ディレクトリに他のフォルダもあります。

とりあえず編集

$ sudo vim /etc/ssl/openssl.cnf
# 43行目からのデフォルト使用フォルダ/ファイルには気を配っておくこと。

 43 [ CA_default ]
 44 
 45 dir             = ./CA          # <= ここだけ変更。

# 75行目の項目でハッシュ方式をsha256に変更
default_md = sha256

# [req_distinguished_name]項目で毎度入れる内容の初期値を入れておく
countryName_default = JP #日本
stateOrProvinceName_default = Tokyo #都道府県
localityName_default = Chiyoda-ku #市区町村
0.organizationName_default = OREORE.INC #組織名

[ usr_cert ]
# このセクションに以下の行を追記
subjectAltName = @alt_names

作業ディレクトリの仕込み

デフォだと /etc/ssl/certs、/etc/ssl/private を使用するが、それとは分けて管理したいのでCAというディレクトリ以下に必要なフォルダを作っておく

# CAフォルダ内で管理する。
$ sudo mkdir /etc/ssl/CA && cd /etc/ssl/CA
# privateフォルダとcertsフォルダを作っておく
$ sudo mkdir private && sudo mkdir certs

認証局(CA = Certification Authority)の秘密鍵を生成

# /etc/ssl/CA に居りまする。
$ sudo openssl genrsa -aes256 -out ./private/cakey.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.........................................................+++++
.........................................................+++++
e is 65537 (0x010001)
Enter pass phrase for ./private/cakey.pem:
Verifying - Enter pass phrase for ./private/cakey.pem:

# 出来た。
$ ll private/
total 12
drwxr-xr-x 2 root root 4096 Feb 18 19:30 ./
drwxr-xr-x 4 root root 4096 Feb 18 19:34 ../
-rw------- 1 root root 1766 Feb 18 19:30 cakey.pem # <= これが出来た

証明書発行要求 CSRファイル作成

秘密鍵から生成された公開鍵が本物の証であることのファイルを発行してもらうCSRファイル。

先ほど生成したcakey.pem という鍵を使ってcacert.csrという発行要求を作るよ!!ということ。

$ sudo openssl req -new -key ./private/cakey.pem -out ./cacert.csr

Enter pass phrase for ./private/cakey.pem: # <= CAの鍵パスフレーズ
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) [JP]: # <= 何も入力しないでEnter
State or Province Name (full name) [Tokyo]: # <= 何も入力しないでEnter
Locality Name (eg, city) [Chiyoda-ku]: # <= 何も入力しないでEnter
Organization Name (eg, company) [OreOre inc.]: # <= 何も入力しないでEnter
Organizational Unit Name (eg, section) []: # <= 何も入力しないでEnter
Common Name (e.g. server FQDN or YOUR name) []:vagrant.test  # <= 何か入れるww
Email Address []: <= 何も入力しないでEnter

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: # <= 何も入力しないでEnter
An optional company name []: # <= 何も入力しないでEnter

# ここの「Common Name」は親玉の名前。あとで出てくるサーバー証明書のCommon Nameにはドメインを指定するが、こちらはそうではなく、好きな名前をつけてよい。

$ ll
total 20
drwxr-xr-x 4 root root 4096 Feb 18 19:43 ./
drwxr-xr-x 5 root root 4096 Feb 18 19:28 ../
-rw-r--r-- 1 root root  993 Feb 18 19:43 cacert.csr # <= これが出来た
drwxr-xr-x 2 root root 4096 Feb 18 19:34 certs/
drwxr-xr-x 2 root root 4096 Feb 18 19:30 private/

オレオレ証明書発行

証明書の発行要求(cacert.csr)を受けて、オレオレ証明書を発行する。すなわち、自分自身の鍵を自分で署名する。
daysは20年(7300日)にしとく。

# cacert.csr と cakey.pem を合わせて cacert.pem を作ります!みたいなカンジ。
$ sudo openssl x509 -days 7300 -in ./cacert.csr -req -signkey ./private/cakey.pem -out ./cacert.pem
Signature ok
subject=C = JP, ST = Tokyo, L = Chiyoda-ku, O = OreOre inc., CN = vagrant.test
Getting Private key
Enter pass phrase for ./private/cakey.pem: # <= CAの鍵パスフレーズ

$ ll
total 24
drwxr-xr-x 4 root root 4096 Feb 18 19:49 ./
drwxr-xr-x 5 root root 4096 Feb 18 19:28 ../
-rw-r--r-- 1 root root  993 Feb 18 19:43 cacert.csr
-rw-r--r-- 1 root root 1196 Feb 18 19:50 cacert.pem # <= これが出来た
drwxr-xr-x 2 root root 4096 Feb 18 19:34 certs/
drwxr-xr-x 2 root root 4096 Feb 18 19:30 private/

認証局運用に必要なファイルの生成

以下の二つのファイル index.txt と serial(拡張子なし)を作って置かないとダメダメ!

$ sudo touch ./index.txt
$ sudo echo 00 > ./serial

echo でserialに数字を書き込むのがうまくいかない場合は、普通に

sudo vim serial

で新規ファイルを作り、「00」だけ書いて保存すればOK

これで認証局側の作業は完了!!


WEBサーバー側の作業:鍵作成からオレオレ認証局でのサーバー証明書発行

Apacheなどwebサーバーで使用したい証明書を発行してもらうための作業

先ほどはCAフォルダで作業したが、今回はtlsというフォルダを作って作業する。

$ sudo mkdir ../tls && cd ../tls
$ sudo mkdir private & sudo mkdir certs

秘密鍵作成

$ sudo openssl genrsa -aes256 -out ./private/privkey.pem 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
.............................+++++
............................................................+++++
e is 65537 (0x010001)
Enter pass phrase for ./private/privkey.pem:
Verifying - Enter pass phrase for ./private/privkey.pem:

$ ll private/
total 12
drwxr-xr-x 2 root root 4096 Feb 18 20:02 ./
drwxr-xr-x 4 root root 4096 Feb 18 20:00 ../
-rw------- 1 root root 1766 Feb 18 20:02 privkey.pem # <= これが出来た

発行要求CSRファイル作成(domain_name.csr)

domain_name の部分は発行したいサイトのドメイン毎に任意に指定すれば良いのだが、当面は複数ドメインで発行する予定はないのでテキトーに。

$ sudo openssl req -new -key ./private/privkey.pem -out ./certs/vagrant.csr
Enter pass phrase for ./private/privkey.pem:
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) [JP]: # <= 何も入力しないでEnter
State or Province Name (full name) [Tokyo]: # <= 何も入力しないでEnter
Locality Name (eg, city) [Chiyoda-ku]: # <= 何も入力しないでEnter
Organization Name (eg, company) [OreOre inc.]: # <= 何も入力しないでEnter
Organizational Unit Name (eg, section) []: # <= 何も入力しないでEnter
Common Name (e.g. server FQDN or YOUR name) []:vagrant.test # <=証明書を発行したいドメイン
Email Address []: # <= 何も入力しないでEnter

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []: # <= 何も入力しないでEnter
An optional company name []: # <= 何も入力しないでEnter

# ここでのCommon Nameは重要。
# 証明書を利用したいサイトのドメインを入れる。
# www.vagrant.test の証明書を発行したいのなら www.vagrant.test
# マルチドメインで www.vagrant.test とか hoge.vagrant.test とか fuga.vagrant.testとかいろいろ使ううよ〜という場合は *.vagrant.test と指定する。
# hoge.fuga.vagrant.testとかになる場合は *.fuga.vagrant.test としてやらなければならない。

サーバー証明書発行(domain_name.crt.pem)

Subject Alternative Name の設定

証明書発行の前に追加設定ファイルを作成

  1. san.ext(ファイル名はなんでも可)
  2. このファイルに subjectAltName=DNS:hogehoge.com を追記(マルチドメインの場合はカンマ区切り)
  3. opensslコマンドに -extfile san.ext を追加して証明書発行を実行
$ sudo echo "subjectAltName=DNS:vagrant.test,DNS:*.vagrant.test" > ../CA/san.ext
# 本来なら上記の一文で一気にやりたいが、Permission deniedでダメだったので↓

$ sudo touch ../CA/san.ext
$ sudo vim ../CA/san.ext

# このsan.extに以下の文字列を入力して保存
subjectAltName=DNS:vagrant.test,DNS:*.vagrant.test

で、openssl.cnfで設定されたパスを使う事情から、一つ上のディレクトリ /etc/ssl に移動。

あと、有効期間については398日未満となったようなので以下を参照。
参考:SSLサーバ証明書の有効期間を短縮するという決定に関する続報

# /etc/sslに移動
$ cd ..
# newcertsというディレクトリが必要らしいので作っておく
$ sudo mkdir ./CA/newcerts

$ sudo openssl ca -in ./tls/certs/vagrant.csr -out ./tls/certs/vagrant.crt.pem -days 397 -extfile ./CA/san.ext

Using configuration from /usr/lib/ssl/openssl.cnf
Enter pass phrase for ./CA/private/cakey.pem: # <= CAの鍵パスフレーズ
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 0 (0x0)
        Validity
            Not Before: Feb 18 11:36:06 2021 GMT
            Not After : Mar 22 11:36:06 2022 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = OreOre inc.
            commonName                = *.vagrant.test
        X509v3 extensions:
            X509v3 Subject Alternative Name: 
                DNS:vagrant.test, DNS:*.vagrant.test
Certificate is to be certified until Mar 22 11:36:06 2022 GMT (397 days)
Sign the certificate? [y/n]:y # y Enter

1 out of 1 certificate requests certified, commit? [y/n]y # y Enter
Write out database with 1 new entries
Data Base Updated

注意すべき点は、
「Using configuration from /usr/lib/ssl/openssl.cnf」(このファイルは/etc/ssl/openssl.cnfのシンボリックリンク)
という点で、このconfファイルのデフォルトディレクトリの記述(以下)によって使用するディレクトリが多少変わる点を理解しておくこと。

 38 ####################################################################
 39 [ ca ]
 40 default_ca      = CA_default            # The default ca section
 41 
 42 ####################################################################
 43 [ CA_default ]
 44 
 45 dir             = ./CA          # Where everything is kept
 46 certs           = $dir/certs            # Where the issued certs are kept
 47 crl_dir         = $dir/crl              # Where the issued crl are kept
 48 database        = $dir/index.txt        # database index file.
 49 unique_subject  = no                    # Set to 'no' to allow creation of
 50                                         # several certs with same subject.
 51 new_certs_dir   = $dir/newcerts         # default place for new certs.
 52 
 53 certificate     = $dir/cacert.pem       # The CA certificate
 54 serial          = $dir/serial           # The current serial number
 55 crlnumber       = $dir/crlnumber        # the current crl number
 56                                         # must be commented out to leave a V1 CRL
 57 crl             = $dir/crl.pem          # The current CRL

ブラウザに証明書を読み込ませる

ブラウザ側に持たせる証明書は

/etc/ssl/CA/cacert.pem
# ホストマシンとの共有フォルダにコピーしてホスト側に取り込む
$ sudo cp /etc/ssl/CA/cacert.pem /var/www/html/cacert.pem

macのキーチェーンアクセスに登録し、「常に信頼」としておく。


ウェブサーバー起動時にパスフレーズを求めらる問題を回避

$ sudo openssl rsa -in /etc/ssl/tls/private/privkey.pem -out /etc/ssl/tls/private/privkey-nopass.pem
# パスフレーズを聞かれるので、鍵を作成したときに入力したパスフレーズを入れる。
Enter pass phrase for /etc/ssl/tls/private/privkey.pem:
writing RSA key

Apacheに読み込ませる

$ sudo vim sites-enabled/vhost.conf

<VirtualHost *:443>
    ServerName vagrant.test
    SSLEngine On
    SSLCertificateFile /etc/ssl/tls/certs/vagrant.crt.pem
    SSLCertificateKeyFile /etc/ssl/tls/private/privkey-nopass.pem
</VirtualHost>

これで、ブラウザから https://vagrant.test にアクセスできる


ここも参考になりました:

Ubuntu 18.04 LTS で OpenSSL を使ったプライベート認証局&証明書を作る

【動画】[【#12 サーバ証明書 オレオレ証明書で遊ぼう】セキュリティのお勉強](