wake-up-neo.com

Spring-Boot mit eingebettetem Tomcat hinter dem Apache-Proxy

Wir haben eine Spring-Boot/Spring-MVC-App mit eingebettetem Tomcat auf einem dedizierten App-Server hinter einem Apache-SSL-Proxy.

Der SSL-Port auf dem Proxyserver ist 4433 und wird an Port 8080 des Anwendungsservers weitergeleitet.

Die URL zum Proxy-Server leitet also weiter:

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

Wenn OHNE Proxy ausgeführt wird, geschieht dies als erstes
spring-security leitet die Anfrage um, wie zum Beispiel:

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

um das Anmeldeformular anzuzeigen, erweitern Sie WebSecurityConfigurerAdapter um

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

Ohne Proxy funktioniert es einwandfrei .__, aber MIT Proxy muss die Weiterleitung geändert werden Spring sollte stattdessen auf die entsprechende Proxy-URL umleiten, z.

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

aber noch kein Erfolg.

Ich versuche diese Lösung anzuwenden:

http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-use-Tomcat-behind-a-proxy-server (59.8 Tomcat hinter einer Front verwenden- Proxy-Server beenden)

Wir haben mod_proxy in Apache konfiguriert und überprüft, dass die erwarteten Header gesendet werden:

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

Die Anwendung wird mit Parametern gestartet:

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

Die Weiterleitung funktioniert immer noch nicht. 

Es wird weiterhin lokal weitergeleitet zu http://appserver:8080/login, das für die Clients nicht verfügbar ist.

Gibt es noch etwas, was wir tun müssen, damit dieses Szenario funktioniert?

EDIT: Ich mache mir auch Sorgen um den Teil "/ appname" in der Proxy-URL. Auf dem Anwendungsserver befindet sich die Anwendung unter "/". Wie sollte spring darüber informiert werden, dass "/ appname" in alle URLs eingeschlossen werden muss, die an die Clients zurückgesendet werden, wenn sie über den Proxy gehen?

23
Rop

Ich hatte das gleiche Problem am anderen Tag. Nach einigem Debuggen von Spring Boot 1.3 habe ich folgende Lösung gefunden.

1. Sie müssen die Header auf Ihrem Apache-Proxy einrichten:

<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. Sie müssen Ihre Spring Boot-App anweisen, diese Header zu verwenden. Fügen Sie die folgende Zeile in Ihre application.properties ein (oder an einen anderen Ort, an dem Spring Boots die Eigenschaften versteht):

server.use-forward-headers=true

Wenn Sie diese beiden Dinge richtig ausführen, wird jede Weiterleitung, die Ihre Anwendung sendet, nicht unter http://127.0.0.1:8080/[path] ablaufen, jedoch automatisch an https: //www.myapp .com/[Pfad]

Update 1. Die Dokumentation zu diesem Thema ist hier . Sie sollten es zumindest lesen, um sich der Eigenschaft server.Tomcat.internal-proxies bewusst zu sein, die den Bereich der IP-Adressen für Proxyserver definiert, der vertrauenswürdig sein kann.

17
Igor Mukhin

Ihr Proxy sieht gut aus, und auch die Backend-App tut dies bis zu einem gewissen Punkt, aber die RemoteIpValve-geänderte Anforderung scheint nicht zu erscheinen. Das Standardverhalten von RemoteIpValve enthält eine Musterübereinstimmung für die Proxy-IP-Adresse (als Sicherheitsüberprüfung) und modifiziert nur Anforderungen, die ihrer Meinung nach von einem gültigen Proxy stammen. Das Muster ist in Spring Boot standardmäßig auf einen bekannten Satz interner IP-Adressen wie 10.*.*.* und 192.168.*.* festgelegt. Wenn sich Ihr Proxy nicht auf einem dieser Adressen befindet, müssen Sie ihn explizit konfigurieren, z.

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

(Bei Verwendung des Eigenschaftendateiformats müssen Sie die umgekehrten Schrägstriche doppelt kennzeichnen).

Sie können in der RemoteIpValve sehen, was passiert, wenn Sie festlegen 

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

oder legen Sie einen Haltepunkt fest.

4
Dave Syer

Eine typische Lösung für dieses Problem besteht darin, dass der Proxy das erforderliche Neuschreiben durchführen muss. In Apache können Sie beispielsweise das rewrite_module und/oder headers_module verwenden, um die Header zu korrigieren. In einem anderen Beispiel behandelt Nginx diese und andere ähnliche Fälle automatisch nach der Konfiguration der Upstream-Server.

Als Antwort auf Kommentare:

Wie lauten die Konfigurationswerte für den Spring-Boot remote_ip_header und protocol_header?

Vergessen wir Spring Boot für einen Moment. Tomcat, der eingebettete Servlet-Container, verfügt über ein als RemoteIpValve bekanntes Ventil. Dieses Ventil ist ein Port des Apache remotip_module . Der Hauptzweck dieses Ventils besteht darin, den "Benutzeragenten, der die Anforderung initiiert hat", als den ursprünglichen Benutzeragenten "zum Zwecke der Autorisierung und Protokollierung" zu behandeln. Damit dieses Ventil verwendet werden kann, muss es konfiguriert werden.

Weitere Informationen zu diesem Ventil hier .

Spring Boot unterstützt die Konfiguration dieses Ventils bequem über application.properties über die Eigenschaften server.Tomcat.remote_ip_header und server.Tomcat.protocol_header.

2
Newbie

Ich hatte genau den gleichen Fall bei der Verwendung von Haproxy als Load Balancer mit der folgenden Konfiguration, was für mich problematisch war. Die Client-IP befindet sich nur in request.getRemoteAddr() und nicht in "X-Forwarded-For"-Header

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 }

In application.properties:

 server.use-forward-headers=true

Stellen Sie die Rewrite-Regel wie folgt ein: https: // proxyserver: 4433/appname >> forward >> http: // appserver: 8080/appname

Setzen Sie dann Ihren Anwendungskontext auf "Anwendungsname" server.context-path =/appname

Sie können also lokal von http: // appserver: 8080/appname laufen, und über Reverse Proxy können Sie über https: // proxyserver: 4433/appname zugreifen.

Da ich JBOSS verwende, ändert sich in Standalone.xm von JBoss:

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

Tomcat hätte eine ähnliche Konfiguration, um Tomcat mitzuteilen (Proxy-Address-Forwarding = "true"), die Proxy-Weiterleitungsadresse zu respektieren.

0
Sagar Mody

Hast du das Einstellen versucht?

  server.context-path=/appname

Im Frühling Boot?

0
Piotr Gwiazda