Apache 搭載の Linux で ASP.NET Core をホストする

作成者: Shayne Boyer

このガイドを使用して、CentOS 7 上にリバース プロキシ サーバーとして Apache を設定し、Kestrel サーバー上で実行されている ASP.NET Core Web アプリに HTTP トラフィックをリダイレクトする方法について学習します。 mod_proxy 拡張機能および関連するモジュールは、サーバーのリバース プロキシを作成します。

注意事項

この記事では、有効期間の終了 (EOL) 状態が近づいている Linux ディストリビューションである CentOS を参照しています。 適宜、使用と計画を検討してください。 詳細については、「CentOS のサポート終了に関するガイダンス」を参照してください。

前提条件

  • CentOS 7 を実行しているサーバーと、sudo 特権を持つ標準ユーザー アカウント。
  • サーバーへの .NET Core ランタイムのインストール。
    1. .NET Core のダウンロード」ページにアクセスします。
    2. プレビューでない最新の .NET Core バージョンを選択します。
    3. [Run apps - Runtime](アプリの実行 - ランタイム) の下の表でプレビューでない最新のランタイムをダウンロードします。
    4. Linux の 「パッケージ マネージャーの手順」 リンクを選択し、CentOS の手順に従います。
  • 既存の ASP.NET Core アプリ。

共有フレームワークをアップグレードした後の任意の時点で、サーバーによってホストされている ASP.NET Core アプリを再起動します。

アプリを介して発行およびコピーする

フレームワークに依存する展開用にアプリを構成します。

アプリが開発環境のローカルで実行され、セキュリティで保護された HTTPS 接続を行うようにサーバーによって構成されていない場合は、次のいずれかの方法を採用してください。

  • セキュリティで保護されたローカル接続を処理するようにアプリを構成します。 詳しくは、「HTTPS の構成」セクションをご覧ください。

  • セキュリティで保護されていないエンドポイントで実行するようにアプリを構成します。

    • 開発環境 (Program.cs) で HTTPS リダイレクト ミドルウェアを非アクティブ化します。

      if (!app.Environment.IsDevelopment())
      {
          app.UseHttpsRedirection();
      }
      

      詳細については、「ASP.NET Core で複数の環境を使用する」を参照してください。

    • Properties/launchSettings.json ファイルの applicationUrl プロパティから https://localhost:5001 を削除します (ある場合)。

環境別の構成については、「ASP.NET Core で複数の環境を使用する」を参照してください。

開発環境から dotnet publish を実行して、サーバー上で実行できるディレクトリ (例: bin/Release/{TARGET FRAMEWORK MONIKER}/publish。このプレースホルダー {TARGET FRAMEWORK MONIKER}ターゲット フレームワーク モニカー (TFM) です) にアプリをパッケージします。

dotnet publish --configuration Release

サーバーで .NET Core ランタイムを管理しない場合、アプリは独立した展開として発行することもできます。

組織のワークフローに統合されているツール (SCP や SFTP など) を使用して、サーバーに ASP.NET Core アプリをコピーします。 Web アプリは一般的に var ディレクトリの下に配置されます (たとえば、var/www/helloapp)。

Note

運用展開シナリオの場合、継続的インテグレーション ワークフローが、アプリの発行処理とサーバーへの資産のコピーを行います。

プロキシ サーバーを構成する

リバース プロキシは、動的 Web アプリを提供するための一般的な仕組みです。 リバース プロキシは HTTP 要求を終了させ、ASP.NET アプリに転送します。

プロキシ サーバーでは、要求自体を実行せずに、別のサーバーにクライアント要求が転送されます。 リバース プロキシは、一般的に任意のクライアントに代わって固定の送信先に転送します。 このガイドでは、Kestrel が ASP.NET Core アプリを提供しているものと同じサーバー上で実行されるリバース プロキシとして Apache を構成します。

