(Express.js)HTTPSサーバ構築時にエラーが出た際の原因確認方法

Express.jsアプリケーションをHTTPSサーバ化ではまった際に見直したい項目、確認方法について記載します。
普通に設定できていれば問題なく繋がるはずです。エラーが出ていた場合は何かしら設定ミスがあるはずなので一つ一つ確認していきましょう。

ポート・サービスの確認

サーバ側でポート、サービスを開放していないとブラウザから接続エラーが表示されます。
CentOS7の場合は、firewalldで設定します。

//ポートの確認
sudo firewall-cmd --list-ports --zone=public
//サービスの確認
sudo firewall-cmd --list-service --zone=public

//4000ポート追加
sudo firewall-cmd --zone=public --add-port=3000/tcp --permanent
//httpsサービス追加
sudo firewall-cmd --zone=public --add-service=https --permanent
//設定後は再起動
sudo systemctl restart firewalld

証明書のアクセス権限確認

アプリケーションを通常ユーザで実行する場合、証明書に権限を設定するのも忘れないようにしましょう。

//権限付与設定例
sudo chmod 755 /etc/letsencrypt/live
sudo chmod 755 /etc/letsencrypt/live/xxxxxxxx.xyz
sudo chmod 744 /etc/letsencrypt/live/xxxxxxxx.xyz/privkey.pem
sudo chmod 744 /etc/letsencrypt/live/xxxxxxxx.xyz/chain.pem
sudo chmod 744 /etc/letsencrypt/live/xxxxxxxx.xyz/cert.pem

上記のサーバ設定ができていれば問題なくつながります。
繋がらない場合はいづれかの設定に不備があるので、設定を確認していきます。

私はブラウザで「ERR_SSL_VERSION_OR_CIPHER_MISMATCH」が出てしばらくはまりましたので、
その際の原因切り分けについて書いていきます。

証明書の確認

openssl

アクセスする端末からopensslコマンドをたたいて確認します。

問題なければ証明書情報が出力されて最後に「Verify return code: 0 (ok)」となります。

openssl s_client -connect xxxxxxxx.xyz:4000

私は「routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure」が出ていました。

参考
SSL SERVER TESTでもう少し詳細にエラーメッセージを確認することもできます。
ポートは443にする必要がありますので、node.jsアプリのlistenポートを443にしてroot権限で起動してからテストしてみてください。

httpdサービスで確認

証明書発行ミスの可能性もありますので、Apache httpdサービスで確認してみます。
Express.jsでもApache httpdでも繋がらなければ証明書が不正と考えられます。

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

//以下項目に取得した証明書を設定
SSLCertificateFile
SSLCertificateKeyFile
SSLCertificateChainFile

//httpd起動
sudo systemctl start httpd

openssl s_client -connect xxxxxxxx.xyz:443

これで繋がれば証明書に問題はないことになります。

httpdサービスが使えない場合、自己証明書で確認することもできます。

//任意の場所で以下コマンドを実行
openssl genrsa 2024 > key.pem
openssl req -new -key key.pem > req.pem
openssl x509 -req -in req.pem -signkey key.pem -out cert.pem

Express.jsでkey:key.pem、cert:cert.pemを設定することで自己証明書を使用したhttpsサーバを構築できます。
自己証明書なので信頼されていない証明書のメッセージが出力されますが、そこまでいければ証明書はOKです。

アプリケーションの確認

証明書に問題がなければアプリケーションでのコーディングミスが考えられます。
公式ドキュメントを参考にhttps.createServerの記載を再度確認してみてください。
ドキュメントにはありませんが、「key」「cert」「ca」の項目名は固定で記載してください。
今回は記載ミスが原因でした。

const http = require('http');
const https = require('https')

option = {
  key: fs.readFileSync('/etc/letsencrypt/live/xxxxxxxx.xyz/privkey.pem'),
  cert: fs.readFileSync('/etc/letsencrypt/live/xxxxxxxx.xyz/cert.pem'),
  ca: fs.readFileSync('/etc/letsencrypt/live/xxxxxxxx.xyz/chain.pem')
}
const httpsServer = https.createServer(option, app);
httpsServer.listen('4000');

サーバ構成図を書きながらやると原因が掴みやすかったのでおすすめです。

ビットコインを購入するならBITPOINT
BITPOINT