2021 年度 OSS リテラシー 3 : セキュリティ対策 (HTTPS)

はじめに

今回はプライベート空間 (10.176.0.0/24) に存在するサーバに対して SSL/TLS サーバー証明書を取得するために, 教員側で DNS の設定とリバースプ ロキシの設定を行なっている.

DNS は以下のような設定になっている. 自分の vm の IP アドレスから対応する ホスト名を把握しておくこと.

  • IP : 10.176.0.1XX => ホスト名 : iot-XX.epi.it.matsue-ct.jp (XX は数字)

なお, DNS の設定を確認する場合には, 以下のような手順で行うとよい. hostname -I コマンドと nslookup コマンドで表示される IP アドレスが一致することを確認すると良い (補足 : 最近は nslookup ではなく dig コマンドが使われることが多い).

$ sudo apt-get update

$ sudo apt-get install dnsutils

$ hostname -I

  10.176.0.1XX   (ホスト名)

$ nslookup iot-XX.epi.it.matsue-ct.jp

  10.0.0.7
  10.0.0.7#53

  Non-authoritative answer:
  iot-50.epi.it.matsue-ct.jp 
  Address: 10.176.0.1XX        <= ホスト名 iot-XX.epi.it.matsue-ct.jp に対応するアドレスが表示
  Name:Address:Server:

HTTPS 対応

Hypertext Transfer Protocol(Hypertext Transfer Protocol, HTTP)は, HTML などのコンテンツの送受信に用いられる通信プロトコルである. 主として World Wide Web において, Web ブラウザと Web サーバとの間での転送に用い られる. HTTP では通信は暗号化されないため, 近年では HTTPS (Hypertext Transfer Protocol Secure) が使われることが当たり前となりつつある. HTTPS では暗号化のために SSL/TLS プロトコルを用いる.

すでに構築した Web サーバ (apache2) を HTTPS 対応させるためには, SSL/TLS サーバー証明書が必要となる. 今回は Let's Encrypt から発行料無料の SSL/TLS サー バー証明書を取得することにする. Let's Encrypt は Linux Foundation の協 業プロジェクトで数多くのスポンサーに支えられて活動しており, Web 全体の 安全性を改善することをミッションに掲げている.

前準備

まず始めに, 80 ポートが開いていることを確認する.

$ nmap -p 80 iot-XX.epi.it.matsue-ct.jp

  PORT   STATE  SERVICE
  80/tcp   open  http     <= STATUS が open になっていることを確認.

次に, ブラウザから, http://iot-XX.epi.it.matsue-ct.jp にアクセスできることを確認する (図は省略).

SSL/TLS 証明書の取得

必要なパッケージをインストールする.

$ sudo -s

# apt-get update

# apt-get install certbot

Let's Encrypt から証明書の取得を行う. ターミナルでコマンドを実行すれば良い. certbot のオプションは以下の通りである.

  • certonly : SSL/TLS サーバ証明書の取得のみを行う
  • renew : 取得済みの SSL/TLS サーバ証明書のうち, 有効期限が近い証明書を自動的に更新する.
  • revoke : 取得済みの SSL/TLS サーバ証明書を、失効させます。
  • --webroot : ウェブサーバの DocumentRoot ディレクトリ以下に認証用のファイルを設置することで SSL/TLS サーバ証明書を取得する.
  • --standalone : Certbot クライアントに内蔵されているウェブサーバを使用して SSL/TLS サーバ証明書を取得する.
  • -w : webroot path (apache2 のデフォルト DocumentRoot は /var/www/html)
  • -d : ホスト名

以下のように certbot コマンドを実行する. すでに apache2 がインストールされているので, --webroot オプションを指定し, -w で apache2 のデフォルト DocumentRoot を指定している. さらに -d 以下でホスト名を指定している (XX は自分の番号に変えること).

