web-dev-qa-db-ja.com

Apacheプロキシの背後に埋め込まれたTomcatを使用したSpring Boot

Apache SSLプロキシの背後にある専用のアプリサーバーにTomcatが組み込まれたSpring Boot(Spring MVC)アプリがあります。

プロキシサーバーのSSLポートは4433で、appserverのポート8080に転送されます。

したがって、プロキシサーバーへのURLは次のように転送されます。

https://proxyserver:4433/appname   >>forward>>   http://appserver:8080/

プロキシなしで実行する場合、最初に起こることは
Spring Securityは、次のようにリクエストをリダイレクトします。

http://appserver:8080/   >>redirect>>   http://appserver:8080/login

WebSecurityConfigurerAdapterを次のように拡張することにより、ログインフォームを表示します。

  ...
  httpSecurity.formLogin().loginPage("/login") ...
  ...

プロキシなしでも正常に動作しますが、プロキシを使用する場合はリダイレクトを変更する必要があります。
したがって、Springは代わりに、対応するプロキシURLにリダイレクトする必要があります。

http://appserver:8080/   >>redirect>>   https://proxyserver:4433/appname/login

しかし、まだ成功していません。

このソリューションを適用しようとしています: 59.8フロントエンドプロキシサーバーの背後でTomcatを使用

Apacheで mod_proxy を設定し、期待されるヘッダーを送信することを確認しました。

X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https

アプリケーションは次のパラメーターで開始されます。

export ARG1='-Dserver.Tomcat.protocol-header=x-forwarded-proto' 
export ARG2='-Dserver.Tomcat.remote-ip-header=x-forwarded-for'
Java $ARG1 $ARG2 -jar webapp.jar

それでもリダイレクトは機能しません。

クライアントが使用できないhttp://appserver:8080/loginにローカルにリダイレクトし続けます。

このシナリオを機能させるために必要なことは他にありますか?


更新

また、プロキシURLの「/ appname」の部分が心配です。アプリサーバーでは、アプリケーションのルートは「/」です。プロキシを経由するときに、クライアントに返送されるすべてのURLに「/ appname」を含めるように、Springにどのように指示する必要がありますか?

25
Rop

先日も同じ問題がありました。 Spring Boot 1.3のデバッグの後、次の解決策が見つかりました。

1。Apacheプロキシにヘッダーを設定する必要があります。

<VirtualHost *:443>
    ServerName www.myapp.org
    ProxyPass / http://127.0.0.1:8080/
    RequestHeader set X-Forwarded-Proto https
    RequestHeader set X-Forwarded-Port 443
    ProxyPreserveHost On
    ... (SSL directives omitted for readability)
</VirtualHost>

2。これらのヘッダーを使用するようにSpring Bootアプリに指示する必要があります。したがって、application.properties(またはSpring Bootsがプロパティを理解するその他の場所)に次の行を追加します。

server.use-forward-headers=true

これらの2つのことを正しく行うと、アプリケーションが送信するすべてのリダイレクトは、nothttp://127.0.0.1:8080/ [ path] しかし、自動的に https://www.myapp.com/ [path]

Update 1。このトピックに関するドキュメントは here です。少なくともプロパティserver.Tomcat.internal-proxies信頼できるプロキシサーバーのIPアドレスの範囲を定義します。

23
Igor Mukhin

プロキシは正常に見えますが、バックエンドアプリもある程度までは正常に動作しますが、RemoteIpValveの変更されたリクエストが表示されていないようです。 RemoteIpValveのデフォルトの動作には、(セキュリティチェックとして)プロキシIPアドレスのパターンマッチが含まれ、有効なプロキシからのものと思われるリクエストのみを変更します。パターンは、Spring Bootで10.*.*.*192.168.*.*などの既知の内部IPアドレスのセットにデフォルト設定されるため、プロキシがそれらのいずれかにない場合、明示的に設定する必要があります。

server.Tomcat.internal-proxies=172\\.17\\.\\d{1,3}\\.\\d{1,3}|127\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}

(プロパティファイル形式を使用しているため、バックスラッシュを二重にエスケープする必要があります)。

設定すると、RemoteIpValveで何が起こっているかを見ることができます

logging.level.org.Apache.catalina.valves.RemoteIpValve=DEBUG

またはその中にブレークポイントを設定します。

4
Dave Syer

この問題の典型的な解決策は、プロキシに必要な書き換えを処理させることです。たとえば、Apacheでは、ヘッダーを修正するために rewrite_module および/または headers_module を使用できます。別の例として、Nginxは、アップストリームサーバーを構成した後、このケースや他の同様のケースを自動的に処理します。

コメントへの応答:

Remote_ip_headerおよびprotocol_headerスプリングブート構成の値は何ですか?

Spring Bootを少し忘れてみましょう。組み込みサーブレットコンテナであるTomcatは、RemoteIpValveとして知られるバルブを備えています。このValveは、Apache remotip_module のポートです。このValveの主な目的は、「リクエストを開始したユーザーエージェントを発信ユーザーエージェントとして扱う」ことです。これは「認証とログ記録の目的」です。このバルブを使用するには、設定する必要があります。

このバルブの詳細については、こちらをご覧ください こちら

Spring Bootは、server.Tomcat.remote_ip_headerおよびserver.Tomcat.protocol_headerプロパティを介してapplication.propertiesを介してこのバルブの設定を便利にサポートします。

2
Newbie

Haproxyをロードバランサーとして使用し、以下の構成でまったく同じケースがありましたが、心配でした。唯一のものは、クライアントIPがrequest.getRemoteAddr()にあり、"X-Forwarded-For"ヘッダーにないことです

frontend www
  bind *:80
  bind *:443 ssl crt crt_path
  redirect scheme https if !{ ssl_fc }
  mode http
  default_backend servers

backend servers
  mode http
  balance roundrobin
  option forwardfor
  server S1 Host1:port1 check
  server S2 Host2:port2 check
  http-request set-header X-Forwarded-Port %[dst_port]
  http-request add-header X-Forwarded-Proto https if { ssl_fc }

Application.propertiesで:

 server.use-forward-headers=true

設定してみましたか

  server.context-path=/appname

春のブーツで?

1
Piotr Gwiazda

次のような書き換えルールを設定してみてください。 https:// proxyserver:4433/appname >> forward >> http:// appserver:8080/appname

そして、アプリケーションコンテキストを「appname」に設定しますserver.context-path =/appname

ローカルで http:// appserver:8080/appname で実行でき、逆プロキシ経由で https:// proxyserver:4433/appname でアクセスできます

JBOSSを使用しているため、jbossのstandalone.xmの変更:

<http-listener name="default" socket-binding="http" redirect-socket="https" proxy-address-forwarding="true" enable-http2="true"/>

Tomcatにも同様の構成があり、Tomcatにプロキシ転送アドレスを尊重するように通知します(proxy-address-forwarding = "true")。

0
Sagar Mody