spring tomcat spring-security reverse-proxy spring-boot

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.