본문 바로가기
ETC

[Apache] CentOS 7.8에서 Apache(httpd)와 Tomcat을 mod_jk(AJP Protocol) 방식으로 연동한 프록시 환경 구성하기

by 임채훈 2021. 2. 8.

CentOS 7.8에서 Apache(httpd)와 Tomcat을 mod_jk 방식으로 연동한 프록시 환경 구성하기

 

들어가기에 앞서 아래와 같은 Apache ↔ Tomcat간 Proxy 구성방식은 Apache 모듈에 따라 크게 3가지가 있습니다.

1. mod_proxy 사용

2. mod_proxy_ajp 사용

3. mod_jk 사용

Software Version

  • CentOS : 7.8
  • Apache (httpd) : 2.4.46
  • Tomcat : 9.0.43
  • Tomcat Connector : 1.2.48

 

 

CentOS 운영체제, Apache HTTP Server, Apache Tomcat은 설치되어 있는 상태이어야 되며 따라서 별도로 각 소프트웨어를 설치하는 과정은 건너뛰도록 하겠습니다.

 

이번에 활용할 Apache 모듈은 mod_jk로 3번 방식인데 구성 및 설정이 1번, 2번 방식보다 비교적 복잡합니다.

하지만 아래의 순서를 잘 따라가면 큰 문제없이 설정을 마칠 수 있습니다.

 

 

1. Connector 컴파일 및 구성에 필요한 OS 라이브러리 설치

yum install httpd-devel gcc 

 

2. Tomcat Connector 설치

 

Apache Tomcat® - Tomcat Connectors (mod_jk) Downloads

You must verify the integrity of the downloaded files. We provide OpenPGP signatures for every release file. This signature should be matched against the KEYS file which contains the OpenPGP keys of Tomcat's Release Managers. We also provide SHA512 checksu

tomcat.apache.org

cd /usr/local
wget https://downloads.apache.org/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.48-src.tar.gz
tar -xvzf tomcat-connectors-1.2.48-src.tar.gz

 

3. Tomcat Connector Config 및 Compile

cd /usr/local/tomcat-connectors-1.2.48-src/native
./configure --with-apxs=/usr/bin/apxs

apxs는 앞전에 httpd-devel을 통해 설치되는데 일반적으로 /usr/bin 디렉토리 이하에 설치됩니다.

