Spring-boot con Tomcat integrado detrás del proxy Apache
spring-security reverse-proxy (5)
Tenemos una aplicación spring-boot / spring-mvc con Tomcat integrado en un servidor de aplicaciones dedicado detrás de un proxy SSL Apache.
El puerto SSL en el proxyserver es 4433, reenviando al puerto 8080 en el servidor de aplicaciones.
Por lo tanto, la URL del servidor proxy se reenvía como:
https://proxyserver:4433/appname >>forward>> http://appserver:8080/
Cuando se ejecuta SIN proxy, lo primero que sucede es que
spring-security redirige la solicitud, como:
http://appserver:8080/ >>redirect>> http://appserver:8080/login
para mostrar el formulario de inicio de sesión, extendiendo WebSecurityConfigurerAdapter
con
...
httpSecurity.formLogin().loginPage("/login") ...
...
Funciona bien sin el proxy, pero con proxy, la redirección debe modificarse, por lo que Spring debería redirigir a la proxy-URL correspondiente, como:
http://appserver:8080/ >>redirect>> https://proxyserver:4433/appname/login
pero aún no hay éxito
Estoy tratando de aplicar esta solución:
http://docs.spring.io/spring-boot/docs/current-SNAPSHOT/reference/htmlsingle/#howto-use-tomcat-behind-a-proxy-server (59.8 Utilizar Tomcat detrás de un servidor proxy front-end)
Hemos configurado mod_proxy en Apache y verificado que envía los encabezados esperados:
X-Forwarded-For: xxx.xxx.xxx.xxx
X-Forwarded-Host: proxyserver
X-Forwarded-Port: 4433
X-Forwarded-Proto: https
La aplicación se inicia con parámetros:
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
Aún así, la redirección no funciona.
Seguirá redirigiendo localmente a http://appserver:8080/login
que no está disponible para los clientes.
¿Hay algo más que debemos hacer para que este escenario funcione?
EDITAR : Además, me preocupa la parte "/ nombre de la aplicación" en la URL proxy. En el servidor de aplicaciones, la aplicación está rooteada en "/". ¿Cómo se debe indicar a la primavera que "/ nombre de la aplicación" se debe incluir en todas las URL que se envían a los clientes, al pasar por el proxy?
Has intentado configurar
server.context-path=/appname
En Spring Boot?
Su proxy se ve bien, al igual que la aplicación back-end, hasta cierto punto, pero parece que no está viendo la RemoteIpValve
modificada de RemoteIpValve
. El comportamiento predeterminado de RemoteIpValve
incluye una coincidencia de patrón para la dirección IP del proxy (como una comprobación de seguridad) y solo modifica las solicitudes que cree que son de un proxy válido. El patrón predeterminado en Spring Boot es un conjunto bien conocido de direcciones IP internas, como 10.*.*.*
Y 192.168.*.*
, Por lo que si su proxy no está en uno de los que necesita configurarlo explícitamente, por ejemplo
server.tomcat.internal-proxies=172//.17//.//d{1,3}//.//d{1,3}|127//.//d{1,3}//.//d{1,3}//.//d{1,3}
(usando el formato de archivo de propiedades, lo que significa que tiene que escapar doblemente de las barras diagonales inversas).
Puede ver lo que está sucediendo en RemoteIpValve
si establece
logging.level.org.apache.catalina.valves.RemoteIpValve=DEBUG
o establecer un punto de interrupción en él.
Tenía exactamente el mismo caso usando haproxy como balanceador de carga con la configuración siguiente, que me preocupó. Lo único es que la IP del cliente está en request.getRemoteAddr()
y no en el encabezado "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 }
En application.properties:
server.use-forward-headers=true
Tuve el mismo problema el otro día. Después de algunas depuraciones de Spring Boot 1.3 encontré la siguiente solución.
1. Tienes que configurar los encabezados en tu proxy 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. Tienes que decirle a tu aplicación Spring Boot que use estos encabezados. Así que ponga la siguiente línea en su application.properties (o en cualquier otro lugar donde Spring Boots comprenda las propiedades):
server.use-forward-headers=true
Si hace estas dos cosas correctamente, cada redireccionamiento enviado a su aplicación no irá a http://127.0.0.1:8080/[path] sino automáticamente a https://www.myapp.com/[path]
Actualización 1. La documentación sobre este tema está aquí . Debería leerlo al menos para conocer la propiedad server.tomcat.internal-proxies
que define el rango de direcciones IP para servidores proxy en los que se puede confiar.
Una solución típica a este problema es permitir que el proxy maneje cualquier reescritura requerida. Por ejemplo, en Apache puede usar rewrite_module y / o headers_module para corregir los encabezados. Como otro ejemplo, Nginx maneja este y otros casos similares de forma automática para usted después de configurar los servidores ascendentes.
En respuesta a los comentarios:
¿Cuáles son los valores de configuración de inicio de primavera de remote_ip_header y protocol_header?
Olvidemos Spring Boot por un momento. Tomcat, el contenedor de servlets incorporado, presenta una válvula conocida como RemoteIpValve. Esta válvula es un puerto del Apache remotip_module . El propósito principal de esta válvula es tratar al "agente de servicio que inició la solicitud como el agente de origen" para "fines de autorización y registro". Para que esta válvula sea utilizada, necesita ser configurada.
Encuentre más información sobre esta válvula aquí .
Spring Boot admite cómodamente configurar esta válvula a través de application.properties mediante las propiedades server.tomcat.remote_ip_header y server.tomcat.protocol_header.