# certbot certonly --webroot -w /var/www/html -d iot-XX.epi.it.matsue-ct.jp

  Saving debug log to /var/log/letsencrypt/letsencrypt.log
  Plugins selected: Authenticator webroot, Installer None
  Enter email address (used for urgent renewal and security notices) (Enter 'c' to
  cancel):                                                                           <=  教員のメールアドレスを入れること.

  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  Please read the Terms of Service at
  https://letsencrypt.org/documents/LE-SA-v1.2-November-15-2017.pdf. You must
  agree in order to register with the ACME server at
  https://acme-v02.api.letsencrypt.org/directory
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  (A)gree/(C)ancel:   A  (A を打鍵)

  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  Would you be willing to share your email address with the Electronic Frontier
  Foundation, a founding partner of the Let's Encrypt project and the non-profit
  organization that develops Certbot? We'd like to send you email about our work
  encrypting the web, EFF news, campaigns, and ways to support digital freedom.
  - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
  (Y)es/(N)o: N     (N を打鍵)

  Saving debug log to /var/log/letsencrypt/letsencrypt.log
  Plugins selected: Authenticator webroot, Installer None
  Obtaining a new certificate
  Performing the following challenges:
  http-01 challenge for iot-50.epi.it.matsue-ct.jp
  Using the webroot path /var/www/html for all unmatched domains.
  Waiting for verification...
  Cleaning up challenges

  IMPORTANT NOTES:                                                     <= "Congratulation" と出ていることを確認.
   - Congratulations! Your certificate and chain have been saved at:
     /etc/letsencrypt/live/iot-50.epi.it.matsue-ct.jp/fullchain.pem
     Your key file has been saved at:
     /etc/letsencrypt/live/iot-50.epi.it.matsue-ct.jp/privkey.pem
     Your cert will expire on 2020-02-09. To obtain a new or tweaked
     version of this certificate in the future, simply run certbot
     again. To non-interactively renew *all* of your certificates, run
     "certbot renew"
   - If you like Certbot, please consider supporting our work by:

     Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
     Donating to EFF:                    https://eff.org/donate-le

"Congratulations" と出たことを確認した後, /etc/letsencrypt/ に証明書が置かれていることを確認する.

  • サーバ証明書の実体(ファイル)は「/etc/letsencrypt/archive/ドメイン名」ディレクトリ配下に保存される.
    • サーバ証明書(公開鍵) … certN.pem
    • 中間証明書 … chainN.pem
    • サーバ証明書と中間証明書の結合ファイル … fullchainN.pem
    • 秘密鍵 … privkeyN.pem
  • シンボリックリンクは「/etc/letsencrypt/live/ドメイン名」ディレクトリ配下に保存される.

    • サーバ証明書(公開鍵) … cert.pem
    • 中間証明書 … chain.pem
    • サーバ証明書と中間証明書の結合ファイル … fullchain.pem
    • 秘密鍵 … privkey.pem
    # ls -l /etc/letsencrypt/archive/iot-XX.epi.it.matsue-ct.jp/    (XX は自分の数字に)
    
      -rw-r--r-- 1 root root 1939 11月 11 18:28 cert1.pem
      -rw-r--r-- 1 root root 1647 11月 11 18:28 chain1.pem
      -rw-r--r-- 1 root root 3586 11月 11 18:28 fullchain1.pem
      -rw------- 1 root root 1704 11月 11 18:28 privkey1.pem
    
    # ls -l /etc/letsencrypt/live/iot-XX.epi.it.matsue-ct.jp/    (XX は自分の数字に)
    
      -rw-r--r-- 1 root root 692 11月 11 18:28 README
      lrwxrwxrwx 1 root root  50 11月 11 18:28 cert.pem -> ../../archive/iot-50.epi.it.matsue-ct.jp/cert1.pem
      lrwxrwxrwx 1 root root  51 11月 11 18:28 chain.pem -> ../../archive/iot-50.epi.it.matsue-ct.jp/chain1.pem
      lrwxrwxrwx 1 root root  55 11月 11 18:28 fullchain.pem -> ../../archive/iot-50.epi.it.matsue-ct.jp/fullchain1.pem
      lrwxrwxrwx 1 root root  53 11月 11 18:28 privkey.pem -> ../../archive/iot-50.epi.it.matsue-ct.jp/privkey1.pem

apache2 の設定

