Ubuntu 16.04でmod_proxyを使用してApacheをリバースプロキシとして使用する方法

前書き

reverse proxyは、HTTP(S)要求を受け取り、それらを1つ以上のバックエンドサーバーに透過的に配布するプロキシサーバーの一種です。 多くの最新のWebアプリケーションは、ユーザーが直接アクセスすることを意図しておらず、多くの場合基本的なHTTP機能のみをサポートするバックエンドアプリケーションサーバーを使用して着信HTTPリクエストを処理するため、リバースプロキシが役立ちます。

リバースプロキシを使用して、これらの基になるアプリケーションサーバーが直接アクセスされるのを防ぐことができます。 また、これらを使用して、着信要求から複数の異なるアプリケーションサーバーに負荷を分散し、大規模なパフォーマンスを向上させ、フェイルセーフを実現できます。 キャッシング、圧縮、SSL暗号化など、アプリケーションサーバーが提供しない機能でギャップを埋めることができます。

このチュートリアルでは、mod_proxy拡張子を使用してApacheを基本的なリバースプロキシとして設定し、同じネットワーク上で実行されている1つまたは複数のバックエンドサーバーに着信接続をリダイレクトします。 このチュートリアルでは、Flask web frameworkで記述された単純なバックエンドを使用しますが、任意のバックエンドサーバーを使用できます。

前提条件

このチュートリアルを実行するには、次のものが必要です。

[[step-1 -—- enableing-necessary-apache-modules]] ==ステップ1—必要なApacheモジュールを有効にする

Apacheには多くのモジュールがバンドルされており、それらは利用可能ですが、新規インストールでは有効になりません。 まず、このチュートリアルで使用するものを有効にする必要があります。

必要なモジュールは、mod_proxy自体とそのアドオンモジュールのいくつかであり、さまざまなネットワークプロトコルをサポートするように機能を拡張します。 具体的には、次のものを使用します。

  • mod_proxy、接続をリダイレクトするためのメインプロキシモジュールApacheモジュール。これにより、Apacheが基盤となるアプリケーションサーバーへのゲートウェイとして機能できるようになります。

  • mod_proxy_http。HTTP接続のプロキシのサポートを追加します。

  • mod_proxy_balancerおよびmod_lbmethod_byrequests。複数のバックエンドサーバーに負荷分散機能を追加します。

これらの4つのモジュールを有効にするには、次のコマンドを連続して実行します。

sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests

これらの変更を有効にするには、Apacheを再起動します。

sudo systemctl restart apache2

Apacheは、HTTPリクエストのリバースプロキシとして機能する準備ができました。 次の(オプションの)ステップでは、2つの非常に基本的なバックエンドサーバーを作成します。 これらは、構成が適切に機能するかどうかを確認するのに役立ちますが、すでに独自のバックエンドアプリケーションがある場合は、手順3にスキップできます。

[[step-2 -—- creating-backend-test-servers]] ==ステップ2—バックエンドテストサーバーの作成

いくつかの単純なバックエンドサーバーを実行すると、Apache構成が適切に機能しているかどうかを簡単にテストできます。 ここでは、HTTP要求に応答してテキスト行を印刷する2つのテストサーバーを作成します。 一方のサーバーはHello world!と表示し、もう一方のサーバーはHowdy world!と表示します。

[.note]#Note:非テスト設定では、バックエンドサーバーは通常すべて同じ種類のコンテンツを返します。 ただし、特にこのテストでは、2つのサーバーが異なるメッセージを返すようにすることで、負荷分散メカニズムが両方を使用していることを簡単に確認できます。

Flaskは、Webアプリケーションを構築するためのPythonマイクロフレームワークです。 基本的なアプリでは数行のコードしか必要ないため、Flaskを使用してテストサーバーを作成しています。 これらを設定するためにPythonを知っている必要はありませんが、学習したい場合は、these Python tutorialsを確認できます。

最初にパッケージリストを更新します。

sudo apt-get update

次に、推奨されるPythonパッケージマネージャーであるPipをインストールします。

sudo apt-get -y install python3-pip

Pipを使用してFlaskをインストールします。

sudo pip3 install flask

必要なすべてのコンポーネントがインストールされたので、現在のユーザーのホームディレクトリに最初のバックエンドサーバーのコードを含む新しいファイルを作成することから始めます。

nano ~/backend1.py

次のコードをファイルにコピーし、保存して閉じます。

~/backend1.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return 'Hello world!'

