개발이야기

Apache Httpd Configuration 정리

adoreje 2021. 8. 16. 21:45

1. Apache Httpd

Apache Httpd 는 Apache 재단에서 제공하는 웹서버이다. Tomcat과는 달리 정적인 리소스만을 제공한다. 동적인 리소스를 처리할 수 있는 서블릿 컨테이너(Tomcat 등)과 연결하여 안정적인 웹 서비스를 제공할 수 있다.

2. Install

2.1 직접 설치

리눅스 OS를 사용한다면 패키지 관리 툴을 사용하여 Apache Httpd를 쉽게 설치할 수 있다.

apt install apache2

2.2 Docker 사용

Docker를 사용한다면 다양한 환경에서 Apache 웹서버를 쉽게 띄울 수 있다.

docker run -d --name="apache" -p 80:80 httpd
docker run -d --name="apache" -p 80:80 adoreje/httpd

httpd는 docker hub에 올라간 httpd의 공식 이미지이다. adoreje/httpd는 이미지 경량화를 위해 alpine 리눅스 기반에서 apache httpd 를 설치한 것이다. 자세한 내용은 github 을 참고한다.

3. Configuration

3.1 Apache httpd 2.4 default layout

ServerRoot              ::      /usr/local/apache2
DocumentRoot            ::      /usr/local/apache2/htdocs
Apache Config File      ::      /usr/local/apache2/conf/httpd.conf
Other Config Files      ::      /usr/local/apache2/conf/extra/
SSL Config File         ::      /usr/local/apache2/conf/extra/httpd-ssl.conf
ErrorLog                ::      /usr/local/apache2/logs/error_log
AccessLog               ::      /usr/local/apache2/logs/access_log
cgi-bin                 ::      /usr/local/apache2/cgi-bin (enabled by default, but some of the bundled scripts are 644)
binaries (apachectl)    ::      /usr/local/apache2/bin
start/stop              ::      /usr/local/apache2/bin/apachectl (start|restart|graceful|graceful-stop|stop|configtest)

Apache 웹서버의 설정파일은 conf 폴더에 있다. httpd.conf 파일에서 여러가지 설정 정보를 관리하며 파일을 기능별로 여러개로 나누고 include하여 사용할 수 있다. 기능별로 나뉜 설정파일은 주로 conf/extra폴더에 위치하며 파일의 이름과 경로 등은 마음대로 설정할 수 있다.

3.2 기본 설정 정보

#### httpd.conf ####

Listen 80
# 기본으로 80포트로 들어오는 요청일 읽는다
# 다른 포트를 추가로 지정할 수 있다

ServerRoot "/usr/local/apache"
# 아파치의 홈 디렉토리, 절대경로로 설정한다. 이후에 나오는 대부분의 경로는 ServerRoot의 상대경로로 설정된다.

User apache
Group apache
# 홈페이지 서비스를 직접 담당하는 자식 프로세스들의 실행소유자와 소유 그룹에 대한 계정정보
# 보안을 위해 nobody로 설정하기도 한다.

ServerAdmin root@domain.com
# 웹 문서 로딩 중 에러 발생 시 보여지는 관리자 메일 주소

DocumentRoot "/var/www/html"
# 서버 내의 웹문서가 있는 경로

LoadModule auth_basic_module modules/mod_auth_basic.so
# /usr/local/apache/modules 에 있는 모듈을 동적으로 불러온다