checking build system type... x86_64-pc-linux-gnu
checking host system type... x86_64-pc-linux-gnu
checking target system type... x86_64-pc-linux-gnu
checking for a BSD-compatible install... /usr/bin/install -c
checking whether build environment is sane... yes
checking for a thread-safe mkdir -p... /usr/bin/mkdir -p
checking for gawk... gawk
checking whether make sets $(MAKE)... yes
checking whether make supports nested variables... yes
checking for test... /usr/bin/test
.
.
.
.
no netscape given
checking that generated files are newer than configure... done
configure: creating ./config.status
config.status: creating Makefile
config.status: creating apache-2.0/Makefile
config.status: creating apache-2.0/Makefile.apxs
config.status: creating common/Makefile
config.status: creating common/list.mk
config.status: creating common/jk_types.h
config.status: creating common/config.h
config.status: common/config.h is unchanged
config.status: executing depfiles commands
config.status: executing libtool commands
make
Making all in common
make[1]: Entering directory `/usr/local/tomcat-connectors-1.2.48-src/native/common'
/usr/lib64/apr-1/build/libtool --silent --mode=compile gcc -std=gnu99 -I. -I/usr/include/httpd  -DHAVE_CONFIG_H -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -I/opt/codeit/openssl111/include -pthread -DHAVE_APR  -I/usr/include/apr-1 -I/usr/include/apr-1  -DHAVE_CONFIG_H -DLINUX -D_REENTRANT -D_GNU_SOURCE -c jk_ajp12_worker.c -o jk_ajp12_worker.lo
/usr/lib64/apr-1/build/libtool --silent --mode=compile gcc -std=gnu99 -I. -I/usr/include/httpd  -DHAVE_CONFIG_H -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -I/opt/codeit/openssl111/include -pthread -DHAVE_APR  -I/usr/include/apr-1 -I/usr/include/apr-1  -DHAVE_CONFIG_H -DLINUX -D_REENTRANT -D_GNU_SOURCE -c jk_connect.c -o jk_connect.lo
/usr/lib64/apr-1/build/libtool --silent --mode=compile gcc -std=gnu99 -I. -I/usr/include/httpd  -DHAVE_CONFIG_H -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -I/opt/codeit/openssl111/include -pthread -DHAVE_APR  -I/usr/include/apr-1 -I/usr/include/apr-1  -DHAVE_CONFIG_H -DLINUX -D_REENTRANT -D_GNU_SOURCE -c jk_msg_buff.c -o jk_msg_buff.lo
/usr/lib64/apr-1/build/libtool --silent --mode=compile gcc -std=gnu99 -I. -I/usr/include/httpd  -DHAVE_CONFIG_H -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -I/opt/codeit/openssl111/include -pthread -DHAVE_APR  -I/usr/include/apr-1 -I/usr/include/apr-1  -DHAVE_CONFIG_H -DLINUX -D_REENTRANT -D_GNU_SOURCE -c jk_util.c -o jk_util.lo
.
.
.
.
.
.
Making all in apache-2.0
make[1]: Entering directory `/usr/local/tomcat-connectors-1.2.48-src/native/apache-2.0'
../scripts/build/instdso.sh SH_LIBTOOL='/usr/lib64/apr-1/build/libtool --silent' mod_jk.la `pwd`
/usr/lib64/apr-1/build/libtool --silent --mode=install cp mod_jk.la /usr/local/tomcat-connectors-1.2.48-src/native/apache-2.0/
libtool: install: warning: remember to run `libtool --finish /usr/lib64/httpd/modules'
make[1]: Leaving directory `/usr/local/tomcat-connectors-1.2.48-src/native/apache-2.0'

 

4. Apache 설정 파일 추가 및 수정 (mod_jk, workers.properties)

  • /etc/httpd/conf/httpd.conf - 파일 수정

