EC2でHTTPS接続

EC2にHTTPSでアクセスするための設定をご紹介します.
また, ドメイン名をすでに持っているという前提で話を進めます.
自分のサーバーのappache環境を載せておきます.

$ httpd -v
Server version: Apache/2.2.34 (Unix)

安全な通信とは

HTTPSとHTTPの違いは, 通信の安全性が保証されているかにあります.
HTTP通信では, AさんがBさんへ送信した通信内容が, 第三者Cさんに盗聴, 改ざんされるおそれがあります.
一方でHTTPS通信では, 通信内容が暗号化されているため, HTTPと比較すると安全に通信を行うことができます.
しかし, 通信内容が暗号化されているだけでは十分に安全とは言えません.
Aさんがデータを送信している相手がBさんであれば安全ですが, 送信先が実はBさんではなく第三者Cさんであった場合, Aさんは気づかずに重要なデータを外部に送信してしまっていることになります.
そこで, 送信先Bさんは”SSL証明書”なるものによって, “Aさんがデータを送信しようとしている送信先は間違いなくBさんである”ということを証明する必要があります.
(SSL証明書のより詳しい仕組みはこちらにまとめられていますので, ぜひご参照ください.)
以下では, サーバー (上例でのBさん) が安全にHTTPS通信を受け付けるための手順を紹介します.

port 443の開放

最初に443番ポート (HTTPSのポート) が開いているか確認しましょう.

$ nmap -sT [サーバーのipアドレス or ドメイン名]

Starting Nmap 6.40 ( http://nmap.org ) at 2019-02-13 06:42 UTC
Nmap scan report for [サーバーのドメイン名] ([サーバーのipアドレス])
Host is up (0.00044s latency).
rDNS record for [サーバーのipアドレス]: ec2-xxxxxxxxxxxxx.ap-northeast-1.compute.amazonaws.com
Not shown: 998 filtered ports
PORT    STATE SERVICE
80/tcp  open  http
443/tcp closed  https

一番最後の行に注目すると “443/tcp closed https” とありますが, この状態ではhttpsは開いてません.
そこで, iptablesというファイアウォールを管理するためのツールを利用しましょう.
このツールでは, 特定のポートへの通信を許可し, それ以外のポートへの通信をファイアウォールで弾く事ができます.
不必要なポートを開いていると攻撃の対象になってしまうため, 必要なポートのみを開放しましょう.
また, 似たようなパケットフィルタリングツールにfirewalldというものが存在しますが, iptablesとの共存はできないのでどちらか一方を使いましょう (どっちでもいいですが今回はiptablesでいきます).
以下のコマンドを実行しましょう.

$ iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
$ service iptables save
$ service iptables restart

1行目で443番ポートの開放, 2行目で設定の変更を保存, 3行目でiptablesを再起動しています.
もう一度ポートの確認をして, 443番ポートが開いていれば成功です.

$ nmap -sT [サーバーのipアドレス or ドメイン名]

Starting Nmap 6.40 ( http://nmap.org ) at 2019-02-13 06:42 UTC
Nmap scan report for [サーバーのドメイン名] ([サーバーのipアドレス])
Host is up (0.00044s latency).
rDNS record for [サーバーのipアドレス]: ec2-xxxxxxxxxxxxx.ap-northeast-1.compute.amazonaws.com
Not shown: 998 filtered ports
PORT    STATE SERVICE
80/tcp  open  http
443/tcp open  https

SSL証明書の取得

次に, 冒頭で紹介したSSL証明書を取得します.
SSL証明書は認証局 (CA) によってサーバーに発行され, “あるユーザーがアクセスしようとしているドメインは, 間違いなく本物のサーバーのドメインである”ということを証明してくれます.
SSL証明書を取得するには証明書署名要求 (CSR) をCAへ送信する必要があるのですが, 一般にこの作業には費用がかかります.
しかし, Let’s EncryptというCAは無料でSSL証明書を発行してくれるので, そちらを利用します.
次のようなコマンドを実行しましょう.

$ sudo curl https://dl.eff.org/certbot-auto -o /usr/bin/certbot-auto
$ chmod 700 /usr/bin/certbot-auto
$ sudo certbot-auto certonly --webroot -w /var/www/html -d [サーバーのドメイン名] --email [自分のメールアドレス]
(略)
IMPORTANT NOTES:
Congratulations! Your Certificate and chain have been saved at:
/etc/letsencrypt/live/[ドメイン名]/fullchain.pem
Your key file has been saved at:
/etc/letsencrypt/live/[ドメイン名]/privkey.pem
(略)

1行目でcert-botという専用のツールをインストールします.
3行目でサーバーのドメイン名に対してSSL証明書を発行するための手続きを行います.
Congratulations! と出力されれば成功です.
ここで, 生成されたファイルの簡単な説明をします.
自分の環境では, /etc/letsencrypt/live/[ドメイン名]/というディレクトリに生成されました.

  • cert.pem
    SSL証明書

  • chain.pem
    中間証明書

  • fullchain.pem
    サーバ証明書と中間証明書が結合されたファイル

  • privkey.pem
    秘密鍵 (鬼大事です, 他人の手に渡らないように気をつけてください)

ちなみに, /etc/letsencrypt/csr/にCAへ署名を要求するためのCSRが生成されますが, SSL証明書がすでに発行された場合, こちらはもう不要です.
また, 次のコマンドで証明書の詳細を確認できます.

$ openssl s_client -connect [サーバーのドメイン名]:443 -showcerts

mod_sslのインストール

ApacheでSSL通信を行うためのモジュールにmod_sslというものが存在します.
まずはこれをインストールしましょう.

$ sudo yum -y install mod_ssl

/etc/httpd/conf.d/ssl.confが設定ファイルとして生成されます. 取得したSSL証明書のパスを書き込みましょう.

#   Server Certificate:
# Point SSLCertificateFile at a PEM encoded certificate.  If
# the certificate is encrypted, then you will be prompted for a
# pass phrase.  Note that a kill -HUP will prompt again.  A new
# certificate can be generated using the genkey(1) command.
#SSLCertificateFile /etc/pki/tls/certs/localhost.crt // コメントアウト
SSLCertificateFile [SSL証明書 (cert.pem) のパス] // 追加

#   Server Private Key:
#   If the key is not combined with the certificate, use this
#   directive to point at the key file.  Keep in mind that if
#   you've both a RSA and a DSA private key you can configure
#   both in parallel (to also allow the use of DSA ciphers, etc.)
#SSLCertificateKeyFile /etc/letsencrypt/csr/0001_csr-certbot.pem // コメントアウト
SSLCertificateKeyFile [秘密鍵 (privkey.pem) のパス] // 追加

#   Server Certificate Chain:
#   Point SSLCertificateChainFile at a file containing the
#   concatenation of PEM encoded CA certificates which form the
#   certificate chain for the server certificate. Alternatively
#   the referenced file can be the same as SSLCertificateFile
#   when the CA certificates are directly appended to the server
#   certificate for convinience.
#SSLCertificateChainFile /etc/pki/tls/certs/server-chain.crt // コメントアウト
SSLCertificateChainFile [中間証明書 (chain.pem) のパス] // 追加

設定は以上で終了です.
Apacheを再起動しましょう.

$ service httpd restart

最後に, https://[サーバーのドメイン名]へアクセスできるか確認してみましょう.
Chrome右上の「︙→ その他のツール→ デベロッパーツール→ Security」をクリックすると, 証明書が正しく反映できているか確認ができます。