SSL(TSL)用のオレオレ証明書を更新

iPhoneから自宅のメールサーバーへのアクセスを復活させる。

我がドメインezto.infoの証明書はいわゆるオレオレ証明書です。
去年だったか一昨年だったか、有効期限切れだったのに気づき証明書を更新したらiPhoneからメールサーバーにアクセスできなくなってしまいました。
Macからはアクセスできていたんですが、MacのOSバージョンアップ(macOS10.15)にあたってなんか嫌な予感がして調べたら、たぶん予感的中。
iOS 13 および macOS 10.15 における信頼済み証明書の要件によりますと、

1)RSA 鍵を利用する TLS サーバ証明書および発行元の CA は、鍵長 2048 ビット以上の鍵を用いる必要がある。2048 ビット未満の鍵長の RSA 鍵を用いた証明書は、TLS 通信において信頼されなくなります。
2)TLS サーバ証明書および発行元の CA は、SHA-2 ファミリーのハッシュアルゴリズムを署名アルゴリズムに用いる必要がある。SHA-1 で署名された証明書は、TLS 通信では信頼されなくなります。
3)TLS サーバ証明書は、証明書の SAN (Subject Alternative Name) 拡張領域にサーバの DNS 名を記述する必要がある。証明書の CommonName の DNS 名は今後は信頼されなくなります。
さらに、2019 年 7 月 1 日以降に発行されるすべての TLS サーバ証明書 (発行日は証明書の NotBefore フィールドに明記)、以下のガイドラインに従う必要があります。
4)TLS サーバ証明書には ExtendedKeyUsage (EKU) 拡張領域を必ず含め、ここに id-kp-serverAuth OID を指定する必要がある。
5)TLS サーバ証明書の有効期間は 825 日以下である (証明書の NotBefore フィールドと NotAfter フィールドで明記)。
iOS 13 や macOS 10.15 では、上記の要件を満たさない TLS サーバには接続できなくなり、接続しようとすると、ネットワーク障害や、App が動かない、Safari に Web サイトが読み込まれないなどの症状につながる場合もあります。とあります。

このままmacOSをバージョンアップするとMacからもメールが取れなくなる可能性が高いと思われ、バージョンアップしてからダメだったでは困ったちゃんなので、その前に証明書をなんとかしましょう。
証明書を買えば簡単なわけですが、自分と家族くらいしか使わないメールアクセスに余計な費用はかけたくありませんのでちょっとジタバタしてみます。
少し調べたら、「要件を満たしたサーバー証明書」「オレオレ証明書の場合は、クライアントのiOS側にCA証明書をインポートして信頼させる」で動くみたいです。

では「使える証明書」をどうやってつくるか。
キーチェーンの証明書マネージャーで作ろうとしたら、カスタム設定で要件に沿うような設定を記述したファイルを用意する必要があるのはわかったのですが、肝心な記述方法がわかりません。(苦笑
そこで、時間ももったいないし情報が豊富なLinuxのOpenSSLで作りたいと思います。
(サーバーをLinuxで運用していた時以来のコマンドでの証明書作りです。)

以下、備忘です。
なお、そもそもサーバーOSも相当にニッチな環境ということも併せて、動作の担保も正確性の保証も致しませんのでよろしくお願いいたします。

まずはLinux環境を作ります。
今回はMacのParallelsでUbuntu日本語版を構築。
Ubuntuに特別な設定はなく、デスクトップ版を普通にインストールしただけです。
起動したら一通りアップデートしておきます。
なお、ほとんどのコマンドがsudoしないと動かなかったんですが、証明書を作るだけの環境ということもあり、理由は深く追求していません。

・バージョン確認
$ openssl version
OpenSSL 1.1.1 11 Sep 2018    (1.1.1以降ならOKみたいです)

・設定ファイル(openssl.cnf)のありかは
/etc/ssl/openssl.cnf
でした。

・要件に沿った証明書作成と作成を簡単にするためにopenssl.cnfを編集します。
$ sudo nano /etc/ssl/openssl.cnf

・default_days を 820(日)に変更

・[req] セクションに下記を追加
req_extensions = v3_req
default_md = sha256

・[ req_distinguished_name ]の変更
countryName_default = JP
stateOrProvinceName_default = 都道府県名(うちはCiba)
localityName_default = 市区町村名(うちはChiba)
0.organizationName_default = 適当な組織名(うちはEZ Lab.としました)

・[ usr_cert ] セクションに下記を追加
authorityKeyIdentifier=keyid,issuer:always
subjectAltName= @alt_names
extendedKeyUsage = critical,timeStamping,serverAuth,clientAuth,codeSigning,codeSigning,emailProtection

・[ v3_req ]セクションに下記を追加
subjectAltName =@alt_names
extendedKeyUsage = serverAuth,clientAuth,codeSigning,emailProtection

・[alt_names]セクションを新たに新設
DNS.1 = 証明したいサーバー名1(今回はwebサーバーのwww.ezto.infoを指定)
DNS.2 =証明したいサーバー名2(今回はメールサーバーのez2.ezto.infoを指定)

保存してnano終了。

・作業ディレクトリ作成、移動
$ sudo mkdir /etc/ssl/ca00
$ cd /etc/ssl/ca00

・認証局の秘密鍵を生成
$ sudo openssl genrsa -out cakey.pem 2048
 以下、opensslの質問応答はデフォルトでよければ何も入れすリターン、何か入れる必要がある場合「適当」なものを入れていきます。

・認証局の証明書発行要求CSRを作成
$ sudo openssl req -new -key cakey.pem -out cacert.csr

・ルートCA証明書発行
$ sudo openssl x509 -in cacert.csr -req -signkey cakey.pem -out cacert.pem

・証明書発行を記録していくファイルの作成
$ sudo touch index.txt
$ sudo touch serial

・シリアルファイルに初期値「00」を記載
$ sudo nano serial

00
と書いて保存、nano終了

・サーバ証明書ディレクトリ作成
$ sudo mkdir /etc/ssl/sv00

・サーバー鍵作成
$ sudo openssl genrsa -out /etc/ssl/sv00/privkey.pem 2048

・サーバーの証明書発行要求CSRを作成
$ sudo openssl req -new -key /etc/ssl/sv00/privkey.pem -out /etc/ssl/sv00/domain_name.csr

・証明書発行
$ sudo openssl ca -in /etc/ssl/sv00/domain_name.csr -keyfile /etc/ssl/ca00/cakey.pem -out /etc/ssl/sv00/domain_name.crt.pem

・パスフレーズなしの鍵を生成
$ sudo openssl rsa -in /etc/ssl/sv00/privkey.pem -out /etc/ssl/sv00/privkey-nopass.pem

・出来上がったファイルを適用

privkey-nopass.pem(パスフレーズなしサーバー鍵)
domain_name.crt.pem(サーバ証明書)
の2つをサーバーに持っていき、適用します。

cacert.pem(ルートCA証明書)をiPhoneに持っていきます。
今回は自分のアカウントのiCloud経由で持っていきました。
iPhoneからダウンロードするとプロファイルをインストールするか聞いてくるのでダイアログをよく読みながらインストール。
設定→一般→プロファイル
 とたどり、コモンネームに設定したドメイン名のルートCA証明書が入っていることを確認します。
設定→一般→情報→証明書信頼設定
 とたどり、先ほどのルートCA証明書の信頼スイッチを入れます。

これでiPhoneから自宅メールサーバーとやりとりができるようになりましたので、MacのOSバージョンアップも安心してできます。