クリーム色の背景、色付き表示、高コントラスト、大きな文字のほうが読みやすいですか?配色と文字を選ぶと、すべてのページに一度で反映されます。

無料レッスン

アプリの前に置くリバースプロキシ

このレッスンのあとで: アプリの前にnginxを置き、アプリに何が見えるかを説明できる。

55分のレッスンコマンド13件Web サーバー堅牢化のラボ:弱い nginx の設定を直して curl で確かめる

三つのアプリへの、一つの入り口

リバースプロキシは、アプリの前に立つサーバーです。訪問者のリクエストを受けて、アプリへ渡します。いくつものアプリに、一つの入り口、一つの記録、守る場所一つを与えます。

ある会社は、店、ブログ、社内ツールを動かしています。それぞれが別のポートで動く小さなプログラムで、どれも一つだけでインターネットに顔を出すべきではありません。

入り口を一つにして、訪問者を受け、正しいプログラムへ渡し、記録を一つだけ書きます。その入り口を、今日は一つ作ります。

このレッスンのゴール

メモ

アプリの前にnginxを置き、アプリに何が見えるかを説明できる。

重要な言葉

ことばいみれい
リバースプロキシ後ろにあるアプリへ、リクエストを渡すサーバー
アップストリームプロキシがリクエストを渡す先のアプリ
負荷分散リクエストを、複数のサーバーに分けること
502プロキシがアプリから返事をもらえなかったことを表す番号Bad Gateway
X-Forwarded-For本当の訪問者のアドレスを運ぶヘッダー
リロード動いているサーバーに、設定を読み直させること

学生が入力するセルは、このプレビューでは空白です。

リバースプロキシはアプリの代わりに答える

訪問者はリバースプロキシと話します。プロキシは、アプリ、つまりアップストリームに聞き、答えを返します。訪問者がアプリに会うことはありません。

ここでは、アプリもnginx自身で作ります。127.0.0.1 のポート9000にあり、この機器からしか届きません。プロキシはポート8080です。それぞれが一つのファイルを使います。

ポート9000のアプリを書く

コマンド
docker exec web sh -c "printf '%s\n' 'server {' '  listen 127.0.0.1:9000;' '  location / { return 200 \"アプリのサーバー: host=\$host forwarded=\$http_x_forwarded_for from=\$remote_addr\n\"; }' '}' > /etc/nginx/conf.d/app.conf"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ポート8080のプロキシを書く

コマンド
docker exec web sh -c "printf '%s\n' 'server {' '  listen 8080;' '  location / {' '    proxy_pass http://127.0.0.1:9000;' '    proxy_set_header Host \$host;' '    proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;' '  }' '}' > /etc/nginx/conf.d/proxy.conf"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

使う前に設定を試す

コマンド
docker exec web nginx -t

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

新しいファイルを読むようnginxをリロードする

コマンド
docker exec web nginx -s reload

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

プロキシ経由で聞く

コマンド
curl -s http://web:8080/

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

プロキシを通さず、アプリに直接聞く

コマンド
curl -sS -m 2 http://web:9000/; echo "exit code $?"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

ヘッダーが、誰が頼んだかを伝える

アプリは、プロキシを送り主だと見ました。本当に誰が頼んだかを知らせるため、プロキシは訪問者のアドレスを、ヘッダーX-Forwarded-Forに書きます。

訪問者が入力した名前も、Host ヘッダーで渡します。その行が無いと、nginxは代わりにアップストリームの名前を送ります。

偽の送り主を名乗るリクエストを送る

コマンド
curl -s -H 'X-Forwarded-For: 203.0.113.9' http://web:8080/

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

よくある間違い

注意

「X-Forwarded-Forの最初のアドレスは、いつも本当の訪問者だ」と考える人が多いのですが、訪問者はそのヘッダーを自分で書けます。信じてよいのは、自分のプロキシが足したアドレス、つまり一覧の最後のものだけです。

例: プロキシが渡すもの

proxy.confの行アプリが知ること
proxy_set_header Host $host;訪問者が入力した名前。ここでは web
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;一覧の最後に足された、訪問者のアドレス
Hostの行が無いアップストリームの名前。例えば pool

学生が入力するセルは、このプレビューでは空白です。

アプリが止まると502になる

アップストリームが答えないと、プロキシはページを取ってこられません。502、Bad Gatewayで答えます。プロキシは無事で、後ろのアプリが無事ではないという意味です。

一つの名前の後ろに二つのアプリを置くのが負荷分散です。nginxは順番にリクエストを渡すので、一つが落ちても、もう一つが答えます。

誰も待っていないポートへ向ける

コマンド
docker exec web sh -c "printf '%s\n' 'server {' '  listen 8080;' '  location / { proxy_pass http://127.0.0.1:9009; }' '}' > /etc/nginx/conf.d/proxy.conf && nginx -t && nginx -s reload"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

プロキシ経由で聞き、ステータスを読む

コマンド
curl -s -i http://web:8080/

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

失敗についてnginxが書いたものを読む

コマンド
docker logs web 2>&1 | grep -F "Connection refused" | tail -n 1

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

一つの名前の後ろに二つのアプリを置く

コマンド
docker exec web sh -c "printf '%s\n' 'upstream pool {' '  zone pool 64k;' '  server 127.0.0.1:9000;' '  server 127.0.0.1:9001;' '}' 'server {' '  listen 127.0.0.1:9001;' '  location / { return 200 \"二つ目のアプリのサーバー\n\"; }' '}' > /etc/nginx/conf.d/pool.conf && sed -i 's#127.0.0.1:9009#pool#' /etc/nginx/conf.d/proxy.conf && nginx -t && nginx -s reload"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

4回聞いて、順番に答えるのを見る

コマンド
for i in 1 2 3 4; do curl -s http://web:8080/; done

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

三つのファイルを消してリロードする

コマンド
docker exec web sh -c "rm -f /etc/nginx/conf.d/app.conf /etc/nginx/conf.d/proxy.conf /etc/nginx/conf.d/pool.conf; nginx -s reload"

ここでは表示のみで、実行されません。無料アカウントを作成すると、実行ボタンで自分のラボのターミナルに入力できます。

発展: host=pool と出た答え

四つの答えをもう一度見ましょう。ある種類の答えは、host=web ではなく host=pool と言っています。

ヘッダーの表のどの行が、それを説明しますか。アプリがまた host=web と言うように、プロキシの location ブロックに足す一行を書きましょう。

このラボとソースについて: Web サーバー堅牢化のラボ:弱い nginx の設定を直して curl で確かめる

授業で使いますか?このモジュールを学生に割り当てると、教員用ガイド、自動採点つきの課題、学生ごとのラボを使えます。