EasyRSA 3 で自己証明ワイルドカード証明書を発行する

[オレオレワイルドカード証明書を作るだけなら OpenSSL を使えば出来る](https://qiita.com/hoto17296/items/8d32d0863d7e102b33f6)けども、OpenVPN のユーティリティである EasyRSA を使ってもできるっぽいのでやってみた。

認証局の設定までは以下を参考にした。

> [Amazon EC2とOpenVPNでサーバ-多拠点クライアント間通信をセキュアに行う ｜ Developers.IO](http://dev.classmethod.jp/cloud/aws/ec2-ssl-vpn-use-openvpn/)

SSL 認証そのものの仕組みについては以下がわかりやすかった。

> [SSL 認証 の仕組みと OpenVPN の認証の仕組み | レンタルサーバー・自宅サーバー設定・構築のヒント](http://server-setting.info/blog/ssl-openvpn-authentication.html)

# EasyRSA をインストール
``` console
$ wget https://github.com/OpenVPN/easy-rsa/releases/download/v3.0.8/EasyRSA-3.0.8.tgz
$ tar xzf EasyRSA-3.0.8.tgz
```

# 認証局を設定する
``` console
$ ./easyrsa init-pki
$ ./easyrsa build-ca
```

途中で CA 証明書のパスフレーズとコモンネームを要求される。

パスフレーズは証明書を発行するときなどに必要になるやつ。
コモンネームはルート証明書の名前になるやつ。(デフォルト値は `Easy-RSA CA`)

# ワイルドカード証明書を発行する
## 秘密鍵(key)と署名要求(req)を作る
コモンネームには証明書の名前を指定する。
SAN (Subject Alt Name) で利用するドメイン名を指定する。[^san]

[^san]: 昔のブラウザは証明書のコモンネームにドメイン名を指定すればそれを読み取ってくれたが、最近のブラウザは SAN が指定されていないと不正な証明書として扱われてしまう。
 https://support.google.com/chrome/a/answer/7391219?hl=ja

``` console
$ ./easyrsa --subject-alt-name='DNS:*.example.com,DNS:example.com' gen-req example.com nopass
Generating a 2048 bit RSA private key
..................+++
..+++
writing new private key to '/usr/local/EasyRSA/pki/private/example.com.key.l6ZG8s1FrC'
-----
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.
-----
Common Name (eg: your user, host, or server name) [example.com]: *.example.com

Keypair and certificate request completed. Your files are:
req: /usr/local/EasyRSA/pki/reqs/example.com.req
key: /usr/local/EasyRSA/pki/private/example.com.key
```

## 証明書(crt)を発行する
``` console
$ ./easyrsa --subject-alt-name='DNS:*.example.com,DNS:example.com' sign-req server example.com


You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 3650 days:

subject=
    commonName                = *.example.com


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: yes
Using configuration from /usr/local/EasyRSA/openssl-1.0.cnf
Enter pass phrase for /usr/local/EasyRSA/pki/private/ca.key:
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'*.example.com'
Certificate is to be certified until Sep 27 09:49:06 2026 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /usr/local/EasyRSA/pki/issued/example.com.crt
```

# Web サーバに証明書を入れる
今回は Nginx だったので Nginx の設定例。
生成した秘密鍵 `example.com.key` と証明書 `example.com.crt` を適当な場所において以下のような感じで設定する。

``` nginx.conf
server {
  listen 80;
  server_name www.example.com;
  return 301 https://$host$request_uri;
}

server {
  listen 443;
  server_name www.example.com;

  ssl                  on;
  ssl_certificate      /etc/nginx/ssl/example.com.crt;
  ssl_certificate_key  /etc/nginx/ssl/example.com.key;

  location / {
    proxy_pass http://localhost:3000;
  }
}
```

# クライアントにルート証明書をインストールする
ルート証明書を入れないとブラウザに「不正な証明書」と警告されるので、ルート証明書 `ca.crt` を PC にインストールする。

Mac の場合は `SSL` と `X.509` を信頼する設定にする。
Windows の場合は「信頼されたルート証明書」にインポートする。

![](https://qiita-image-store.s3.amazonaws.com/0/16369/59ea7ce3-47c1-1166-184b-1a973440e03d.png)

# ブラウザから確認
ブラウザから https で通信できていれば OK

![](https://qiita-image-store.s3.amazonaws.com/0/16369/1475024f-c6ae-3713-a602-2de76f43bada.png)