要求はリバース プロキシによって転送されます。そのため、Microsoft.AspNetCore.HttpOverrides パッケージの Forwarded Headers Middleware を使用します。 リダイレクト URI とその他のセキュリティ ポリシーを正しく機能させるために、このミドルウェアは、X-Forwarded-Proto ヘッダーを利用して、Request.Scheme を更新します。

認証、リンクの生成、リダイレクト、および地理的位置情報など、スキームに依存するすべてのコンポーネントは、Forwarded Headers Middleware の呼び出し後に配置する必要があります。

Forwarded Headers Middleware は、他のミドルウェアの前に実行する必要があります。 この順序により、転送されるヘッダー情報に依存するミドルウェアが処理にヘッダー値を使用できます。 診断およびエラー処理ミドルウェアの後に Forwarded Headers Middleware を実行する方法については、「Forwarded Headers Middleware の順序」を参照してください。

他のミドルウェアを呼び出す前に、Startup.Configure の一番上にある UseForwardedHeaders メソッドを呼び出します。 ミドルウェアを構成して、X-Forwarded-For および X-Forwarded-Proto ヘッダーを転送します。

名前空間 Microsoft.AspNetCore.HttpOverrides をファイルの先頭に追加します。

using Microsoft.AspNetCore.HttpOverrides;

アプリ処理パイプラインで、次の処理を行います。

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

app.UseAuthentication();

ミドルウェアに対して ForwardedHeadersOptions が指定されていない場合、転送される既定のヘッダーは None です。

標準 localhost アドレス (127.0.0.1) を含むループバック アドレス (127.0.0.0/8, [::1]) 上で実行されるプロキシは、既定で信頼されます。 組織内のその他の信頼されているプロキシまたはネットワークによってインターネットと Web サーバーの間の要求が処理される場合は、それらを、ForwardedHeadersOptions を使用して KnownProxies または KnownNetworks のリストに追加します。 次の例では、IP アドレス 10.0.0.100 にある信頼されているプロキシ サーバーが Startup.ConfigureServices 内の Forwarded Headers Middleware KnownProxies に追加されます。

名前空間 System.Net をファイルの先頭に追加します。

using System.Net;

次のサービス登録を使用します。

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

詳細については、「プロキシ サーバーとロード バランサーを使用するために ASP.NET Core を構成する」を参照してください。

Apache をインストールする

CentOS パッケージを最新の安定したバージョンに更新します。

sudo yum update -y

1 つの yum コマンドで、CentOS に Apache Web サーバーをインストールします。

sudo yum -y install httpd mod_ssl

コマンド実行後の出力例:

Downloading packages:
httpd-2.4.6-40.el7.centos.4.x86_64.rpm               | 2.7 MB  00:00:01
Running transaction check
Running transaction test
Transaction test succeeded
Running transaction
Installing : httpd-2.4.6-40.el7.centos.4.x86_64      1/1 
Verifying  : httpd-2.4.6-40.el7.centos.4.x86_64      1/1 

Installed:
httpd.x86_64 0:2.4.6-40.el7.centos.4

Complete!

Note

この例では、CentOS 7 のバージョンが 64 ビットなので、出力は httpd.86_64 を反映しています。 Apache がインストールされている場所を確認するには、コマンド プロンプトから whereis httpd を実行します。

Apache を構成する

Apache の構成ファイルは、/etc/httpd/conf.d/ ディレクトリ内にあります。 Ubuntu 上の Apache では、すべての仮想ホスト構成ファイルが /etc/apache2/sites-available に格納されています。 /etc/httpd/conf.modules.d/ 内のモジュール構成ファイルに加え、拡張子が .conf のファイルがアルファベット順で処理されます。このディレクトリには、モジュールの読み込みに必要な構成ファイルが含まれています。

アプリ用に helloapp.conf という名前の構成ファイルを作成します。

<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}s
</VirtualHost>

