ポケモンクイズWebサイトのセキュリティ対策をする

(この記事は12月12日の分です。)

こんにちは。コーディング課3回生のYoneです。

前回は、Microsoft Azureの仮想マシン上にポケモンクイズのWebサイトを構築しました。

今回は、それを外部に公開できるようにWebサイトのセキュリティ対策などをします。具体的にすることは以下の通りです。

  1. ドメインを取得する
  2. Pythonファイルを直接実行するのではなく、Gunicornを使う
  3. リバースプロキシとして、Nginxを設置する
  4. HTTPS通信にするために、Let’s EncryptでSSL/TLS証明書を取得する

前回の記事はこちら↓

はじめに

今回も、Azure上の仮想マシンにSSH接続した状態で行います。

システム構成

システムの構成図は以下の通りです。

ドメインの取得

今まではSSH接続やWebサイトの接続にIPアドレスを使用していましたが、IPアドレスは覚えにくいのでドメインを取得してIPアドレスとの紐づけを行います。

無料でドメインを取得できるサービスはいくつかありますが、今回はMyDNS.JPを利用します。

MyDNS.JPとは

無料で利用できる動的(ダイナミック)DNSサービスです。動的DNSとは、インターネット上の端末に割り当てられるIPアドレスが動的に変化する場合でも、その端末に対して一定のホスト名(ドメイン名)でアクセスできるようにする仕組みです。

また、サブドメインも無料で提供されているのでこれを利用します。

MyDNS.JPの利用方法

以下のサイトが参考になったのでこちらを読んでください。

https://cyberhub.jp/posts/33

今回は、「pokequiz.mydns.jp」を取得しました。

注意点

MyDNS.JPのIPアドレスの登録について、そのままの設定ではログインしたデバイスのIPアドレスが登録されます。なので、普通にブラウザでログインすると手元のPCのIPアドレスが登録されます。Azureなどの外部マシンのIPアドレスを登録するには、以下の2つの方法のどちらかで登録してください。

1つ目

IPアドレスを登録したいマシンのコマンドライン上で、curl -u <id>:<password> https://www.mydns.jp/login.htmlを実行してください。

Login and IP address notify OK. login_status = 1 となればOKです。

2つ目

MyDNS.JPの「IP ADDR DIRECT」タブで、直接IPアドレスの編集ができます。Modeを「固定IP」とすると、ログインした端末のIPアドレスに関わらず指定したIPアドレスが通知されます。

確認ボタンを押すと確認画面が表示されるので、送信ボタンを押すと登録できます。

また、上記の記事にもありますが、IPアドレスを定期的に通知しないとアカウントごと削除されてしまうため、cronなどで定期的に通知してください。

Gunicornの設定

Gunicornとは

Gunicorn(Green Unicorn)は、FlaskなどのWebフレームワークで構築されたアプリケーションを外部に公開するためのWSGI(Web Server Gateway Interface)サーバーです。PythonのWebアプリケーションを効率的に動作させるための仕組みとして利用されます。

(前回の記事では、Flaskのデフォルトサーバーである「Werkzeug」を使用していました。これは本番環境での使用を想定していないため、Gunicornのような専用のサーバーを使うのが一般的です。)

インストール

前回作成したPythonの仮想環境に入り、pip install gunicornを実行します。

実行

プロジェクトディレクトリ内で、gunicorn -w <起動するプロセス数> -b 0.0.0.0:5000 '<インポートするモジュール>:<Flaskアプリを読み込む変数>'を実行すると、Gunicornを起動できます。今回は、gunicorn -w 2 -b 0.0.0.0:5000 'main:app'としています。

http://<取得したドメイン>:5000にアクセスすることでWebサイトを確認できます。(今回の例では、http://pokequiz.mydns.jp:5000)

使用するサーバーを前回ものから変更しただけなので、Webサイトの内容が変わったりすることはありません。

これでGunicornの設定は完了です。

