Microsoft 社는 2022년 6월 15일 Internet Explorer 11의 지원을 종료했습니다.

mod_proxy_http.so 를 이용한 Apache httpd 와 Apache Tomcat 연동

제목

mod_proxy_http.so 를 이용한 Apache httpd 와 Apache Tomcat 연동

1. mod_proxy_http.so 모듈 활성화

1.1. Apache httpd 를 컴파일해서 설치한 경우

conf/httpd.conf 에서 다음을 찾아 주석을 풀어준다.

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so

2개 이상의 Apache Tomcat 과 연동하는 경우 다음의 항목들도 찾아서 주석을 해제한다.

LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule slotmem_shm_module modules/mod_slotmem_shm.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so

1.2. Ubuntu 에서 apt 로 Apache httpd 를 설치한 경우

다음과 같은 명령을 실행한다.

sudo a2enmod proxy
sudo a2enmod proxy_http

2개 이상의 Apache Tomcat 과 연동하는 경우 다음의 명령들도 실행한다.

sudo a2enmod proxy_balancer
sudo a2enmod slotmem_shm
sudo a2enmod lbmethod_byrequests

2. 설정

2.1. localhost 에 1개의 Apache Tomcat 을 두는 경우

VirtualHost 내에 다음과 같이 추가한다.

<VirtualHost 0.0.0.0:80>
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
ProxyRequests Off
</VirtualHost>

필수는 아니지만, 다음과 같은 것들도 추가할 수 있다.

RequestHeader set X-Forwarded-Secure-Request "false"
RequestHeader set X-Forwarded-Proto "http"
RequestHeader set X-Forwarded-Port "80"

https(포트 443) 인 경우는 다음과 같다.

RequestHeader set X-Forwarded-Secure-Request "true"
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"

ProxyPreserveHost on 을 추가하면 ServerAlias 로 요청이 들어온 경우 Apache Tomcat 에 ServerAlias 로 요청을 보낸다.

ProxyPreserveHost on 을 설정했다면, Apache Tomcat 의 server.xml 에서 <Host> 아래에 <Alias> 를 추가해서, Apache httpd 와 Apache Tomcat 의 가상 호스트 설정을 동일하게 해야 한다.

만약, Apache Tomcat 에 manager 와 같은 context 를 차단하고 싶다면, VirtualHost 에 다음과 같은 설정을 추가할 수 있다.

ProxyPass /docs !
ProxyPass /examples !
ProxyPass /host-manager !
ProxyPass /manager !

2.2. 2개 이상의 Apache Tomcat 을 두는 경우

<VirtualHost 0.0.0.0:443>
ProxyPass / balancer://mytomcatcluster/
ProxyPassReverse / balancer://mytomcatcluster/
<Proxy balancer://mytomcatcluster>
BalancerMember http://localhost:8080
BalancerMember http://192.168.0.2:8080
</Proxy>
</VirtualHost>

필수는 아니지만, 다음과 같은 것들도 추가할 수 있다.

ProxyRequests Off
RequestHeader set X-Forwarded-Secure-Request "true"
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"

만약, Apache Tomcat 에 manager 와 같은 context 를 차단하고 싶다면, VirtualHost 에 다음과 같은 설정을 추가할 수 있다.

ProxyPass /docs !
ProxyPass /examples !
ProxyPass /host-manager !
ProxyPass /manager !

2.3. Sticky Session 설정

다음과 같이 Apache Tomcat 의 conf/server.xml<Engine> 항목에 jvmRoute 속성을 추가하고, Apache Tomcat 을 재시작한다.

jvmRoute 속성은 node_001, node_002 와 같이 설정한다고 가정한다.

<Engine name="Catalina" defaultHost="localhost" jvmRoute="node_001">

jvmRoute 속성값은 JSESSIONID Cookie 의 뒤에 자동으로 붙는다.

Apache httpd 의 <VirtualHost> 부분을 다음과 같이 변경하고, Apache httpd 를 재시작한다.

<VirtualHost 0.0.0.0:443>
ProxyPass / balancer://mytomcatcluster/
ProxyPassReverse / balancer://mytomcatcluster/
ProxyRequests Off
<Proxy balancer://mytomcatcluster>
BalancerMember http://localhost:8080 route=node_001
BalancerMember http://192.168.0.2:8080 route=node_002
ProxySet stickysession=JSESSIONID|jsessionid
</Proxy>
</VirtualHost>