Include conf.d/*.conf
# conf.d 디렉토리 내의 .conf 파일을 불러온다.

ServerName www.example.com
# 클라이언트에서 보여주는 호스트 이름
# 사용중인 도메인이 없다면 IP주소를 입력

Timeout 300
# 클라이언트에서 300초 동안 아무런 요청이 없을 때 연결을 중지

KeepAlive On
# 아파치의 한 프로세스가 특정사용자의 지속적인 요청을 처리

MaxKeepAliveRequests 100
# KeepAlive 가 on일경우에만 유효
# 사용자의 요청을 처리할 때 100이 넘어가면 프로세스를 종료하고 다른 프로세스가 사용자의 요청을 처리
# 하나의 프로세스가 지속적으로 요청을 처리하면 메모리 효율 저하 -> 시스템 성능 저하

KeepAliveTimeout 2
# KeepAlive On인 경우에만 유효
# 2초동안 요청이 없을 경우 timeout

3.3 Directives(지시어)

Related Modules Related Directives
core <Directory>
mod_version <DirectoryMatch>
mod_proxy <Files>
  <FileMatch>
  <If>
  <IfDefine>
  <IfModule>
  <IfVersion>
  <Location>
  <LocationMatch>
  <DomainSet>
  <Proxy>
  <ProxyMatch>
  <VirtualHost>

<IfDefine>, <IfModule>, <IfVersion> 은 서버가 시작할 때(재시작 포함) 적용된다. 다른 지시어는 request마다 적용된다.

3.3.1 서버 전체 설정

  • <IfDefine>
<IfDefine ClosedForNow>
    Redirect "/" "http://otherserver.example.com/"
</IfDefine>

===========================================
서버가 httpd -DClosedForNow 명령어로 실행되어야만 적용된다.
  • <IfModule>
<IfModule mod_mime_magic.c>
    MimeMagicFile "conf/magic"
</IfModule>

============================================
서버에서 해당 모듈이 있을때만 적용된다. 서버 내에 모듈이 컴파일되어 있거나
<IfModule>을 호출하기 전 LoadModule을 통해 해당 모듈을 load해야 쓸 수 있다
  • <IfVersion>
<IfVersion >= 2.4>
    # this happens only in versions greater or
    # equal 2.4.0.
</IfVersion>

===========================================
서버 버전이 2.4 이상일때만 적용된다.

3.3.2 파일 시스템

  • <Directory>
<Directory "/var/www/html">
     Options None
     Order allow,deny
     Allow from all
		 (Deny from all)
</Directory>

=========================================
DocumentRoot의 <Directory> 설정이다. Options 설정에 따라 DocumentRoot의파일이 목록화되어 나타날 수 있기 때문에 보안상 None으로 설정한다.

Order는 접근을 통제하는 순서를 나타낸다. allow, deny 순으로 지정하면 allow를 먼저 수행하고 deny를 나중에 수행하라는 의미이다.

Allow from(혹은 Deny from) 뒤에 쓸 수 있는 항목은 다음과 같다.
 - 도메인
 - 호스트 이름
 - 호스트 IP 주소
 - IP 주소의 A.B.C 클래스
 - all (모든 주소)
  • <Files>
<Files "private.html">
    Require all denied
</Files>

=========================================
경로에 상관없이 private.html이라는 파일 모두에 적용된다.

3.3.3 WebSpace

클라이언트로 전송되어 화면에 보여지는 부분이다.

  • <Location>, <LocationMatch>
<LocationMatch "^/private">  
Require all denied
================================================
*/private이 들어간 url 요청을 모두 거부한다.
<Location "/server-status">
    SetHandler server-status
</Location>

================================================
/server-status 을 호출했을 때 핸들러를 지정한다.
<Location> 지시어는 파일시스템을 따로 호출해야하는 과정이 필요 없다.

3.3.4 VirtualHost

한 서버에서 여러개의 서비스를 호스팅할 때 사용한다.

  • <VirtualHost>
<VirtualHost 10.1.2.3:80>
  ServerAdmin webmaster@host.example.com
  DocumentRoot "/www/docs/host.example.com"
  ServerName host.example.com
  ErrorLog "logs/host.example.com-error_log"
  TransferLog "logs/host.example.com-access_log"
</VirtualHost>

===============================================
10.1.2.3:80으로 요청이 들어올 경우 적용된다. ip뿐 만 아니라 도메인도 들어올 수 있으며 wildcard(*)를 적용할 수 있다.
<VirtualHost>마다 ServerName을 지정해주어야 하며 따로 지정해주지 않을 경우
메인 서버의 ServerName을 상속한다.

4. 주요 설정

4.1 WAS 연동

Apache Httpd와 WAS를 연동하는 방법은 3가지가 있다.

