【SSL/TLS】自己署名SSLサーバ証明書を利用したhttps通信

##目標
プライベート認証局を構築し、自己署名証明書を利用したhttps通信を実現すること。

##前提
・AWS EC2インスタンスが構築済みであること。
・上記EC2インスタンスの**セキュリティグループ443番ポート（https）を開けておくこと**。

##利用環境
仮想マシン：　**AWS EC2 1台**
OS（AMI）:　**Amazon Linux 2 AMI (HVM), SSD Volume Type**
ミドルウェア：　**Apache HTTP Server 2.4.46**、**OpenSSL 1.0.2**

##認証局（CA）に関して
CAに関しては以下のサイトが分かりやすく説明されておりました。
[「分かりそう」で「分からない」でも「分かった」気になれるIT用語辞典（認証局（CA）とは)](https://wa3.i-3-i.info/word1832.html)

##作業の流れ
| 項番 | タイトル |
|:----:|:-------------|
| 1 | [プライベート認証局の構築](#1プライベート認証局の構築) |
| 2 | [SSLサーバ証明書の発行](#2sslサーバ証明書の発行)|
| 3 | [httpsサーバの構築](#3httpsサーバの構築)|
| 4 | [httpsアクセス確認](#4httpsアクセス確認)|

##手順
###事前準備

```bash
# EC2インスタンスにログイン後、ルートスイッチ
sudo su -
```

必要パッケージ**Apache**（WEBサーバ）、**mod_ssl**（ApacheからSSL/TLS機能を利用するためのApache用追加モジュール）のインストール

```
yum -y install httpd
yum -y install mod_ssl
```

SSL/TLS機能を提供する**OpenSSL**が事前インストールされていることを確認

```
[root@ip-172-31-34-112 ~]# openssl version
OpenSSL 1.0.2k-fips  26 Jan 2017
```


###1.プライベート認証局の構築
**①認証局構築用スクリプトの実行**
Amazon Linux 2にはデフォルトで**/etc/pki/tls/misc/CA**という認証局構築用スクリプトが事前インストールされています。
まずはそれを実行してプライベート認証局の作成を行います。

```bash
# 作業ディレクトリ移動
cd /etc/pki/tls/misc/
```

CAスクリプト実行

```
./CA -newca
```

実行すると対話型のコンソールとなるので以下のように入力

```bash

[root@ip-172-31-34-112 misc]# ./CA -newca
CA certificate filename (or enter to create)

Making CA certificate ...
Generating a 2048 bit RSA private key
...........................+++
............................................................................................................................................................................+++
writing new private key to '/etc/pki/CA/private/./cakey.pem'
# 認証局秘密鍵のパスフレーズ（1234とかでOK）を入力
Enter PEM pass phrase:
# パスフレーズ再入力
Verifying - 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、State or Province Name、Common Name 以外は未入力
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server hostname) []:private-ca
Email Address []:

Please enter the following 'extra' attributes
to be sent with your certificate request
# 未入力
A challenge password []:
An optional company name []:
Using configuration from /etc/pki/tls/openssl.cnf
# 認証局秘密鍵のパスフレーズ再入力
Enter pass phrase for /etc/pki/CA/private/./cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            98:da:72:01:e0:81:d9:7c
        Validity
            Not Before: Oct 30 06:09:35 2020 GMT
            Not After : Oct 30 06:09:35 2023 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = Default Company Ltd
            commonName                = private-ca
        X509v3 extensions:
            X509v3 Subject Key Identifier:
                3B:A0:AC:D6:74:E8:36:C3:A1:1E:56:CE:9F:1A:2F:BB:5A:C2:92:FB
            X509v3 Authority Key Identifier:
                keyid:3B:A0:AC:D6:74:E8:36:C3:A1:1E:56:CE:9F:1A:2F:BB:5A:C2:92:FB

            X509v3 Basic Constraints:
                CA:TRUE
Certificate is to be certified until Oct 30 06:09:35 2023 GMT (1095 days)

Write out database with 1 new entries
Data Base Updated
```

プライベート認証局の秘密鍵`/etc/pki/CA/private/cakey.pem`（SSLサーバ証明書に対する署名で利用）、及びプライベート認証局証明書`/etc/pki/CA/cacert.pem`（これをブラウザにインポートすることで、今回作成した認証局の署名を受けたSSLサーバ証明書を信頼されたものとして認識させることが可能）が存在していることを確認

```
[root@ip-172-31-34-112 misc]# ll /etc/pki/CA/private/cakey.pem
-rw-r--r-- 1 root root 1834 Oct 30 06:09 /etc/pki/CA/private/cakey.pem
[root@ip-172-31-34-112 misc]# ls -l /etc/pki/CA/cacert.pem
-rw-r--r-- 1 root root 4307 Oct 30 06:09 /etc/pki/CA/cacert.pem
```

###2.SSLサーバ証明書の発行
SSL通信に必要となる各種ファイル（※）を発行します。

※SSL関連ファイル（[Linux教科書 LPICレベル2 Version4.5対応](https://www.shoeisha.co.jp/book/detail/9784798151250)より）

| ファイル名 | 説明 |
|:-----------|------------|
| server.key | SSLサーバ秘密鍵 |
| server.csr| 認証局に対するSSLサーバ証明書発行要求書 |
| server.crt | SSLサーバ証明書 |

**①SSLサーバ秘密鍵の作成**
SSLサーバ秘密鍵`server.key`を作成します。

```
openssl genrsa -out server.key 2048
```

**②SSLサーバ証明書発行要求書作成**
SSLサーバ証明書発行要求書`server.csr`の作成をします。

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

再度対話型の形式となるので以下のように入力

```bash
[root@ip-172-31-34-112 misc]# openssl req -new -key server.key -out server.cs
r
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、State or Province Name、Common Name のみ入力
Country Name (2 letter code) [XX]:JP
State or Province Name (full name) []:Tokyo
Locality Name (eg, city) [Default City]:
Organization Name (eg, company) [Default Company Ltd]:
Organizational Unit Name (eg, section) []:
Common Name (eg, your name or your server hostname) []:52.194.253.70
Email Address []:

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

**③SSLサーバ証明書作成**

先ほど作成したプライベート認証局の秘密鍵を利用した署名実施がなされた、SSLサーバ証明書`server.crt`を作成します。

```
openssl ca -out server.crt -infiles server.csr
```

```bash

[root@ip-172-31-34-112 misc]# openssl ca -out server.crt -infiles server.csr
Using configuration from /etc/pki/tls/openssl.cnf
# 認証局秘密鍵のパスフレーズを入力（本記事に沿った場合、1234でOK）
Enter pass phrase for /etc/pki/CA/private/cakey.pem:
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number:
            98:da:72:01:e0:81:d9:7d
        Validity
            Not Before: Oct 30 07:14:43 2020 GMT
            Not After : Oct 30 07:14:43 2021 GMT
        Subject:
            countryName               = JP
            stateOrProvinceName       = Tokyo
            organizationName          = Default Company Ltd
            commonName                = 52.194.253.70
        X509v3 extensions:
            X509v3 Basic Constraints:
                CA:FALSE
            Netscape Comment:
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier:
                88:F1:F0:A6:BF:56:DC:D7:DA:70:C3:1E:89:CE:00:1C:28:0C:87:37
            X509v3 Authority Key Identifier:
                keyid:3B:A0:AC:D6:74:E8:36:C3:A1:1E:56:CE:9F:1A:2F:BB:5A:C2:92:FB

Certificate is to be certified until Oct 30 07:14:43 2021 GMT (365 days)
# y入力
Sign the certificate? [y/n]:y

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

**④SSLサーバ秘密鍵とSSLサーバ証明書を移動**
Apache⇔OpenSSLの連携のためにはSSLサーバ秘密鍵`server.key`とSSLサーバ証明書`server.crt`をApache側に読み込ませる必要があります。
両ファイルを一応、Apache側に移動します。

```
mv server.key /etc/httpd/conf
mv server.crt /etc/httpd/conf
```

また、SSLサーバ証明書発行要求書は不要なので削除

```
rm server.csr
```

###3.httpsサーバの構築
ApacheのSSL連携用設定ファイル`/etc/httpd/conf.d/ssl.conf`を利用して、SSLサーバ秘密鍵`server.key`とSSLサーバ証明書`server.crt`を読み込ませます

```
vi /etc/httpd/conf.d/ssl.conf
```

編集内容は以下（該当箇所のみの抜粋）

```bash

# SSLサーバ証明書
SSLCertificateFile /etc/httpd/conf/server.crt

# SSLサーバ秘密鍵
SSLCertificateKeyFile /etc/httpd/conf/server.key
```

httpdの起動、自動起動、状態確認（状態がrunningとなること）を行います。

```
systemctl start httpd
systemctl enable httpd
systemctl status httpd
```

###4.httpsアクセス確認
現時点でhttps通信は可能です。
試しにブラウザからアクセスを行います。
`https://EC2のグローバルIPアドレス`をブラウザに入力すると以下のようにこの接続ではプライバシーが保護されませんという画面に遷移します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/5031c0fe-16b7-4b45-ecc2-f77b584ce9ab.png)

送られてきたSSLサーバ証明書が信頼できないですよという意味で、正当な認証局から認証を受けてないSSLサーバ証明書の場合この注意が発せられます。
このまま無理矢理アクセスしても問題ないのですが、
WEBブラウザ（本記事ではFireFoxを利用）に前手順で作成したプライベート認証局証明書`/etc/pki/CA/cacert.pem`を読みこませることで、
今回作成したプライベート認証局によって署名を受けたSSL証明書を信頼出来る存在として認識させることが可能です。

TeraTermのファイル転送機能を利用して`/etc/pki/CA/cacert.pem`をローカルコンピュータにコピーします。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/afdc559c-d762-bc25-8668-a42c41986d9e.png)

FireFoxの場合、右上の各種設定用アイコンクリック後、`オプション`⇒`プライバシーとセキュリティー`⇒`証明書を表示`とクリックします。
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/5d2c8e1e-cd20-6c5e-7cbb-e625994dc2b7.png)

`認証局証明書`⇒`インポート`をクリック
![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/fd26aaf4-1ea4-3f04-d34e-99ee8c06c670.png)

`この認証局によるウェブサイトの識別を信頼する`にチェックを入れOKをクリック

![tempsnip.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/cc299ae5-b021-8367-e38e-d0a217de8e16.png)

再度https通信をかけて、警告なしにApacheのTestPageがでればOKです！
![キャプチャ.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/647616/c92d8a11-4fa5-8d7e-be5b-bb3d8e84d250.png)

##参考にさせて頂いた書籍及びサイト
・参考書籍
[Linux教科書 LPICレベル2 Version4.5対応](https://www.shoeisha.co.jp/book/detail/9784798151250)
・参考サイト
[５分でわかる！プライベート認証局(CA)の構築とサーバー証明書の発行方法](https://blog.apar.jp/linux/8587/)