リバースプロキシサーバで設定されるHTTPヘッダを使ったアプリの機能が必要になる場合がありますが、開発環境にリバースプロキシサーバが用意されることは経験的にほとんどなく、動作確認に困ることが多々あります…
ここでは開発や検証に使用できる簡易なリバースプロキシサーバの構築方法について説明します。
概要
- 開発や検証を目的とし、ローカルPCにリバースプロキシサーバを構築する方法を説明します。
- 前提とする環境は次の通りです。
- Windows 10(64ビット)環境を使用します。
- プロキシサーバとしてWindows向けのApache httpdを使用します。使用するバージョンは、Apache Loungeの2.4.43-win64-VS16です。
- ここで構築するリバースプロキシサーバの仕様は次の通りです。
- リバースプロキシサーバで公開するURI
https://localhost:8443/
- 転送先のWebアプリURIは下記を想定
※ポート番号等は実行環境に合わせて修正してください。https://localhost:44338/
- 転送時に次のヘッダを付与
HTTPヘッダ名 説明 X-Forwareded-For クライアントのIPアドレスを付与
(WebアプリにおけるクライアントIPが全てリバースプロキシサーバになってしまうため。) - 自己署名のルートCA証明書、サーバ証明書を使用してSSL/TLSを有効化
- 関連ファイルの配置場所フォルダ1C:\reverse-proxy
- リバースプロキシサーバで公開するURI
- ここではあくまでの開発環境での検証を目的としているため、最低限の設定内容になっています。
本番使用を想定する場合はセキュリティや性能等の考慮した設定を検討してください。
インストール
Apache httpdをダウンロードし、所定のフォルダに展開します。
- httpdサーバのダウンロード
Apacheのダウンロードページから[Files for Microsoft Windows]のリンクを開きます。
ApacheHaus, Apache Lounge等のいくつかのバージョンがありますが、ここではApache Loungeの[httpd-2.4.43-win64-VS16.zip]をダウンロードします。 - ダウンロードファイルの配置
ダウンロードしたバイナリを”C:\reverse-proxy”直下に展開します。
展開後は次のようなフォルダ構造になる想定です。C:\reverse-proxy\httpd-2.4.46-win64-VS16\Apache24\...
サーバ証明書の準備
リバースプロキシサーバで使用するサーバ証明書を作成し、所定のフォルダに配置します。
(検証の都合、ルートCA証明書とサーバ証明書を使用する前提です。)
- ルートCA証明書、サーバ証明書の作成
ネットやこちらの情報を参考に次の証明書を作成します。証明書ファイル名 説明 server-ca.crt ルートCA証明書(PEM形式) server.crt サーバ証明書(PEM形式) server.key サーバ証明書の鍵(PEM形式) - 証明書ファイルの配置
上記の証明書関連ファイル3つを次のフォルダにコピーします。C:\reverse-proxy\httpd-2.4.46-win64-VS16\Apache24\conf
(後述のhttpd.confでは、サーバ証明書の配置フォルダとしてconfフォルダを想定しており、これに合わせています。)
httpサーバの設定
基本設定
httpd.confを次のように編集します。
詳細はApacheのリファレンスを参考のこと。
なお、編集前にhttpd.confをhttpd.conf.orgにコピーする等の退避を推奨します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | ... # # ServerRoot: The top of the directory tree under which the server's # configuration, error, and log files are kept. # # Do not add a slash at the end of the directory path. If you point # ServerRoot at a non-local disk, be sure to specify a local disk on the # Mutex directive, if file-based mutexes are used. If you wish to share the # same ServerRoot for multiple httpd daemons, you will need to change at # least PidFile. # Define SRVROOT "C:\reverse-proxy\httpd-2.4.46-win64-VS16\Apache24" ... # # Listen: Allows you to bind Apache to specific IP addresses and/or # ports, instead of the default. See also the <VirtualHost> # directive. # # Change this to Listen on specific IP addresses as shown below to # prevent Apache from glomming onto all bound IP addresses. # #Listen 12.34.56.78:80 Listen 127.0.0.1:8888 ... # # Dynamic Shared Object (DSO) Support # ... LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so LoadModule socache_shmcb_module modules/mod_socache_shmcb.so LoadModule ssl_module modules/mod_ssl.so ... # # ServerName gives the name and port that the server uses to identify itself. # This can often be determined automatically, but we recommend you specify # it explicitly to prevent problems during startup. # # If your host doesn't have a registered DNS name, enter its IP address here. # ServerName localhost:8888 ... # Secure (SSL/TLS) connections Include conf/extra/httpd-ssl.conf ... |
- 12行目: Apacheのホームフォルダを指定する。
- 24行目: HTTP要求の受付インターフェイス・ポートを指定する。今回の用途ではSSL/TLSを使用する前提なので任意の値を指定している。
- 31-34行目: SSLを有効化するためにmod_ssl, mod_socache_shmcbを有効にする。
リバースプロキシとして動作させるためにmod_proxy, mod_proxy_httpを有効化する。 - 44行目: 起動時の警告を回避するために適当な名前を指定した。
- 48行目: SSL/TLSの設定を組み込む。
SSLとリバースプロキシ
httpd-ssl.confを次のように編集します。
詳細はApache httpdリファレンスのmod_proxy, mod_sslを参考のこと。
なお、編集前にhttpd-ssl.confをhttpd-ssl.conf.orgにコピーする等の退避を推奨します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 | ... # # When we also provide SSL we have to listen to the # standard HTTP port (see above) and to the HTTPS port # Listen 8443 ... ## ## SSL Virtual Host Context ## <VirtualHost _default_:8443> # General setup for the virtual host DocumentRoot "${SRVROOT}/htdocs" ServerName localhost:8443 ServerAdmin admin@example.com ErrorLog "${SRVROOT}/logs/error.log" TransferLog "${SRVROOT}/logs/access.log" ... # Server Certificate: # Point SSLCertificateFile at a PEM encoded certificate. If # the certificate is encrypted, then you will be prompted for a # pass phrase. Note that a kill -HUP will prompt again. Keep # in mind that if you have both an RSA and a DSA certificate you # can configure both in parallel (to also allow the use of DSA # ciphers, etc.) # Some ECC cipher suites (http://www.ietf.org/rfc/rfc4492.txt) # require an ECC certificate which can also be configured in # parallel. SSLCertificateFile "${SRVROOT}/conf/server.crt" #SSLCertificateFile "${SRVROOT}/conf/server-dsa.crt" #SSLCertificateFile "${SRVROOT}/conf/server-ecc.crt" # Server Private Key: # If the key is not combined with the certificate, use this # directive to point at the key file. Keep in mind that if # you've both a RSA and a DSA private key you can configure # both in parallel (to also allow the use of DSA ciphers, etc.) # ECC keys, when in use, can also be configured in parallel SSLCertificateKeyFile "${SRVROOT}/conf/server.key" #SSLCertificateKeyFile "${SRVROOT}/conf/server-dsa.key" #SSLCertificateKeyFile "${SRVROOT}/conf/server-ecc.key" # Server Certificate Chain: # Point SSLCertificateChainFile at a file containing the # concatenation of PEM encoded CA certificates which form the # certificate chain for the server certificate. Alternatively # the referenced file can be the same as SSLCertificateFile # when the CA certificates are directly appended to the server # certificate for convenience. SSLCertificateChainFile "${SRVROOT}/conf/server-ca.crt" ... # Per-Server Logging: # The home of a custom SSL log file. Use this when you want a # compact non-error SSL logfile on a virtual host basis. CustomLog "${SRVROOT}/logs/ssl_request.log" \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b" # reverse proxy settings SSLProxyEngine on ProxyRequests Off ProxyPass / https://localhost:44338/ ProxyPassReverse / https://localhost:44338/ # Add proxy information in X-Forwarded-* headers(default: on) ProxyAddHeaders On </VirtualHost> |
- 6行目: SSL/TLS用ポートとして8443を指定する。
- 13, 17行目: SSL/TLS用のバーチャルホストを宣言する。
- 33行目: サーバ証明書ファイルのパスを指定する。(既定値のまま)
- 43行目: サーバ証明書(鍵)ファイルのパスを指定する。(既定値のまま)
- 54行目: ルートCA証明書ファイルのパスを指定する。(既定値のまま)
- 63-70行目: リバースプロキシサーバの動作を指定する。
- SSLでのリバースプロキシを有効にするためにSSLProxyEngineを指定
- フォワードプロキシとしての動作(クライアントの情報を隠す)を無効するためにProxyRequestsを指定
- リバースプロキシのURIと転送先URIを対応付けするためにProxyPass, ProxyPassReverseを指定
- クライアントのIPアドレス(X-Forwarded-For)、元々の要求ホスト名(X-Forwarded-Host)、プロキシサーバ名(X-Forwarded-Server)を転送先に送信するためにProxyAddHeadersを指定
(既定で有効だが、意図を明確にするために明示的に指定)
動作確認
- 転送先のアプリの起動
転送先となるアプリを起動します。
Visua Studio用のサンプルプロジェクトであれば、こちらで公開しています。このアプリではHTTP要求ヘッダをダンプします。 - apachenの起動
次のフォルダにあるhttpd.exeを実行します。C:\reverse-proxy\httpd-2.4.46-win64-VS16\Apache24\bin
- ブラウザでの確認
ブラウザでリバースプロキシのURIを開き、転送先アプリのページが表示されることを確認します。https://localhost:8443/
(参考)
chromeで動作確認を行うとX-Forwarded-ForはIPv6のループバックである”::1″になります。
Ipv4の値にしたい場合、次のような対応が考えられます。
- ホスト名をIPv4のIPアドレスで指定
“https://127.0.0.1:8443/”のように接続先としてIPv4のIPアドレスを指定する。
この方法は簡単ですが、SSLの警告が表示されてしまいます。 - IPv6が無効化されたインターフェイスを使用
上記の設定では、リバースプロキシサーバは全てのインターフェイス(0.0.0.0)でリッスンします。「ネットワークアダプタの設定でIPv6を無効化したインターフェイス」のIPアドレスを指定してページを開く。
この方法では、SSLの警告が表示されてしまいます。 - 別のブラウザを使用
例えばFirefox(83.0)では、URL欄に”about:config”を入力して詳細設定画面を表示し、”network.dns.disableIPv6″と入力し、trueを選択するとIPv6は無効になります。
なお、”netsh interface ipv6 set prefixpolicy”等を使って、ループバックの名前解決の順番変更を試してみました。pingに関しては効果はあるようですが、ChromeにはIPv6のまま、Firefox(83.0)はIpv4になりました。