필수는 아니지만, 다음과 같은 것들도 추가할 수 있다.

RequestHeader set X-Forwarded-Secure-Request "true"
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"

만약, Apache Tomcat 에 manager 와 같은 context 를 차단하고 싶다면, VirtualHost 에 다음과 같은 설정을 추가할 수 있다.

ProxyPass /docs !
ProxyPass /examples !
ProxyPass /host-manager !
ProxyPass /manager !

Sticky Session 은 구성이 단순해 진다는 장점이 있다.

Sticky Session 을 설정하면, cookie 에 ProxySet ProxySet stickysession=JSESSIONID|jsessionid 에서 설정했던 JSESSIONID 가 붙어서 들어오면 종전에 접속했던 Apache Tomcat 서버로 연결한다.

Sticky Session 은 인트라넷이나 업무시스템에 어울리고 HA 구성을 원한다면 Apache Tomcat 간에 Session 을 공유하도록 설정해야 한다.

Apache Tomcat 간에 Session 공유는 Apache Tomcat 이 공동으로 바라보고 있는 RDBMS나 스토리지에 Session 을 저장하거나, 규모가 크다면 NOSQL 의 일종인 Key–value 를 지원하는 in-memory database 를 다중화하여 Session 저장소로 사용하도록 설정한다.

Cluster 는 Apache Tomcat 간에 의존성을 높인다는 단점이 있다.

3. 주의사항

3.1. 소스코드에서

request.getRemoteAddr() 는 Apache httpd 서버 주소, 이 글과 같은 설정이라면, 항상 127.0.0.1 을 반환한다.

따라서, request.getRemoteAddr() 대신 request.getHeader("X-Forwarded-For") 을 사용해야 한다.

request.getLocalPort() 는 항상 8080 을 반환하고, request.getScheme() 도 항상 http 이고, request.isSecure() 도 항상 false 이다.

request.isSecure() 의 경우, RequestHeader set X-Forwarded-Secure-Request "true" 설정을 했다면, request.getHeader("X-Forwarded-Secure-Request") 를 사용할 수 있다.

Apache httpd 에서는 다음의 3개의 헤더를 자동으로 추가한다.

  • X-Forwarded-For
  • X-Forwarded-Host
  • X-Forwarded-Server

MDN 의 HTTP headers 에서 X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Proto 헤더에 대해 소개하고 있지만, X-Forwarded 로 시작하는 헤더들은 표준이 아니기 때문에 X-Forwarded-Port 와 같은 것들도 많이 사용되고, Apache httpd 와 Apache Tomcat 이 서로 약속한 헤더를 사용하는 경우도 많다.

Apache httpd 가 자동으로 추가하지 않는 것들은 다음과 같은 방식으로 설정파일에 추가해야 한다.

RequestHeader set X-Forwarded-Secure-Request "true"
RequestHeader set X-Forwarded-Proto "https"
RequestHeader set X-Forwarded-Port "443"

클라이언트가 보낸 X-Forwarded-For 와 같은 헤더를 신뢰할 수 없다면, 다음과 같이 Apache httpd 와 Apache Tomcat 이 서로만 알고 있는 헤더를 주고 받아야 한다.

RequestHeader set X-Forwarded-RemoteAddr %{REMOTE_ADDR}s

mod_jk, mod_proxy_ajp 는 이런 제약이 없다.

Apache Tomcat 을 단독으로 사용하고 있었거나, mod_jk 로 연동하고 있었다면, 특별한 이유없이 mod_proxy_http.so 로 방식으로 변경하는 것은 신중을 기해야 한다.

mod_proxy 를 사용하면 mod_cache 설정을 쉽게 할 수 있다는 장점이 있다.

mod_proxy_http.so 는 8009 AJP/1.3 Connector 를 추가하지 않아도 되는 장점이 있겠지만, Apache Tomcat 에서 서비스하는 프로그램에서 request.getRemoteAddr() 와 같은 코드를 사용하지 않을 때만 적합한 방식이다.

3.2. 보안과 관련해서

8080 포트 보안과 Apache Tomcat 의 manager 등의 Context 와 관련된 것은 mod_jk.so 를 이용한 Apache httpd 와 Apache Tomcat 연동 을 참조한다.

제목

첨부파일