Nodejs(Express) で Let’s Encrypt の無料HTTPS証明書を使う!HTTPからHTTPSは10行以下で書き換え可能だ
こんにちは!
暗号化とか認証などのセキュリティ技術のような、世の中に悪い人がいるから自分の身を守ることが必要になってしまい、そのために出現した技術は苦手だなー、と感じるのは、実は「自分がとってもいい人」だからだ!っと勝手に信じている、しずかなかずしです。
サーバーのセキュリティに注意していますか??
セキュリティとか、暗号化とか、認証や証明書、などといったキーワードを聞くと、なにか危険な香りがして、身構えてしまいますね。
しかし、身近なところで暗号化は使われていいます。例えば、今読んでいただいている、しずかなかずしブログ。このブログのコンテンツをサーバーから取ってきてブラウザに表示する際も、HTTPSという暗号化プロトコルが使われているのをご存知でしたか?
私は、ITバブルと言われた2000年代前半に、一時期Webサービスの仕事をしていたことがあります。今で言うところの、Webのフロント系の仕事をしていました。まだ、「クラウド」という言葉がなかった頃です。そして、「ブログ」が「Weblog」という名前で呼ばれていた頃です。(古い…)
その頃、インターネットの暗号通信HTTPSを使うためには、認証局にお金を払ってサーバー証明書を「購入」するのがあたり前でした。企業が立ち上げるサイトともなれば、お金を払ってHTTPS通信を使い、競うように安全性をアピールしたものです。
ところが今日、2020年では、ブログのサーバーでも個人趣味サイトでも、HTTPS通信はあたり前。しかも、「無料」でHTTPS通信を始めることができます。
なぜ、そんなことができるようになったのか!??
それが本日のテーマ、「Let’s Encrypt(レッツ・エンクリプト)」が提供する無料のHTTPSサーバー証明書なのです。
しかも、今日はプログラマー向けのネタでnodejsでサーバー開発をする際に、どのようにLet’s Encryptを使っていくのか、実例を交えてご紹介していきます。Certbotという自動証明書発行のツールを使います。
Let’s Encryptとは
世の中には、立派な方がいらっしゃるものです。Let’s Encrypt(レッツ・エンクリプト)は無料でHTTPS通信に必要な証明書を発行する認証局です。世界中のWebサーバーをHTTPSにするために無料で証明書を発行するというミッションを掲げる非営利団体です。インターネットにおける神様のような存在という訳です。
Wikipediaによると、以下のような記載があります。
Let’s Encrypt(レッツ・エンクリプト)は、2016年4月に正式に開始された認証局である。自動化された発行プロセスにより、TLSのX.509証明書の発行を無料で行っている。
しかも、Let’s Encryptのすごいところは、プログラムで自動で証明書を取得できるところです。
Let’s Encryptの証明書を取得するためのプログラムがCertbotと呼ばれるプログラムです。
CertbotのWebサイトは英語ですが、とてもわかり易いです。
稼働させるHTTPのサーバーがApacheなのか、Nginxなのか、…そして、サーバーのOSが何か、といった条件を選択すると、それに合わせたやり方が順を追って説明されています。
ざっと説明をしますと、
- コマンドラインに馴染みがあること
- HTTPのWebサーバーがオンラインであること
- SSHでアクセスできて、sudoコマンドが使えること
という条件であれば、使えます。
しかも、もし上をクリアしていなくても大丈夫(!)。世の中には、自動HTTPS認証取得をサポートしているホスティングサービスもあるよ、と上の四角枠の中で解説しています。
どこで使われているか見てみよう
「ほんとに、自動HTTPS認証取得をサポートしているホスティングサイトがあるの?」
「日本でも利用できるものなの?」
そんな疑問が沸いたあなた!心配ご無用です。
私が使っている、エックスサーバーというレンタルサーバーは、そんなホスティングサービスの1つです。
以下のように、いくつかある「ドメイン認証SSL」ラインナップのなかに、料金無料で「Let’s Encrypt」が選択可能です。ありがたいことです。
そして、私のサイト「しずかなかずし」はこのサービスを利用しているので、HTTPSを使って通信しています。WebブラウザにGoogle Chromeをお使いであれば、下の図のように、URLの前の鍵マークを押してみて下さい。ちゃんと「この接続は保護されています」のマークが表示されるているのがわかるはずです。
そして、「証明書」の中身を見てみますと、以下のように確かに、shizuka-na-kazushi.style向けに発行されている証明書で、発行元が「Let’s Encrypt」と表示されています。
Nodejs(Express)のサーバーおさらい
本日は、さらに一歩踏み込んで、Nodejs + Express で作ったJavasciptのサーバープログラムを公開する場合の、Let’s Encryptの証明書の使い方を見ていきます。
Expressについては、以下の記事で紹介していますので、こちらも合せてご覧ください↓
おさらいすると、Expressとは、Nodejsで動作するJavascriptのWebアプリケーションを簡単に作ることができる「フレームワーク」です。上記の記事では、Express generatorを使用してスケルトンコードを作成していました。
今日はもっとシンプルに、Expressを使った、以下のようようなソースコードで試してみましょう。
単に、赤い文字でおなじみの「hello, world!」を表示するサーバー・プログラムです。
var express = require('express');
var http = require('http');
var app = express();
app.get('/', function(req, res, next) {
res.send('<html><body><h1 style=\'color:red\'>hello, world!</h1></body></html>');
});
var server = http.createServer(app);
server.listen(3000, function() {
console.log('example app listening on port 3000!');
});
2行目や9行目でわかるように、この状態ではHTTPSではなく、暗号化しないHTTPのライブラリを使って実装しています。
このスクリプトを実行して、 http://localhost:3000 を開くと以下のようにh1(大きい文字)で赤く、hello, world!が表示されます。
たったこれだけで、Webサービスを構築できるなんてnodejsって素晴らしい!
Certbotの使い方
Certbotのページには、先程の説明のように、HTTPのサーバーやOSの種類ごとに手順説明が用意されています。
nodejsのサーバーはその中にはありませんので、
- Software = 'None of the above’
- System = 'Ubuntu 18.04 LTS (bionic)’
を選択しました。それがこちらのページ(ubuntubionic-other)です。
順番に見ていきたいと思います。
1. SSHでサーバーにログイン
sudo が使えるHTTPサーバーが動作するマシンにSSHでログインします。
2. CertbotのPPAを追加する
サーバーマシンのパッケージ・リポジトリに、CertbotのPPA (Personal Package Archive) を登録します。以下のコマンドを実行します。
$ sudo apt-get update
$ sudo apt-get install software-properties-common
$ sudo add-apt-repository universe
$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
3. Certbotのインストール
以下のコマンドにより、certbotのインストールを行います。
4. どのようにCertbotを実行したいかを選択
/etc/letsencrypt/live/example.com/privkey.pem
証明書を読み込む
変更した後のソースコードはこちらです。
var express = require('express');
var https = require('https');
var fs = require('fs');
var app = express();
app.get('/', function(req, res, next) {
res.send('<html><body><h1 style=\'color:red\'>hello, world!</h1></body></html>');
});
var options = {
key: fs.readFileSync('/etc/letsencrypt/live/XXXXX.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/XXXXX.com/fullchain.pem'),
}
var server = https.createServer(options, app);
server.listen(443, function() {
process.setuid && process.setuid('node');
console.log(`user was replaced to uid: ${process.getuid()} ('node')`);
console.log('example app listening on port 443!');
});
証明書ファイルを読み込むためfsモジュールを使って、12、13行目で、keyにprivkey.pemを、certにfullchain.pemをそれぞれ読み込んでいるところがポイントです。
それを行う上で、最初のサンプルでは’http’としていたモジュールを、’https’へと変更しています。これだけでHTTPのサーバーが、HTTPSで使えるようになるというのはNodejsやExpressの素晴らしいところです。
ちなみに、19行目のsetuid()は、HTTPSのデフォルトのポート番号である443にセキュリティ上のアクセス制限がかかっている場合に、
$ sudo nodejs server.js
のようにルート権限でnodeを実行して443ポートのオープンをした後、一般ユーザ(ここでは ’node’ ユーザ)権限にランクを落とすためのコードです。これにより、サーバーアプリが乗っ取られた時に、ルートで悪意のあるプログラムを実行できないようにするための、セキュリティ上、および、サーバー運用上の1つの解決策です。
という訳で、とても簡単にNodejs+ExpressのHTTPサーバーを、HTTPS暗号通信サポートのサーバーにできていましましたー