<VirtualHost *:80>
    ProxyPreserveHost On
    ProxyPass / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5000/
    ServerName www.example.com
    ServerAlias *.example.com
    ErrorLog ${APACHE_LOG_DIR}/helloapp-error.log
    CustomLog ${APACHE_LOG_DIR}/helloapp-access.log common
</VirtualHost>

注: 2.4.6 より前の Apache バージョンでは、RequestHeader set の末尾に s を含める必要はありません。

<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>

詳しくは、「Apache モジュール mod_headers」の %{VARNAME}s をご覧ください。

VirtualHost ブロックは、サーバー上の 1 つまたは複数のファイルに複数回出現することができます。 上記の構成ファイルでは、Apache はポート 80 でパブリック トラフィックを受け入れます。 ドメイン www.example.com が提供されており、別名 *.example.com は同じ Web サイトに解決されます。 詳細については、名前ベースのバーチャル ホストのサポートに関するページを参照してください。 要求は、ルートにおいて、127.0.0.1 にあるサーバーのポート 5000 にプロキシされます。 双方向通信の場合は、ProxyPassProxyPassReverse が必要です。 Kestrel の IP/ポートを変更する場合は、Kestrel のエンドポイントの構成に関する記事を参照してください。

VirtualHost ブロックは、サーバー上の 1 つまたは複数のファイルに複数回出現することができます。 上記の構成ファイルでは、Apache はポート 80 でパブリック トラフィックを受け入れます。 ドメイン www.example.com が提供されており、別名 *.example.com は同じ Web サイトに解決されます。 詳細については、名前ベースのバーチャル ホストのサポートに関するページを参照してください。 要求は、ルートにおいて、127.0.0.1 にあるサーバーのポート 5000 にプロキシされます。 双方向通信の場合は、ProxyPassProxyPassReverse が必要です。 Kestrel の IP/ポートを変更する場合は、Kestrel のエンドポイントの構成に関する記事を参照してください。

Apache が起動時に読み取る /etc/apache2/sites-enabled ディレクトリへのシンボリック リンクを作成します。

sudo ln -s /etc/apache2/sites-available/helloapp.conf /etc/apache2/sites-enabled/

警告

VirtualHost ブロックで適切な ServerName ディレクティブを指定しないと、アプリにセキュリティ上の脆弱性が生じます。 親ドメイン全体を制御する場合、サブドメイン ワイルドカード バインド (たとえば、*.example.com) にこのセキュリティ リスクはありません (脆弱である *.com とは対照的)。 詳細については、RFC 9110: HTTP セマンティクス (セクション 7.2: 「Host and :authority (ホストと :authority)」) に関するページを参照してください。

ErrorLog および CustomLog ディレクティブを使って、VirtualHost ごとにログを構成できます。 ErrorLog は、サーバーがエラーをログに記録する場所です。CustomLog には、ログ ファイルのファイル名と形式を設定します。 この例では、要求の情報がログに記録される場所です。 1 つの要求につき 1 行が記録されます。

ファイルを保存し、構成をテストします。 すべてに合格すると、応答は Syntax [OK] になります。

sudo apachectl configtest

Apache を再起動します。

sudo systemctl restart httpd
sudo systemctl enable httpd

ヘッダー ディレクティブの値について詳しくは、「Apache モジュール mod_headers」を参照してください。

アプリを監視する

これで、http://localhost:80 に対して行われた要求を http://127.0.0.1:5000 の Kestrel で実行されている ASP.NET Core アプリに転送するように Apache が設定されました。 ただし、Apache は Kestrel プロセスを管理するようには設定されていません。 systemd を使って、基礎 Web アプリを起動して監視するサービス ファイルを作成します。 systemd は init システムであり、プロセスを起動、停止、管理するためのさまざまな高性能機能を提供します。

サービス ファイルを作成する

次のように、サービス定義ファイルを作成します。

sudo nano /etc/systemd/system/kestrel-helloapp.service