Apache のセットアップ で述べたように, Debian の場合は /etc/apache2 以下に sites-available, mods-available, conf-available の下に設定ファイルが置かれている. それを a2ensite, a2enmod, a2enconf といったコマンドを用いて有効にする.

まず, SSL モジュールを有効にする. メッセージから分かるように依存関係にあるモジュールも全て有効になる.

# a2enmod ssl
  Considering dependency setenvif for ssl:
  Module setenvif already enabled
  Considering dependency mime for ssl:
  Module mime already enabled
  Considering dependency socache_shmcb for ssl:
  Enabling module socache_shmcb.
  Enabling module ssl.
  See /usr/share/doc/apache2/README.Debian.gz on how to configure SSL and create self-signed certificates.
  To activate the new configuration, you need to run:
    systemctl restart apache2

次に, HTTPS の設定を有効にする. /etc/apache2/sites-available/ 以下に default-ssl.conf という デフォルトの設定ファイルが存在する. それを有効にする.

# a2ensite default-ssl

  Enabling site default-ssl.
  To activate the new configuration, you need to run:
    systemctl reload apache2

有効にされた default-ssl.conf ファイルは /etc/apache2/sites-enabled/ 以下にコピーされる. Let's Encrypt から取得した証明書を使うように設定を書き換える. iot-XX の部分は自分のホスト名にあわせること.

# vi /etc/apache2/sites-enabled/default-ssl.conf 

  (以下の項目だけ書き換える. 公開鍵/秘密鍵の設定)
  #SSLCertificateFile      /etc/ssl/certs/ssl-cert-snakeoil.pem
  SSLCertificateFile     /etc/letsencrypt/live/iot-XX.epi.it.matsue-ct.jp/fullchain.pem

  #SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
  SSLCertificateKeyFile  /etc/letsencrypt/live/iot-XX.epi.it.matsue-ct.jp/privkey.pem

次に, 今までの http (80 ポート) 通信はすべて https へリダイレクトするようにする. 設定ファイルを追加する場合は, /etc/apache2/site-available/ 以下にファイルを作る.

# vi /etc/apache2/sites-available/redirect.conf

  (以下の内容を書く)
  <VirtualHost *:80>
      RewriteEngine On
      RewriteCond %{HTTPS} off
      RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [R=301,L]
  </VirtualHost>

1 行目の "RewriteEngine On" はリダイレクトを有効にする設定, 2 行目は, サーバ(Apache)への接続ポートが443番では無かったら(即ち、HTTPSでの接続ではなかったら), 次の 3 行目を適用するという意味である. 3 行目は正規表現でマッチングをし, http を https に置き換える ということを行なっている.

前述のリダイレクトを行うためには, rewrite モジュールを有効にする必要がある.

# a2enmod rewrite

  Enabling module rewrite.
  To activate the new configuration, you need to run:
    systemctl restart apache2

これまでの設定 (000-default.conf) の読み込みを止めて, 新しく作成した redirect.conf を読み込むようにする. a2ensite, a2dissite コマンドを使うが, それらは有効にする設定を /etc/apache2/sites-enabled/ 以下に置き, 無効にする設定を/etc/apache2/sites-enabled/ 以下から消すという作業を行なっている.

# ls /etc/apache2/sites-enabled/

  000-default.conf  default-ssl.conf 

# a2dissite 000-default

  Site 000-default disabled.
  To activate the new configuration, you need to run:
    systemctl reload apache2

# a2ensite redirect

  Enabling site redirect.
  To activate the new configuration, you need to run:
    systemctl reload apache2

# ls /etc/apache2/sites-enabled/

  default-ssl.conf   redirect.conf

apache2 を再起動して, 新たな設定ファイルを読み込む.

# /etc/init.d/apache2 restart

  [ ok ] Restarting apache2 (via systemctl): apache2.service.

# exit

$

