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 설치
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 오픈채팅을 통해서 문의해주시면 친절하게 알려드리겠습니다~!
전체 소스코드는 개인 Github에 올려두었습니다.
'ETC' 카테고리의 다른 글
MAC M1 Chip PC에서 UTM 가상머신 사용하기 및 Ubuntu 20.04 설치 (2) | 2021.11.23 |
---|---|
실전 부하테스트 경험 및 후기 (Apache JMeter) (2) | 2020.11.26 |
[Apache] Apache (httpd) Response Header에 server version, OS 제거 (0) | 2020.10.06 |
공적마스크 공공데이터를 활용하여 위치 기반으로 마스크 판매처 및 실시간 재고현황 데이터를 제공하는 웹서비스입니다 (코로나거기 - Thereright) (0) | 2020.03.13 |
댓글