.
.
.
# Supplemental configuration
#
# Load config files in the "/etc/httpd/conf.d" directory, if any.
IncludeOptional conf.d/*.conf
IncludeOptional conf/extra/*.conf

Apache 최상위 설정 파일(httpd.conf)에서 앞으로 추가할 설정 파일들을 Include 할 수 있도록 IncludeOptional conf/extra/*.conf 부분을 추가해줍니다.

  • /etc/httpd/conf/workers.properties - 신규 파일 작성

worker.list=instance

worker.instance.port=8009
worker.instance.host=127.0.0.1
worker.instance.type=ajp13

worker 이름은 instance로 지정해주고 포트와 ip를 위와 같이 설정합니다.

  • /etc/httpd/conf.modules.d/mod_jk.conf - 신규 파일 작성

<ifModule jk_module>
        JkWorkersFile           conf/workers.properties
        JkLogFile               logs/mod_jk.log
        JkLogLevel              info
        JkShmFile               /var/log/httpd/jk-runtime-status
        JkWatchdogInterval      30
</ifModule>

여기서는 바라볼 workers.properties 경로를 지정 및 logging 등을 설정해줍니다.

  • /etc/httpd/conf/extra/default.conf - 신규 파일 작성

cd /etc/httpd/conf
mkdir extra
vi /etc/httpd/conf/extra/default.conf
LoadModule jk_module modules/mod_jk.so

Include conf.modules.d/mod_jk.conf

<VirtualHost *:80>
        ServerName      localhost

        JkMount /*      instance
</VirtualHost>

해당 파일은 기본 Apache VirtualHost 설정파일로 신규 작성해주는것이고 ServerName은 임시로 localhost로 지정해주겠습니다.

여기서 중요한 부분은 JkMount /* instance 부분인데 도메인이 localhost인 모든 요청은 이전에 설정해준 ajp worker의 이름인 instance로 처리하겠다라는 설정입니다.

일반적으로 아파치에서 디렉토리 매칭 및 Port Forwarding을 설정할때 사용하는 Location 설정과 비슷하다고 보시면 됩니다.

 

 

5. Apache Service 재기동

systemctl restart httpd
Job for httpd.service failed because the control process exited with error code. See "systemctl status httpd.service" and "journalctl -xe" for details.

모든 설정을 마친 후 아파치 재기동을 해주는데 위와 같은 오류를 나타내며 재기동에 실패하는 경우가 발생할 수 있습니다.

 

그에 따른 오류 로그를 확인해보면 아래와 같을 수 있습니다.

tail -200f /var/log/httpd/error_log

[Mon Feb 08 12:25:05.869376 2021] [core:notice] [pid 20292:tid 140548072179904] SELinux policy enabled; httpd running as context system_u:system_r:httpd_t:s0
[Mon Feb 08 12:25:05.870217 2021] [suexec:notice] [pid 20292:tid 140548072179904] AH01232: suEXEC mechanism enabled (wrapper: /usr/sbin/suexec)
[Mon Feb 08 12:25:05.870287 2021] [core:emerg] [pid 20292:tid 140548072179904] (13)Permission denied: AH00023: Couldn't create the proxy mutex
[Mon Feb 08 12:25:05.870299 2021] [proxy:crit] [pid 20292:tid 140548072179904] (13)Permission denied: AH02478: failed to create proxy mutex
AH00016: Configuration Failed

무언가 오류가 났는데 정확이 어떤 원인으로 발생한 오류인지는 모르겠습니다.

아마 mod_jk 모듈을 컴파일하여 적용하는 과정에서 발생하는 오류인듯 한데..

아무튼 해결법은 아래의 명령어를 통해 해결할 수 있습니다.

chcon -u system_u -r object_r -t httpd_modules_t /etc/httpd/modules/mod_jk.so
setenforce 0

mod_jk.so 경로가 다른 경우 주어진 환경에서 해당 파일을 찾아 해당 경로로 chcon 명령어를 수행해주면 됩니다.

systemctl restart httpd

 

6. Tomcat AJP 설정

  • /usr/local/tomcat9/conf/server.xml - 파일 수정

<!-- Define an AJP 1.3 Connector on port 8009 -->
<!--
<Connector protocol="AJP/1.3"
           address="::1"
           port="8009"
           redirectPort="8443" />
-->

초기 tomcat의 server.xml 파일을 보면 위와 같이 AJP 관련된 설정이 주석처리 되어있는걸 확인할 수 있습니다.

해당 부분 주석을 제거한 후 아래와 같이 address 설정secretRequired 설정을 추가로 해줍니다.

* secretRequired 옵션은 이전 tomcat release version에서 GhostCat 관련한 이슈(AJP Protocol의 취약점을 이용한 해킹) 가 발생하여 필수적으로 해야되도록 추가되었습니다.

<!-- Define an AJP 1.3 Connector on port 8009 -->
<Connector protocol="AJP/1.3"
           address="localhost"
           port="8009"
           redirectPort="8443"
           secretRequired="false" />

 

7. Tomcat 기동

cd /usr/local/tomcat9

./bin/startup.sh

모든 설정을 마친 후 Tomcat을 기동한 후 설정이 완료된 서버 IP의 80 포트로 접속해보면 아래와 같이 Tomcat 메인 화면이 나온다면 성공적으로 연동이 된것입니다.

 

 

혹시나 오류가 발생하거나 질문할 사항이 있으시면 댓글 및 카카오톡 1:1 오픈채팅을 통해서 문의해주시면 친절하게 알려드리겠습니다~!

 

지나가던 백엔드 개발자

 

open.kakao.com

전체 소스코드는 개인 Github에 올려두었습니다.

댓글