CAを作る(openssl.cnf )
MyCAという名前でRoot CA を作る。
mkdir MyCA cd MyCA
必要なディレクトリを作る。
mkdir ./newcerts mkdir ./requests touch index.txt echo 00 > serial echo 00 > crlnumber
openssl.cnf を作る。
/etc/ssl/openssl.cnf
から必要な部分、[ ca ]
セクション から [ tsa ]
セクション手前 までを取り出す
cat /etc/ssl/openssl.cnf \ | sed -n '/\[ ca \]/,$p' \ | sed '/\[ tsa/,$d' \ > openssl.cnf
keyUsage(鍵用途)で証明書発行を許可した証明書(CAになれる)となるよう設定を変更
sed -i openssl.cnf -e '/^keyUsage = nonRepudiation/s|^|# |' sed -i openssl.cnf -e '/keyUsage = cRLSign/s|^# ||'
有効期限を10年くらいにする(1年は365日と覚えてるだろうが、360日で計算してたほうが楽なので、1年は360日+誤差だと考えてたほうが計算が楽。)
sed -i openssl.cnf -e 's|365|3600|'
CAディレクトリをカレントにする
sed -i openssl.cnf -e 's|\./demoCA|\.|'
設定ファイルを確定させる。
cp openssl.cnf myCA.openssl.cnf
openssl genrsa > myCA.priv.key openssl req -new -subj "/C=JP/ST=Kyoto/O=my/CN=MyCA" -key myCA.priv.key > myCA.csr openssl req -text < myCA.csr openssl x509 -req -in myCA.csr -signkey myCA.priv.key > myCA.crt
自己署名証明書を作る。
openssl ca -config myCA.openssl.cnf -extensions v3_ca -in myCA.csr -keyfile myCA.priv.key -selfsign
PEM をコピーする
openssl x509 < newcerts/00.pem > myCA.crt
ここまでで、次のようになった
~/MyCA$ tree . . ├── crlnumber ├── index.txt ├── index.txt.attr ├── index.txt.old ├── myCA.crt ├── myCA.csr ├── myCA.openssl.cnf ├── myCA.priv.key ├── newcerts │ └── 00.pem ├── openssl.cnf ├── requests ├── serial └── serial.old 2 directories, 12 files
中間認証局(intermediate)を作成してみる。
ディレクトリを確保する
mkdir MedCA cd MedCA
初期化しておいて
mkdir ./newcerts mkdir ./requests touch index.txt echo 00 > serial echo 00 > crlnumber
設定ファイルをサクッと作る。
cat /etc/ssl/openssl.cnf \ | sed -n '/\[ ca \]/,$p' \ | sed '/\[ tsa/,$d' \ | sed -e 's|365|3600|' \ | sed -e '/^keyUsage = nonRepudiation/s|^|# |' \ | sed -e '/keyUsage = cRLSign/s|^# ||' \ | sed -e '/copy_extensions/s|^# ||' \ | sed -e 's|\./demoCA|\.|' \ > medCA.openssl.cnf
openssl genrsa > medCA.priv.key openssl req -new -subj "/C=JP/ST=Kyoto/O=my medium/CN=MedCA" -key medCA.priv.key > medCA.csr openssl req -text < medCA.csr
Root CA(MyCA)にリクエストを送信(コピー)する
cp MedCA/medCA.csr MyCA/requests/
Root CAに入り、中間認証局向けに証明書を発行してあげる
cd ../myCA openssl ca \ -config myCA.openssl.cnf \ -extensions v3_ca \ -policy policy_anything \ -cert myCA.crt \ -in ./requests/medCA.csr \ -keyfile myCA.priv.key
結果を確認
openssl x509 -text < ./newcerts/01.pem
証明書PEMを払い出し(コピー)
openssl x509 < ./newcerts/01.pem > medCA.crt mv medCA.crt ../MedCA/
一般利用者向けに証明書を中間認証局から発行する
nginx などで使えるように、DNS証明書(DV証明書を作る。)対象とするホスト名はraspi3.lan
とする。IPアドレスでも使えるようにIP:xxx.xxx.xxx.xxx
にも署名した証明書を作る。
今回は、SAN値(subject alternative name )を使って証明書を発行する。
SAN値を使うにはコンフィグ(openssl.cnf)の構成が必要
mkdir srv cd srv
san.conf を作る。
cat << 'EOF' > san.cnf [ req ] default_bits = 2048 distinguished_name = req_distinguished_name req_extensions = req_ext [ req_distinguished_name ] countryName = Country Name (2 letter code) stateOrProvinceName = State or Province Name (full name) localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) commonName = Common Name (e.g. server FQDN or YOUR name) [ req_ext ] subjectAltName = @alt_names [alt_names] # Write SANs(Subject Alternative Names) DNS.1 = raspi3.lan DNS.2 = raspi3.local IP.1 = 10.3.0.2 IP.2 = 127.0.0.1 EOF
SANつきでCSRを作る
openssl genrsa > server.priv.key openssl req -new \ -config san.cnf \ -subj "/C=JP/ST=Kyoto/L=Kyoto City/O=acid/CN=raspi3.lan" \ -key server.priv.key \ > server.csr
cp server.csr ../MedCA/requests/
中間認証局で署名する。
cd ../MedCA openssl ca \ -config medCA.openssl.cnf \ -policy policy_anything \ -in requests/server.csr \ -cert medCA.crt \ -keyfile medCA.priv.key
サーバーの証明書を払い出し(コピー)
openssl x509 < newcerts/00.pem > server.crt mv server.crt ../srv/
ここまでで、MyCA(root CA) → MedCA(中間CA) -> サーバー(証明書利用者)の3層構造が出来上がったわけである。
証明書の検証を行う。
証明書チェーンのファイルを作る
cat ../MedCA/medCA.crt ../MyCA/myCA.crt > chain.pem
verify すると。
openssl verify -verbose -CAfile chain.pem server.crt # => server.crt: OK
これで使えることがわかる。
nginx で使ってみる
nginx で作った証明書と鍵を導入する。
/etc/nginx/sites-enabled/raspi3.lan.conf
server { server_name raspi3.lan; add_header X-Robots-Tag "noindex, nofollow, nosnippet, noarchive"; listen 10.3.0.2:443 ssl http2; ssl_certificate_key /home/takuya/certs/srv/server.priv.key; ssl_certificate /home/takuya/certs/srv/chain.crt; if ($scheme = http) { return 301 https://$server_name$request_uri; } location / { add_header Content-Type "text/html"; return 200 "<h1>It works.(nginx)</h1>\n"; } }
設定を反映
sudo nginx -t sudo nginx -s reload
クライアントから接続してみる
HTTPSで証明書が使えるか検証してみる
curl --cacert ./MyCA/myCA.crt https://raspi3.lan # => <h1>It works.(nginx)</h1>
-k
の insecure オプションを使わなくても、curl が complainせずに暗号化通信が行えている
openssl でALPN/TLSプロトコルを見てみる。問題なさそう。
openssl s_client -connect 10.3.0.2:443 -crlf -servername raspi3.lan
Chromeブラウザ(Windows)でみてみる。
Windowsの証明書マネージャに作ったMyCAを「ルート証明書」として突っ込む
(これはとても危険行為です。通常はルート証明書を書き換えることは禁忌です。)
certmgr.msc
すべてのタスク→インポート
ウイザードの開始
ファイルを選ぶ
最終確認が出る
ルート証明書を触るのは非常時なので「通常やらないことやってるけどダイジョブか」と更に注意が出る。
インポートされた(後で削除を忘れないよう)
chromeブラウザで確認する。
ローカルドメイン ( .lan ) に対して証明書エラーが回避され、通常通りHTTPS通信になっている。
中間認証局の役割。
中間認証局を作って見るために、煩雑なことをやっている。
HTTPS化するだけなら
オレオレ・ルート証明書だけで十分である。