手順なので、認証局や自己証明書についての説明はあまりしていない。
ただの自己証明書でSSL通信を実装する手順。
SSL 通信実装
環境
- OS : CentOS 6
環境はgcpのVMインスタンスを使用しており、インスタンスイメージは「CentOS 6」を使用している。
準備するもの
- ドメイン
本記事では、fmbrain.work
という個人取得のドメインを使用する。
概要
CentOSに入っているApacheでたてられたWebサイトを自己証明書を使ってSSL化する。
秘密鍵の作成
$ openssl genrsa 2048 > /etc/httpd/conf/server.key
RSA秘密鍵を2048bitの鍵長で作成する。
RSA秘密鍵の拡張子は.key
や.pem
がよく使用されている。
$ cat server.key | openssl rsa -text
一応、作成した秘密鍵を確認しておく。
$ sudo chmod 600 server.key
今、作成した秘密鍵はrootのみで参照できるように権限を変更する。
CSRの作成
CSRは、サーバーの情報とさっき作成した秘密鍵とペアの公開鍵が入る。
$ openssl req -new -key /etc/httpd/conf/server.key > /etc/httpd/conf/server.csr
> Country Name (2 letter code) [XX]:JP
> State or Province Name (full name) []:Kanagawa
> Locality Name (eg, city) [Default City]:Yokohama
> Organization Name (eg, company) [Default Company Ltd]:(Enter)
> Organizational Unit Name (eg, section) []:(Enter)
> Common Name (eg, your name or your server's hostname) []:fmbrain.work
> Email Address []:dozo13189@gmail.com
> Please enter the following 'extra' attributes
> to be sent with your certificate request
> A challenge password []:(Enter)
> An optional company name []:(Enter)
openssl req
で、CSRの作成要求をして、-key
でインプットとなる秘密鍵を指定する。
-new
は、新しい鍵の生成を意味する。
入力を求められているCSRに書くサーバー情報は、ドメインのwhois情報と一致される必要があるが(一致しないと認証局は署名してくれないはず)、今回は自己証明書なのでCommon Nameだけ取得したドメインを書いておけば、後はどうでもいい。
openssl req -new -days 365 -sha256 -key /etc/httpd/conf/server.key > /etc/ httpd/conf/server.csr
さっきのCSRの発行コマンドだと、有効期限が短く、ハッシュ関数も脆弱なため、実用に耐えれないので、ちゃんと指定する。
CSRの有効期限を365日にするために-days 365
を指定し、ハッシュ関数は-sha256
で指定している。有効期限は、引数の指定なしだと30日になり、ハッシュ関数は引数の指定なしだとsha1になる。
cat /etc/httpd/conf/server.csr | openssl req -text
生成したCSRの確認をする。
Certificate Request:
Data:
Version: 0 (0x0)
Subject: C=JP, ST=Kanagawa, L=Yokohama, CN=fmbrain.work/emailAddress=xxxxxx@gmail.com
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (2048 bit)
Modulus:
...省略
Exponent: 65537 (0x10001)
Attributes:
challengePassword :unable to print attribute
Signature Algorithm: sha256WithRSAEncryption
...省略
-----BEGIN CERTIFICATE REQUEST-----
...省略
-----END CERTIFICATE REQUEST-----
Subject
に入力したサーバーの情報が書かれている。Common Name(=CN)だけちゃんと見ておく。
Subject Public Key Info
にCSR生成に使用した秘密鍵とペアの公開鍵が書かれている。Subject Public Key Info
に書かれている公開鍵に対して認証局は署名を行う。署名がされれば、Subject Public Key Info
の公開鍵がSubject
に入力したサーバーのものであるという証明になる。
Signature Algorithm
には、公開鍵暗号とハッシュ関数のアルゴリズムが書かれている。
例では、sha256WithRSAEncryption
と記載されているため、sha256
のハッシュ関数、RSA
の公開鍵暗号方式であることがわかる。
-----BEGIN CERTIFICATE REQUEST-----
から-----END CERTIFICATE REQUEST-----
は、PEM形式で記述された実際のCSRになる。
自己証明書
本来は作成したCSRを元に認証局に証明書を作成してもらうことになる。
今回は自己証明書のため、作成したCSRを元に自分で証明書を作成する。
$ openssl x509 -req -signkey /etc/httpd/conf/server.key < /etc/httpd/conf/server.csr > /etc/httpd/conf/server.crt
x509
は、標準証明書フォーマットを意味している。(RFCのドキュメント参照)
https://www.ipa.go.jp/security/rfc/RFC5280-03JA.html#031
openssl x509 -req
は、フォーマットx509
の証明書を作成する、という意味になる。
パブリック証明書を作成する場合は、server.csr
を認証局に送り、認証局の秘密鍵で署名をしてもらうはず。 今回は、-signkey server.key
で、自分の秘密鍵を使用して署名しているため、server.crt
は自己証明書となる。
自己証明書なのでserver.csr
に書かれている公開鍵は、fmbrain.work
の公開鍵であると、fmbrain.work
が言っている、ことになる。
$ cat /etc/httpd/conf/server.crt | openssl x509 -text
生成された証明書を確認する。
これで自己証明書の作成が完了したため、これをApacheに設定して、通信をSSL化していく。
Apacheの設定
ApacheはCentOSにデフォルトでインストールされているものを使用する。
index.html
$ vim /var/www/html/index.html
> <p>hello world</p>
httpd.conf
sudo vim /etc/httpd/conf/httpd.conf
> ServerAdmin dozo13189@gmail.com
> ServerName fmbrain.work:443
# Listen 443は削除する。ポートは`ssl.conf`で設定する。
> Listen 443
DocumentRootはデフォルトで"/var/www/html"のはずなので、変更はない。
DirectoryIndexもデフォルトで、index.htmlが設定されているはずなので、/var/www/html/index.htmlが読み込まれる。
ServerAdminは適当に何か書いて(サーバー管理者のメールアドレスが推奨)、ServerNameにドメインを書き、接続ポートも合わせて書く。
ssl.conf
$ vim /etc/httpd/conf.d/ssl.conf
# Listen 443があることを確認する。
> Listen 443
> SSLCertificateFile /etc/httpd/conf/server.crt
> SSLCertificateKeyFile /etc/httpd/conf/server.key
SSLCertificateFileに証明書のパスを設定して、SSLCertificateKeyFileには秘密鍵のパスを設定する。
これでSSL通信をする最低限の設定は完了したので、Apacheを再起動する。
Apacheの起動
$ service httpd status
> httpd is stopped
$ service httpd status
httpd (pid 13529) is running...
ドメインにアクセスする。(プロトコルはhttpではなく、httpsでアクセスする)

アクセス後は、このサイトが使用している証明書は正しい認証局が署名したものではないため、警告が出る。(正しい認証局は、ブラウザに信頼された認証局として登録されており、登録されていない認証局が署名していない証明書が使用されている場合は、このように警告が出る。つまり、これが正しい挙動)
トラブルシューティング
エラーが発生した場合のトラブルシューティング。
ErrorLog logs/error_log
httpd.conf
にエラーログの場所が書いてある。
$ tail -n 100 /var/log/httpd/error_log
エラーログを見よう。
$ apachectl configtest
> Syntax OK
Apacheのconfigファイルのシンタックスが正しいかどうかは、上記のコマンドで確認できるらしい。
この接続ではプライバシーが保護されません問題
自己証明書でSSL化されたサイトへのアクセスは、信頼された認証局が署名した証明書ではないため、当然、ブラウザはそれを警告する。
これを解決方法を書いておく。
解決方法1(作成した自己証明書をChromeに設定する)
ブラウザに「この証明書は信頼できる」ということを設定する方法。
https://blog.fileshelfplus.com/vps/312
解決方法2(SANを設定する)
解決方法1では、chromiumベースのブラウザは問題が解決できない。(chromeなど)
理由は、IEやEdgeの場合は、証明書のCN(Common Name)とアクセスするドメインが同一であれば問題ないが、chromeの場合は、CNではなくSANのDNS Nameの値と同一にする必要がある、ということらしい。
SANは、Subject Alternative Nameの略。
SANのDNS Nameは、CRT(証明書)に追加情報として書くことができる。
面倒だが、もう一度、CRT(証明書)を作り直し、作り直すときに追加オプションコマンドを指定する。
$ vim san.txt
> subjectAltName = DNS:fmbrain.work
ファイル名は何でもいいので、SANを書く。
$ openssl x509 -req -signkey server.key -extfile san.txt < server.csr > server.crt
-extfile
でSANを書いたファイルを指定して、CRT(証明書)を作成する。
$ cat server.crt | openssl x509 -text
> X509v3 extensions:
> X509v3 Subject Alternative Name:
> DNS:fmbrain.work
作成したCRT(証明書)を確認すると、X509v3 extensions
にSANが書かれている。
このCRT(証明書)をApacheに設定しなおして、再起動して、ブラウザにも設定し直してやると、「この接続ではプライバシーが保護されません問題」は解決する。
参考
食べる!SSL! ―HTTPS環境構築から始めるSSL入門(小島 拓也; 中嶋 亜美; 吉原 恵美; 中塚 淳. )
https://qiita.com/nis_nagaid_1984/items/b8f87d41ea108d47af61