#
ドキュメント

Document

自分のための備忘録です。

リバースプロキシー

Ref.

概要

リバースプロキシ Apache は遠隔地にあるドキュメントをローカルのサーバの URL 空間に 持ってくることもできます。この手法はリバースプロキシと呼ばれています。 ウェブサーバが遠隔地のドキュメントを取得してクライアントに送り返すのが プロキシサーバの動作のように見えるからです。クライアントにはドキュメントが リバースプロキシサーバから送られてきているように見える点が通常の プロキシとは異なります。

次の例では、クライアントが /foo/ ディレクトリの下にある ドキュメントをリクエストすると、サーバが internal.example.com の /bar/ ディレクトリから取得して、さもローカルサーバからの ドキュメントのようにしてクライアントに返します。

ProxyPass /foo/ http://internal.example.com/bar/
ProxyPassReverse /foo/ http://internal.example.com/bar/
ProxyPassReverseCookieDomain internal.example.com public.example.com
ProxyPassReverseCookiePath /foo/ /bar/

ProxyPass ディレクティブは サーバが適切なドキュメントを取得するように設定し、 ProxyPassReverse ディレクティブは internal.example.com からのリダイレクトがローカルサーバの 適切なディレクトリを指すように書き換えます。 同様に ProxyPassReverseCookieDomain と ProxyPassReverseCookiePath でバックエンド側サーバの発行した Cookie を書き換えることができます。

ただし、ドキュメントの中のリンクは書き換えられない、 ということは知っておいてください。 ですから、internal.example.com への絶対パスによるリンクでは、 クライアントがプロキシサーバを抜け出して internal.example.com に 直接リクエストを送る、ということになります。 サードパーティ製モジュールの mod_proxy_html は、HTML と XHTML 中のリンクを書き換えることができます。

-- https://httpd.apache.org/docs/2.4/urlmapping.html#proxy

ディレクティブ

※ ProxyPassReverse、ProxyPassReverseCookieDomain、ProxyPassREverseCookiePath は、HTTP のリダイレクトに関する設定。

必要があれば設定するディレクティブ。

  • RequestHeader unset Accept-Encoding
  • AddOutputFilterByType
  • Substitute

設定フロー

  1. mod_proxy と proxy_http を有効化
  2. /etc/apache2/sites-available/ の VirtualHost ディレクティブにリバースプロキシーの定義を記載
  3. $ sudo apache2ctl configtest
  4. $ sudo systemctl restart apache2

mod_proxyproxy_http を有効化

$ sudo a2enmod proxy proxy_http
// or mod_proxyがデフォルトで有効な場合
$ sudo a2enmod proxy_http

※ バーチャルホストで複数のドメインを運用している場合は、VirtualHost ディレクティブに記載する。
proxy.conf は全体に影響するので、個別ドメインのみに適用することはできない。

VirtualHost ディレクティブに設定追加

例) example.com-le-ssl.conf

<VirtualHost *:443>
       ServerName example.com

       ServerAdmin postmaster@example.com
       DocumentRoot /var/www/html/example.com

       ErrorLog ${APACHE_LOG_DIR}/error.log
       CustomLog ${APACHE_LOG_DIR}/access.log combined

       SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
       SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
       Include /etc/letsencrypt/options-ssl-apache.conf

       ProxyRequests Off
       SSLProxyEngine On
       ProxyPass /blog/ https://blog.example.com/
       ProxyPassReverse /blog/ https://blog.example.com/
       ProxyPassReverseCookieDomain blog.example.com example.com
       ProxyPassReverseCookiePath / /blog/
</VirtualHost>

上記のように記載して保存すると自動で先頭に <IfModule mod_proxy.c> が追加されるよう?

ref. https://www.server-world.info/query?os=Ubuntu_16.04&p=httpd2&f=5

X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto

リバースプロキシとして振る舞う時 (例えば、ProxyPass ディレクティブを使う時) 、 mod_proxy_http は、オリジンサーバに情報を渡すために いくつかのリクエストヘッダを追加します。これらのヘッダは以下になります。

X-Forwarded-For クライアントの IP アドレス。 X-Forwarded-Host オリジナルのホスト名。クライアントが Host リクエストヘッダで渡す。 X-Forwarded-Server プロキシサーバのホスト名。 オリジンサーバ上でこれらのヘッダを扱う時は注意してください。 と言うのも、オリジナルのリクエストが既に同じヘッダを持っていると、 ヘッダが一つ以上の値 (コンマで区切られます) を持つ可能性があるからです。 例えば、 オリジンサーバ上でオリジナルのクライアントのIPアドレスをログに 記録するため、ログフォーマットに %{X-Forwarded-For}i を 指定したとします。この時、リクエストが複数のプロキシを経由していると、 複数のアドレスがログに載る可能性があります。

ProxyPreserveHost と ProxyVia ディレクティブ も参照してください。これらは他のリクエストヘッダに影響を与えます。

リバースプロキシのリクエストヘッダ

Apache + WordPress

https://blog.example.com

Apache

conf ファイルの ServerName ディレクティブは blog.example.com を指定する。

wp-config.php

define('WP_HOME', 'https://example.com/blog');
define('WP_SITEURL', 'https://example.com/blog'); 

if(isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https') {
    $_SERVER['HTTPS'] = 'on';
    $_SERVER['REQUEST_SCHEME'] = 'https';
}

if ( ! empty($_SERVER['HTTP_X_FORWARDED_FOR']) ) {
    $_SERVER['REMOTE_ADDR'] = $_SERVER['HTTP_X_FORWARDED_FOR'];
}

if ( ! empty( $_SERVER['HTTP_X_FORWARDED_HOST'] ) ) {
    $_SERVER['HTTP_HOST'] = $_SERVER['HTTP_X_FORWARDED_HOST'];
}

ref. リバースプロキシを使用している場合には WordPress をどうやって使えばよいですか ?

備考

ローカル Mac

設定ファイル: /usr/local/etc/httpd/httpd.conf

mod_ssl を有効化する

SSL(mod_ssl) を有効化する。

- #LoadModule ssl_module lib/httpd/modules/mod_ssl.so
+ LoadModule ssl_module lib/httpd/modules/mod_ssl.so

mod_proxy 関連を有効化する

- #LoadModule proxy_module lib/httpd/modules/mod_proxy.so
+ LoadModule proxy_module lib/httpd/modules/mod_proxy.so

- #LoadModule proxy_http_module lib/httpd/modules/mod_proxy_http.so
+ LoadModule proxy_http_module lib/httpd/modules/mod_proxy_http.so