最初の2行は、Flaskフレームワークを初期化します。 1行のテキスト(Hello world!)を返す1つの関数home()があります。 home()関数定義の上の@app.route('/')行は、アプリケーションの/ルートURLに向けられたHTTP要求への応答としてhome()の戻り値を使用するようにFlaskに指示します。

2番目のバックエンドサーバーは、最初のサーバーとまったく同じですが、異なるテキスト行に戻ることを除けば、最初のファイルを複製することから始めます。

cp ~/backend1.py ~/backend2.py

新しくコピーしたファイルを開きます。

nano ~/backend2.py

返されるメッセージをHello world!からHowdy world!に変更し、ファイルを保存して閉じます。

~/backend2.py

from flask import Flask
app = Flask(__name__)

@app.route('/')
def home():
    return 'Howdy world!'

次のコマンドを使用して、ポート8080で最初のバックグラウンドサーバーを起動します。 これにより、Flaskの出力が/dev/nullにリダイレクトされます。これは、コンソール出力がさらに曇ってしまうためです。

FLASK_APP=~/backend1.py flask run --port=8080 >/dev/null 2>&1 &

ここでは、flaskコマンドの前に、同じ行にFLASK_APP環境変数を設定しています。 環境変数は、シェルから生成されるプロセスに情報を渡す便利な方法です。 環境変数の詳細については、How To Read and Set Environmental and Shell Variables on a Linux VPSを参照してください。

この場合、環境変数を使用すると、設定が実行中のコマンドにのみ適用され、その後は使用できなくなります。これは、flaskコマンドに2番目のサーバーを起動するように指示するのと同じ方法で別のファイル名を渡すためです。

同様に、このコマンドを使用して、ポート8081で2番目のサーバーを起動します。 FLASK_APP環境変数の値が異なることに注意してください。

FLASK_APP=~/backend2.py flask run --port=8081 >/dev/null 2>&1 &

curlを使用して、2つのサーバーが実行されていることをテストできます。 最初のサーバーをテストします。

curl http://127.0.0.1:8080/

これにより、端末にHello world!が出力されます。 2番目のサーバーをテストします。

curl http://127.0.0.1:8081/

代わりにHowdy world!が出力されます。

[.note]#Note:このチュートリアルを終了するときのように、両方のテストサーバーが不要になった後で閉じるには、killall flask
#を実行するだけです。

次のステップでは、Apacheの構成ファイルを変更して、リバースプロキシとして使用できるようにします。

[[step-3 -—- modifying-the-default-configuration-to-enable-reverse-proxy]] ==ステップ3—デフォルト構成を変更してリバースプロキシを有効にする

このセクションでは、デフォルトのApache仮想ホストを設定して、単一のバックエンドサーバーまたは負荷分散されたバックエンドサーバーのアレイのリバースプロキシとして機能します。

[。注意]##

Note:このチュートリアルでは、仮想ホストレベルで構成を適用します。 Apacheのデフォルトのインストールでは、単一のデフォルトの仮想ホストのみが有効になっています。 ただし、他の仮想ホストでもこれらの構成フラグメントをすべて使用できます。 Apacheの仮想ホストの詳細については、このHow To Set Up Apache Virtual Hosts on Ubuntu 16.04チュートリアルをお読みください。

ApacheサーバーがHTTPサーバーとHTTPSサーバーの両方として機能する場合は、HTTPとHTTPSの両方の仮想ホストにリバースプロキシ構成を配置する必要があります。 Apacheを使用したSSLの詳細については、このHow To Create a Self-Signed SSL Certificate for Apache in Ubuntu 16.04チュートリアルを参照してください。

nanoまたはお気に入りのテキストエディタを使用して、デフォルトのApache設定ファイルを開きます。

sudo nano /etc/apache2/sites-available/000-default.conf

そのファイル内には、最初の行から始まる<VirtualHost *:80>ブロックがあります。 以下の最初の例では、このブロックを単一のバックエンドサーバーのリバースプロキシに構成する方法を説明し、2番目の例では複数のバックエンドサーバーの負荷分散リバースプロキシを設定します。

[[example-1 -—- reverse-proxying-a-single-backend-server]] ===例1—単一のバックエンドサーバーのリバースプロキシ

VirtualHostブロック内のすべての内容を次のように置き換えると、構成ファイルは次のようになります。

/etc/apache2/sites-available/000-default.conf


    ProxyPreserveHost On

    ProxyPass / http://127.0.0.1:8080/
    ProxyPassReverse / http://127.0.0.1:8080/

手順2でサーバーの例を実行した場合は、上記のブロックに記述されているように127.0.0.1:8080を使用します。 独自のアプリケーションサーバーがある場合は、代わりにそのアドレスを使用します。