アプリのサービス ファイルの例を次に示します。

[Unit]
Description=Example .NET Web API App running on CentOS 7

[Service]
WorkingDirectory=/var/www/helloapp
ExecStart=/usr/local/bin/dotnet /var/www/helloapp/helloapp.dll
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=dotnet-example
User=apache
Environment=ASPNETCORE_ENVIRONMENT=Production 

[Install]
WantedBy=multi-user.target

注: お使いのディストリビューションの local/bin フォルダーを設定します。 Ubuntu の一部のバージョンには ExecStart=/usr/bin/dotnet が必要です

前の例では、サービスを管理するユーザーは User オプションによって指定されています。 ユーザー (apache) が存在し、アプリのファイルの適切な所有権を持っている必要があります。

アプリが最初の割り込み信号を受信してからシャットダウンするのを待機する期間を構成するには、TimeoutStopSec を使用します。 この期間内にアプリがシャットダウンしない場合は、SIGKILL を発行してアプリを終了します。 タイムアウトを無効にするには、値として、単位なしの秒数 (150 など)、期間の値 (2min 30s など)、または infinity を指定します。 TimeoutStopSec は、既定ではマネージャー構成ファイル (systemd-system.confsystem.conf.dsystemd-user.confuser.conf.d) 内の DefaultTimeoutStopSec の値に設定されます。 ほとんどのディストリビューションにおいて、タイムアウトの既定値は 90 秒となります。

# The default value is 90 seconds for most distributions.
TimeoutStopSec=90

構成プロバイダーが環境変数を読み取れるようにするために、一部の値 (たとえば SQL の接続文字列) をエスケープする必要があります。 次のコマンドを使用して、構成ファイルで使用するために適切にエスケープされた値を生成します。

systemd-escape "<value-to-escape>"

コロン (:) 区切り記号は、環境変数の名前ではサポートされていません。 コロンの代わりに 2 つのアンダースコア (__) を使用します。 環境変数が構成に読み取られるときに、環境変数構成プロバイダーによって 2 つのアンダースコアがコロンに変換されます。 次の例では、接続文字列キー ConnectionStrings:DefaultConnection はサービス定義ファイルでは ConnectionStrings__DefaultConnection と設定されています。

コロン (:) 区切り記号は、環境変数の名前ではサポートされていません。 コロンの代わりに 2 つのアンダースコア (__) を使用します。 環境変数が構成に読み取られるときに、環境変数構成プロバイダーによって 2 つのアンダースコアがコロンに変換されます。 次の例では、接続文字列キー ConnectionStrings:DefaultConnection はサービス定義ファイルでは ConnectionStrings__DefaultConnection と設定されています。

Environment=ConnectionStrings__DefaultConnection={Connection String}

ファイルを保存し、サービスを有効にします。

sudo systemctl enable kestrel-helloapp.service

サービスを起動し、動作を確認します。

sudo systemctl start kestrel-helloapp.service
sudo systemctl status kestrel-helloapp.service

◝ kestrel-helloapp.service - Example .NET Web API App running on CentOS 7
    Loaded: loaded (/etc/systemd/system/kestrel-helloapp.service; enabled)
    Active: active (running) since Thu 2016-10-18 04:09:35 NZDT; 35s ago
Main PID: 9021 (dotnet)
    CGroup: /system.slice/kestrel-helloapp.service
            └─9021 /usr/local/bin/dotnet /var/www/helloapp/helloapp.dll

構成されたリバース プロキシと systemd 経由で管理される Kestrel を使用して、Web アプリが完全に構成され、http://localhost のローカル コンピューター上のブラウザーからアクセスできます。 応答ヘッダーを調べると、ASP.NET Core アプリが Kestrel によって提供されていることが Server ヘッダーに示されています。

HTTP/1.1 200 OK
Date: Tue, 11 Oct 2016 16:22:23 GMT
Server: Kestrel
Keep-Alive: timeout=5, max=98
Connection: Keep-Alive
Transfer-Encoding: chunked

