복붙노트

[SPRING] 아파치 프록시 뒤에 톰캣이 내장 된 스프링 부트

SPRING

아파치 프록시 뒤에 톰캣이 내장 된 스프링 부트

우리는 아파치 SSL 프록시 뒤에있는 전용 애플리케이션 서버에 Tomcat이 내장 된 스프링 부트 (Spring MVC) 애플리케이션을 가지고있다.

프록시 서버의 SSL 포트는 4433이며, 응용 프로그램 서버의 포트 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에게 어떻게 지시해야합니까?

해결법

  1. ==============================

    1.요 전날 같은 문제가있었습니다. 스프링 부트 1.3을 디버깅 한 후 다음 해결책을 찾았습니다.

    요 전날 같은 문제가있었습니다. 스프링 부트 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
    

    이 두 가지를 올바르게 수행하면 애플리케이션 리디렉션이 http://127.0.0.1:8080/[path]로 이동하지 않고 https://www.myapp.com/ [경로]로 자동 전송됩니다.

    업데이트 1.이 항목에 대한 설명서는 여기에 있습니다. 최소한 신뢰할 수있는 프록시 서버의 IP 주소 범위를 정의하는 server.tomcat.internal-proxy 속성을 알고 있어야합니다.

  2. ==============================

    2.프록시는 괜찮아 보이고, 백엔드 앱도 마찬가지지만, RemoteIpValve 수정 요청을 보지 않는 것 같습니다. RemoteIpValve의 기본 동작에는 프록시 IP 주소에 대한 패턴 일치 (보안 검사)가 포함되어 있으며 유효한 프록시에서 온 것으로 판단되는 요청 만 수정합니다. 패턴은 Spring Boot에서 10 *. *. * 및 192.168. *. * 같은 잘 알려진 내부 IP 주소 집합으로 기본 설정됩니다. 따라서 프록시가 명시 적으로 구성해야하는 경우 (예 :.

    프록시는 괜찮아 보이고, 백엔드 앱도 마찬가지지만, 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
    

    또는 그 안에 중단 점을 설정하십시오.

  3. ==============================

    3.이 문제점에 대한 일반적인 해결책은 프록시가 필요한 모든 다시 쓰기를 처리하도록하는 것입니다. 예를 들어, Apache에서는 rewrite_module 및 / 또는 headers_module을 사용하여 헤더를 수정할 수 있습니다. 다른 예로, Nginx는 업스트림 서버를 구성한 후 자동으로이 경우와 다른 유사한 경우를 처리합니다.

    이 문제점에 대한 일반적인 해결책은 프록시가 필요한 모든 다시 쓰기를 처리하도록하는 것입니다. 예를 들어, Apache에서는 rewrite_module 및 / 또는 headers_module을 사용하여 헤더를 수정할 수 있습니다. 다른 예로, Nginx는 업스트림 서버를 구성한 후 자동으로이 경우와 다른 유사한 경우를 처리합니다.

    의견에 대한 답변 :

    remote_ip_header 및 protocol_header 스프링 부팅 구성 값은 무엇입니까?

    잠시 봄 부트를 잊자. 임베디드 서블릿 컨테이너 인 Tomcat에는 RemoteIpValve라는 밸브가 있습니다. 이 밸브는 Apache remotip_module의 포트입니다. 이 밸브의 주된 목적은 "요청을 시작한 사용자 에이전트를 원래 사용자 에이전트로" "권한 부여 및 로깅의 목적"으로 처리하는 것입니다. 이 밸브를 사용하려면 밸브를 구성해야합니다.

    이 밸브에 대한 자세한 내용은 여기를 참조하십시오.

    Spring Boot는 server.tomcat.remote_ip_header 및 server.tomcat.protocol_header 속성을 통해 application.properties를 통해이 밸브를 쉽게 구성 할 수 있도록 지원합니다.

  4. ==============================

    4.나는 아래의 구성으로로드 밸런서와 같은 haproxy를 사용하여 정확하게 동일한 케이스를 가졌습니다. 유일한 것은 클라이언트 IP가 request.getRemoteAddr ()에 있고 "X-Forwarded-For"헤더에 없다는 것입니다.

    나는 아래의 구성으로로드 밸런서와 같은 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
    
  5. ==============================

    5.설정을 시도 했습니까?

    설정을 시도 했습니까?

      server.context-path=/appname
    

    스프링 부트?

  6. ==============================

    6.다시 쓰기 규칙을 다음과 같이 설정해보십시오. https : // proxyserver : 4433 / appname >> forward >> http : // appserver : 8080 / appname

    다시 쓰기 규칙을 다음과 같이 설정해보십시오. https : // proxyserver : 4433 / appname >> forward >> http : // appserver : 8080 / appname

    그런 다음 응용 프로그램 컨텍스트를 "appname"으로 설정하십시오.   server.context-path = / appname

    따라서 로컬로 http : // appserver : 8080 / appname을 실행하고 https : // proxyserver : 4433 / appname을 통해 액세스하는 역방향 프록시를 통해 실행할 수 있습니다.

    JBossS를 사용하고 있기 때문에 jboss의 standalone.xml에서 변경된 사항은 다음과 같습니다.

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

    Tomcat은 프록시 포워딩 주소를 존중하도록 Tomcat (proxy-address-forwarding = "true")에 알리기 위해 유사한 구성을 갖습니다.

  7. from https://stackoverflow.com/questions/25455969/spring-boot-with-embedded-tomcat-behind-apache-proxy by cc-by-sa and MIT license