ここには3つのディレクティブがあります。

  • ProxyPreserveHostにより、Apacheは元のHostヘッダーをバックエンドサーバーに渡します。 これは、アプリケーションへのアクセスに使用されるアドレスをバックエンドサーバーに認識させるので便利です。

  • ProxyPassは、メインのプロキシ構成ディレクティブです。 この場合、ルートURL(/)の下にあるすべてのものを、指定されたアドレスのバックエンドサーバーにマップする必要があることを指定します。 たとえば、Apacheが/exampleの要求を受け取ると、http://your_backend_server/exampleに接続し、元のクライアントに応答を返します。

  • ProxyPassReverseは、ProxyPassと同じ構成にする必要があります。 Apacheにバックエンドサーバーからの応答ヘッダーを変更するよう指示します。 これにより、バックエンドサーバーがロケーションリダイレクトヘッダーを返す場合、クライアントのブラウザーはバックエンドサーバーアドレスではなくプロキシアドレスにリダイレクトされます。これは意図したとおりに機能しません。

これらの変更を有効にするには、Apacheを再起動します。

sudo systemctl restart apache2

これで、Webブラウザーでhttp://your_server_ipにアクセスすると、標準のApacheウェルカムページの代わりにバックエンドサーバーの応答が表示されます。 手順2に従った場合、これはHellow world!が表示されることを意味します。

[[example-2 -—- load-balancing-across-multiple-backend-servers]] ===例2—複数のバックエンドサーバー間での負荷分散

複数のバックエンドサーバーがある場合、プロキシ時にトラフィックをサーバー間で分散する良い方法は、mod_proxyの負荷分散機能を使用することです。

VirtualHostブロック内のすべての内容を次のように置き換えると、構成ファイルは次のようになります。

/etc/apache2/sites-available/000-default.conf



    BalancerMember http://127.0.0.1:8080
    BalancerMember http://127.0.0.1:8081


    ProxyPreserveHost On

    ProxyPass / balancer://mycluster/
    ProxyPassReverse / balancer://mycluster/

構成は前の構成と似ていますが、単一のバックエンドサーバーを直接指定する代わりに、追加のProxyブロックを使用して複数のサーバーを定義しました。 ブロックの名前はbalancer://mycluster(名前は自由に変更できます)で、1つ以上のBalancerMember+`s, which specify the underlying backend server addresses. The `+ProxyPassで構成され、ProxyPassReverseディレクティブは特定の代わりにmyclusterという名前のロードバランサープールを使用しますサーバ。

手順2のサーバーの例に従った場合は、上記のブロックに記述されているように、BalancerMemberディレクティブに127.0.0.1:8080127.0.0.1:8081を使用します。 独自のアプリケーションサーバーがある場合は、代わりにそのアドレスを使用します。

これらの変更を有効にするには、Apacheを再起動します。

sudo systemctl restart apache2

Webブラウザでhttp://your_server_ipにアクセスすると、標準のApacheページではなく、バックエンドサーバーの応答が表示されます。 手順2を実行した場合、ページを複数回更新すると、Hello world!Howdy world!が表示されます。これは、リバースプロキシが機能し、両方のサーバー間で負荷分散されていることを意味します。

結論

これで、Apacheを1つ以上の基礎となるアプリケーションサーバーへのリバースプロキシとして設定する方法がわかりました。 mod_proxyを効果的に使用して、PythonとDjango、RubyとRuby on Railsなど、さまざまな言語とテクノロジーで記述されたアプリケーションサーバーへのリバースプロキシを構成できます。 また、トラフィックの多いサイトの複数のバックエンドサーバー間のトラフィックのバランスをとったり、複数のサーバーで高可用性を提供したり、SSLをネイティブにサポートしていないバックエンドサーバーに安全なSSLサポートを提供したりするためにも使用できます。

mod_proxymod_proxy_httpは、おそらく最も一般的に使用されるモジュールの組み合わせですが、さまざまなネットワークプロトコルをサポートする他のいくつかの組み合わせがあります。 ここでは使用しませんでしたが、他の一般的なモジュールには次のものがあります。

  • FTPの場合はmod_proxy_ftp

  • SSLトンネリングの場合はmod_proxy_connect

  • TomcatベースのバックエンドのようなAJP(Apache JServ Protocol)のmod_proxy_ajp

  • Webソケットの場合はmod_proxy_wstunnel

mod_proxyの詳細については、the official Apache mod_proxy documentationを参照してください。

Related