4.1.1 Tomcat connector(mod_jk)

Tomcat과 연결하기 위한 전용 모듈이다. AJP/1.3 프로토콜을 사용하며 설정이 조금 복잡하긴 하지만 JkMount 옵션을 이용하여 유연한 설정이 가능하다.

# 1. 공식 홈페이지에서 최신 버전을 다운로드한다.(현재 최신버전 : 1.2.48)
wget https://mirror.navercorp.com/apache/tomcat/tomcat-connectors/jk/tomcat-connectors-1.2.48-src.tar.gz

# 2. 설치
tar zxvf tomcat-connectors-1.2.48-src.tar.gz
cd tomcat-connectors-1.2.48-src/native
./configure --with-apxs=/usr/sbin/apxs
make
make install
make install을 완료하면 apache 경로의 modules 폴더에 mod_jk.so 가 복사된다.
  • httpd.conf 설정
# 모듈 load
LoadModule jk_module modules/mod_jk.so

# 설정파일 include
Include conf/extra/mod_jk.conf
================================
경로와 파일 이름은 변경할 수 있다.
  • extra/mod_jk.conf 설정

폴더와 이름은 변경해도 된다.

<IfModule mod_jk.c>
  # worker 설정 파일 경로
  JkWorkersFile conf/workers_jk.properties
  
  # jk 공유메모리 파일 위치
  JkShmFile run/mod_jk.shm
  
  # 로그 파일 경로
  JkLogFile logs/mod_jk.log
  
  # 로그 레벨 설정 [debug/error/info]
  JkLogLevel info
  
  # 로그 출력 시 시간 포맷 설정
  JkLogStampFormat "[%a %b %d %H:%M:%S %Y] "
  
  ## url pattern 에 따른 connector mapping
  ##JkMountFile conf/uriworkermap.properties
</IfModule>
  • conf/workers_jk.properties 설정
worker.list=worker1, worker2
worker.worker1.port=8009
worker.worker1.host=server1
worker.worker1.type=ajp13
worker.worker1.lbfactor=1

## server 2
worker.worker2.port=8009
worker.worker2.host=server2
worker.worker2.type=ajp13
worker.worker2.lbfactor=1
여기서 설정하는 port는 톰캣에서 사용하는 AJP/1.3 프로토콜에서 사용하는 port를 지정한다. 관련된 설정은 톰캣의 server.xml을 확인한다.
<Connector protocol="AJP/1.3" port="8009" connectionTimeout="20000" redirectPort="8443" secretRequired="false" URIEncoding="UTF-8" address="0.0.0.0"/>​
  • conf/uriworkermap.properties