ログを表示する

Kestrel を使う Web アプリは systemd を使って管理されるため、イベントとプロセスは中心的ジャーナルに記録されます。 ただし、このジャーナルには、systemd によって管理されるすべてのサービスとプロセスのエントリが含まれます。 kestrel-helloapp.service 固有の項目を表示するには、次のコマンドを使用します。

sudo journalctl -fu kestrel-helloapp.service

時間フィルタリングの場合は、コマンドで時間のオプションを指定します。 たとえば、現在の日付でフィルター処理するには --since today を使い、前の 1 時間のエントリを参照するには --until 1 hour ago を使います。 詳しくは、journalctl の man ページをご覧ください。

sudo journalctl -fu kestrel-helloapp.service --since "2016-10-18" --until "2016-10-18 04:00"

データの保護

ASP.NET Core データ保護スタックは、認証ミドルウェア (cookie ミドルウェアなど) やクロスサイト リクエスト フォージェリ (CSRF) 保護を含む、いくつかの ASP.NET Core ミドルウェアで使用されます。 データ保護 API がユーザーのコードから呼び出されない場合でも、永続的な暗号化キー ストアを作成するようにデータ保護を構成する必要があります。 データ保護を構成しない場合、既定でキーはメモリ内に保持され、アプリが再起動すると破棄されます。

キーリングがメモリに格納されている場合、アプリを再起動すると次のことが行われます。

  • すべての cookie ベースの認証トークンは無効になります。
  • ユーザーは、次回の要求時に再度サインインする必要があります。
  • キーリングで保護されているデータは、いずれも復号化できなくなります。 これには、CSRF トークンASP.NET Core MVC TempData cookie が含まれます。

キー リングを永続化して暗号化するようにデータ保護を構成する場合は、次を参照してください。

アプリをセキュリティで保護する

ファイアウォールを構成する

Firewalld は、ネットワーク ゾーンをサポートするファイアウォールを管理するための動的デーモンです。 ポートとパケットのフィルター処理は、iptables によって引き続き管理できます。 Firewalld は既定でインストールされます。 yum を使ってパッケージをインストールしたり、インストールされていることを確認したりできます。

sudo yum install firewalld -y

アプリに必要なポートのみを開くには、firewalld を使います。 この場合、ポート 80 と 443 が使用されています。 次のコマンドは、ポート 80 と 443 が永続的に開かれるように設定します。

sudo firewall-cmd --add-port=80/tcp --permanent
sudo firewall-cmd --add-port=443/tcp --permanent

ファイアウォールの設定を再度読み込みます。 既定のゾーンで使用できるサービスとポートを確認します。 オプションは firewall-cmd -h を調べることで使用できます。

sudo firewall-cmd --reload
sudo firewall-cmd --list-all
public (default, active)
interfaces: eth0
sources: 
services: dhcpv6-client
ports: 443/tcp 80/tcp
masquerade: no
forward-ports: 
icmp-blocks: 
rich rules: 

HTTPS の構成

セキュリティで保護された (HTTPS) ローカル接続用にアプリを構成する

