SSLのメモ
まず当方の環境。
Server OS: Ubuntu
Http Server: Appache
Client: Windows 10
参考にしたサイト
https://qiita.com/fururun02/items/e22a773516b961a081a5
https://www.golinuxcloud.com/create-certificate-authority-root-ca-linux/
オレオレ証明書作ってみたものの、ブラウザで表示するとERR_CERT_INVALID
の嵐。
ブラウザでSSL系のエラーが出たらキーボードでthisisunsafe
を入力すればエラーを無視は出来るのですが、
VSCodeでTypeScriptをデバッグする際にソースマップを読み込めず苦労しました。
Could not read source map for https://kurage-service/scripts/apps/shiritori/main.js: Unexpected 503 response from https://kurage-service/scripts/apps/shiritori/main.js.map: unable to verify the first certificate
結局オレオレ証明書を成功させないとどうにもならず数日苦戦。
えーと、中間証明書って必須なの? やり方間違ってるの? よくわからない。
原因がわからず試行錯誤した結果、何とか成功したのでメモしておきます。
ただ何が悪かったか理解はしてないです。
作業フォルダは/etc/ssl/myca
にしてます。
設定ファイル
OpenSSLの設定ファイルが/etc/ssl/openssl.cnf
にあるのですがその辺はよくわかっておらず、
大体変更した辺りを抜粋します。
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = /etc/ssl/myca/ca # Where everything is kept
certs = $dir/certs # Where the issued certs are kept
crl_dir = $dir/crl # Where the issued crl are kept
database = $dir/index.txt # database index file.
#unique_subject = no # Set to 'no' to allow creation of
# several certs with same subject.
new_certs_dir = $dir/newcerts # default place for new certs.
certificate = $dir/ca.crt # The CA certificate - --------------- Change: $dir/ca.crt
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
# must be commented out to leave a V1 CRL
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/ca.key # The private key --------------------- Change: $dir/private/ca.key
RANDFILE = $dir/private/.rand # private random number file
x509_extensions = usr_cert # The extensions to add to the cert
subjectAltName = @alt_names
[ alt_names ]
DNS.3 = oreore
後重要なのはルート証明書、中間証明書は認証局の設定でbasicConstraints=CA:TRUE
を指定して、
サーバー証明書はbasicConstraints=CA:FALSE
に設定しました。
シェルスクリプトとSAN
コマンド直打ちだと数十回は失敗したのでシェルスクリプトでまとめておきます。
#!/bin/bash
initDirs()
{
local P="${1}"
local DIRS=($P/private $P/certs $P/crl $P/newcerts)
for d in "${DIRS[@]}"; do
if [ ! -d "$d" ]; then
mkdir -p "$d"
fi
done
}
initFiles()
{
local DIR="${1}"
if [[ ! -f $DIR/serial ]]; then
echo 01 > $DIR/serial
fi
if [[ ! -f $DIR/crlnumber ]]; then
echo 01 > $DIR/crlnumber
fi
if [ ! -f $DIR/index.txt ]; then
touch $DIR/index.txt
fi
if [ ! -f $DIR/index.txt.attr ]; then
touch $DIR/index.txt.attr
fi
}
initFD()
{
local P="${1}"
mkdir $P
initDirs $P
initFiles $P
}
ca()
{
local P="/etc/ssl/myca"
# 実行毎に作業ディレクトリを掃除しておく。
rm -R $P/*
echo " ||||| CREATE ROOT CA CERT"
local CA=$P/ca
initFD $CA
echo "CA 鍵作成"
openssl genrsa -aes256 -out $CA/private/ca.key.pem -passout pass:pass-word 2048
echo "CSR + 自己証明(-x509を設定すると自己署名)"
openssl req -new -x509 -days 365 -key $CA/private/ca.key.pem -out $CA/ca.cert.pem -passin pass:pass-word
echo "----- ルート証明書表示"
cat $CA/ca.cert.pem
echo " ||||| CREATE INTER CHAIN CERT"
local INTER=$P/inter
initFD $INTER
echo "中間CA 鍵作成"
openssl genrsa -aes256 -out $INTER/private/inter.key.pem -passout pass:pass-word 2048
echo "中間 CSR"
openssl req -new -key $INTER/private/inter.key.pem -out $INTER/inter.csr.pem -passin pass:pass-word
echo "中間証明書"
openssl ca -days 365 -in $INTER/inter.csr.pem -out $INTER/inter.cert.pem -cert $CA/ca.cert.pem -keyfile $CA/private/ca.key.pem -extfile /etc/ssl/san/inter.txt -passin pass:pass-word
echo "中間証明書のチェック"
openssl verify -CAfile $CA/ca.cert.pem $INTER/inter.cert.pem
echo "中間:バンドル"
cat $INTER/inter.cert.pem $CA/ca.cert.pem > $INTER/inter.bundle.cert.pem
echo "中間:バンドルチェック"
openssl verify -CAfile $CA/ca.cert.pem $INTER/inter.bundle.cert.pem
echo " ||||| CREATE SERVER CERT"
local SERVER=$P/server
initFD $SERVER
echo "サーバ 鍵作成"
openssl genrsa -aes256 -out $SERVER/private/server.key.pem -passout pass:pass-word 2048
openssl rsa -in $SERVER/private/server.key.pem -out $SERVER/private/server.key.pem -passin pass:pass-word
echo "サーバ CSR"
openssl req -new -key $SERVER/private/server.key.pem -out $SERVER/server.csr.pem -passin pass:pass-word
echo "サーバ 証明書"
openssl x509 -req -days 365 -in $SERVER/server.csr.pem -out $SERVER/server.cert.pem -CA $INTER/inter.bundle.cert.pem -CAkey $INTER/private/inter.key.pem -CAserial $SERVER/serial -extfile /etc/ssl/san/server.txt -passin pass:pass-word
echo "サーババンドル"
cat $SERVER/server.cert.pem $INTER/inter.bundle.cert.pem > $SERVER/server.bundle.cert.pem
}
# 関数実行
ca
*注!
無駄なコードが散在します。
certsやnewcertsディレクトリなんて使ってないやん、とかいう箇所がありますが面倒なので放置してます。
では、
中間の外部設定ファイル
/etc/ssl/san/inter.txt
subjectAltName=DNS:inter
basicConstraints=CA:TRUE
サーバの外部設定ファイル
/etc/ssl/san/server.txt
subjectAltName=DNS:kurage, DNS:kurage-service, DNS:wordpress
basicConstraints=CA:FALSE
コマンド周りは、秘密鍵作って、CSR(要求書)発行して、署名するの手順です。
それをルート、中間、サーバとそれぞれ秘密鍵と証明書を作成します。
ルート証明書をブラウザにインストール、サーバの秘密鍵と証明書をサーバ(今回はApache)に設定して使います。
コマンドでちょくちょく出てくるオプション。
-passout pass:pass-word
パスワードを設定します。
このオプションをあらかじめ設定しておくと、コンソールでは求められなくなります。
-passin pass:pass-word
コンソールからパスワードの入力を求められれなくなります。
出力結果
コンソールの出力結果。
||||| CREATE ROOT CA CERT
CA 鍵作成
Generating RSA private key, 2048 bit long modulus (2 primes)
........................+++++
...........................................................+++++
e is 65537 (0x010001)
CSR作成
自己証明書
CSR + 自己証明(-x509を設定すると自己署名)
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) [AU]:jp
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:OREORE
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:oreore
Email Address []:
----- ルート証明書表示
-----BEGIN CERTIFICATE-----
<<秘密だよ>>
-----END CERTIFICATE-----
||||| CREATE INTER CHAIN CERT
中間CA 鍵作成
Generating RSA private key, 2048 bit long modulus (2 primes)
.........................................................................................+++++
......................................................................................+++++
e is 65537 (0x010001)
中間 CSR
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) [AU]:jp
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:INTER
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:inter
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 /usr/lib/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
Serial Number: 1 (0x1)
Validity
Not Before: Mar 21 02:26:32 2022 GMT
Not After : Mar 21 02:26:32 2023 GMT
Subject:
countryName = jp
stateOrProvinceName = Some-State
organizationName = INTER
commonName = inter
X509v3 extensions:
X509v3 Subject Alternative Name:
DNS:inter
X509v3 Basic Constraints:
CA:TRUE
Certificate is to be certified until Mar 21 02:26:32 2023 GMT (365 days)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated
中間証明書のチェック
/etc/ssl/myca/inter/inter.cert.pem: OK
中間:バンドル
中間:バンドルチェック
/etc/ssl/myca/inter/inter.bundle.cert.pem: OK
||||| CREATE SERVER CERT
サーバ 鍵作成
Generating RSA private key, 2048 bit long modulus (2 primes)
.............+++++
..................................+++++
e is 65537 (0x010001)
writing RSA key
サーバ CSR
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) [AU]:jp
State or Province Name (full name) [Some-State]:
Locality Name (eg, city) []:
Organization Name (eg, company) [Internet Widgits Pty Ltd]:SERVER
Organizational Unit Name (eg, section) []:
Common Name (e.g. server FQDN or YOUR name) []:server
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
サーバ 証明書
Signature ok
subject=C = jp, ST = Some-State, O = SERVER, CN = server
Getting CA Private Key
サーババンドル
CSR作成の際注意した点。
Country Name (2 letter code) [AU]:
と
Organization Name (eg, company) [Internet Widgits Pty Ltd]:
と
Common Name (e.g. server FQDN or YOUR name) []:
だけ入力しました。
Country Nameはjp
に、
他はそれぞれ(Organization Name / Common Name)
ルート: OREORE/oreore
中間: INTER/inter
サーバ: SERVER/server
と入力しました。
ここでの入力は後で意味を知ることになります。
チラ見
0 s:C = jp, ST = Some-State, O = SERVER, CN = server
i:C = jp, ST = Some-State, O = INTER, CN = inter
1 s:C = jp, ST = Some-State, O = INTER, CN = inter
i:C = jp, ST = Some-State, O = OREORE, CN = oreore
2 s:C = jp, ST = Some-State, O = OREORE, CN = oreore
i:C = jp, ST = Some-State, O = OREORE, CN = oreore
Apacheの設定
Apacheの設定ファイル、/etc/apache2/sites-available/default-ssl.conf
を編集。
SSLCertificateFile /etc/ssl/myca/server/server.bundle.cert.pem
SSLCertificateKeyFile /etc/ssl/myca/server/private/server.key.pem
を追加します。
サーバーの証明書と秘密鍵を設定したらApache再起動
sudo service apache2 restart
証明書のインストール
大事なのが証明書のインストール。
今回作成したルート証明書のパスは/etc/ssl/myca/ca/ca.cert.pem
です。
証明書作成した側のOS(Ubuntu)で使う場合はその場所を覚えておきます。
別のOSから使うには先にファイルをそのOSにダウンロードしておきます。
出来上がったルート証明書をChromeにインストールします。
Windowsなら設定
-> セキュリティとプライバシー
-> セキュリティ
-> 証明書の管理
-> インポート
の手順でインストールします。
ウィザードが開くので、ここで指示に従ってインストールしますが、重要なのはどこにインストールするかです。
証明書ストアに信頼されたルート証明機関
を選びます。
Ubuntuなら設定
-> 詳細設定(スクロールして一番下にある)
-> 証明書の管理
-> 認証局
-> インポート
の手順でインストールします。
いったんChromeを再起動します!
そしてhttps
にアクセスします。
成功しましたか?
正常に動いているかチェック
SSLが正常に動いているかチェックするには以下のコマンドを使います。
Ubuntuにて、
openssl s_client -connect kurage-service:443
kurage-service
の部分はドメインで環境に合わせてください。
GoogleとかYahooを覗いてみるといいかもしれません。
もし今回のオレオレ証明書設定だけでは次のエラーが出ます。
Verify return code: 19 (self signed certificate in certificate chain)
成功した場合は
Verify return code: 0 (ok)
とか表示されてます。
これはルート証明書をOS(Ubuntu)にインストールしてないから?
ブラウザにインストールしてもOSにインストールしてなかったらopenssl
は証明書手に入れようないですよね?
今回はある部分をチェックしたいだけで成功では無くてもいいのでOSにルート証明書をインストールしなくてもいいです。
で、出力結果を見ます。
CONNECTED(00000005)
depth=2 C = jp, ST = Some-State, O = OREORE, CN = oreore
verify return:1
depth=1 C = jp, ST = Some-State, O = INTER, CN = inter
verify return:1
depth=0 C = jp, ST = Some-State, O = SERVER, CN = server
verify return:1
---
Certificate chain
0 s:C = jp, ST = Some-State, O = SERVER, CN = server
i:C = jp, ST = Some-State, O = INTER, CN = inter
1 s:C = jp, ST = Some-State, O = INTER, CN = inter
i:C = jp, ST = Some-State, O = OREORE, CN = oreore
2 s:C = jp, ST = Some-State, O = OREORE, CN = oreore
i:C = jp, ST = Some-State, O = OREORE, CN = oreore
---
Server certificate
-----BEGIN CERTIFICATE-----
<<秘密だよ!>>
-----END CERTIFICATE-----
subject=C = jp, ST = Some-State, O = SERVER, CN = server
issuer=C = jp, ST = Some-State, O = INTER, CN = inter
---
No client certificate CA names sent
Peer signing digest: SHA256
Peer signature type: RSA-PSS
Server Temp Key: X25519, 253 bits
---
SSL handshake has read 3105 bytes and written 396 bytes
Verification: OK
---
New, TLSv1.3, Cipher is TLS_AES_256_GCM_SHA384
Server public key is 2048 bit
Secure Renegotiation IS NOT supported
Compression: NONE
Expansion: NONE
No ALPN negotiated
Early data was not sent
Verify return code: 0 (ok)
---
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: A5905C77592570908C9F22E17B1D7EC4049DA3EE0764F04AAE0AF86008A64345
Session-ID-ctx:
Resumption PSK: 50A456AE608975B1F3C95D8C91F0466334211AA6C29E7CA8F9F227FA553586F5C95E61139D9EE7807D58B147735789F2
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
<<秘密だよ>>
Start Time: 1647834600
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
---
read R BLOCK
---
Post-Handshake New Session Ticket arrived:
SSL-Session:
Protocol : TLSv1.3
Cipher : TLS_AES_256_GCM_SHA384
Session-ID: 42D7827B4E80C743CA5FF251D70EDA671D614B2235654FFE5843AA6DFE51418E
Session-ID-ctx:
Resumption PSK: 83E700E4AD0503C24164386EF7E9443653A0A0E3C6626C3512E6864F2BA53AD97BD8C8F4DD1737DCD436BB5871064850
PSK identity: None
PSK identity hint: None
SRP username: None
TLS session ticket lifetime hint: 300 (seconds)
TLS session ticket:
<<秘密だよ>
Start Time: 1647834600
Timeout : 7200 (sec)
Verify return code: 0 (ok)
Extended master secret: no
Max Early Data: 0
---
read R BLOCK
closed
注目点その1
depth=2 C = jp, ST = Some-State, O = OREORE, CN = oreore
verify return:1
depth=1 C = jp, ST = Some-State, O = INTER, CN = inter
verify return:1
depth=0 C = jp, ST = Some-State, O = SERVER, CN = server
verify return:1
depth(階層)を見ると、0=サーバ, 1=中間, 2=ルート になってることが確認出来ます。
注目点その2
Certificate chain
0 s:C = jp, ST = Some-State, O = SERVER, CN = server
i:C = jp, ST = Some-State, O = INTER, CN = inter
1 s:C = jp, ST = Some-State, O = INTER, CN = inter
i:C = jp, ST = Some-State, O = OREORE, CN = oreore
2 s:C = jp, ST = Some-State, O = OREORE, CN = oreore
i:C = jp, ST = Some-State, O = OREORE, CN = oreore
sがSubject(主体者), iがIssuer(発行者)で、serverはinterに、interはoreoreに、そしてoreoreはoreoreに発行されてることが確認できます。
oreoreがoreoreに、自己署名ですね。
失敗しているとこの辺がおかしいことになってます。
OS(Ubuntu)にインストールする場合
https://qiita.com/msi/items/9cb90271836386dafce3
もうここ見た方が早いです。