次のNginx、Let’s Encryptの設定時にアクセスの確認を行うので、nohup gunicorn -w 2 -b 0.0.0.0:5000 'main:app' &で常にアクセスできるようにしておいてください。

Nginxの設定

Nginxとは

基本の機能としてはWebサーバーですが、それだけでなく、リバースプロキシやロードバランサーの役割も担うことができます。

今回は、リバースプロキシサーバーとして利用します。

Nginxのインストール

sudo apt update

sudo apt install nginx

設定ファイルの編集

/etc/nginx/sites-availableに移動して、sudo nano defaultでdefaultファイルを以下のように書き換えます。

今までは5000番ポートでHTTP通信をしていましたが基本は80番ポートで行うので、外部からの80番ポートを受け付けるようにしています。外部からの80番ポートのアクセスをGunicornに転送しています。

server {
    listen 80;
    server_name pokequiz.mydns.jp;

    location / {
        proxy_pass http://127.0.0.1:5000;  # Gunicornが5000番でlisten
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

設定後、sudo nginx -tで構文チェック、sudo systemctl restart nginxでNginxを再起動します。

80番ポートのアクセスを許可するために、受信ポートの規則から設定を変更してください。また、この後にHTTPS化するため、HTTPSの標準ポートである443番ポートのアクセスも許可しておいてください。

今までは5000番ポートでアクセスしていましたが、Nginxから間接的にアクセスするため5000番ポートへのアクセスが不要になりました。なので、5000番ポートを許可する設定を削除してください。

この時点でhttp://pokequiz.mydns.jpにアクセスするとFlaskアプリが表示されます。

ここまでできたら、Let’s Encryptの設定を行います。

Let’s Encryptの設定

Let’s Encryptとは

無料でWebサーバ向けのSSL/TLS証明書を発行している認証局です。
発行する証明書の有効期限は90日と、短めになっています。

HTTPS通信をすることで、HTTP通信よりも安全に通信することができます。

Certbotを使って証明書を取得する

Certbotを使って、自動で証明書の取得や更新を行います。これはLet’s Encrypt公式のクライアントツールです。

  1. sudo apt install certbot python3-certbot-nginxで、Certbotをインストールします。
  2. sudo certbot --nginx -d <取得したドメイン>で、SSL証明書を取得します。(今回は、sudo certbot --nginx -d pokequiz.mydns.jp)いくつか質問されるので回答します。

設定が完了すると、Successfully received certificate. と表示されます。

/etc/nginx/sites-available/defaultでNginxの設定ファイルを確認すると、以下のように自動で書き換わっています。

server {
    server_name pokequiz.mydns.jp;

    location / {
        proxy_pass http://127.0.0.1:5000;  # Gunicornが5000番でlisten
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/pokequiz.mydns.jp/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/pokequiz.mydns.jp/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

}
server {
    if ($host = pokequiz.mydns.jp) {
        return 301 https://$host$request_uri;
    } # managed by Certbot


    listen 80;
    server_name pokequiz.mydns.jp;
    return 404; # managed by Certbot


}

systemctl status certbot.timerで、証明書の自動更新の設定を確認します。

Active: active (waiting) の状態であれば、タイマーは正常に動作しています。
Trigger は次回のタイマー実行予定時刻を示します。

画像のような表示になれば、設定は完了です。

動作の確認

ブラウザにドメインを入力して、HTTPS接続ができていたら成功です。

ドメインの前に「https://」とありWebサイトが正常に表示できていたら、HTTPS接続ができています。

さいごに

全3回にわたってAzure仮想マシン上にWebサイトの構築を行いました。

ここまで長かったと思います。お疲れ様でした。

Webサイト構築の一連の流れが伝わったら嬉しいです。

今回作成したWebサイトはしばらく公開しておきますので、ぜひポケモンクイズにチャレンジしてみてください!

https://pokequiz.mydns.jp

コメントを残す

CAPTCHA