dotnet run コマンドでは、アプリの Properties/launchSettings.json ファイルが使用されます。このファイルでは、applicationUrl プロパティによって提供される URL でリッスンするように、アプリが構成されます (例: https://localhost:5001;http://localhost:5000)。

次のいずれかの方法を使用して、dotnet run コマンド用の開発または開発環境 (Visual Studio Code の F5 または Ctrl + F5 キー) で証明書を使用するように、アプリを構成します。

セキュリティで保護された (HTTPS) クライアント接続用にリバース プロキシを構成する

警告

このセクションのセキュリティ構成は、さらにカスタマイズするための出発点として使用される一般的な構成です。 サードパーティ製のツール、サーバー、およびオペレーティング システムに対しては、サポートを提供できません。 "このセクションの構成は、自己責任で使用してください。 " 詳細については、次のリソースをご覧ください。

HTTPS 用に Apache を構成するには、mod_ssl モジュールを使います。 httpd モジュールがインストールされていると、mod_ssl モジュールもインストールされています。 インストールされていない場合は、yum を使って構成に追加します。

sudo yum install mod_ssl

HTTPS を強制するには、mod_rewrite モジュールをインストールして URL の書き換えを有効にします。

sudo yum install mod_rewrite

helloapp.conf ファイルを変更して、ポート 443 での通信をセキュリティで保護します。

次の例では、セキュリティで保護されていない要求をリダイレクトするようにサーバーを構成していません。 HTTPS リダイレクト ミドルウェアを使用することをお勧めします。 詳細については、「ASP.NET Core で HTTPS を適用する」を参照してください。

Note

サーバー構成で HTTPS リダイレクト ミドルウェアではなくセキュリティで保護されたリダイレクトを処理する開発環境では、永続的なリダイレクト (301) ではなく、一時的なリダイレクト (302) を使用することをお勧めします。 リンク キャッシュを使用すると、開発環境で不安定な動作が発生する可能性があります。

Strict-Transport-Security (HSTS) ヘッダーを追加すると、クライアントが行う後続のすべての要求が HTTPS 経由になります。 Strict-Transport-Security ヘッダーの設定に関するガイダンスについては、「ASP.NET Core で HTTPS を適用する」を参照してください。

<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>

<VirtualHost *:443>
    Protocols             h2 http/1.1
    ProxyPreserveHost     On
    ProxyPass             / http://127.0.0.1:5000/
    ProxyPassReverse      / http://127.0.0.1:5000/
    ErrorLog              /var/log/httpd/helloapp-error.log
    CustomLog             /var/log/httpd/helloapp-access.log common
    SSLEngine             on
    SSLProtocol           all -SSLv3 -TLSv1 -TLSv1.1
    SSLHonorCipherOrder   off
    SSLCompression        off
    SSLSessionTickets     on
    SSLUseStapling        off
    SSLCertificateFile    /etc/pki/tls/certs/localhost.crt
    SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
    SSLCipherSuite        ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
</VirtualHost>

Note

この例では、ローカルで生成された証明書を使います。 SSLCertificateFile は、ドメイン名のプライマリ証明書ファイルです。 SSLCertificateKeyFile は、CSR の作成時に生成されるキー ファイルです。 SSLCertificateChainFile は、証明機関から提供された中間証明書ファイル (存在する場合) です。

OpenSSL 1.1.1 で TLS 1.3 Web サーバーを操作するには、Apache HTTP Server バージョン 2.4.43 以降が必要です。

Note

前の例では、オンライン証明書状態プロトコル (OCSP) のスタンプを無効にしています。 OCSP を有効にする方法の詳細とガイダンスについては、「OCSP Stapling」 (Apache ドキュメント) を参照してください。

ファイルを保存し、構成をテストします。

sudo service httpd configtest

Apache を再起動します。

sudo systemctl restart httpd

Apache に関するその他の推奨事項

共有されたフレームワークの更新プログラムを使用してアプリを再起動する

サーバー上で共有フレームワークをアップグレードしたら、サーバーによってホストされている ASP.NET Core アプリを再起動します。

その他のヘッダー

悪意のある攻撃からセキュリティで保護するために、変更または追加する必要があるヘッダーがいくつかあります。 必ず mod_headers モジュールをインストールします。

sudo yum install mod_headers

Apache をクリックジャッキング攻撃から保護する

クリックジャッキングは "UI 着せ替え攻撃" とも呼ばれ、Web サイトの訪問者を騙して現在訪れているものとは異なるページのリンクやボタンをクリックさせる悪意のある攻撃です。 サイトをセキュリティで保護するには、X-FRAME-OPTIONS を使います。

クリックジャッキング攻撃を軽減するには、次の手順に従います。

  1. httpd.conf ファイルを編集します。

    sudo nano /etc/httpd/conf/httpd.conf
    

    Header append X-FRAME-OPTIONS "SAMEORIGIN" を追加します。

  2. ファイルを保存します。

  3. Apache を再起動します。

MIME タイプ スニッフィング

X-Content-Type-Options ヘッダーは、Internet Explorer を "MIME スニッフィング" から防ぎます (ファイルの内容からファイルの Content-Type を判断します)。 サーバーが nosniff オプションを指定して Content-Type ヘッダーを text/html に設定すると、Internet Explorer はファイルの内容に関係なく text/html として内容をレンダリングします。

httpd.conf ファイルを編集します。

sudo nano /etc/httpd/conf/httpd.conf

Header set X-Content-Type-Options "nosniff" を追加します。 ファイルを保存します。 Apache を再起動します。

負荷分散

この例では、同じインスタンス コンピューターの CentOS 7 と Kestrel に、Apache をセットアップおよび構成する方法を示します。 単一障害点を持たないように、mod_proxy_balancer を使い、VirtualHost を変更することで、Apache プロキシ サーバーの背後で Web アプリの複数インスタンスを管理できるようにします。

sudo yum install mod_proxy_balancer

次に示す構成ファイルでは、ポート 5001 上で実行するように helloapp の追加インスタンスを設定しています。 Proxy セクションは、2 メンバーのバランサー構成を使って byrequests を負荷分散するように設定されています。

<VirtualHost *:*>
    RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>

<VirtualHost *:80>
    RewriteEngine On
    RewriteCond %{HTTPS} !=on
    RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
</VirtualHost>

<VirtualHost *:443>
    ProxyPass / balancer://mycluster/ 

    ProxyPassReverse / http://127.0.0.1:5000/
    ProxyPassReverse / http://127.0.0.1:5001/

    <Proxy balancer://mycluster>
        BalancerMember http://127.0.0.1:5000
        BalancerMember http://127.0.0.1:5001 
        ProxySet lbmethod=byrequests
    </Proxy>

    <Location />
        SetHandler balancer
    </Location>
    ErrorLog /var/log/httpd/helloapp-error.log
    CustomLog /var/log/httpd/helloapp-access.log common
    SSLEngine on
    SSLProtocol all -SSLv2
    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4
    SSLCertificateFile /etc/pki/tls/certs/localhost.crt
    SSLCertificateKeyFile /etc/pki/tls/private/localhost.key
</VirtualHost>

速度の制限

httpd モジュールに含まれる mod_ratelimit を使って、クライアントの帯域幅を制限できます。

sudo nano /etc/httpd/conf.d/ratelimit.conf

次のファイルの例では、ルートの場所の下での帯域幅を 600 KB/秒に制限しています。

<IfModule mod_ratelimit.c>
    <Location />
        SetOutputFilter RATE_LIMIT
        SetEnv rate-limit 600
    </Location>
</IfModule>

要求ヘッダー フィールドが長すぎます

プロキシ サーバーの既定の設定では、通常、要求ヘッダー フィールドが 8190 バイトに制限されます。 アプリでは、既定値よりも長いフィールドが必要になる場合があります (たとえば、Microsoft Entra ID を使うアプリ)。 長いフィールドが必要な場合は、プロキシ サーバーの LimitRequestFieldSize ディレクティブに対して調整が必要になります。 適用する値は、シナリオによって異なります。 詳細については、ご利用のサーバーのドキュメントを参照してください。

警告

必要な場合を除いて、LimitRequestFieldSize の既定値を増やさないでください。 値を増やすと、悪意のあるユーザーによるバッファー オーバーラン (オーバーフロー) とサービス拒否 (DoS) の攻撃のリスクが増加します。

その他の技術情報