## Mapping the URI /service1 under worker1
/service1/*.do=worker1
/service1/*.jsp=worker1

# /service2 요청으로 들어온 것은 worker2 로 mount
/service2/*=worker2

# png와 jpg 는 apache 가 처리
!/service2/*.png=worker2
!/service2/*.jpg=worker2

======================================================
uri 별로 유연한 처리가 가능하다.
  • <VirtualHost> 적용
<VirtualHost *:81>
    ServerName dgbp.daeguedu.com
    JkMount /* worker1
</VirtualHost>
=========================================================
81번 포트로 들어오는 모든 요청을 worker1로 mount 한다.

4.1.2 mod_proxy 사용

reverse proxy로 동작하는 모듈이다.

  • load module
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_module modules/mod_proxy.so
  • <VirtualHost> 적용
<VirtualHost *:8080>
  ServerName was2
  <Proxy *>
    Order deny,allow
    Allow from all
  </Proxy>

  ProxyRequests Off
  ProxyPreserveHost On
  ProxyPass / http://10.36.25.73:8080/ retry=1 acquire=3000 timeout=600 Keepalive=On
  ProxyPassReverse / http://10.36.25.73:8080/
</VirtualHost>
========================================================================
8080로 들어오는 모든 요청을 http://10.36.25.73:8080 로 전달한다.

- ProxyRequests
  On : Forword proxy
  Off : Reverse Proxy
- ProxyPreserveHost On
  HTTP 헤더의 Host 부분을 유지한다.

4.1.3 mod_proxy_ajp 사용

AJP/1.3 프로토콜과 reverse proxy를 결합한 방식이다.

  • <VirtualHost> 적용
<VirtualHost *:9090>
    ServerName was2

    <Proxy *>
	  Order deny,allow
      Allow from all
  	</Proxy>

    ProxyRequests Off
    ProxyPreserveHost On
    ProxyPass / ajp://10.36.25.73:8009/
    ProxyPassReverse / ajp://10.36.25.73:8009/
</VirtualHost>
=============================================================================
reverse proxy와 비슷한 방식으로 적용할 수 있으며 프로토콜을 ajp로 변경하고 ajp에서 사용하는 포트를 적용한다.

4.2 SSL 적용

  • extra/httpd-ssl.conf
<VirtualHost _default_:443>
	DocumentRoot "/usr/local/apache2/htdocs"
	ServerName www.example.com:443
	ServerAdmin you@example.com
	ErrorLog /proc/self/fd/2
	TransferLog /proc/self/fd/1

	JkMount /* worker1

	SSLEngine on
	SSLCertificateFile [인증서 파일 경로]
	SSLCertificateKeyFile [키파일 경로]
	SSLCACertificateFile [CA인증서 파일경로]
</VirtualHost>
  • httpd.conf
# 모듈 load
LoadModule ssl_module modules/mod_ssl.so
  • mod_proxy 에 적용
<VirtualHost *:8182>
        ServerName dgbp.daeguedu.com

        ServerName dgbp.daeguedu.com

        ProxyRequests Off
        ProxyPreserveHost On
        ProxyPass / http://10.36.3.140:8080/ retry=1 acquire=3000 timeout=600 Keepalive=On
        ProxyPassReverse / http://10.36.3.140:8080/

        SSLEngine on
        SSLProxyEngine on
        SSLProtocol all -SSLv2 -SSLv3
        SSLProxyProtocol all -SSLv2 -SSLv3
        SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
        SSLProxyCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
        SSLCertificateKeyFile /usr/local/apache//sslFile/server.key.pem
        SSLCertificateFile /usr/local/apache//sslFile/server.crt.pem
        SSLCACertificateFile /usr/local/apache//sslFile/rootca.crt.pem

</VirtualHost>
====================================================================
mod_proxy에 SSL을 적용하고자 하는 경우 SSLProxyEngine 을 활성화한다.

4.3 HTTPS Redirect

# 1. rewrite module을 로드한다.
LoadModule rewrite_module modules/mod_rewrite.so

# 2. Virtual Host에서 80으로 들어온 요청을 443으로 redirect 한다.
<VirtualHost *:80>
    DocumentRoot "/www/example1"
    ServerName www.example.com

    RewriteEngine On
	  RewriteCond %{HTTPS} !on
	  RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R,L]
</VirtualHost>

<VirtualHost *:443>
    ServerName www.example.com
    DocumentRoot "/var/www/html"

    SSLEngine on
    SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1

    SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:RC4+RSA:+HIGH:+MEDIUM:+LOW
    SSLHonorCipherOrder on
	
		SSLCertificateFile [인증서 파일 경로]
		SSLCertificateKeyFile [키파일 경로]
		SSLCACertificateFile [CA인증서 파일경로]

    ErrorLog logs/example.com-ssl-error_log
    TransferLog logs/example.com-ssl-access_log
    CustomLog logs/ssl_request_log \
        "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"
</VirtualHost>

===========================================================================
- RewriteEngine
  활성화 여부
- RewriteCond
  조건 설정. 설정한 패턴과 일치하는 경우 RewriteRule 적용
- RewriteRule
  실질적인 Rewrite 규칙을 적용하는 지시자
  RewriteRule [input URL] [Return URL]
* Rewrite Subrutine 지시자
  L : 뒤 구문 여부를 무시하고 그 줄에서 끝낸다.
  R : 무조건 redirect를 적용한다.
  P : proxy를 사용한다.