ブラウザからアクセスすると (https://iot-XX.epi.it.matsue-ct.jp)

ブラウザに HTTP から始まる URL を入力すると (例えば, http://iot-XX.epi.it.matsue-ct.jp), ブラウザの URL が HTTPS から始まる URL (https://iot-XX.epi.it.matsue-ct.jp) に置き換わることもわかる.さらに,URL に鍵マークが付いており, HTTPS で通信していることがわかる.

また,証明書でホスト名が指定されているため,https://10.176.0.XXX のように IP アドレスを指定した場合には, 「プライバシーが保護できない」といったメッセージが出る.複数のホスト名を使いたい場合は,ホスト名毎に証明書を取得する必要がある.

ポートの確認

HTTPS が使えるようになったということは,HTTPS に対応するポートが外部に開放されたということも意味する. nmap で IP アドレスを引数に与えて実行すると,ポート番号 443 が外部に開放されたことが確認できる.

$ nmap 10.176.0.147

  PORT     STATE SERVICE
  22/tcp   open  ssh
  80/tcp   open  http
  443/tcp  open  https         <-- 追加!
  3000/tcp open  ppp

補足) SSL/TLS 証明書の更新

Let's Encrypt で発行される証明書の有効期限は 90 日である. 更新するときは, certbot renew コマンドで証明書を再取得する必要がある.

Basic 認証

本節では, セキュリティを担保するために, アクセス制限をかけることにする. PHP のセットアップ では, HTTP GET メソッドを用いて PHP スクリプトからデータベースにデータを入力した. 先の資料では特にアクセス制限をかけていないため, 悪意のあるユーザがおかしなデータをデータベースに入力することができてしまう.

Basic 認証は HTTP/HTTPS で利用できる基本的な認証システムである. 以下では https://iot-XX.epi.it.matsue-ct.jp/~hogehoge/php (XX は数字, hogehoge は自分のユーザ名) にアクセスする際にユーザ名とパスワードで認証するための設定を行う.

まず, 認証に用いるユーザ名とパスワードを設定する. -c オプションで認証情 報を保存するファイル(以下の例では .users) を指定する. ホームディレクト リ以下のファイルを指定することを推奨する. 間違っても ~/public_html 以下 に置かないこと, 他者にパスワード情報が漏洩します.

$ htpasswd -c ~/.users ユーザ名

  New password:                      <= パスワード入れる (コンソールには何も表示されない)
  Re-type new password:              <= パスワード入れる (コンソールには何も表示されない)
  Adding password for user herohero

次にアクセス制限をかけたいディレクトリに移動し, そこに設定ファイル (.htaccess) を新規作成する.

$ cd ~/public_html/php

$ vi .htaccess

  AuthType Basic                          <= Basic 認証であることを指定
  AuthName Sample                         <= 名前は何でも良い
  AuthUserFile /home/hogehoge/.users      <= 認証用ファイルの置き場. hogehoge は自分のユーザ名で置き換えること.
  require valid-user                      <= 認証用ファイルに書かれた有効なユーザなら認証 OK という書き方.

ブラウザから https://iot-XX.epi.it.matsue-ct.jp/~hogehoge/php (XX は数字, hogehoge は自分のユーザ名) にアクセスしてみて, 認証がうまくいくか確認すること.

課題 (1)

HTTPS の動作確認として,適当な Web ページを作成し,そのスクリーンショットを提出せよ.

  • スクリーンショットには必ずブラウザのアドレスバー (http://iot-XX.epi.it.matsue-ct.jp/~hogehoge/YYY.htm といった文字列が表示されている部分) を含めること.
  • 2 枚提出すること.1 枚は Basic 認証がなされていることを示すもの,もう 1 枚は自分の作った Web ページ.
    • 楽しいページほど良い評価をつけます.

課題 (2)

  • 次の単語の意味を調べて, wbt のオンラインテキストにまとめよ. なお, Let's Encrypt では OV 証明書や EV 証明書は取得できない.
    • 認証局
    • 中間証明書
    • 公開鍵
    • 秘密鍵
    • 自己署名 (オレオレ) 証明書
    • ドメイン検証 (Domain Validation) 型の証明書
    • Organization Validation (OV) 証明書
    • Extended Validation (EV) 証明書
  • Let's Encrypt では発行量無料の証明書が入手できるが, 一般的には証明書の発行料は安くない. Let's Encrypt 以外で証明書を取得する時の費用を調べよ (ベリサイン(Verisign, Inc.)やサイバートラストなどが有名).