Apache HTTP Server Version 2.0 문서 - Apache HTTP Server

Apache HTTP Server Version 2.0

Apache > HTTP Server > Documentation

Apache HTTP Server Version 2.0 문서

발표문

  • 버전 2.0의 새로운 기능
  • 1.3에서 2.0 버전으로 업그레이드
  • 아파치 라이선스

참조 설명서

  • 컴파일과 설치
  • 시작
  • 중단과 재시작
  • 설정 지시어
  • 지시어 빠른참조
  • 모듈
  • 다중처리모듈 (MPM)
  • 필터
  • 핸들러
  • 서버와 지원 프로그램
  • 용어

사용자 지침서

  • 주소와 포트 지정
  • 설정파일
  • 섹션 설정
  • 내용협상 (content negotiation)
  • 동적공유객체 (DSO)
  • 환경변수
  • 로그파일
  • URL을 파일시스템에 대응
  • 성능향상
  • 보안 팁
  • 서버 전역 설정
  • SSL/TLS 암호화
  • CGI의 Suexec 실행
  • URL 재작성(rewriting) 지침서
  • 가상호스트

How-To / 투토리얼

  • 인증, 권한부여, 접근제어
  • CGI: 동적 페이지 생성
  • .htaccess 파일
  • Server Side Includes (SSI)
  • 사용자별 웹디렉토리 (public_html)

플래폼별 설명

  • Microsoft Windows
  • Novell NetWare
  • EBCDIC 포팅

다른 주제

  • 자주 물어보는 질문 (FAQ)
  • 사이트맵
  • 개발자를 위한 문서
  • 기타

Copyright 1995-2005 The Apache Software Foundation or its licensors, as applicable.
Licensed under the Apache License, Version 2.0.


1.3에서 2.0으로 업그레이드 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

1.3에서 2.0으로 업그레이드

우리는 기존 아파치 사용자가 업그레이드하는 것을 돕기위해 중요한 정보를 알려주는 문서를 제공한다. 이 문서는 간단한 요약이므로, 새로운 기능 문서나 src/CHANGES 파일에서 정보를 찾아봐야 한다.

참고

  • 아파치 2.0의 새로운 기능 요약

컴파일시 구성 변화

  • 아파치는 이제 아파치 컴파일과 설치를 위해 autoconf와 libtool 시스템을 사용한다. 이 시스템의 사용법은 Apache 1.3의 APACI 시스템과 같지는 않지만 비슷하다.
  • 컴파일 여부를 선택할 모듈외에 Apache 2.0은 요청을 처리하는 주요 부분을 다중처리 모듈 (Multi-Processing Modules) (MPM)로 옮겼다.

실행시 설정 변화

  • Apache 1.3에서 서버 핵심에 있었던 많은 지시어들이 이제는 MPM에 있다. 서버가 Apache 1.3과 최대한 비슷하게 동작하길 바란다면 prefork MPM을 선택해야 한다. 다른 MPM은 다른 지시어를 사용하여 프로세스 생성과 요청의 처리를 조절한다.
  • proxy 모듈은 HTTP/1.1에 맞추어 수정되었다. 중요한 변화중 하나는 이제 프록시 접근제어가 <Directory proxy:> 블록이 아니라 <Proxy> 블록에 위치하는 점이다.
  • 몇몇 모듈에서 PATH_INFO (진짜 경로명 뒤에 나오는 경로 정보) 처리 방식이 변경되었다. 전에 핸들러였지만 이제 필터로 구현되는 모듈은 더 이상 PATH_INFO가 있는 요청을 받아들이지 못한다. INCLUDES나 PHP와 같은 필터는 core 핸들러 위에 구현되기때문에 PATH_INFO가 있는 요청을 거부한다. core 핸들러가 PATH_INFO가 있는 요청을 받아들이고 server-side include에서 PATH_INFO를 사용하게 하려면, AcceptPathInfo 지시어를 사용해야 한다.
  • CacheNegotiatedDocs 지시어는 이제 아규먼트로 on과 off를 받는다. 기존의 CacheNegotiatedDocs는 CacheNegotiatedDocs on으로 수정해야 한다.
  • ErrorDocument 지시어는 더이상 메세지를 나타내는 아규먼트 앞에 따옴표를 사용하지 않는다. 대신 쌍따옴표로 메세지를 묶어야 한다. 예를 들어 과거

    ErrorDocument 403 "Some Message

    는 다음과 같이 수정해야 한다.

    ErrorDocument 403 "Some Message"

    두번째 아규먼트가 유효한 URL이나 경로명이 아니라면 메세지로 간주한다.
  • AccessConfig와 ResourceConfig 지시어는 사라졌다. 기존에 사용하던 지시어는 같은 기능을 하는 Include 지시어로 대체할 수 있다. 과거에 설정파일에서 이 지시어들을 사용하지않고 이 지시어들의 기본값을 사용했다면, http.conf에 Include conf/access.conf와 Include conf/srm.conf를 추가할 필요가 있다. 아파치가 이전 지시어와 같은 순서로 설정파일을 읽게하려면 Include 지시어를 httpd.conf 끝에 두고, srm.conf이 access.conf 앞에 나와야 한다.
  • BindAddress와 Port 지시어는 사라졌다. 더 유연한 Listen 지시어가 같은 기능을 한다.
  • Apache-1.3에서 Port는 자기참조 URL의 포트 번호를 설정하는 일도 했다. Apache-2.0에서 이 기능은 새로운 ServerName으로 한다. 한 지시어에 호스트명과 자기참조 URL을 위한 포트 번호를 같이 설정할 수 있다.
  • ServerType 지시어는 사라졌다. 요청을 서비스하는 방법은 이제 MPM 선택에 달렸다. 현재 inetd에서 시작하도록 설계된 MPM은 없다.
  • AgentLog, RefererLog, RefererIgnore 지시어를 제공한 mod_log_agent와 mod_log_referer 모듈이 없어졌다. agent 로그와 referer 로그는 mod_log_config의 CustomLog 지시어를 사용하여 계속 제공된다.
  • AddModule과 ClearModuleList 지시어는 사라졌다. 이 지시어들은 모듈을 올바른 순서로 활성화하려고 사용했다. 새로운 Apache 2.0 API는 모듈이 활성화되는 순서를 명시적으로 지정할 수 있어서, 이 지시어들이 필요없게 되었다.
  • FancyIndexing 지시어가 없어졌다. IndexOptions 지시어의 FancyIndexing 옵션이 같은 기능을 한다.
  • mod_negotiation의 MultiViews 내용협상이 더 엄격하게 기본파일을 찾는다. 내용협상은 협상가능한 파일 중에서만 선택한다. MultiviewsMatch 지시어를 사용하여 이전과 같이 동작하게 할 수 있다.
  • (2.0.51 버전 이후)

    ErrorHeader 지시어는 잘못된 명칭으로, 이 지시어가 담당한 기능은 Header 지시어로도 가능하다. 원하는 기능을 위해,

    Header always set 어쩌고 저쩌고

    와 같이 설정한다.

기타 변화

  • Apache 1.3에서 실험적이였던 mod_auth_digest 모듈이 이제 표준 모듈이 되었다.
  • Apache 1.3에서 실험적이였던 mod_mmap_static 모듈이 mod_file_cache로 대체되었다.
  • 배포본이 완전히 새로 구성되어 더이상 독립된 src 디렉토리가 없다. 대신 소스는 주 배포본 디렉토리 아래 논리적으로 구성되있고, 컴파일한 서버는 다른 디렉토리로 설치된다.

제삼자가 만든 모듈

Apache 2.0에서 서버 API가 많이 변경되었다. Apache 1.3 API에 맞춰진 기존 모듈을 수정없이 Apache 2.0에서 사용할 수 없다. 자세한 정보는 개발자 문서를 참고하라.


Apache 2.0의 새로운 기능 개요 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

Apache 2.0의 새로운 기능 개요

이 문서는 아파치 웹서버 1.3 버전과 2.0버전간의 주된 차이점을 설명한다.

참고

  • 1.3에서 2.0으로 업그레이드

핵심 부분에서 나아진 점

유닉스 쓰레드
POSIX 쓰레드를 지원하는 유닉스 시스템에서 아파치를 여러 프로세스와 여러 쓰레드로 혼합해서 실행할 수 있다. 전부는 아니지만 많은 경우 확장가능성(scalability)을 높인다.
새로운 컴파일 시스템
컴파일 시스템이 autoconf와 libtool을 사용하도록 재작성되었다. 그래서 아파치 구성 시스템이 다른 패키지들과 좀더 비슷해졌다.
여러 프로토콜 지원
이제 아파치는 여러 프로토콜을 서비스할 수 있는 구조를 갖췄다. mod_echo가 그 예로 작성되었다.
비유닉스 플래폼에 대한 더 나은 지원
Apache 2.0는 BeOS, OS/2, 윈도우즈와 같은 비유닉스 플래폼에서 더 빠르고 안정화되었다. 이제 아파치는 이들 플래폼에서 버그가 많고 성능이 느렸던 POSIX 호환층 대신 자체 API로 구현된 플래폼 특유의 다중처리 모듈 (MPM)과 Apache Portable Runtime (APR)을 사용하여 구현된다.
새로운 아파치 API
모듈 API가 2.0에서 상당히 변했다. 1.3의 여러 모듈 순서와 우선순위 문제가 사라졌다. 2.0은 이를 대부분 자동으로 처리하며, 모듈 순서는 이제 더 유연한 훅(hook) 단위로 지정한다. 또, 아파치 서버 핵심 부분을 수정하지 않고 새로운 모듈 기능을 제공하는 함수가 추가되었다.
IPv6 지원
하위 Apache Portable Runtine 라이브러리가 IPv6를 지원하는 시스템에서 아파치는 기본적으로 IPv6 소켓을 기다린다. 또, Listen, NameVirtualHost, VirtualHost 지시어가 IPv6 숫자 주소를 지원한다. (예, "Listen [fe80::1]:8080").
필터링
이제 아파치 모듈을 서버로 오고가는 흐름에 대한 필터로 사용할 수 있다. 예를 들어 mod_include의 INCLUDES 필터를 사용하여 CGI 스크립트 출력에서 Server Side Include 지시어를 처리할 수 있다. mod_ext_filter 모듈은 CGI 프로그램을 핸들러로 사용하는 것과 같이 외부 프로그램을 필터로 사용할 수 있게 한다.
다국어 오류 응답
브라우저로 보내는 오류 응답문이 이제 SSI 문서를 사용하여 다국어로 제공된다. 관리자는 통일된 외관을 위해 이 문서를 수정할 수 있다.
간단해진 설정
혼란을 주던 많은 지시어들이 간단해졌다. 자주 혼란을 주던 Port와 BindAddress 지시어는 없어지고 IP 주소 연결에 Listen 지시어만을 사용한다. ServerName 지시어는 리다이렉션과 가상호스트 인식에만 사용될 서버명과 포트를 지정한다.
Windows NT 유니코드 자체 지원
Windows NT에서 Apache 2.0은 이제 모든 파일명 인코딩에 utf-8을 사용한다. 파일명은 하위 유니코드 파일시스템으로 직접 변역되어, Windows 2000과 Windows XP를 포함한 모든 Windows NT기반 시스템에 다국어 지원을 제공한다. 이 기능은 Windows 95, 98, ME에는 지원되지않고, 파일시스템 접근에 전과 같이 시스템의 지역 코드페이지를 사용한다.
정규표현식 라이브러리 Updated
Apache 2.0은 Perl호환 정규표현식 라이브러리 (Perl Compatible Regular Expression Library) (PCRE)를 포함한다. 이제 모든 정규표현식에 더 강력한 Perl 5 문법을 사용할 수 있다.

모듈에서 나아진 점

mod_ssl
Apache 2.0에서 새로 추가되었다. 이 모듈은 OpenSSL이 제공하는 SSL/TLS 암호화 프로토콜의 인테페이스다.
mod_dav
Apache 2.0에서 새로 추가되었다. 이 모듈은 웹컨텐츠를 올리고 관리하기위한 HTTP Distributed Authoring and Versioning (DAV) 표준을 구현한다.
mod_deflate
Apache 2.0에서 새로 추가되었다. 네트웍 사용량을 줄이기위해 브라우저에게 컨텐츠를 압축해서 보내라고 요청할 수 있다.
mod_auth_ldap
Apache 2.0.41에서 새로 추가되었다. 이 모듈은 HTTP Basic Authentication에 사용하는 정보를 LDAP 데이터베이스에 저장한다. 관련된 mod_ldap 모듈은 연결풀(connection pool)을 제공하고, 결과를 캐싱한다.
mod_auth_digest
공유메모리를 사용하여 프로세스간 세션 캐싱을 지원한다.
mod_charset_lite
Apache 2.0에서 새로 추가되었다. 이 실험적인 모듈은 문자집합 변환과 문자집합 재작성 기능을 제공한다.
mod_file_cache
Apache 2.0에서 새로 추가되었다. 이 모듈은 Apache 1.3의 mod_mmap_static 기능에 더 나은 캐쉬 기능을 추가했다.
mod_headers
이 모듈은 Apache 2.0에서 더 유연해졌다. 이제 mod_proxy가 사용하는 요청 헤더를 수정할 수 있고, 경우에 따라서 응답 헤더를 설정할 수도 있다.
mod_proxy
이 프록시 모듈은 새로운 필터 구조를 이용하고 더 믿을만한 HTTP/1.1 프록시를 구현하기위해 완전히 재작성되었다. 추가로 새로운 <Proxy> 설정 섹션은 프록시 설정을 더 쉽게 (그리고 내부적으로 더 빠르게) 만든다. 과거 <Directory "proxy:..."> 설정은 이제 지원하지 않는다. 모듈은 proxy_connect, proxy_ftp, proxy_http와 같이 지원하는 프로토콜 별로 나눠졌다.
mod_negotiation
새로운 ForceLanguagePriority 지시어는 클라이언트가 NOT ACCEPTABLE이나 MULTIPLE CHOICES 응답 대신 모든 경우 한 문서를 받음을 보장한다. 추가로 협상 알고리즘과 MultiViews 알고리즘이 더 일관된 결과를 내도록 수정되었고, 문서 내용을 포함할 수 있는 새로운 형식의 type map이 추가되었다.
mod_autoindex
자동으로 생성된 디렉토리 목록이 이제 더 깔끔한 형식을 위해 HTML 표를 사용할 수 있게 되었고, 버전 정렬을 포함하여 정렬순서를 자세히 조절할 수 있으며, 디렉토리 목록을 와일드카드로 걸러낼 수 있다.
mod_include
새로운 지시어를 사용하여 SSI 요소의 기본 시작 태그와 마침 태그를 변경할 수 있고, 오류와 시간형식을 SSI 문서외에 주 설정파일에서도 설정할 수 있게 되었다. mod_include에서 (이제 Perl 정규표현식 문법으로) 정규표현식 파싱과 그룹의 결과를 mod_include의 $0 ... $9 변수로 얻을 수 있다.
mod_auth_dbm
이제 AuthDBMType 지시어를 사용하여 여러 DBM류 데이터베이스를 지원한다.


The Apache License, Version 2.0 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

The Apache License, Version 2.0

Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/

TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION

  1. Definitions

    "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.

    "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.

    "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.

    "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.

    "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.

    "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.

    "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).

    "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.

    "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."

    "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.

  2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
  3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
  4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
    1. You must give any other recipients of the Work or Derivative Works a copy of this License; and
    2. You must cause any modified files to carry prominent notices stating that You changed the files; and
    3. You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
    4. If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.

    You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.

  5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
  6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
  7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
  8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
  9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.

END OF TERMS AND CONDITIONS

APPENDIX: How to apply the Apache License to your work.

To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.

Copyright [yyyy] [name of copyright owner]

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


컴파일과 설치 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

컴파일과 설치

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 문서는 유닉스와 유닉스류 시스템에서 아파치를 컴파일하고 설치하는 것만을 다룬다. 윈도우즈에서 컴파일하고 설치하는 방법은 마이크로소프트 윈도우즈에서 아파치 사용을 참고하라. 다른 플래폼에 대해서는 플래폼 문서를 참고하라.

아파치 2.0의 구성과 설치 환경은 1.3과 매우 다르다. 아파치 1.3은 쉬운 설치를 위해 자체 스크립트를 사용했다. 아파치 2.0은 이제 다른 여러 오픈소스 프로젝트와 비슷한 환경을 만들기위해 libtool과 autoconf를 사용한다.

만약 작은 버전을 한단계 업그레이드한다면 (예를 들어, 2.0.50에서 2.0.51), 업그레이드 장으로 바로 가길 바란다.

참고

  • 소스 트리 구성
  • 아파치 시작
  • 아파치 중단과 재시작

성미 급한 사람을 위한 개요

다운로드 | $ lynx http://httpd.apache.org/download.cgi
압축 풀기 $ gzip -d httpd-2_0_NN.tar.gz
$ tar xvf httpd-2_0_NN.tar
구성 | $ ./configure --prefix=PREFIX
컴파일 | $ make
설치 | $ make install
설정 | $ vi PREFIX/conf/httpd.conf
검사 | $ PREFIX/bin/apachectl start

NN은 현재 작은 버전 숫자로, PREFIX는 서버가 설치될 파일시스템 경로로 대체해야 한다. PREFIX를 지정하지 않으면 기본값으로 /usr/local/apache2를 사용한다.

아래는 아파치 웹서버를 컴파일하고 설치하기위한 요구사항부터 컴파일과 설치 과정을 각각 자세히 설명한다.

요구사항

아파치를 컴파일하기위해 다음과 같은 것들이 필요하다:

디스크 공간
디스크 여유공간이 최소 50 MB 이상인지 확인하라. 설치후 아파치는 약 10 MB의 디스크 공간을 차지한다. 실제 필요한 디스크 공간은 선택한 구성 옵션과 추가 모듈에 따라 상당히 차이가 난다.
ANSI-C 컴파일러와 컴파일 시스템
ANSI-C 컴파일러가 설치되있는지 확인하라. Free Software Foundation (FSF)의 GNU C compiler (GCC)를 추천한다. (버전 2.7.2면 된다.) GCC가 없다면 최소한 사용하는 컴파일러가 ANSI 호환인지 확인하라. 추가로 PATH 환경변수는 make와 같은 기본적인 컴파일 도구를 포함해야 한다.
정확한 시간
HTTP 프로토콜에는 하루중 시간을 표현하는 부분이 있다. 그래서 이제 시스템의 시간 동기화 기능을 살펴볼 시간이다. 보통 이를 위해 Network Time Protocol (NTP)에 기반한 ntpdate나 xntpd를 사용한다. NTP 소프트웨어와 공개 시간 서버에 대한 정보는 뉴스그룹 comp.protocols.time.ntp와 NTP 홈페이지를 참고하라.
Perl 5 [선택사항]
(Perl로 쓰여진) apxs나 dbmmanage와 같은 지원 스크립트를 위해 Perl 5 인터프리터가 필요하다. (버전 5.003 이상이면 된다.) `configure' 스크립트가 이 인터프리터를 찾지 못해도 문제없이 아파치 2.0을 컴파일하고 설치할 수 있다. 다만 지원 스크립트를 사용하지 못할 뿐이다. 여러 Perl 인터프리터가 설치되있다면 (아마도 살때 포함된 Perl 4와 직접 컴파일한 Perl 5) ./configure가 올바른 것을 찾기위해 --with-perl 옵션을 (아래 참고) 사용하길 바란다.

다운로드

아파치는 여러 미러 목록이 있는 아파치 웹서버 다운로드 사이트에서 다운로드할 수 있다. 유닉스류 시스템을 사용한다면 소스코드를 다운받아서 컴파일하는 편이 낫다. 쉽게 (아래에서 설명) 컴파일할 수 있고, 자신의 용도에 알맞게 서버를 맞출 수 있다. 또, 최신 버전 바이너리 배포본이 없는 경우도 많다. 바이너리를 다운받는다면 배포본에 있는 INSTALL.bindist 파일의 지시를 따르라.

다운로드후 다운받은 파일이 완전하고 변경되지않은 아파치 웹서버임을 확인하는 것이 중요하다. PGP 서명을 가지고 다운로드한 타볼(tarball)을 검사하여 확인한다. 자세한 방법은 다운로드 페이지에 있고, PGP 사용법을 설명하는 상세한 예도 있다.

압축 풀기

아파치 웹서버 타볼에서 소스를 푸는 작업은 단순히 압축과 tar를 푸는 것이다:

$ gzip -d httpd-2_0_NN.tar.gz
$ tar xvf httpd-2_0_NN.tar

그러면 현재 디렉토리 아래에 배포본의 소스코드를 담은 새로운 디렉토리가 생긴다. 서버를 컴파일하기 전에 그 디렉토리로 cd해야 한다.

소스 트리 구성하기

다음 과정은 특정 플래폼과 개인적인 필요에 따라 아파치 소스 트리를 구성하는 일이다. 이를 위해 배포본의 최상위 디렉토리에 있는 configure 스크립트를 사용한다. (아파치 소스 트리의 CVS 버전을 다운로드한 개발자는 이미 autoconf와 libtool가 설치되있고, 다음 과정으로 넘어가기 전에 buildconf를 실행해야 한다. 이는 정식 버전에서는 필요없다.)

모두 기본 옵션을 사용하여 소스 트리를 구성하려면 간단히 ./configure를 입력하면된다. 기본 옵션을 수정하려면 ./configure에 여러 변수와 명령행 옵션을 사용한다.

가장 중요한 옵션은 아파치가 정상적으로 작동하기위해 아파치를 구성하고 설치할 장소인 --prefix다. 다른 configure 옵션들을 사용하여 파일의 위치를 더 자세히 설정할 수도 있다.

모듈을 포함하거나 빼서 아파치에 포함할 기능을 선택한다. Base 상태인 모듈은 기본적으로 아파치에 포함된다. 다른 상태의 모듈은 --enable-module 옵션을 사용하여 포함한다. 여기서 module은 모듈 이름에서 mod_를 빼고 밑줄을 빼기기호로 변경한 결과다. --enable-module=shared 옵션을 사용하면 모듈을 실행중에 포함하거나 뺄 수 있는 공유객체(shared object, DSO)로 컴파일한다. 또, --disable-module 옵션을 사용하여 Base 모듈을 뺄 수 있다. 지정한 모듈이 없어도 configure가 경고하지않고 그냥 무시하기때문에 모듈 이름을 정확히 입력하라.

가끔 configure 스크립트에게 컴파일러, 라이브러리, 헤더파일 등의 위치를 알려줘야 할 경우가 있다. 이 정보는 환경변수나 configure의 명령행 옵션을 사용하여 전달한다. 자세한 내용은 configure manpage를 참고하라.

여러분이 선택할 수 있는 가능성을 보여주기위해 다음은 특정 컴파일러와 플래그를 사용하고 나중에 DSO로 읽어들일 두 모듈 mod_rewrite와 mod_speling을 추가하여 /sw/pkg/apache에 설치할 아파치를 컴파일하는 전형적인 예이다:

$ CC="pgcc" CFLAGS="-O2" \
./configure --prefix=/sw/pkg/apache \
--enable-rewrite=shared \
--enable-speling=shared

configure를 실행하면 몇분간 시스템의 기능을 검사하여 나중에 서버를 컴파일할때 사용할 Makefile들을 만든다.

configure 옵션들에 대한 자세한 설명은 configure manpage에 있다.

컴파일

이제 다음 명령어 하나로 아파치의 여러 부분을 컴파일할 수 있다:

$ make

여기서 좀 기다려라. 펜티엄 III/리눅스 2.2 시스템에서 기본 구성을 컴파일하는데 약 3분 정도 걸린다. 이 시간은 하드웨어와 포함한 모듈수에 따라 크게 변한다.

설치

이제 다음 명령어로 패키지를 (위의 --prefix 옵션 참고) 지정한 설치 위치 PREFIX에 설치한다:

$ make install

업그레이드한다면 이 설치 과정이 기존 설정파일이나 문서를 덮어쓰지 않는다.

설정

다음으로 PREFIX/conf/에 있는 설정파일을 편집하여 아파치 웹서버를 설정한다.

$ vi PREFIX/conf/httpd.conf

사용가능한 설정 지시어에 대한 완전한 설명과 이 문서의 가장 최근 판은 docs/manual/이나 http://httpd.apache.org/docs-2.0/에 있는 아파치 설명서를 참고하라.

검사

이제 다음과 같이 아파치 웹서버를 시작할 수 있다:

$ PREFIX/bin/apachectl start

그리고 URL http://localhost/로 첫 문서를 요청한다. 보게될 웹페이지는 아마도 PREFIX/htdocs/일 DocumentRoot 아래에 있다. 그리고 다음 명령어로 다시 서버를 중단한다:

$ PREFIX/bin/apachectl stop

업그레이드

업그레이드한다면 먼저 사이트에 영향을 줄 수 있는 변화가 있는지 알아보기위해 발표문과 소스 배포본의 CHANGES 파일을 읽는다. (예를 들어, 1.3에서 2.0이나 2.0에서 2.2와 같은) 큰 버전이 변한 경우 컴파일 옵션과 설정을 직접 수정해야할 정도의 큰 변화가 있을 것이다. 모든 모듈도 모듈 API의 변화에 알맞게 업그레이드해야 한다.

작은 버전을 한단계 업그레이드하는 것은 (예를 들어, 2.0.55에서 2.0.57) 쉽다. make install 작업은 기존의 문서, 로그파일, 설정파일을 수정하지 않는다. 또, 개발자는 작은 버전간에 configure 옵션, 설정, 모듈 API의 호환성없는 변화를 최대한 막는다. 대부분의 경우 동일한 configure 명령행, 동일한 설정파일을 사용할 수 있고, 모듈들도 모두 계속 동작할 것이다. (이 말은 2.0.41이후 버전에만 해당한다. 이전 버전들에는 호환성없는 변화가 있다.)

이전에 설치했던 소스를 가지고 있다면, 업그레이드가 더 쉬워진다. 이전 소스 최상위에 있는 config.nice 파일에는 소스를 구성할 때 사용했던 configure 명령행 옵션이 그대로 있다. 그래서 다음 버전으로 업그레이드한다면 새로운 버전 소스로 config.nice 파일을 복사하고, 원한다면 조금 수정을 한 후, 다음과 같이 실행한다:

$ ./config.nice
$ make
$ make install
$ PREFIX/bin/apachectl stop
$ PREFIX/bin/apachectl start

새로운 버전을 사용하기 전에 항상 검사해봐야 한다. 예를 들어, 업그레이드를 마치기 전에 호환성 문제가 있는지 알아보기위해 다른 --prefix와 (Listen 지시어로) 다른 포트를 사용하여 새로운 버전을 설치한후 이전 버전과 같이 실행해볼 수 있다.


아파치 시작 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

아파치 시작

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

보통 아파치는 Windows NT, 2000, XP에서는 서비스로, Windows 95과 ME에서는 콘솔 프로그램으로 실행된다. 자세한 내용은 서비스로 아파치를 실행하기와 콘솔 프로그램으로 아파치를 실행하기.

유닉스에서 httpd 프로그램은 백그라운드에서 계속 요청을 처리하는 데몬으로 실행된다. 이 문서는 httpd를 시작하는 방법을 설명한다.

참고

  • 아파치 중단과 재시작
  • httpd
  • apachectl

어떻게 아파치가 시작하나

설정파일에서 Listen이 기본값인 80(혹은 1024이하의 다른 포트)이라면 이 특권 포트에 연결하기위해 root 권한이 필요하다. 서버는 시작하여 로그파일을 여는 등의 몇몇 기초적인 작업을 마친후, 클라이언트의 요청을 기다리고 응답하는 자식(child) 프로세스를 여러개 띄운다. 주 httpd 프로세스는 계속 root 사용자로 실행되지만, 자식 프로세스들은 더 권한이 작은 사용자로 실행된다. 이는 선택한 다중처리 모듈로 조정한다.

apachectl 스크립트를 사용하여 httpd 실행파일을 시작하길 권장한다. 이 스크립트는 httpd가 몇몇 운영체제에서 정상적으로 동작하기위해 필요한 환경변수들을 설정하고 httpd 실행파일을 시작한다. apachectl은 명령행 아규먼트를 그대로 넘기기때문에, httpd의 어떤 옵션이라도 apachectl에 사용가능하다. 또, apachectl 스크립트의 앞부분에 나오는 HTTPD 변수를 httpd 실행파일이 있는 위치와 항상 사용할 명령행 아규먼트로 직접 수정할 수 있다.

httpd를 실행하면 먼저 설정파일 httpd.conf를 찾아서 읽는다. 이 파일의 위치는 컴파일 중에 지정하나, 실행시 다음과 같이 -f 명령행 옵션으로 지정할 수도 있다.

/usr/local/apache2/bin/apachectl -f /usr/local/apache2/conf/httpd.conf

시작하는 과정에서 문제가 없다면, 서버는 터미널에서 떨어지고 명령 프롬프트가 거의 즉시 나오게된다. 이는 서버가 실행됨을 의미한다. 브라우저로 서버에 연결하여 DocumentRoot 디렉토리에 있는 테스트 페이지와 그 페이지에 링크된 (로컬카피) 설명서를 볼 수 있다.

시작중 오류

아파치가 시작하는 과정중에 심각한 문제가 발생하면, 종료하기 전에 문제를 알리는 문구를 콘솔이나 ErrorLog에 쓴다. 가장 흔한 오류문 중 하나는 "Unable to bind to Port ..."이다. 이 메세지는 보통 다음 두 경우에 발생한다:

  • root 사용자로 로그인하지 않고 특권 포트에 서버를 시작하려 한 경우. 혹은
  • 이미 아파치나 다른 웹서버가 사용중인 포트에 서버를 시작하려 한 경우.

기타 문제해결 방법은 아파치 FAQ를 참고하라.

부팅할때 시작하기

시스템이 재시작한 후에도 서버가 계속 실행되길 바란다면, 시스템 시작파일(보통 rc.local이나 rc.N 디렉토리에 있는 파일)에 apachectl을 추가해야 한다. 이 경우 아파치는 root로 시작된다. 이전에 서버의 보안이나 접근 제한(파일권한)이 올바로 설정되었는지 확인하라.

apachectl은 표준 SysV init 스크립트와 비슷하게 동작하도록 만들어졌다. 스크립트는 아규먼트로 start, restart, stop을 받으면 각각 적절한 시그널을 httpd에 보낸다. 그래서 보통은 apachectl을 적절한 init 디렉토리로 링크를 걸면된다. 그러나 사용하는 시스템의 정확한 요구사항을 확인하라.

추가 정보

httpd와 apachectl, 기타 서버에 포함된 지원 프로그램들의 명령행 옵션은 서버와 지원 프로그램 페이지를 참고하라. 또 아파치 배포본에는 모든 모듈과 그들이 제공하는 지시어에 대한 문서가 있다.


중단과 재시작 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

중단과 재시작

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 문서는 유닉스류 시스템에서 아파치를 중단하고 재시작하는 내용을 담고있다. 윈도우즈 NT, 2000, XP 사용자는 서비스로 아파치 실행하기에서, 윈도우즈 9x와 ME 사용자는 콜솔 프로그램으로 아파치 실행하기에서 플래폼별 아파치 조작법을 알 수 있다.

참고

  • httpd
  • apachectl

소개

아파치를 중단하고 재시작하려면 실행하고 있는 httpd 프로세스에 시그널을 보내야 한다. 시그널을 보내는 방법은 두가지다. 하나는 유닉스 kill 명령어를 사용하여 프로세스에 직접 시그널을 보내는 방법이다. 시스템에 많은 httpd가 실행되지만, PidFile에 pid가 기록된 부모외에 다른 프로세스에 시그널(signal)을 보내면 안된다. 즉, 부모이외에 다른 프로세스에 시그널을 보낼 필요가 없다는 말이다. 부모에게 보낼 수 있는 시그널은 세가지로, 이제 설명할 TERM, HUP, USR1이다.

다음과 같이 부모에게 시그널을 보낸다:

kill -TERM `cat /usr/local/apache2/logs/httpd.pid`

httpd 프로세스에게 시그널을 보내는 다른 방법은 명령행 옵션 -k를 사용하는 것이다. 아래서 설명할 stop, restart, graceful은 httpd 실행파일의 아규먼트들이다. 그러나 이 아규먼트들로 httpd를 실행하는, apachectl 스크립트를 사용하길 권한다.

httpd에 시그널을 보낸후, 다음 명령어로 진행상황을 알 수 있다:

tail -f /usr/local/apache2/logs/error_log

위 예를 당신의 ServerRoot와 PidFile 설정에 알맞게 수정하라.

당장 중단

시그널: TERM
apachectl -k stop

TERM이나 stop 시그널을 부모에게 보내면 즉시 모든 자식을 죽인다. 자식을 완전히 죽이는데는 몇 초가 걸릴 수 있다. 그런후 부모가 종료한다. 처리중인 요청은 중단되고, 더 이상 요청을 받지않는다.

점잖은 재시작

시그널: USR1
apachectl -k graceful

USR1이나 graceful 시그널을 부모에게 보내면 부모 프로세스는 자식들에게 현재 요청을 처리한후 종료하라고 (혹은 현재 아무것도 처리하지 않다면 즉시 종료하라고) 조언한다. 부모는 설정파일을 다시읽고 로그파일도 다시 연다. 자식이 죽을때마다 부모는 죽은 자식대신 새로운 설정 세대에 기초한 자식을 실행하여 즉시 요청을 처리하게 한다.

점잖은 재시작(graceful restart)으로 USR1을 사용할 수 없는 플래폼에서는 대신 (WINCH와 같은) 다른 시그널을 사용할 수 있다. apachectl graceful은 플래폼에 알맞은 시그널을 보낸다.

점잖은 재시작은 항상 MPM의 프로세스 조절 지시어 설정을 고려하여, 재시작동안 클라이언트를 서비스하는 프로세스나 쓰레드가 적당한 수를 유지하도록 설계되었다. 게다가 StartServers는, 일초 후 최소한 StartServers만큼 새로운 자식이 안만들어지면 자식이 StartServers 개가 되도록 새로 만든다. 즉, 프로그램은 서버의 현재 부하에 알맞은 자식의 개수를 유지하며, StartServers 파라미터로 지정한 당신의 기대를 존중한다.

mod_status 사용자는 USR1을 받을때 서버 통계가 0이 되지 않음을 봤을 것이다. 서버는 새로운 요청을 (운영체제는 이들을 큐에 담아서 어떤 경우에도 잃어버리지 않는다) 처리하지 못하는 시간을 최소화하고 당신의 튜닝 파라미터를 존중하도록 만들어졌다. 이를 위해 세대간 모든 자식을 기록하는 scoreboard를 유지한다.

status 모듈은 또한 점잖은 재시작 전에 시작하여 아직도 요청을 처리하고 있는 자식을 G로 알려준다.

현재로는 USR1을 사용하는 로그순환 스크립트가 재시작전에 모든 자식이 로그작성을 마쳤는지 알 수 있는 방법이 없다. 우리는 USR1 시그널을 보내고 적당한 시간이 지난후 이전 로그를 다루도록 제안한다. 예를 들어 낮은 대역폭 사용자의 경우 접속 대부분이 마치는데 10분이 안걸린다면, 이전 로그를 다루기전에 15분 기다린다.

설정파일에 오류가 있다면 재시작시 부모는 재시작하지 않고 오류를 내며 종료한다. 또, 점잖은 재시작의 경우 종료할때 자식이 실행되도록 놔둔다. (자식들은 자신의 마지막 요청을 처리하고 "점잖게 종료한다".) 이는 서버를 재시작할때 문제가 된다. 서버는 자신이 기다릴 포트에 연결하지 못한다. 재시작전에 -t 명령행 옵션(httpd 참고)으로 설정파일 문법을 검사할 수 있다. 그러나 이런 검사도 서버가 올바로 재시작할지를 보장하지 못한다. 설정파일의 문법이 아닌 의미를 검사하려면 root가 아닌 사용자로 httpd를 시작해볼 수 있다. root가 아니기때문에 (아니면 현재 그 포트를 사용하는 httpd가 실행되기때문에) 오류가 없다면 소켓과 로그파일을 열려고 시도하는 과정에서 실패할 것이다. 다른 이유때문에 실패한다면 아마도 설정파일에 오류가 있을 것이다. 점잖은 재시작을 하기전에 오류를 고쳐야한다.

당장 재시작

시그널: HUP
apachectl -k restart

HUP이나 restart 시그널을 부모에게 보내면 TERM과 같이 모든 자식을 죽이지만 부모는 종료하지 않는다. 부모는 설정파일을 다시읽고 로그파일을 다시 연다. 그리고 새로운 자식들을 만들고 서비스를 계속한다.

mod_status 사용자는 HUP를 보내면 서버 통계가 0이 됨을 알 수 있다.

설정파일에 오류가 있다면 재시작을 해도 부모는 재시작하지 않고 오류를 내며 종료할 것이다. 이를 피하는 방법은 위를 참고하라.

부록: 시그널과 레이스 컨디션

Apache 1.2b9 이전에는 재시작과 종료 시그널에 관계된 레이스 컨디션(race condition)이 있었다. (레이스 컨디션은 간단한 설명하자면, 어떤 일이 잘못된때 일어나서 기대한대로 동작하지 않는 시간에 민감한 문제다.) "올바른" 기능이 있는 아키텍쳐에서 우리는 이런 문제를 최대한 해결했다. 그러나 어떤 아키텍쳐에는 아직도 레이스 컨디션이 존재함을 주의하라.

ScoreBoardFile을 디스크에 저장하는 아키텍쳐는 scoreboard를 망가트릴 가능성이 있다. 그러면 (HUP후) "bind: Address already in use" 혹은 (USR1 후) "long lost child came home!"이 발생할 수 있다. 전자는 심각한 오류이고, 후자는 단지 서버가 scoreboard slot을 잃게 만든다. 그래서 강제 재시작을 줄이고 점잖은 재시작을 사용하길 추천한다. 이 문제는 해결하기 매우 힘들다. 그러나 다행히도 대부분의 아키텍쳐는 scoreboard로 파일을 사용하지 않는다. 파일을 사용하는 아키텍쳐라면 ScoreBoardFile 문서를 참고하라.

모든 아키텍쳐에는 지속되는 HTTP 연결 (KeepAlive)에서 두번째 이후 요청을 처리하는 자식에 약간의 레이스 컨디션이 있다. 자식은 요청줄을 읽은 후 요청 헤더를 읽기전에 종료할 수 있다. 이 문제는 너무 늦게 발견하여 1.2 버전이 나온후에야 수정되었다. 그러나 네트웍 지연이나 서버 시간제한때문에 KeepAlive 클라이언트는 이런 경우를 예상해야하기 때문에 이론상 문제는 안된다. 실제로 서버를 검사하기위해 일초에 20번 재시작하는 동안 클라이언트가 깨진 그림이나 빈 문서없이 사이트를 성공적으로 읽어들이길 기대하지 않는다면 문제가 안된다.


설정파일 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

설정파일

이 문서는 아파치 웹서버를 설정하는 파일들을 설명한다.

주설정파일

관련된 모듈 관련된 지시어
  • mod_mime
  • <IfDefine>
  • Include
  • TypesConfig

일반 문서 파일인 설정파일에 지시어를 사용하여 아파치를 설정한다. 주설정파일을 보통 httpd.conf라고 부른다. 이 파일의 위치는 컴파일시 정해지나, -f 명령행 옵션으로 지정해줄 수 있다. 또 다른 설정파일을 Include 지시어를 사용하여 포함할 수 있고, 와일드카드를 사용하여 많은 설정파일을 포함할 수도 있다. 이 경우 지시어를 어떤 설정파일에나 사용해도 된다. 주설정파일을 수정하면 아파치를 시작하거나 재시작한 이후에 반영된다.

서버는 mime 문서타입을 담은 파일도 읽는다. 파일명은 TypesConfig 지시어로 설정하고, 기본값은 mime.types이다.

설정파일 문법

아파치 설정파일은 한줄에 한 지시어를 사용한다. 줄 마지막 문자가 백슬래쉬 "\"이면 지시어가 다음 줄에서 계속됨을 뜻한다. 이 경우 백슬래쉬 뒤에 어떤 문자나 공백도 나오면 안된다.

설정파일의 지시어는 대소문자를 구별하지 않지만, 지시어의 아규먼트는 대소문자를 구별하는 경우가 있다. 해쉬문자 "#"로 시작하는 줄은 주석으로 무시한다. 주석을 설정 지시어와 같은 줄에 사용할 수 없다. 빈줄과 지시어 앞에 나오는 공백은 무시하므로, 간결하게 보이도록 지시어를 줄들임할(indent) 수 있다.

apachectl configtest나 -t 명령행 옵션을 사용하여 아파치를 실행하지 않고도 설정파일의 문법 오류를 검사할 수 있다.

모듈

관련된 모듈 관련된 지시어
  • mod_so
  • <IfModule>
  • LoadModule

아파치는 모듈화된 서버다. 이는 매우 기본적인 기능만이 서버 핵심에 포함되있음을 뜻한다. 아파치는 모듈을 읽어들여서 기능을 확장한다. 기본적으로 컴파일하면 서버에 base 모듈들이 포함된다. 서버를 동적으로 읽어들이는 모듈을 사용할 수 있게 컴파일하였다면 모듈을 따로 컴파일하여 아무때나 LoadModule 지시어로 추가할 수 있다. 그렇지 않으면 모듈을 추가하거나 빼기위해 아파치를 다시 컴파일해야 한다. 설정 지시어를 IfModule 블록으로 감싸서 특정 모듈이 있는 경우에만 선택적으로 처리할 수 있다.

현재 서버에 어떤 모듈이 컴파일되있는지 보려면 -l 명령행 옵션을 사용한다.

지시어 적용범위

관련된 모듈 관련된 지시어
  • <Directory>
  • <DirectoryMatch>
  • <Files>
  • <FilesMatch>
  • <Location>
  • <LocationMatch>
  • <VirtualHost>

주설정파일에 있는 지시어는 서버 전체에 적용된다. 지시어가 서버의 일부에만 적용되게 하려면 지시어를 <Directory>, <DirectoryMatch>, <Files>, <FilesMatch>, <Location>, <LocationMatch> 섹션 안에 두어야한다. 이 섹션들은 그들이 감싸는 지시어의 적용범위를 파일시스템이나 URL의 특정 위치로 한정한다. 또, 서로 겹쳐서 사용할 수 있기때문에 매우 세밀한 설정이 가능하다.

아파치는 여러 다른 웹사이트를 동시에 서비스하는 능력이 있다. 이를 가상호스트라고 한다. 지시어를 <VirtualHost> 섹션 안에 두어 특정 웹사이트에만 지시어를 적용할 수 있다.

지시어는 대부분 어떤 섹션에 나와도 되지만, 어떤 지시어는 특정 장소에서 의미가 없다. 예를 들어 프로세스 생성을 조절하는 지시어는 주서버설정 장소에서만 사용할 수 있다. 지시어가 어떤 섹션에 위치할 수 있는지 알려면 지시어의 사용장소를 확인하라. 더 자세한 정보는 어떻게 Directory, Location, Files 섹션이 동작하나를 참고하라.

.htaccess 파일

관련된 모듈 관련된 지시어
  • AccessFileName
  • AllowOverride

아파치는 특별한 파일을 사용하여 설정을 나눠서(분권적으로) 관리할 수 있다. 이 특별한 파일을 보통 .htaccess라고 부르지만, 이름은 AccessFileName 지시어로 지정할 수 있다. .htaccess 파일에 있는 지시어는 파일이 있는 디렉토리와 모든 하위디렉토리에 적용된다. .htaccess 파일은 주설정파일과 같은 문법을 따른다. .htaccess 파일은 매 요청때마다 읽기때문에 파일을 수정하면 즉시 효과를 볼 수 있다.

어떤 지시어를 .htaccess 파일에 사용할 수 있는지 알려면 지시어의 사용장소를 확인하라. 서버 관리자는 주설정파일의 AllowOverride 지시어로 .htaccess 파일에 어떤 지시어를 사용할 수 있는지 조절할 수 있다.

.htaccess 파일에 대한 더 자세한 정보는 .htaccess 투토리얼을 참고하라.


섹션 설정 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

섹션 설정

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

설정파일에 있는 지시어는 서버 전체에 적용되거나, 특정 디렉토리, 파일, 호스트, URL에만 적용될 수 있다. 이 문서는 다른 지시어의 적용범위를 제한하기위해 설정 섹션이나 .htaccess 파일을 사용하는 방법을 설명한다.

설정 섹션의 종류

관련된 모듈 관련된 지시어
  • core
  • mod_proxy
  • <Directory>
  • <DirectoryMatch>
  • <Files>
  • <FilesMatch>
  • <IfDefine>
  • <IfModule>
  • <Location>
  • <LocationMatch>
  • <Proxy>
  • <ProxyMatch>
  • <VirtualHost>

섹션에는 두가지 종류가 있다. 대부분은 매요청마다 처리된다. 해당하는 요청에만 안에 포함한 지시어를 적용한다. 반대로, <IfDefine>과 <IfModule>은 서버가 시작할때와 꺼질때만 처리한다. 시작할때 상태가 참이면 안에 있는 지시어가 모든 요청에 적용된다. 참이 아니면 안에 있는 지시어는 무시한다.

<IfDefine> 지시어는 httpd 명령행에 적절한 파라미터가 있는 경우에만 안에 포함한 지시어를 적용한다. 다음 설정을 예로 들면, 서버를 httpd -DClosedForNow로 시작할 경우에만 모든 요청이 다른 사이트로 리다이렉션된다:

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

<IfModule> 지시어도 특정 모듈이 서버에 포함된 경우에만 안에 든 지시어를 적용한다는 점을 제외하고는 매우 비슷하다. 모듈을 서버에 정적으로 컴파일하거나 동적으로 컴파일한후 설정파일 앞에 LoadModule 줄이 있어야 한다. 이 지시어는 특정 모듈의 설치유무에 따라 설정파일이 다를 필요가 있을때만 사용해야 한다. 모듈이 없는 경우 유용한 오류문이 나오지않을 수 있기 때문에 언제나 사용하길 원하는 지시어를 안에 두면 안된다.

다음 예에서 mod_mime_magic이 있을때만 MimeMagicFiles 지시어를 처리한다.

<IfModule mod_mime_magic.c>
MimeMagicFile conf/magic
</IfModule>

<IfDefine>과 <IfModule>의 검사 앞에 "!"을 붙여 조건을 역으로 할 수 있다. 또, 여러 섹션들을 겹쳐서 사용하여 더 복잡한 효과를 얻을 수 있다.

파일시스템과 웹공간

가장 자주 사용되는 설정 섹션은 파일시스템과 웹공간(webspace)의 특정 장소에 대한 설정을 변경하는 것들이다. 먼저 이 둘의 차이를 이해하는 것이 중요하다. 파일시스템은 운영체제 입장에서 디스크를 보는 관점이다. 예를 들어, 기본값으로 아파치를 설치를 하면 유닉스 파일시스템의 경우 /usr/local/apache2, 윈도우즈 파일시스템의 경우 "c:/Program Files/Apache Group/Apache2"에 설치된다. (아파치는 윈도우즈에서 조차 항상, 역슬래쉬가 아닌, 슬래쉬를 사용함을 주의하라.) 반대로 웹공간은 웹서버가 제공하고 클라이언트가 보게될 사이트의 관점이다. 그래서 유닉스에서 기본 아파치 설치를 한 경우 웹경로의 경로 /dir/은 파일시스템 경로 /usr/local/apache2/htdocs/dir/에 해당한다. 웹공간은 데이타베이스 등에서 동적으로 생성될 수 있기때문에 반드시 파일시스템에 직접 대응될 필요는 없다.

파일시스템 섹션

<Directory>와 <Files> 지시어와 정규표현식을 사용하는 지시어는 파일시스템의 특정 부분에 지시어를 적용한다. <Directory> 지시어에 포함된 지시어들은 지정한 파일시스템 디렉토리와 그 하위 디렉토리에 적용된다. .htaccess 파일을 사용해도 결과는 같다. 다음 설정을 예로 들면, 디렉토리 목록(index)이 /var/web/dir1 이하 디렉토리에서 디렉토리 목록(index)이 가능하다.

<Directory /var/web/dir1>
Options +Indexes
</Directory>

<Files> 섹션에 포함된 지시어들은 어떤 디렉토리에 있는지 관계없이 지정한 이름을 가진 파일에 적용된다. 설정파일의 주설정부분에 있는 다음 설정을 예로 들면, 장소와 관계없이 private.html이란 이름을 한 파일의 접근을 거부한다.

<Files private.html>
Order allow,deny
Deny from all
</Files>

파일시스템의 특정 부분에 있는 파일을 지칭하기위해 <Files>와 <Directory> 섹션을 같이 사용한다. 다음 설정을 예로 들면, /var/web/dir1/private.html, /var/web/dir1/subdir2/private.html, /var/web/dir1/subdir3/private.html 같이 /var/web/dir1/ 디렉토리 아래에 있는 이름이 private.html인 파일의 접근을 거부한다.

<Directory /var/web/dir1>
<Files private.html>
Order allow,deny
Deny from all
</Files>
</Directory>

웹공간 섹션

<Location> 지시어와 이에 해당하는 정규표현식을 사용하는 지시어는 반대로 특정 웹공간의 설정을 바꾼다. 다음 설정을 예로 들면, /private으로 시작하는 URL-경로의 접근이 거부된다. 여기에는 http://yoursite.example.com/private, http://yoursite.example.com/private123, http://yoursite.example.com/private/dir/file.html 같이 /private 문자열로 시작하는 요청이 해당된다.

<Location /private>
Order Allow,Deny
Deny from all
</Location>

<Location> 지시어는 파일시스템에 대응할 필요가 없다. 다음 예는 어떻게 특정 URL을 mod_status가 제공하는 아파치 내부 핸들러로 대응시키는지를 보여준다. 파일시스템에 server-status라는 파일은 필요없다.

<Location /server-status>
SetHandler server-status
</Location>

와일드카드와 정규표현식

<Directory>, <Files>, <Location> 지시어에서 C 표준 파이브러리의 fnmatch와 같은 쉘에서 사용하는 와일드카드 문자를 사용할 수 있다. "*" 문자는 어떤 문자열이라도 나타내고, "?" 문자는 어떤 문자 한개를 나타내며, "[seq]"는 seq 중에 한 문자를 나타낸다. 어떤 와일드카드도 "/" 문자를 나타내지는 못한다. 그래서 이 문자는 직접 사용해야 한다.

더 유연한 설정이 필요하면 perl호환 정규표현식을 사용하는 <DirectoryMatch>, <FilesMatch>, <LocationMatch>를 사용할 수 있다. 그러나 아래 설정의 결합에 관한 절에서 정규표현식 섹션을 사용하면 지시어가 적용되는 방법이 어떻게 변하는지 살펴봐라.

모든 사용자 디렉토리 설정을 변경하는 비정규표현식 와일드카드 섹션은 다음과 같다:

<Directory /home/*/public_html>
Options Indexes
</Directory>

정규표현식 섹션을 사용하여 한번에 여러 종류의 그림파일에 대한 접근을 거부할 수 있다:

<FilesMatch \.(?i:gif|jpe?g|png)$>
Order allow,deny
Deny from all
</FilesMatch>

무엇을 사용하나

파일시스템 섹션과 웹공간 섹션 중 하나를 선택하는 것은 실제로 매우 쉽다. 파일시스템에 있는 객체에 지시어를 적용할때는 항상 <Directory>나 <Files>를 사용한다. (데이타베이스에서 생성한 웹페이지와 같이) 파일시스템에 있지 않는 객체에 지시어를 적용할때는 <Location>을 사용한다.

파일시스템에 있는 객체의 접근을 제한하기위해 <Location>을 사용하면 절대 안된다. 여러 다른 웹공간 장소(URL)가 같은 파일시스템 장소에 대응될 수 있으므로, 걸어둔 제한을 우회할 수 있기 때문이다. 다음 설정의 예를 살펴보자:

<Location /dir/>
Order allow,deny
Deny from all
</Location>

이 설정은 http://yoursite.example.com/dir/을 요청한다면 잘 작동한다. 그러나 대소문자를 구별하지않는 파일시스템을 사용한다면 어떻게되나? http://yoursite.example.com/DIR/을 요청하여 쉽게 제한을 우회할 수 있다. 반대로 <Directory> 지시어는 어떻게 요청하였는지 관계없이 그 장소에서 서비스되는 내용에 적용된다. (예외는 파일시스템 링크를 사용하는 경우다. 심볼링크를 사용하여 한 디렉토리를 파일시스템의 여러 장소에 둘 수 있다. <Directory> 지시어는 심볼링크를 따라간다. 그러므로 높은 수준의 보안을 위해서는 적절한 Options 지시어를 사용하여 심볼링크를 무시해야 한다.)

아마도 당신은 대소문자를 구별하는 파일시스템을 사용하므로 이런 일이 일어나지 않는다고 생각할지도 모른다. 그러나 다른 방법으로도 여러 웹공간 위치가 한 파일시스템 위치에 대응될 수 있음을 기억하라. 그래서 가능하면 항상 파일시스템 섹션을 사용해야 한다. 그러나 이 규칙에 예외가 하나 있다. 설정 제한을 <Location /> 섹션에 두면 이 섹션이 특정 URL이 아닌 모든 요청에 적용되므로 완벽하게 안전하다.

가상호스트

<VirtualHost> 섹션은 특정 호스트에 적용되는 지시어들을 포함한다. 이는 한 컴퓨터에서 각각 다른 설정을 사용한 여러 호스트를 서비스할때 유용하다. 더 자세한 정보는 가상호스트 문서를 참고하라.

프록시

<Proxy>와 <ProxyMatch> 섹션은 지정한 URL에 대해 mod_proxy 프록시 서버를 거쳐 접근하는 경우에만 적용된다. 다음 설정을 예로 들면, 프록시 서버를 통해 cnn.com 웹사이트에 접근할 수 없다.

<Proxy http://cnn.com/*>
Order allow,deny
Deny from all
</Proxy>

안에 어떤 지시어를 사용할 수 있나?

어떤 설정 섹션안에 사용할 수 있는 지시어를 알려면 지시어의 사용장소를 확인하라. <Directory>에서 사용가능한 지시어는 <DirectoryMatch>, <Files>, <FilesMatch>, <Location>, <LocationMatch>, <Proxy>, <ProxyMatch> 섹션에서도 사용가능하다. 그러나, 예외가 있다.

  • AllowOverride 지시어는 <Directory> 섹션에서만 사용할 수 있다.
  • FollowSymLinks, SymLinksIfOwnerMatch, Options는 <Directory> 섹션이나 .htaccess 파일에서만 사용할 수 있다.
  • Options 지시어는 <Files>과 <FilesMatch> 섹션에서 사용할 수 없다.

섹션들이 결합하는 방법

설정 섹션은 매우 특별한 방법으로 적용된다. 이 순서가 설정 지시어를 해석하는 방법에 중요한 영향을 주기때문에 이 방법을 이해하는 것이 중요하다.

결합하는 순서는:

  1. (정규표현식을 사용하지않는) <Directory>와 .htaccess는 동시에 일어난다 (경우에 따라 .htaccess이 <Directory>를 무시하도록 설정할 수 있다)
  2. <DirectoryMatch> (그리고 <Directory ~>)
  3. <Files>와 <FilesMatch>는 동시에 일어난다
  4. <Location>과 <LocationMatch>는 동시에 일어난다

<Directory>를 제외하고 각 섹션들을 설정파일에 나온 순서대로 처리된다. (위의 순서 1) <Directory>는 디렉토리 내용이 가장 짧은 것에서 긴쪽으로 처리된다. 그래서 예를 들어, <Directory /var/web/dir>을 <Directory /var/web/dir/subdir> 이전에 처리한다. 같은 디렉토리를 지칭하는 여러 <Directory> 섹션이 있다면 이들을 설정파일 순서대로 처리한다. Include 지시어로 포함한 설정은 Include 지시어 위치에 포함한 파일 내용이 있는 것처럼 처리한다.

<VirtualHost> 섹션 안에 포함된 섹션은 가상호스트 정의 밖에 있는 해당 섹션 이후에 적용된다. 그래서 가상호스트 안에서 주서버의 설정사항을 수정할 수 있다.

다음에 나오는 섹션은 이전 섹션의 결과를 수정한다.

기술적 주의

실제로 <Location>/<LocationMatch>는 (Aliases와 DocumentRoot를 사용하여 URL을 파일명으로 변환하는) 이름번역 단계 이전에 처리된다. 변역이 끝난 이후에는 완전히 무시한다.

예제

다음은 겹합하는 순서를 설명하는 예다. 이들 모두 요청에 적용된다고 가정하면 지시어는 A > B > C > D > E 순서로 처리된다.

<Location />
E
</Location>

<Files f.html>
D
</Files>

<VirtualHost *>
<Directory /a/b>
B
</Directory>
</VirtualHost>

<DirectoryMatch "^.*b$">
C
</DirectoryMatch>

<Directory /a/b>
A
</Directory>

더 현실적인 예는 다음과 같다. <Location> 섹션을 나중에 처리하므로 <Directory> 섹션에 있는 접근제한과 관계없이 서버에 무제한 접근을 가능하다. 즉, 결합하는 순서는 중요하므로 주의하라!

<Location />
Order deny,allow
Allow from all
</Location>

# 악! 이 <Directory> 섹션은 아무런 효과가 없다
<Directory />
Order allow,deny
Allow from all
Deny from badguy.example.com
</Directory>


서버 전역 설정 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

서버 전역 설정

이 문서는 core 서버가 서버의 기본 행동을 설정하기위해 제공하는 지시어중 일부를 설명한다.

서버 식별

관련된 모듈 관련된 지시어
  • ServerName
  • ServerAdmin
  • ServerSignature
  • ServerTokens
  • UseCanonicalName

ServerAdmin과 ServerTokens 지시어는 오류문 등 서버가 생성하는 문서에 나올 서버에 대한 정보를 설정한다. ServerTokens 지시어는 서버 HTTP 응답 헤더를 설정한다.

서버는 ServerName과 UseCanonicalName 지시어를 사용하여 자기참조 URL을 만든다. 예를 들어, 클라이언트가 디렉토리를 요청했지만 디렉토리명 뒤에 슬래쉬를 붙이지않은 경우 아파치는 뒤에 슬래쉬를 붙인 전체 이름을 클라이언트에게 리다이렉트하여, 클라이언트가 문서의 상대참조를 올바로 찾게 한다.

파일 위치

관련된 모듈 관련된 지시어
  • CoreDumpDirectory
  • DocumentRoot
  • ErrorLog
  • LockFile
  • PidFile
  • ScoreBoardFile
  • ServerRoot

이 지시어들은 아파치가 정상적으로 동작하기위해 필요한 여러 파일들의 위치를 설정한다. 경로명이 슬래쉬(/)로 시작하지 않으면, ServerRoot에 상대적인 파일을 찾는다. root가 아닌 사용자에게 쓰기권한이 있는 경로에 파일을 두지않도록 조심해라. 더 자세한 정보는 보안 팁 문서를 참고하라.

자원사용 제한

관련된 모듈 관련된 지시어
  • LimitRequestBody
  • LimitRequestFields
  • LimitRequestFieldsize
  • LimitRequestLine
  • RLimitCPU
  • RLimitMEM
  • RLimitNPROC
  • ThreadStackSize

LimitRequest* 지시어는 아파치가 클라이언트의 요청을 읽을 때 사용할 자원량을 제한한다. 이런 값들을 제한하여 서비스거부(denial of service)류 공격을 줄일 수 있다.

RLimit* 지시어는 아파치 자식이 생성하는 프로세스가 사용할 자원량을 제한한다. 특히 CGI 스크립트나 SSI exec 명령어가 사용할 자원을 제한한다.

ThreadStackSize 지시어는 스택 크기를 조절하기위해 Netware에서만 사용한다.


로그파일 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

로그파일

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

효율적으로 웹서버를 관리하려면 발생하는 문제와 함께 서버의 활동과 성능에 대해 알아야 한다. 아파치 웹서버는 매우 종합적이고 유연한 로그 기능을 제공한다. 이 문서는 로그 기능을 설정하는 방법과 로그에 들어갈 내용을 설명한다.

보안 경고

누군가에게 아파치의 로그파일이 있는 디렉토리에 쓰기권한이 있다면 (보통 root) 서버를 실행하는 uid를 거의 확실히 얻을 수 있다. 이를 고려하지않고 로그가 저장된 디렉토리에 쓰기권한을 주지 마라. 자세한 내용은 보안 팁 문서를 참고하라.

또, 클라이언트가 제공한 정보는 로그파일에 거의 그대로 기록된다. 그래서 악의가 있는 클라이언트가 로그파일에 제어문자를 넣을 수 있으므로, 로그를 다룰때는 주의해야 한다.

오류 로그 (Error Log)

관련된 모듈 관련된 지시어
  • ErrorLog
  • LogLevel

ErrorLog 지시어는 가장 중요한 로그파일인 서버 오류 로그의 이름과 위치를 지정한다. 아파치 웹서버는 이 파일에 진단정보와 요청을 처리하는 도중 발생한 오류를 기록한다. 서버가 시작하거나 동작하는데 문제가 있다면 무엇이 잘못되었고 때때로 어떻게 고치는지를 알려주는 이곳을 가장 먼저 살펴봐야 한다.

오류 로그는 보통 (전형적으로 유닉스 시스템에서는 error_log, 윈도우즈와 OS/2에서는 error.log) 파일에 기록된다. 유닉스 시스템에서 서버는 오류를 syslog나 파이프를 사용하여 다른 프로그램으로 보낼 수도 있다.

오류 로그의 형식은 상대적으로 자유롭고 자세하다. 그러나 대부분의 오류 로그 항목에 공통적으로 나오는 정보가 있다. 예를 들어, 항목은 보통 다음과 같다.

[Wed Oct 11 14:32:52 2000] [error] [client 127.0.0.1] client denied by server configuration: /export/home/live/ap/htdocs/test

로그 항목에서 첫번째 항목은 날짜와 시간이다. 두번째 항목은 보고하는 오류의 심각성을 나타낸다. LogLevel 지시어로 오류 로그에 기록되는 오류의 심각성을 제한할 수 있다. 세번째 항목은 오류를 발생한 클라이언트의 IP 주소이다. 이 다음부터 오류문이 나오며, 이 경우 서버가 클라이언트의 접근을 거부하도록 설정되었다고 나와있다. 요청한 문서의 (웹 경로가 아닌) 파일시스템 경로도 보인다.

오류 로그에는 매우 다양한 종류의 문구가 나올 수 있다. 대부분은 위와 비슷하다. CGI 스크립트의 디버깅 출력도 오류 로그에 기록된다. CGI 스크립트가 stderr에 쓴 정보는 그대로 오류 로그로 복사된다.

오류 로그에 정보를 추가하가나 생략할 수 없다. 그러나 요청에 대한 오류 로그의 경우 접근 로그에도 대응하는 항목이 생긴다. 예를 들어, 위의 경우 상태코드가 403인 접근 로그 항목이 생긴다. 접근 로그는 사용자정의할 수 있으므로 이 파일을 참고하여 오류 상황에 대한 추가정보를 얻을 수 있다.

검사할때 어떤 문제가 생기는지 오류 로그를 계속 살펴보는 것이 좋다. 유닉스 시스템에서 다음과 같이 한다:

tail -f error_log

접근 로그 (Access Log)

관련된 모듈 관련된 지시어
  • mod_log_config
  • mod_setenvif
  • CustomLog
  • LogFormat
  • SetEnvIf

서버 접근 로그는 서버가 처리하는 모든 요청을 기록한다. CustomLog 지시어는 접근 로그의 위치와 내용을 지정한다. LogFormat 지시어를 사용하여 로그에 포함할 내용을 쉽게 선택할 수 있다. 이 절은 서버가 접근 로그에 쓸 내용을 설정하는 방법을 설명한다.

물론 접근 로그에 정보를 기록하는 것은 로그 관리의 시작일 뿐이다. 다음 단계는 이 정보를 분석하여 유용한 통계를 만드는 것이다. 이 문서는 일반적인 로그 분석에 대해서 다루지 않으며, 로그 분석은 실제 웹서버가 할 일이 아니다. 로그 분석에 대한 정보와 로그를 분석하는 소프트웨어에 대해서는 Open Directory나 Yahoo를 참고하라.

아파치 웹서버는 이전부터 mod_log_referer, mod_log_agent, CustomLog 같은 모듈과 지시어를 사용하여 접근 로그를 다루었다. 지금은 CustomLog 지시어가 오래된 지시어들의 모든 기능을 이어받았다.

접근 로그의 형식은 매우 사용자정의 가능하다. 형식은 C의 printf(1) 형식문자열과 매우 유사한 형식문자열을 사용하여 지정한다. 다음 절에 예를 들었다. 형식문자열에 사용가능한 모든 내용을 알려면 mod_log_config 형식문자열을 참고하라.

Common 로그 형식

접근 로그의 전형적인 설정은 다음과 같다.

LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common

그러면 지정한 로그 형식문자열을 별명 common으로 정의한다. 형식문자열은 퍼센트 지시어들로 구성되며, 각각은 어떤 정보를 기록할지 알린다. 형식문자열에 일반 문자를 적으면 그대로 로그에 출력된다. 따옴표 문자(")를 출력하고 싶다면 백슬래쉬를 앞에 붙여서 형식문자열의 끝이 아님을 표시한다. 형식문자열에 줄바꿈 "\n", 탭 "\t"와 같은 특수 조절문자를 사용할 수 있다.

CustomLog 지시어는 정의한 별명을 사용하는 새로운 로그파일을 만든다. 접근 로그의 파일명이 슬래쉬로 시작하지않으면 ServerRoot의 상대경로이다.

앞의 설정은 공통로그형식(Common Log Format, CLF)이라는 형식으로 로그 항목을 기록한다. 여러 다른 웹서버들도 이런 표준 형식으로 로그를 만들며, 여러 로그 분석 프로그램에서 읽을 수 있다. CLF로 만든 로그파일 항목은 다음과 같다:

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326

이제 로그 항목의 각 부분을 설명한다.

127.0.0.1 (%h)
서버에 요청을 한 클라이언트(원격 호스트)의 IP 주소이다. HostnameLookups가 On이라면 호스트명을 찾아서 IP 주소 자리에 대신 쓴다. 그러나 이 설정은 서버를 매우 느리게 할 수 있으므로 추천하지 않는다. 호스트명을 알려면 대신 나중에 logresolve와 같은 로그를 처리하는 프로그램을 사용하는 것이 좋다. 여기에 나온 IP 주소는 사용자가 사용하는 컴퓨터 주소가 아닐 수 있다. 프록시 서버가 사용자와 서버사이에 존재한다면, 원래 컴퓨터 주소가 아니라 프록시의 주소가 기록될 것이다.
- (%l)
출력에서 "빼기기호"는 요청한 정보가 없음을 나타낸다. 이 경우 여기에 나올 정보는 클라이언트 컴퓨터의 identd가 제공할 클라이언트의 RFC 1413 신원이다. 이 정보는 매우 믿을 수 없기때문에, 긴밀히 관리되는 내부 네트웍이 아니라면 절대로 이 정보를 사용하면 안된다. IdentityCheck가 On이 아니라면 아파치 웹서버는 이 정보를 알아보려고 시도하지도 않는다.
frank (%u)
이는 HTTP 인증으로 알아낸 문서를 요청한 사용자의 userid이다. 보통 이 값은 CGI 스크립트에게 REMOTE_USER 환경변수로 넘겨진다. 요청의 상태코드가 401이라면 (아래 참고) 사용자가 아직 인증을 거치지 않았으므로 이 값을 믿으면 안된다. 문서를 암호로 보호하지 않는다면 이 항목은 이전 항목과 같이 "-"이다.
[10/Oct/2000:13:55:36 -0700] (%t)
서버가 요청처리를 마친 시간. 형식은:

[day/month/year:hour:minute:second zone]
day = 숫자 2개
month = 숫자 3개
year = 숫자 4개
hour = 숫자 2개
minute = 숫자 2개
second = 숫자 2개
zone = (`+' | `-') 숫자 4개

로그 형식문자열에 %{format}t를 사용하여 다른 형식으로 시간을 출력할 수 있다. format은 C 표준 라이브러리의 strftime(3)과 같다.
"GET /apache_pb.gif HTTP/1.0" (\"%r\")
클라이언트의 요청줄이 쌍따옴표로 묶여있다. 요청줄은 매우 유용한 정보를 담고 있다. 첫째, 클라이언트가 사용한 메써드는 GET이다. 둘째, 클라이언트는 자원 /apache_pb.gif를 요청한다. 세번째, 클라이언트는 HTTP/1.0 프로토콜을 사용한다. 요청줄의 여러 부분을 따로 로그할 수도 있다. 예를 들어, 형식문자열 "%m %U%q %H"은 "%r"과 똑같이 메써드, 경로, 질의문자열, 프로토콜을 로그한다.
200 (%>s)
이는 서버가 클라이언트에게 보내는 상태코드이다. 이 정보는 (2로 시작하는 코드) 요청이 성공하였는지, (4로 시작하는 코드) 클라이언트에 오류가 있는지, (5로 시작하는 코드) 서버에 오류가 있는지 알려주므로 매우 중요하다. 상태코드의 전체 목록은 HTTP 규약 (RFC2616 section 10)에서 찾을 수 있다.
2326 (%b)
마지막 항목은 응답 헤더를 제외하고 클라이언트에게 보내는 내용의 크기를 나타낸다. 클라이언트에게 보내는 내용이 없다면 이 값은 "-"이다. 내용이 없는 경우 "0"을 로그하려면 대신 %B를 사용한다.

Combined 로그 형식

자주 사용되는 다른 형식문자열은 결합된로그형식(Combined Log Format)이다. 다음과 같이 사용한다.

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\"" combined
CustomLog log/access_log combined

이 형식은 두 항목을 더 추가한 것을 제외하고는 Common 로그 형식과 완전히 같다. 추가된 항목들은 퍼센트 지시어 %{header}i를 사용한다. 여기서 header 자리에 HTTP 요청 헤더 이름이 나올 수 있다. 이 형식의 접근 로그는 다음과 같다:

127.0.0.1 - frank [10/Oct/2000:13:55:36 -0700] "GET /apache_pb.gif HTTP/1.0" 200 2326 "http://www.example.com/start.html" "Mozilla/4.08 [en] (Win98; I ;Nav)"

추가된 항목은:

"http://www.example.com/start.html" (\"%{Referer}i\")
"Referer" (맞춤법 틀리지않았음) HTTP 요청 헤더. 클라이언트가 참조했다고 서버에게 알린 사이트이다. (즉, /apache_pb.gif를 링크하였거나 포함한 사이트이다.)
"Mozilla/4.08 [en] (Win98; I ;Nav)" (\"%{User-agent}i\")
User-Agent HTTP 요청 헤더. 클라이언트 브라우저가 자신에 대해 알리는 식별정보이다.

여러 접근 로그

설정파일에 여러 CustomLog 지시어를 사용하면 접근 로그가 여러개 만들어진다. 예를 들어, 다음 설정은 세가지 접근 로그를 만든다. 첫번째는 기본 CLF 정보를 기록하고, 두번째와 세번째는 referer와 브라우저 정보를 기록한다. 마지막 두 CustomLog 줄은 어떻게 이전 ReferLog와 AgentLog 지시어의 기능을 흉내낼 수 있는지 보여준다.

LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common
CustomLog logs/referer_log "%{Referer}i -> %U"
CustomLog logs/agent_log "%{User-agent}i"

또, 이 예는 LogFormat으로 반드시 별명을 정의할 필요는 없음을 보여준다. 대신 CustomLog 지시어에 직접 로그 형식을 지정할 수 있다.

조건부 로그

클라이언트 요청의 성격에 따라 해당 항목을 접근 로그에 기록하지않고 싶을 때가 있다. 환경변수를 사용하면 쉽게 해결된다. 먼저, 클라이언트가 특정 조건을 만족하면 환경변수를 설정한다. 이 작업에는 보통 SetEnvIf를 사용한다. 그리고 CustomLog 지시어에 env=을 사용하여 환경변수 유무에 따라 요청을 집어넣거나 뺀다. 예를 들면:

# loop-back 인터페이스에서 요청을 표시한다
SetEnvIf Remote_Addr "127\.0\.0\.1" dontlog
# robots.txt 파일에 대한 요청을 표시한다
SetEnvIf Request_URI "^/robots\.txt$" dontlog
# 나머지를 로그에 남긴다
CustomLog logs/access_log common env=!dontlog

다른 예로 영어권 사용자의 요청만을 한 로그파일에 기록하고, 비영어권 사용자의 요청은 다른 로그파일에 기록하는 경우를 생각해보자.

SetEnvIf Accept-Language "en" english
CustomLog logs/english_log common env=english
CustomLog logs/non_english_log common env=!english

조건부 로그는 매우 강력하고 유연하지만, 이것이 로그 내용을 조절하는 유일한 방법은 아니다. 로그파일은 서버의 모든 행동을 기록할때 더 유용하다. 나중에 원하지않는 요청을 제외하고 로그파일을 분석하는 것이 더 쉽다.

로그 순환 (Log Rotation)

조금 바쁜 서버조차도 로그파일에 저장되는 정보량은 매우 많다. 접속 로그는 보통 만번 요청당 1MB 이상 증가한다. 결과적으로 기존의 로그를 옮기거나 지우는 방법으로 로그를 주기적으로 순활할 필요가 있다. 아파치는 파일을 열고있는 동안에는 계속 이전 로그파일에 쓰기때문에 서버가 실행중일때 로그를 순환할 수 없다. 대신 로그파일을 옮기거나 지운후 서버를 재시작하여, 로그파일을 새로 열어야 한다.

점잖은 재시작을 사용하면 서버는 클라이언트와 기존의 혹은 대기된 연결을 잃지않고 새 로그파일을 열 수 있다. 그러나 이를 위해 서버는 오래된 요청의 서비스를 끝내는 동안 이전 로그파일을 계속 사용해야 한다. 그러므로 재시작한후 로그파일을 처리하기 전에 얼마간 기다릴 필요가 있다. 일반적으로 다음과 같이 로그를 순환하고, 디스크공간을 절약하기위해 이전 로그를 압축한다:

mv access_log access_log.old
mv error_log error_log.old
apachectl graceful
sleep 600
gzip access_log.old error_log.old

로그를 순환하는 다른 방법은 다음 절에서 설명할 파이프 로그를 사용하는 것이다.

로그를 파이프로 보내기

아파치 웹서버는 오류 로그와 접근 로그를 파일에 직접 쓰지않고 파이프를 통해 다른 프로세스로 보낼 수 있다. 이 기능을 사용하면 서버에 코드를 추가하지않고도 매우 유연하게 로그를 처리할 수 있다. 로그를 파이프에 쓰기위해 파일명 자리에 파이프문자 "|"와 뒤에 표준입력으로 로그 항목을 읽을 실행파일명을 적으면 된다. 아파치는 서버가 시작할때 파이프로 연결할 로그 프로세스를 시작하고, 서버가 실행되는 동안 프로세스가 죽으면 다시 시작한다. (이 마지막 기능때문에 우리는 이 방법을 "믿을 수 있는 파이프 로그"라고 부른다.)

파이프로 연결된 로그 프로세스는 부모 아파치 httpd 프로세스가 띄우고, 프로세스의 userid도 같다. 즉, 파이프로 연결된 로그 프로그램은 보통 root로 실행된다. 그러므로 프로그램을 간단하고 안전하게 만드는 것이 매우 중요하다.

파이프로 부르는 전체 명령어를 따옴표로 묶음을 명심하라. 이 예는 접근 로그에 대한 것이지만, 오류 로그도 마찬가지다.

서버를 재시작하지않고 로그를 순환할 수 있는 것이 파이프 로그를 사용하는 중요한 이유다. 아파치 웹서버는 이를 위해 rotatelogs라는 간단한 프로그램을 포함한다. 예를 들어 24시간마다 로그를 순환한다면:

CustomLog "|/usr/local/apache/bin/rotatelogs /var/log/access_log 86400" common

다른 사이트에 cronolog라는 비슷하지만 훨씬 더 유연한 로그 순환 프로그램이 있다.

조건부 로그와 같이 파이프 로그는 매우 강력한 도구지만, 나중에 처리하는 등의 더 간단한 방법이 가능한 경우 사용해서는 안된다.

가상호스트

많은 가상호스트가 있는 서버를 운영할때 여러가지 방법으로 로그파일을 다룰 수 있다. 먼저, 호스트가 한개인 서버와 같이 로그를 사용할 수 있다. <VirtualHost> 섹션이 아닌 주서버 설정에 로그 지시어를 두면 모든 요청이 같은 접근 로그와 오류 로그로 기록된다. 이 방법은 가상호스트별로 쉽게 통계처리를 할 수 없다.

<VirtualHost> 섹션 안에 CustomLog나 ErrorLog 지시어를 사용하면 해당 가상호스트에 대한 요청과 오류만이 지정된 파일에 기록된다. 로그 지시어가 없는 다른 가상호스트는 계속 주서버 로그에 로그를 기록한다. 이 방법은 가상호스트 개수가 적을 경우 매우 유용하지만, 호스트 수가 많다면 관리하기 힘들어진다. 또, 파일기술자가 부족한 문제가 자주 발생한다.

접근 로그의 경우 매우 좋은 해결책이 있다. 로그 형식문자열에 가상호스트에 대한 정보를 추가하면 모든 호스트가 같은 로그를 사용하고, 나중에 로그를 가상호스트별로 나눌 수 있다. 예를 들어, 다음 지시어를 봐라.

LogFormat "%v %l %u %t \"%r\" %>s %b" comonvhost
CustomLog logs/access_log comonvhost

%v는 요청을 서비스하는 가상호스트 이름을 기록한다. 나중에 split-logfile 같은 프로그램으로 접근 로그를 가상호스별로 나눌 수 있다.

다른 로그파일

관련된 모듈 관련된 지시어
  • mod_cgi
  • mod_rewrite
  • PidFile
  • RewriteLog
  • RewriteLogLevel
  • ScriptLog
  • ScriptLogBuffer
  • ScriptLogLength

PID 파일

아파치 웹서버는 시작할때 logs/httpd.pid 파일에 부모 httpd 프로세스의 process id를 저장한다. 이 파일명은 PidFile 지시어로 변경할 수 있다. process-id는 관리자가 부모 프로세스에 시그널을 보내 서버를 재시작하거나 죽일때 사용한다. 윈도우즈에서는 대신 -k 명령행옵션을 사용한다. 더 자세한 정보는 중단과 재시작 페이지를 참고하라.

스크립트 로그

디버깅을 돕기위해 ScriptLog 지시어를 사용하여 CGI 스크립트의 입력과 출력을 기록할 수 있다. 이 지시어는 오직 테스트용으로만 사용해야 한다. 실제 사용하는 서버에서 사용하면 안된다. 더 자세한 정보는 mod_cgi 문서를 참고하라.

재작성 로그

mod_rewrite의 강력하고 복잡한 기능을 사용한다면 디버깅을 위해 거의 항상 RewriteLog를 사용할 필요가 있다. 이 로그파일은 재작성 엔진이 어떻게 요청을 변환하는지에 대해 자세히 알려준다. 자세한 정도는 RewriteLogLevel 지시어로 조절한다.


URL을 파일시스템 위치로 대응하기 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

URL을 파일시스템 위치로 대응하기

이 문서는 요청의 URL을 가지고 아파치가 어떻게 서비스할 파일의 파일시스템상 위치를 찾는지 설명한다.

관련된 모듈과 지시어들

관련된 모듈 관련된 지시어
  • mod_alias
  • mod_proxy
  • mod_rewrite
  • mod_userdir
  • mod_speling
  • mod_vhost_alias
  • Alias
  • AliasMatch
  • CheckSpelling
  • DocumentRoot
  • ErrorDocument
  • Options
  • ProxyPass
  • ProxyPassReverse
  • Redirect
  • RedirectMatch
  • RewriteCond
  • RewriteMatch
  • ScriptAlias
  • ScriptAliasMatch
  • UserDir

DocumentRoot

요청을 받은 아파치는 어떤 파일을 서비스할지 결정하기위해 기본적으로 요청의 URL-경로(URL에서 호스트명과 포트 뒤에 나오는 부분)를 설정파일에서 지정한 DocumentRoot 뒤에 붙인다. 그래서 DocumentRoot 아래있는 파일과 디렉토리들은 웹에서 보게될 기본적인 내용이다.

DocumentRoot 밖에 있는 파일들

종종 파일시스템에서 DocumentRoot 아래 있지않은 부분을 웹에서 접근할 필요가 있다. 아파치는 이 경우 여러가지 방법을 사용할 수 있다. 유닉스 시스템에서 심볼링크를 사용하여 파일시스템의 다른 부분을 DocumentRoot 아래에 둘 수 있다. 보안을 위해 아파치는 해당 디렉토리의 Options 설정에 FollowSymLinks나 SymLinksIfOwnerMatch가 있는 경우에만 심볼링크를 따라간다.

또, Alias 지시어는 파일시스템의 특정 부분을 웹공간에 대응한다. 예를 들어 다음과 같다면

Alias /docs /var/web

URL http://www.example.com/docs/dir/file.html은 /var/web/dir/file.html을 가지고 서비스한다. 지정한 경로에 있는 모든 내용을 CGI 스크립트로 취급하는 것을 제외하고는 ScriptAlias 지시어도 같은 일을 한다.

AliasMatch와 ScriptAliasMatch 지시어의 강력한 정규표현식기반 대응과 대치를 사용하여 더 유연한 설정이 가능하다. 예를 들어,

ScriptAliasMatch ^/~([a-zA-Z0-9]+)/cgi-bin/(.+) /home/$1/cgi-bin/$2

는 http://example.com/~user/cgi-bin/script.cgi로의 요청을 경로 /home/user/cgi-bin/script.cgi로 대응하고, 해당 파일을 CGI 스크립트로 취급한다.

사용자 디렉토리

유닉스 시스템은 전통적으로 특정 사용자 user의 홈디렉토리를 ~user/로 지칭한다. mod_userdir 모듈은 이 개념을 웹에까지 확장하여, 다음과 같은 URL을 가지고 각 사용자 홈디렉토리 안에 있는 파일을 서비스한다.

http://www.example.com/~user/file.html

보안상 웹에서 사용자 홈디렉토리로 직접 접근할 수 있으면 안된다. 그래서 UserDir 지시어는 사용자 홈디렉토리에서 웹용 파일들이 있을 디렉토리를 지정한다. 기본 설정 Userdir public_html을 사용하고 /home/user/가 /etc/passwd에 지정된 사용자 홈디렉토리라면, 위의 URL은 파일 /home/user/public_html/file.html에 대응한다.

또, Userdir 지시어는 /etc/passwd에 홈디렉토리의 위치가 저장되지않는 시스템을 위해 여러 다른 형태를 사용할 수 있다.

어떤 사람은 (보통 웹에서 %7e로 인코딩되는) "~" 기호가 이상하여 다른 방식으로 사용자 디렉토리를 나타내고 싶어한다. 이 기능은 mod_userdir이 제공하지않는다. 그러나 사용자 홈디렉토리가 규칙적인 방법으로 구성되있다면, AliasMatch 지시어를 사용하여 원하는 효과를 얻을 수 있다. 예를 들어, 다음의 AliasMatch 지시어를 사용하면 http://www.example.com/upages/user/file.html이 /home/user/public_html/file.html에 대응한다:

AliasMatch ^/upages/([a-zA-Z0-9]+)/?(.*) /home/$1/public_html/$2

URL 리다이렉션(Redirection)

앞에서 설명한 설정 지시어들은 아파치가 파일시스템의 특정 장소에 있는 내용을 클라이언트에게 보내게 만든다. 그러나 때때로 요청한 내용이 다른 URL에 있다고 클라이언트에게 알려주어, 클라이언트가 새로 그 URL을 요청하도록 만드는 것이 좋을 때가 있다. 이를 리다이렉션(redirection)이라고 하며, Redirect 지시어를 사용한다. 예를 들어, DocumentRoot 아래 /foo/ 디렉토리의 내용을 새로 /bar/ 디렉토리로 옮겼다면 다음과 같이 클라이언트가 새로운 위치를 요청하도록 한다:

Redirect permanent /foo/ http://www.example.com/bar/

그러면 www.example.com 서버의 /foo/로 시작하는 URL-경로는 /foo/를 /bar/로 바꾼 URL로 리다이렉션된다. 클라이언트를 원래 서버외에 어떤 다른 서버로도 리다이렉션할 수 있다.

또, 아파치는 더 복잡한 재작성 문제를 위해 RedirectMatch 지시어를 제공한다. 예를 들어, 다른 요청은 그대로 두고 사이트 홈페이지에 대한 요청만을 다른 사이트로 리다이렉션하려면:

RedirectMatch permanent ^/$ http://www.example.com/startpage.html

임시로 사이트의 모든 페이지를 다른 사이트의 특정 페이지로 리다이렉션하려면:

RedirectMatch temp .* http://othersite.example.com/startpage.html

역프록시(Reverse Proxy)

아파치는 다른 서버에 있는 문서를 서버의 URL 공간으로 가져올 수 있다. 이 경우 웹서버가 원격 서버에서 문서를 가져와서 클라이언트에게 전달하는 프록시 서버와 같이 동작하기때문에 이런 방법을 역프록시(reverse proxying)라고 한다. 클라이언트의 입장에서 역프록시 서버가 문서를 보내주는 것처럼 보이므로 일반 프록시와는 다르다.

아래 설정에서 클라이언트가 /foo/에 있는 문서를 요청하면, 서버는 internal.example.com의 /bar/ 디렉토리에서 문서를 가져와서 문서가 마치 서버에 있었던 것처럼 클라이언트에게 보낸다.

ProxyPass /foo/ http://internal.example.com/bar/
ProxyPassReverse /foo/ http://internal.example.com/bar/

ProxyPass는 서버가 적절한 문서를 가져오도록 설정하며, ProxyPassReverse 지시어는 internal.example.com이 보내는 리다이렉션을 재작성하여 리다이렉션이 현재 서버의 적절한 디렉토리를 가리키도록 한다. 그러나 문서 안에 있는 링크는 재작성하지 않음을 주의하라. internal.example.com에 대한 절대링크는 클라이언트가 프록시서버가 아니라 internal.example.com으로 직접 요청하게 한다.

재작성 엔진 (Rewriting Engine)

더 강력한 치환이 필요할때 mod_rewrite의 재작성 엔진이 도움이 된다. 이 모듈의 지시어는 브라우저 종류나 클라이언트의 IP 주소 등 요청의 특징을 가지고 어디에 있는 내용을 서비스할지 결정할 수 있다. 또, mod_rewrite는 요청을 어떻게 처리할지 결정하기위해 외부 데이터베이스 파일이나 프로그램을 사용할 수 있다. 재작성 엔진은 위에서 다룬 세 종류 대응, 즉, 내부 리다이렉션 (alias), 외부 리다이렉션, 프록시, 모두를 지원한다. mod_rewrite를 사용하는 실제 예는 URL 제작성 지침서에서 설명한다.

File Not Found

결국 요청한 URL에 대응하는 파일을 파일시스템에서 찾지 못한 경우이다. 여러 가지 이유가 있다. 어떤 경우 문서를 다른 곳으로 옮겼기 때문일 수 있다. 이 경우 클라이언트에게 URL 리다이렉션으로 자원의 새로운 위치를 알려주는 방법이 제일 좋다. 그러면 자원을 옮겨도 오래된 북마크나 링크가 계속 유효하다.

"File Not Found" 오류의 다른 일반적인 원인은 브라우저에 직접 혹은 HTML 링크에 URL이 잘못 입력된 경우이다. 아파치는 mod_speling (맞춤법이 틀리지 않았음) 모듈로 이와 같은 문제를 돕는다. 이 모듈을 사용하면 "File Not Found" 오류가 발생하는 경우 비슷한 파일명을 가진 자원을 찾는다. 만약 발견하면 mod_speling은 클라이언트를 올바른 위치로 HTTP 리다이렉션한다. "비슷한" 파일이 여러개 있다면 클라이언트에게 목록을 보낸다.

mod_speling의 특히 유용한 장점은 대소문자를 구별하지않고 파일명을 비교하는 기능이다. 그래서 유닉스 파일시스템과 URL의 대소문자 성질을 알지못하는 사용자가 있는 시스템에 도움이 된다. 그러나 mod_speling이 자주 URL을 고쳐야한다면, "잘못된" 요청때마다 URL 리다이렉션과 클라이언트의 새로운 요청이 일어나므로 서버에 부담이 된다.

찾는 시도가 모두 실패하면 아파치는 HTTP status code 404 (file not found) 오류페이지를 보낸다. 이 페이지의 내용은 ErrorDocument 지시어로 조절하며, 사용자정의 오류 응답과 다국어 서버 오류문 문서를 참고하여 사용자정의할 수 있다.


보안 팁 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

보안 팁

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

웹서버를 운영할때 도움이 될 보안 관련 힌트와 팁이다. 어떤 것은 일반적이고, 어떤 것은 아파치에만 해당하는 것이다.

최신판으로 유지하기

아파치 웹서버는 안전과 보안 문제에 관심이 많은 개발자 공동체로 유명하다. 그러나 크건 작건 발표후 발견되는 문제들을 피할 수 없다. 그래서 소프트웨어를 최신버전으로 유지하는 것이 중요하다. 아파치에서 직접 웹서버를 다운로드했다면, 새로운 버전과 보안 업데이트를 알려주는 아파치 웹서버 발표 메일링리스트를 구독하길 강력히 권한다. 아파치 소프트웨어를 배포하는 많은 제삼자들도 비슷한 서비스를 제공한다.

물론 웹서버 코드때문에 웹서버가 공격을 당하는 경우는 많지 않다. 그보다 추가 코드, CGI 스크립트, 하위 운영체제의 문제로 공격을 당하는 경우가 많다. 그러므로 항상 주의하며 시스템의 모든 소프트웨어를 업데이트해야 한다.

ServerRoot 디렉토리 권한

보통 root 사용자가 아파치를 시작한 후, 요청을 서비스하기위해 User 지시어로 지정한 사용자로 변환한다. root가 실행하는 명령어가 있다면, root 이외의 사용자가 수정하지 못하도록 주의해야 한다. 이 파일들을 root만 쓸 수 있어야 하고, 디렉토리와 모든 상위디렉토리도 마찬가지다. 예를 들어, ServerRoot로 /usr/local/apache를 사용한다면 root 사용자가 다음과 같이 디렉토리를 만들길 제안한다:

mkdir /usr/local/apache
cd /usr/local/apache
mkdir bin conf logs
chown 0 . bin conf logs
chgrp 0 . bin conf logs
chmod 755 . bin conf logs

그러면 /, /usr, /usr/local 은 root만이 수정할 수 있다. httpd 실행파일을 설치할때 다음과 같이 보호해야 한다:

cp httpd /usr/local/apache/bin
chown 0 /usr/local/apache/bin/httpd
chgrp 0 /usr/local/apache/bin/httpd
chmod 511 /usr/local/apache/bin/httpd

htdocs 하위디렉토리는 다른 사용자들이 수정할 수 있도록 만들 수 있다 -- root는 그곳에 있는 파일을 실행하지도, 만들지도 않아야 한다.

root가 아닌 사용자가 root가 실행하거나 쓰기가능한 파일을 수정할 수 있다면 시스템의 root 권한을 훔칠 수 있다. 예를 들어, 누군가 httpd 실행파일을 변경하였다면 다음번 시작할때 임의의 코드를 실행하게 된다. logs 디렉토리가 (root가 아닌 사용자에게) 쓰기가능하다면 누군가 로그파일을 다른 시스템파일로 심볼링크를 걸어서 root가 파일에 임의의 자료를 덮어쓸 수 있다. 로그파일이 (root가 아닌 사용자에게) 쓰기가능하다면 누군가 로그에 이상한 자료를 기록할 수 있다.

Server Side Includes

Server Side Includes (SSI)는 서버 관리자에게 보안상 몇가지 잠재적인 위험이다.

첫번째 위험은 서버의 부하를 늘리는 점이다. 아파치는 파일에 SSI 지시어가 있는지 여부와 관계없이 모든 SSI 파일을 분석해야 한다. 조금 부하가 늘지만, 서버를 여러 사람이 같이 사용하는 환경에서는 심각할 수 있다.

또, SSI 파일은 일반적인 CGI 스크립트와 동일한 위험을 가진다. SSI 파일에서 "exec cmd"를 사용하면 httpd.conf에서 아파치를 실행하도록 설정한 사용자와 그룹 권한으로 CGI 스크립트나 프로그램을 실행할 수 있다.

장점을 활용하면서 SSI 파일의 보안을 향상시키는 방법이 있다.

SSI 파일이 가져올 수 있는 피해를 격리하기위해 서버관리자는 일반적인 CGI 절에서 설명하는 방법으로 suexec를 사용할 수 있다

.html이나 .htm 확장자를 SSI 파일로 사용하는 것은 위험하다. 특히 여러 사람이 공유하거나 통신량이 많은 서버 환경에서 위험하다. SSI 파일은 일반적으로 많이 사용하는 .shtml 같은 별도의 확장자를 가져야 한다. 그러면 서버 부하를 최소화하고 위험요소를 쉽게 관리할 수 있다.

다른 방법은 SSI 페이지가 스크립트나 프로그램을 실행하지 못하도록 만드는 것이다. Options 지시어에서 Includes 대신 IncludesNOEXEC를 사용한다. 그래도 스크립트가 ScriptAlias 지시어로 지정한 디렉토리에 있다면 <--#include virtual="..." -->를 사용하여 CGI 스크립트를 실행할 수 있음을 주의하라.

일반적인 CGI

결국 당신은 항상 CGI 스크립트/프로그램의 저자를 신뢰해야 하고, 고의건 실수이건 CGI의 잠재적인 보안상 허점을 발견할 수 있어야 한다. 기본적으로 CGI 스크립트는 웹서버 사용자 권한으로 시스템에서 어떤 명령어라도 실행할 수 있기때문에 주의있게 확인하지 않으면 매우 위험하다.

모든 CGI 스크립트가 같은 사용자로 실행되기때문에 다른 스크립트와 (고의건 실수이건) 충돌할 가능성이 있다. 예를 들어, 사용자 A는 사용자 B를 매우 싫어하여, 사용자 B의 CGI 데이터베이스를 지워버리는 스크립트를 작성할 수 있다. 아파치 1.2 버전부터 포함되었고 아파치 서버에서 특별한 훅(hook)으로 동작하는 suEXEC는 스크립트를 다른 사용자로 실행하는 방법중 하나다. 다른 대중적인 방법에는 CGIWrap이 있다.

ScriptAlias하지 않은 CGI

다음 조건을 만족할때만 사용자가 어떤 디렉토리에서라도 CGI 스크립트를 실행하도록 허용할 수 있다:

  • 당신은 고의건 실수이건 사용자가 시스템을 공격에 노출시키는 스크립트를 작성하지 않는다고 믿는다.
  • 시스템의 다른 부분의 보안이 약해서, 잠재적인 허점을 하나 더 만들어도 나빠질 것이 없다고 생각하는 경우.
  • 사용자가 없고, 아마 아무도 서버를 방문하지않는 경우.

ScriptAlias한 CGI

특정 디렉토리에서만 CGI를 실행할 수 있도록 제한하면 관리자는 이들 디렉토리를 통제할 수 있다. 이 경우는 scriptalias하지 않은 CGI보다 확실히 안전하다. 단, 신뢰하는 사용자만 디렉토리에 접근할 수 있고, 관리자가 새로운 CGI 스크립트/프로그램의 잠재적인 보안상 허점을 검사할 용이가 있다면.

대부분의 사이트는 scriptalias하지 않은 CGI 방식 대신 이 방식을 사용한다.

동적 내용을 생성하는 다른 방법

mod_php, mod_perl, mod_tcl, mod_python 같이 서버의 일부로 동작하는 임베디드 스크립트는 서버와 같은 사용자로 (User 지시어 참고) 실행되기때문에, 스크립트 엔진이 실행하는 스크립트는 잠재적으로 서버 사용자가 접근할 수 있는 모든 것에 접근할 수 있다. 어떤 스크립트 엔진은 어느정도 제한을 하지만, 안전하다고 가정하지 않는 것이 좋다.

시스템 설정 보호하기

정말로 안전한 서버를 운영하려면 사용자가 .htaccess 파일을 사용하여 당신이 설정한 보안기능을 변경하길 바라지 않을 것이다. 그러기위해 다음과 같은 방법이 있다.

서버 설정파일에 다음을 추가한다

<Directory />
AllowOverride None
</Directory>

그러면 사용가능하도록 명시적으로 허용한 디렉토리를 제외하고는 .htaccess 파일을 사용할 수 없다.

기본적으로 서버에 있는 파일 보호하기

사람들은 종종 아파치의 기본 접근에 대해 잘못 알고있다. 즉, 서버가 일반적인 URL 대응 규칙을 사용하여 파일을 찾을 수 있다면, 특별히 조치를 하지 않는한 클라이언트에게 파일이 서비스될 수 있다.

예를 들어, 아래와 같은 경우:

# cd /; ln -s / public_html
http://localhost/~root/ 에 접근한다

그러면 클라이언트는 전체 파일시스템을 돌아다닐 수 있다. 이를 막기위해 서버설정에서 다음과 같은 조치를 한다:

<Directory />
Order Deny,Allow
Deny from all
</Directory>

그러면 파일시스템 위치에 대해 기본 접근이 거부된다. 원하는 영역에 접근할 수 있도록 다음과 같은 Directory 블록을 추가한다.

<Directory /usr/users/*/public_html>
Order Deny,Allow
Allow from all
</Directory>
<Directory /usr/local/httpd>
Order Deny,Allow
Allow from all
</Directory>

Location과 Directory 지시어를 같이 사용하는 경우 특별히 주의를 기울여라. 예를 들어, <Directory />가 접근을 거부하더라도 <Location /> 지시어가 이를 무시할 수 있다

UserDir 지시어를 사용하는 경우에도 주의하라. 지시어를 "./" 같이 설정하면 root 사용자에 대해 바로 위의 경우와 같은 문제가 발생한다. 아파치 1.3 이상을 사용한다면 서버 설정파일에 아래 줄을 추가하길 강력히 권한다:

UserDir disabled root

로그 살펴보기

실제로 서버에서 무슨 일이 있어나고 있는지 알려면 로그파일을 살펴봐야 한다. 로그파일은 이미 일어난 일만을 보고하지만, 서버에 어떤 공격이 있었는지 알려주고 현재 필요한 만큼 안전한지 확인하게 해준다.

여러가지 예:

grep -c "/jsp/source.jsp?/jsp/ /jsp/source.jsp??" access_log
grep "client denied" error_log | tail -n 10

첫번째 예는 잘못된 Source.JSP 요청으로 서버정보를 알아낼 수 있는 Tomcat의 취약점를 이용하려는 공격 횟수를 알려주고, 두번째 예는 접근이 거부된 최근 클라이언트 10개를 다음과 같이 보여준다:

[Thu Jul 11 17:18:39 2002] [error] [client foo.bar.com] client denied by server configuration: /usr/local/apache/htdocs/.htpasswd

잘 알 듯이 로그파일은 이미 발생한 사건만을 보고한다. 그래서 클라이언트가 .htpasswd 파일에 접근할 수 있었다면 접근 로그에 다음과 같은 기록이 남을 것이다:

foo.bar.com - - [12/Jul/2002:01:59:13 +0200] "GET /.htpasswd HTTP/1.1"

즉, 당신은 서버 설정파일에서 다음 부분을 주석처리했을 것이다:

<Files ~ "^\.ht">
Order allow,deny
Deny from all
<Files>


동적공유객체 (DSO) 지원 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

동적공유객체 (DSO) 지원

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

아파치 웹서버는 관리자가 모듈들을 선택하여 서버에 포함할 기능을 결정할 수 있는 모듈화된 프로그램이다. 서버를 컴파할때 httpd 실행파일에 정적으로 모듈을 컴파일할 수 있다. 아니면 모듈을 httpd 실행파일과 분리하여 동적공유객체(Dynamic Shared Objects, DSO)로 컴파일할 수 있다. DSO 모듈은 서버를 컴파일할때 컴파일하거나, Apache Extension Tool (apxs)을 사용하여 나중에 컴파일하여 추가할 수 있다.

이 문서는 DSO 모듈 사용법과 배경 이론을 설명한다.

구현

관련된 모듈 관련된 지시어
  • mod_so
  • LoadModule

아파치 핵심에 정적으로 컴파일해야할 mod_so.c라는 모듈은 아파치 모듈을 읽어들이기위한 DSO를 지원한다. 이 모듈은 core를 제외하고 DSO가 될 수 없는 유일한 모듈이다. 실제로 다른 모든 아파치 모듈은 설치 문서에서 설명한 configure의 --enable-module=shared 옵션을 사용하여 DSO로 컴파일할 수 있다. 모듈을 mod_foo.so와 같이 DSO로 컴파일한후 httpd.conf 파일에 mod_so의 LoadModule 명령어를 사용하여 서버 시작시 혹은 재시작시 그 모듈을 읽어들일 수 있다.

아파치 모듈(특히 제삼자가 만든 모듈)로 사용할 DSO 파일을 쉽게 만들기위해 apxs (APache eXtenSion)라는 새로운 지원 프로그램이 있다. 이 프로그램은 아파치 소스 트리 밖에서 DSO로 사용할 모듈을 컴파일할때 사용한다. 개념은 쉽다. 아파치를 설치할때 configure와 make install이 아파치 C 헤더파일을 설치하고, DSO 파일을 컴파일하기위한 플래폼 특유의 컴파일러 옵션과 링커 옵션을 apxs 프로그램에 기록한다. 그래서 apxs를 사용하는 사용자는 아파치 배포본 소스 트리없이, 또 DSO 지원을 위한 플래폼 특유의 컴파일러 옵션와 링커 옵션에 신경을 쓰지않고 자신의 아파치 모듈 소스를 컴파일할 수 있다.

사용법 요약

Apache 2.0의 DSO 기능에 대한 짧고 간략한 요약이다:

  1. 배포본에 있는 아파치 모듈을 컴파일하고 설치하는 경우. 예를 들어 mod_foo.c를 DSO mod_foo.so로:

    $ ./configure --prefix=/path/to/install --enable-foo=shared
    $ make install

  2. 제삼자가 만든 아파치 모듈을 컴파일하고 설치하는 경우. 예를 들어 mod_foo.c를 DSO mod_foo.so로:

    $ ./configure --add-module=module_type:/path/to/3rdparty/mod_foo.c --enable-foo=shared
    $ make install

  3. 공유 모듈을 나중에 사용하기위해 아파치를 구성하는 경우:

    $ ./configure --enable-so
    $ make install

  4. 제삼자가 만든 아파치 모듈을 컴파일하고 설치하는 경우. apxs를 사용하여 아파치 소스 트리 밖에서 mod_foo.c를 DSO mod_foo.so로:

    $ cd /path/to/3rdparty
    $ apxs -c mod_foo.c
    $ apxs -i -a -n foo mod_foo.la

모든 경우 일단 공유 모듈이 컴파일되면, httpd.conf에 LoadModule 지시어를 사용하여 아파치가 그 모듈을 읽어들이게 만든다.

배경지식

현대적인 유닉스류에는 동적공유객체 (DSO)의 동적 링킹/로딩(dynamic linking/loading)이라고 하여, 특별한 형식의 실행코드 조각을 만들어 실행중인 실행프로그램의 주소공간에 읽어들이는 멋진 기능이 있다.

보통 두가지 방법으로 읽어들일 수 있다. 하나는 실행프로그램이 시작할때 ld.so라는 시스템 프로그램이 자동으로 읽어들이는 경우고, 다른 하나는 실행중인 프로그램이 dlopen()/dlsym() 시스템호출로 유닉스 로더(loader)의 시스템 인터페이스을 사용하여 직접 읽어들이는 경우다.

첫번째 경우 DSO를 보통 공유라이브러리(shared libraries) 혹은 DSO 라이브러리라고 부르며, 파일은 libfoo.so나 libfoo.so.1.2 같은 이름을 가진다. 이들은 시스템 디렉토리(보통 /usr/lib)에 있고, 컴파일시 링커 명령어에 -lfoo를 주어 실행파일과 연결한다. 이렇게 직접 써준 라이브러리는 실행파일에 참조되여서, 프로그램이 시작할때 링커 옵션 -R로 직접 지정한 경로, 환경변수 LD_LIBRARY_PATH로 지정한 경로 혹은 /usr/lib에서 유닉스 로더가 libfoo.so를 찾을 수 있다. 그러면 실행프로그램의 (아직 못찾은(unresolved)) 심볼(symbol)을 DSO에서 찾게된다.

DSO는 보통 실행프로그램의 심볼을 찾지않기 때문에 (DSO가 재사용가능한 일반적인 코드 라이브러리이므로) 찾기는 여기서 끝난다. 유닉스 로더가 심볼 찾기를 완전히 담당하므로 실행프로그램이 직접 DSO에서 심볼을 찾을 필요가 없다. (사실 ld.so를 부르는 코드는 정적이 아닌 모든 실행프로그램에 링크되는 실행시 시작코드의 일부다.) 공통된 라이브러리 코드를 동적으로 읽어들이는 장점은 명확하다. 라이브러리 코드가 모든 프로그램에 중복해서 저장되는 대신 libc.so와 같은 시스템 라이브러리에 한번만 저장되기 때문에 디스크 공간이 절약된다.

두번째 경우 DSO를 보통 공유객체(shared objects) 혹은 DSO 파일이라고 부르고, (규칙상 이름은 foo.so이지만) 파일의 확장자는 자유롭다. 이 파일들은 보통 프로그램 자체 디렉토리에 위치하고 실행프로그램에 자동으로 연결되지 않는다. 대신 실행프로그램은 실행시 dlopen()을 사용하여 DSO를 주소공간에 직접 읽어들여야 한다. 이때 실행프로그램은 DSO에서 심볼을 찾지 않는다. 대신 앞에서 본 유닉스 로더는 자동으로 실행파일과 실행파일이 이미 읽어들인 DSO 라이브러리(특히 항상 존재하는 libc.so의 모든 심볼)에서 DSO의 (아직 못찾은) 심볼을 찾는다. 그래서 DSO는 마치 처음부터 실행프로그램에 정적으로 링크된것과 같이 실행파일의 심볼을 알게된다.

DSO의 API를 이용하기위해서 마지막으로 실행프로그램은 dlsym()으로 DSO에서 특정 심볼을 찾아서, 앞으로 사용하기위해 디스패치(dispatch) 표 등에 저장한다. 다른 말로 실행프로그램은 사용할 모든 실볼을 직접 찾아야한다. 이런 구조의 장점은 프로그램의 일부를 프로그램이 필요할때까지 읽어들이지 않아도 (그래서 메모리를 낭비하지 않게) 된다는 점이다. 기본 프로그램의 기능을 확장하기위해 필요한 경우 이 부분을 동적으로 읽어들일 수 있다.

이런 DSO 구조가 자연스럽게 보이지만, 최소한 어려운 점이 한가지있다. 프로그램을 확장하기위해 DSO를 사용할때 DSO가 실행프로그램의 심볼을 찾는 일이다. 왜? DSO가 실행프로그램의 심볼을 "역으로 찾는 것"은 (라이브러리는 자신을 사용하는 프로그램에 대해 모른다는) 라이브러리 설계에 반하며, 모든 플래폼에서 지원되지않고 표준화되지도 않았기 때문이다. 실제로 실행파일의 전역심볼(global symbol)은 보통 익스포트(export)되지 않기때문에 DSO가 사용할 수 없다. DSO를 사용하여 실행중 프로그램을 확장하려면 링커에게 모든 전역심볼을 익스포트하도록 강제하는 것이 주된 해결책이다.

공유라이브러리는 DSO 방식의 설계원칙대로 전형적이기때문에 운영체제가 제공하는 거의 모든 종류의 라이브러리가 사용한다. 반대로 많은 프로그램은 프로그램을 확장하기위해 공유객체를 사용하지 않는다.

1998년 실행중 실제로 기능을 확장하기위해 DSO 구조를 사용한 소프트웨어 패키지는 (XS 구조와 DynaLoader 모듈을 사용한) Perl 5, Netscape Server 등으로 드물었다. 아파치는 이미 기능을 확장하기위해 모듈 개념을 사용했고 외부 모듈을 아파치 핵심기능에 연결하기위해 내부적으로 디스패치목록을 이용한 접근방법을 사용했기때문에 1.3 버전부터 이 대열에 합류했다. 그래서 아파치는 실행중 모듈을 읽어들이는데 DSO를 사용하도록 운명지워졌다.

장단점

앞에서 말한 DSO를 사용하면 다음과 같은 장점이 있다:

  • 실제 서버 프로세스가 컴파일시 configure 옵션대신 httpd.conf의 LoadModule을 사용하여 실행중에 결합되므로 서버 패키지 실행이 더 유연하다. 예를 들어 한번의 아파치 설치만으로 다른 서버(표준 버전과 SSL 버전, 최소화 버전과 기능추가 버전 [mod_perl, PHP3] 등)를 실행할 수 있다.
  • 서버는 설치후에도 제삼자가 만든 모듈을 사용하여 쉽게 확장할 수 있다. 최소한 기업의 패키지 제작자는 아파치 핵심 패키지와 별도로 PHP3, mod_perl, mod_fastcgi 등을 추가 패키지로 만들 수 있어서 큰 이득이다.
  • DSO와 apxs를 가지고 아파치 소스 트리 밖에서 작업하고 apxs -i와 apachectl restart 명령어만으로 현재 개발한 모듈의 새 버전을 실행중인 아파치 서버에 반영할 수 있어서 더 쉽게 아파치 모듈을 개발할 수 있다.

DSO는 다음과 같은 단점이 있다:

  • 프로그램의 주소공간에 코드를 동적으로 읽어들이는 기능을 지원하지않는 운영체제가 있기 때문에 모든 플래폼에서 DSO를 사용할 수 없다.
  • 유닉스 로더가 심볼을 찾아야하기 때문에 서버 시작이 약 20% 정도 늦어진다.
  • 서버는 위치독립코드(position independent code, PIC) 때문에 절대주소지정(absolute addressing)보다 느린 상대주소지정(relative addressing)의 복잡한 어셈블러 기법이 필요하므로 어떤 플래폼에서 실행시 약 5% 정도 늦다.
  • DSO 모듈을 다른 DSO기반 라이브러리(ld -lfoo)에 링크할 수 없는 플래폼이 있기때문에 (예를 들어 ELF기반 플래폼은 지원하지만 a.out기반 플래폼은 보통 이 기능을 지원하지 않는다) 모든 종류의 모듈에 DSO를 사용할 수 없다. 다른 말로 DSO 파일로 컴파일하는 모듈은 아파치 핵심과 아파치 핵심이 사용하는 C 라이브러리(libc)와 다른 동적/정적 라이브러리, 위치독립코드를 담고 있는 정적 라이브러리 아카이브(libfoo.a)의 심볼만을 사용할 수 있다. 다른 코드를 사용하려면 아파치 핵심이 그것을 참조하던지, dlopen()으로 직접 코드를 읽어들여야 한다.


내용협상 (Content Negotiation) - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

내용협상 (Content Negotiation)

아파치는 HTTP/1.1 규약에 기술된 내용협상(content negotiation)을 지원한다. 내용협상은 media type, 언어, 문자집합, 인코딩 등에 대해 브라우저가 제공한 선호도에 따라 자원의 가장 적합한 표현을 선택한다. 또 불완전한 협상 정보를 보내는 브라우저의 요청을 지능적으로 처리하는 기능도 있다.

기본적으로 컴파일되는 mod_negotiation 모듈이 내용협상 기능을 제공한다.

내용협상에 대해

자원은 여러 다른 표현을 가질 수 있다. 예를 들어, 다른 언어나 다른 media type 혹은 둘 모두가 다른 표현들이 있을 수 있다. 가장 적당한 표현을 선택하는 한가지 방법은 사용자에게 목록 페이지를 보여주고 선택하게 하는 것이다. 그러나 서버가 자동으로 선택하는 것도 가능하다. 이는 브라우저가 요청의 일부로 그들이 선호하는 표현에 대한 정보를 보내기때문에 가능하다. 예를 들어, 브라우저는 가능한한 불어로, 그러나 없다면 영어로 정보를 보고싶다고 알려줄 수 있다. 브라우저는 요청의 헤더로 그들의 기호를 나타낸다. 오직 불어로된 표현만을 요청한다면 브라우저는 다음과 같이 보낸다.

Accept-Language: fr

이런 기호는 표현이 언어별로 다를 경우에만 고려된다.

다음은 더 복잡한 요청의 예로 브라우저가 불어와 영어를 받을 수 있지만, 불어를 더 선호하고, 여러 media type을 받을 수 있지만, 일반 텍스트 보다는 HTML, 다른 media type 보다는 GIF와 JPEG을 선호한다고 알려준다.

Accept-Language: fr; q=1.0, en; q=0.5
Accept: text/html; q=1.0, text/*; q=0.8, image/gif; q=0.6, image/jpeg; q=0.6, image/*; q=0.5, */*; q=0.1

아파치는 HTTP/1.1 규약에 정의된 '서버 주도(server driven)' 내용협상을 지원한다. 아파치는 Accept, Accept-Language, Accept-Charset, Accept-Encoding 요청 헤더를 모두 지원한다. 또, 아파치는 RFC 2295와 RFC 2296에 정의된 실험적인 내용협상인 '자연스러운(transparent)' 요청 헤더도 지원한다. 그러나 이 RFC에 정의된 '기능 협상(feature negotiation)'은 지원하지 않는다.

자원(resource)은 (RFC 2396) URI로 구별하는 개념적인 존재다. 아파치와 같은 웹서버는 자원의 표현(representations)을 제공한다. 표현은 지정된 media type, 문자집합, 인코딩 등을 가진 바이트들로 되있다. 자원은 여러 표현과 (때로는 없을 수도 있다) 연관된다. 자원에 여러 표현이 있다면 자원을 협상가능하다고(negotiable) 부르며, 이때 각 표현을 변형(variant)이라고 한다. 협상가능한 자원의 변형 종류를 협상의 범위(dimension)라고 한다.

아파치의 협상

자원을 협상하기위해 서버는 각 변형에 대한 정보가 필요하다. 다음 두가지 방법중 하나로 정보를 얻는다:

  • 변형을 담은 파일들을 직접 열거한 type map을 (예를 들어, *.var 파일) 사용하거나,
  • 직접 지정하지않아도 서버가 파일명에서 규칙을 찾아서 결과를 선택하는 'MultiViews'를 사용한다.

type-map 파일 사용하기

type map은 type-map이란 핸들러와 연결된 (혹은 이전 아파치 설정과 호환을 위해 MIME type이 application/x-type-map인) 문서다. 이 기능을 사용하려면 설정에서 type-map 핸들러에 대한 파일 확장자를 지정해야 한다. 서버 설정파일에 다음과 같이 설정하는 것이 좋다.

AddHandler type-map .var

Type map 파일은 해당하는 자원과 이름이 같아야 하고, 각 변형에 대한 항목이 있어야 한다. 항목은 여러 HTTP형식 헤더 줄로 구성된다. 변형에 대한 각각의 항목들은 빈줄로 구분한다. 항목안에서 빈줄을 사용할 수 없다. (이렇게 할 필요가 없고, 있어도 무시하지만) 여러 항목이 공통으로 가지고 있는 내용으로 map 파일을 시작하는 것이 보통이다. 다음은 map 파일 예다. 이 파일의 이름은 foo.var로, foo라는 자원을 설명한다.

URI: foo

URI: foo.en.html
Content-type: text/html
Content-language: en

URI: foo.fr.de.html
Content-type: text/html;charset=iso-8859-2
Content-language: fr, de

typemap 파일이 파일명 확장자 보다, 심지어 Multiviews를 사용하여도, 우선권을 가짐을 주의하라. 변형이 서로 다른 품질을 가진다면, 다음과 같이 (JPEG, GIF, ASCII-art에 해당하는) media type에 "qs" 파라미터로 품질(source quality)을 표시할 수 있다:

URI: foo

URI: foo.jpeg
Content-type: image/jpeg; qs=0.8

URI: foo.gif
Content-type: image/gif; qs=0.5

URI: foo.txt
Content-type: text/plain; qs=0.01

qs 값은 0.000에서 1.000 사이다. qs 값이 0.000인 변형은 절대 선택되지 않음을 주의하라. 'qs' 값이 없는 변형은 1.0으로 취급된다. qs 값은 클라이언트의 능력과는 관계없이 다른 변형들과 비교하여 그 변형의 상대적인 '품질'을 나타낸다. 예를 들어, 사진을 나타내려는 경우 JPEG 파일이 ASCII 파일보다는 항상 높은 품질을 가진다. 그러나 자원이 원래 ASCII art였다면 ASCII 표현이 JPEG 표현보다 더 높은 품질을 가질 수 있다. 그러므로 어떤 변형의 qs 값은 표현하려는 자원의 성질에 따라 다르다.

지원하는 모든 헤더 목록은 mod_negotation typemap 문서를 참고하라.

Multiviews

MultiViews는 디렉토리별 옵션이므로, httpd.conf의 <Directory>, <Location>, <Files> 섹션 혹은 (AllowOverride가 적절히 설정되었다면) .htaccess 파일의 Options 지시어에 설정할 수 있다. Options All은 MultiViews를 포함하지않음을 주의하라. 따로 직접 써줘야 한다.

MultiViews를 사용하면 다음과 같은 일이 일어난다: 서버가 /some/dir/foo에 대한 요청을 받고 /some/dir/foo에 MultiViews가 동작하며 /some/dir/foo가 존재하지 않을 경우, 서버는 디렉토리에서 이름이 foo.*인 파일들을 모든 포함하는 가상의 type map을 만든다. 클라이언트가 요청한 media type과 content-encoding을 가지고 이중에 가장 적합한 것을 선택한다.

MultiViews는 서버가 디렉토리를 참조할때 파일을 찾는 DirectoryIndex 지시어에도 적용된다. 설정파일이 다음과 같다면,

DirectoryIndex index

index.html과 index.html3이 모두 있다면 서버는 이둘 중에 하나를 결정한다. 둘 모두 없고 index.cgi가 있다면, 서버는 그것을 실행한다.

디렉토리를 읽을때 파일중 하나가 Charset, Content-Type, Language, Encoding를 판단하는 mod_mime이 모르는 확장자를 가진다면, 결과는 MultiViewsMatch 지시어 설정에 달렷다. 이 지시어는 핸들러, 필터, 다른 확장형들이 MultiViews 협상에 참여할지 여부를 결정한다.

협상방법

아파치가 type-map 파일이나 디렉토리에 있는 파일명들로 주어진 자원에 대한 변형 목록을 얻게되면 '최적의' 변형을 결정하기위해 두 방법중 하나를 사용한다. 아파치 내용협상 기능을 사용하기위해 정확히 협상이 어떻게 일어나는지 자세히 알 필요는 없다. 그러나 궁금한 사람을 위해 이 방법을 설명한다.

두가지 협상방법이 있다:

  1. 아파치 알고리즘을 사용하여 서버가 주도하는 협상은 일반적인 경우에 사용한다. 아파치 알고리즘은 아래서 자세히 설명한다. 이 알고리즘을 사용하면 아파치는 더 나은 결과를 얻기위해 종종 특정 범위의 품질계수(quality factor)를 '조작한다'. 아파치가 품질계수를 조작하는 방법은 아래서 자세히 설명한다.
  2. 자연스러운(Transparent) 내용협상은 브라우저가 RFC 2295에 정의된 방법으로 요청할 경우에만 사용한다. 이 협상방법은 '최적의' 변형을 결정할 권한을 브라우저에게 부여한다. 그래서 결과는 브라우저의 알고리즘에 달렸다. 자연스러운 협상과정중에 브라우저는 아파치에게 RFC 2296에 정의된 '원격 변형선택 알고리즘(remote variant selection algorithm)'을 요청할 수 있다.

협상의 범위

범위 | 설명
Media Type | 브라우저는 Accept 헤더로 선호를 나타낸다. 각 항목은 품질계수를 가질 수 있다. 변형의 설명도 품질계수를 ("qs" 파라미터) 가질 수 있다.
Language | 브라우저는 Accept-Language 헤더로 선호를 나타낸다. 각 항목은 품질계수를 가질 수 있다. 변형은 여러 언어를 가질 (혹은 아무 언어도 없을) 수 있다.
Encoding | 브라우저는 Accept-Encoding 헤더로 선호를 나타낸다. 각 항목은 품질계수를 가질 수 있다.
Charset | 브라우저는 Accept-Charset 헤더로 선호를 나타낸다. 각 항목은 품질계수를 가질 수 있다. 변형은 media type의 파라미터로 문자집합을 나타낼 수 있다.

아파치 협상 알고리즘

아파치는 브라우저에게 보낼 '최적의' 변형을 (있다면) 선택하기위해 아래 알고리즘을 사용한다. 이 알고리즘은 변경할 수 없다. 다음와 같이 동작한다:

  1. 먼저, 협상의 각 범위에 대해 해당하는 Accept* 헤더를 검사하고, 각 변형에 품질값을 매긴다. 어떤 범위의 Accept* 헤더가 받아들이지 않는 변형은 후보에서 제외한다. 어떤 변형도 남지않으면 4 단계로 간다.
  2. 후보에서 하나씩 제외하여 '최적의' 변형을 찾는다. 다음 각 검사는 순서대로 일어난다. 각 검사에서 선택되지않은 변형은 제외된다. 각 검사후 한 변형만 남으면 이를 최적의 변형으로 선택하고 3 단계로 간다. 여러 변형이 남으면 다음 검사를 진행한다.
    1. Accept 헤더의 품질계수와 변형의 media type에 대한 품질값을 곱하여 가장 높은 값을 가진 변형을 선택한다.
    2. 가장 높은 언어(language) 품질계수를 가진 변형을 선택한다.
    3. Accept-Language 헤더에 (있다면) 나온 언어의 순서 혹은 LanguagePriority 지시어에 (있다면) 나온 언어의 순서를 가지고 가장 적합한 언어를 가진 변형을 선택한다.
    4. 가장 높은 (text/html media type의 버전을 나타내는) 'level' media 파라미터를 가진 변형을 선택한다.
    5. Accept-Charset 헤더를 가지고 가장 적합한 charset media 파라미터를 가진 변형을 찾는다. 헤더가 없다면 ISO-8859-1 문자집합을 가장 선호한다. text/* media type을 가지지만 명시적으로 특정 문자집합과 연결되지않은 변형은 ISO-8859-1로 가정한다.
    6. ISO-8859-1이 아닌 charset media 파라미터를 가진 변형들을 선택한다. 그런 변형이 없다면, 대신 모든 변형을 선택한다.
    7. 가장 적합한 인코딩을 가진 변형을 선택한다. user-agent에 적합한 인코딩을 가진 변형이 있다면 그 변형만을 선택한다. 그렇지않고 인코딩된 변형과 인코딩안된 변형이 같이 있다면 인코딩안됨 변형만을 선택한다. 변형이 모두 인코딩되었거나 모두 인코딩안된 경우 모든 변형을 선택한다.
    8. content length가 가장 적은 변형을 선택한다.
    9. 남은 것중 첫번재 변형을 선택한다. 이는 type-map 파일의 앞에 나왔거나, 디렉토리에서 변형을 읽은 경우 파일명을 ASCII 코드 순서로 하여 앞에 나오는 것이다.
  3. 이제 알고리즘이 '최적의' 변형을 선택했다. 이것을 응답으로 보낸다. HTTP 응답 헤더 Vary는 협상의 범위를 나타내게 된다. (브라우저와 캐쉬는 자원을 캐쉬할때 이 정보를 사용할 수 있다.) 끝.
  4. 이 단계에 도달했다면 (모두 브라우저가 받지못하기 때문에) 어떤 변형도 선택이 안된 경우다. ("No acceptable representation"를 뜻하는) 상태 406과 내용으로 사용가능한 변형의 목록을 담은 HTML 문서를 응답을 보낸다. 또, HTML Vary 헤더는 변형의 범위를 나타낸다.

품질계수 조작하기

아파치는 종종 위의 아파치 협상 알고리즘을 엄격히 지키지않고 품질계수를 변경한다. 이유는 완전하고 정확한 정보를 보내지않는 브라우저에게 (알고리즘의) 더 나은 결과를 보내기 위해서다. 널리 쓰이는 브라우저중 일부는 자주 잘못된 변형을 선택하도록 Accept 헤더를 보낸다. 브라우저가 완전하고 올바른 정보를 보낸다면, 조작을 하지않는다.

Media Type과 와일드카드

Accept: 요청 헤더는 media type에 대한 선호를 나타낸다. 또, *는 어떤 문자열이라도 가능하기때문에 "image/*"나 "*/*" 같이 '와일드카드' media type을 사용할 수도 있다. 그래서 다음과 같은 요청은:

Accept: image/*, */*

"image/"로 시작하는 어떤 type과 다른 어떤 type도 가능함을 의미한다. 어떤 브라우저는 자신이 실제로 다룰 수 있는 type에 추가로 와일드카드를 보낸다. 예를 들면:

Accept: text/html, text/plain, image/gif, image/jpeg, */*

이유는 직접 열거한 type을 선호하지만 다른 표현이 있다면 그것도 괜찮음을 나타내기 위해서다. 브라우저가 실제로 원한 것은 다음과 같이 명시적으로 품질값을 사용한 것이다.

Accept: text/html, text/plain, image/gif, image/jpeg, */*; q=0.01

직접 열거한 type은 품질계수가 없어서 기본값인 (가장 높은) 1.0을 가진다. 와일드카드 */*는 낮은 선호도 0.01을 가지므로 직접 열거한 type에 맞는 변형이 없는 경우에만 다른 type들이 사용된다.

Accept: 헤더에 q 계수가 전혀 없고 "*/*"가 있다면, 아파치는 바람직한 행동을 위해 q 값으로 0.01을 지정한다. 또, "type/*" 형태의 와일드카드에는 ("*/*"보다는 더 선호하도록) 0.02를 지정한다. Accept: 헤더에서 q 계수를 가지는 media type이 있다면 이런 특별한 값을 추가하지 않는다. 그래서 명시적인 정보를 보내는 브라우저의 요청은 요청한데로 처리한다.

언어(language) 협상의 예외

아파치 2.0은 언어 협상이 실패한 경우 부드럽게 복구하기위해 협상 알고리즘에 새로 예외를 몇개 추가했다.

클라이언트가 서버에 페이지를 요청했을때 서버가 브라우저가 보낸 Accept-language에 맞는 페이지를 단 한개만 찾으면 문제가 없지만, 그러지 않은 경우 서버는 클라이언트에게 "No Acceptable Variant"나 "Multiple Choices" 응답을 보낸다. 이런 오류문을 피하기위해 이 경우 Accept-language를 무시하고 클라이언트의 요청에 명확히 맞지는 않지만 문서를 보내도록 아파치를 설정할 수 있다. ForceLanguagePriority 지시어는 서버가 이런 오류문중 하나 혹은 둘다를 무시하고 LanguagePriority 지시어로 판단하도록 한다.

또, 서버는 맞는 언어를 못찾은 경우 부모언어를 찾을 수도 있다. 예를 들어 클라이언트가 영국영어를 뜻하는 en-GB 언어로 문서를 요청한 경우, HTTP/1.1 표준에 따르면 서버는 en으로만 표시된 문서를 일반적으로 선택하지 못한다. (그래서 영국영어를 이해하는 독자가 일반적인 영어도 이해할 수 있으므로 Accept-Language 헤더에 en-GB만 포함하고 en을 포함하지않으면 거의 확실히 잘못된 설정임을 유의하라. 불행히도 현재 많은 클라이언트들은 이런 식으로 기본설정되있다.) 다른 언어를 찾지 못하여 서버가 "No Acceptable Variants" 오류를 보내거나 LanguagePriority로 돌아가야 한다면, 서버는 하위언어 규약을 무시하고 en-GB를 en 문서에 대응한다. 암묵적으로 아파치는 부모언어를 매우 낮은 품질값으로 클라이언트의 허용언어 목록에 추가한다. 그러나 클라이언트가 "en-GB; q=0.9, fr; q=0.8"을 요청하고 서버에 "en"과 "fr" 문서가 있다면, "fr" 문서가 선택됨을 주의하라. 이는 HTTP/1.1 표준을 지키고, 올바로 설정된 클라이언트와 효율적으로 동작하기위함이다.

사용자가 선호하는 언어를 알아내기위한 (쿠키나 특별한 URL-경로 같은) 고급 기법을 지원하기위해 아파치 2.0.47부터 mod_negotiation은 prefer-language라는 환경변수를 인식한다. 이 환경변수가 존재하고 적절한 언어태그를 포함한다면, mod_negotiation은 해당하는 변형을 선택하려고 시도한다. 그런 변형이 없다면 일반적인 협상과정을 시작한다.

예제

SetEnvIf Cookie "language=en" prefer-language=en
SetEnvIf Cookie "language=fr" prefer-language=fr

자연스러운(transparent) 내용협상의 확장

아파치는 다음과 같이 자연스러운 내용확장 프로토콜을 (RFC 2295) 확장한다. 변형 목록의 새로운 {encoding ..}는 특정 content-encoding을 가진 변형만을 지칭한다. RVSA/1.0 알고리즘은 (RFC 2296) 목록에서 인코딩된 변형을 인식할 수 있고, 인코딩이 Accept-Encoding 요청 헤더에 맞는 경우 인코딩된 변형들도 후보로 사용하도록 확장되었다. RVSA/1.0 구현은 최적의 변형을 찾기 전에 계산된 품질계수를 소수점 5자리에서 반올림하지 않는다.

하이퍼링크와 이름규칙에 대하여

언어(language) 협상을 사용한다면 파일은 여러 확장자를 가지고 확장자의 순서는 보통 관계없으므로 파일명에 여러 다른 이름규칙을 사용할 수 있다. (자세한 내용은 mod_mime 문서를 참고하라.)

전형적인 파일은 MIME-type 확장자 (예를 들어, html), 경우에 따라 encoding 확장자 (예를 들어, gz), 파일에 여러 언어 변형이 있는 경우 물론 언어 확장자를 (예를 들어, en) 가진다.

예제:

  • foo.en.html
  • foo.html.en
  • foo.en.html.gz

다음은 몇몇 파일명과 그 파일에 대한 유효하고 유효하지않은 하이퍼링크를 보인다:

파일명 | 유효한 하이퍼링크 | 유효하지않은 하이퍼링크
foo.html.en | foo foo.html | -
foo.en.html | foo | foo.html
foo.html.en.gz | foo foo.html | foo.gz foo.html.gz
foo.en.html.gz | foo | foo.html foo.html.gz foo.gz
foo.gz.html.en | foo foo.gz foo.gz.html | foo.html
foo.html.gz.en | foo foo.html foo.html.gz | foo.gz

위 표를 보면 하이퍼링크에 어떤 확장자도 없는 이름을 (예를 들어, foo) 항상 사용할 수 있음을 알 수 있다. 이 경우 장점은 문서의 실제 종류를 숨길 수 있어서, 예를 들어 하이러링크 참조를 수정하않고 html 파일을 shtml이나 cgi로 변경할 수 있다는 점이다.

계속 하이퍼링크에 MIME-type을 (예를 들어, foo.html) 사용하고 싶다면 (encoding 확장자가 있다면 이것도 포함하여) 언어 확장자를 MIME-type 확장자보다 오른쪽에 (예를 들어, foo.html.en) 두어야한다.

캐쉬에 대하여

캐쉬가 표현을 저장하면 표현과 요청 URL을 연관시킨다. 다음번 그 URL을 요청하면 캐쉬는 저장된 표현을 사용한다. 그러나 서버와 협상이 가능한 자원인 경우 첫번째 요청한 변형만 캐쉬되어 이후 요청은 캐쉬된 잘못된 응답을 얻을 수 있다. 이를 막기위해 아파치는 보통 내용협상후 반환되는 모든 요청에 HTTP/1.0 클라이언트가 캐쉬를 못하도록 표시를 한다. 또, 아파치는 협상한 응답의 캐쉬를 허용하는 HTTP/1.1 프로토콜의 기능을 지원한다.

CacheNegotiatedDocs 지시어는 HTTP/1.0 호환 클라이언트(브라우저 혹은 캐쉬)가 보낸 요청에 대해 협상한 응답을 캐쉬할 수 있게 한다. 이 지시어는 서버나 가상호스트 설정에 사용하며, 아규먼트를 받지않는다. 이 지시어는 HTTP/1.1 클라이언트의 요청과는 관계가 없다.

다른 정보

내용협상에 대한 다른 정보는 Alan J. Flavell가 쓴 Language Negotiation Notes를 참고하라. 그러나 이 문서는 아직 아파치 2.0의 변화를 반영하지 않을 수 있다.


사용자정의 오류 응답 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

사용자정의 오류 응답

웹마스터는 오류나 문제가 발생했을때 아파치의 응답을 설정할 수 있다.

서버가 오류나 문제를 발견했을때 보낼 사용자정의 응답을 정의할 수 있다.

스크립트가 죽은 경우 "500 Server Error" 응답 대신 사용자에게 더 친근한 문구를 사용하거나 다른 (같은 사이트나 외부 사이트의) URL로 리다이렉션을 할 수 있다.

행동

이전 행동

NCSA httpd 1.3은 사용자에게 무의미하고 지루한 오류문을 보냈다. 문제가 발생한 이유를 로그에 남길 수도 없었다.

새로운 행동

서버는 다음과 같은 일을 할 수 있다:

  1. NCSA의 고정된 문구 대신 다른 문구를 보여주거나
  2. 같은 사이트의 URL로 리다이렉션하거나
  3. 외부 사이트의 URL로 리다이렉션한다.

다른 사이트의 URL로 리다이렉션하는 것이 유용할 수 있지만, 이 경우 문제를 설명하거나 로그하는데 필요한 정보중 일부만 전달된다.

오류에 대한 정보를 전달하기위해 아파치는 CGI식의 새로운 환경변수를 정의한다:

        REDIRECT_HTTP_ACCEPT=*/*, image/gif, image/x-xbitmap,
            image/jpeg
REDIRECT_HTTP_USER_AGENT=Mozilla/1.1b2 (X11; I; HP-UX A.09.05
            9000/712)
REDIRECT_PATH=.:/bin:/usr/local/bin:/etc
REDIRECT_QUERY_STRING=
REDIRECT_REMOTE_ADDR=121.345.78.123
REDIRECT_REMOTE_HOST=ooh.ahhh.com
REDIRECT_SERVER_NAME=crash.bang.edu
REDIRECT_SERVER_PORT=80
REDIRECT_SERVER_SOFTWARE=Apache/0.8.15
REDIRECT_URL=/cgi-bin/buggy.pl

REDIRECT_ 접두사에 주목하라.

최소한 REDIRECT_URL과 REDIRECT_QUERY_STRING은 (cgi-script나 cgi-include일) 새 URL로 넘겨진다. 다른 변수는 오류가 발생하기 이전에 (역주; 이름에서 REDIRECT_를 뺀 환경변수가) 존재한 경우에만 있다. ErrorDocument가 외부로 (같은 서버라도 http:와 같은 스킴(scheme)으로 시작한다면) 리다이렉션한다면 이중 어떤 것도 설정되지 않는다.

설정

AllowOverride가 적절히 설정되었다면 .htaccess 파일에서 ErrorDocument를 사용할 수 있다.

다음은 예이다...

ErrorDocument 500 /cgi-bin/crash-recover
ErrorDocument 500 "Sorry, our script crashed. Oh dear"
ErrorDocument 500 http://xxx/
ErrorDocument 404 /Lame_excuses/not_found.html
ErrorDocument 401 /Subscription/how_to_subscribe.html

문법은,

ErrorDocument <3-digit-code> <action>

가능한 action은,

  1. 출력할 문구. 따옴표 (")를 문구 앞에 붙인다. 뒤에 나오는 따옴표는 출력된다. 주의: 앞에 붙은 따옴표 (")는 출력되지 않는다.
  2. 리다이렉션할 외부 URL.
  3. 리다이렉션할 내부 URL.

사용자정의 오류 응답과 리다이렉션

URL로 리다이렉션하는 아파치 행동은 스크립트/server-include에 환경변수를 더 넘겨주도록 변경되었다.

이전 행동

리다이렉션되는 스크립트에 표준 CGI 변수들이 넘어간다. 어디에서 리다이렉션이 일어났는지 알 수 없다.

새로운 행동

리다이렉션된 스크립트는 새로운 환경변수들을 사용할 수 있다. 모두 앞에 REDIRECT_가 붙어있다. REDIRECT_ 환경변수는 원래 CGI 환경변수명 앞에 REDIRECT_를 붙여서 만든다. 예를 들어, HTTP_USER_AGENT는 REDIRECT_HTTP_USER_AGENT가 되었다. 이런 변수에 추가로 스크립트가 원래 URL을 알도록 아파치는 REDIRECT_URL과 REDIRECT_STATUS를 정의한다. 원래 URL과 리다이렉션된 URL 모두 접근 로그에 기록할 수 있다.

ErrorDocument가 같은 서버에 있는 CGI 스크립트로 리다이렉션한다면, 스크립트는 클라이언트에게 오류 상황을 확실히 전달하기위해 출력에 "Status:" 헤더 필드를 포함해야 한다. 예를 들어, Perl로 작성한 ErrorDocument 스크립트는 다음과 같다:

...
print "Content-type: text/html\n";
printf "Status: %s Condition Intercepted\n", $ENV{"REDIRECT_STATUS"};
...

404 Not Found와 같은 특정 오류 상황에 대한 스크립트라면, 대신 (역주; 고정된) 특정 상태코드와 오류문을 사용할 수 있다.

(클라이언트에게 리다이렉션을 요청하기위해) 응답에 Location: 헤더를 포함한다면, 스크립트는 반드시 (302 Found 같은) 적절한 Status: 헤더를 출력해야 함을 주의하라. 그렇지않으면 Location: 헤더가 아무 소용없게 될 수 있다.


주소와 포트 지정 (Binding) - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

주소와 포트 지정 (Binding)

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

아파치가 특정 주소와 포트에서 서비스하도록 설정하기.

참고

  • 가상호스트
  • DNS 문제

개요

관련된 모듈 관련된 지시어
  • core
  • mpm_common
  • <VirtualHost>
  • Listen

아파치를 시작하면 아파치는 컴퓨터의 어떤 포트와 주소에 연결하여, 들어오는 요청을 기다린다. 기본적으로 아파치는 컴퓨터의 모든 주소에서 기다린다. 그러나 아파치가 특정 포트나 선택한 주소만을 기다리게 해야할 경우가 있다. 또 이 문제는 아파치가 어떻게 다른 IP 주소, 호스트명, 포트에 반응할지를 결정하는 가상호스트 기능과도 관련되있다.

Listen 지시어는 서버가 특정 포트나 주소와 포트 조합에서만 요청을 받게 한다. Listen 지시어에 포트 번호만 지정하면, 서버는 모든 인터페이스에서 지정한 포트를 기다린다. 여러 Listen 지시어로 기다릴 여러 주소와 포트를 지정할 수도 있다. 서버는 열거한 주소와 포트로 요청이 들어오면 응답한다.

예를 들어, 서버가 80번과 8000번 포트 모두에서 연결을 받도록 하려면:

Listen 80
Listen 8000

서버가 지정한 두 인터페이스와 포트에서 연결을 기다리도록 하려면,

Listen 192.170.2.1:80
Listen 192.170.2.5:8000

IPv6 주소는 다음과 같이 대괄호로 묶어야 한다:

Listen [fe80::a00:20ff:fea7:ccea]:80

IPv6에서 특별히 고려할 점

IPv6를 구현한 플래폼이 늘고 있고 APR이 이들 플래폼 대부분에서 IPv6를 지원하기때문에, 아파치는 IPv6 소켓을 할당하여 IPv6로 받은 요청을 처리할 수 있다.

아파치 관리자에게 복잡한 부분은 IPv6 소켓이 IPv4 연결과 IPv6 연결을 모두 처리할 수 있느냐는 점이다. 대부분의 플래폼에서는 IPv4-대응(mapped) IPv6 주소를 사용하여 IPv6 소켓에서 IPv4 연결을 받지만, FreeBSD와 NetBSD와 OpenBSD은 시스템전체 정책때문에 기본적으로 허용하지 않는다. 그러나 기본적으로 허용하지않는 시스템이라도 아파치를 위해 특별한 설정 파라미터로 변경할 수 있다.

아파치가 최소한의 소켓을 사용하여 IPv4 연결과 IPv6 연결을 모두 받도록하려면 IPv4-대응 IPv6 주소를 사용해야 한다. 그러기위해서 컴파일때 구성 옵션 --enable-v4-mapped를 사용하고, 다음과 같이 일반적인 Listen 지시어를 사용한다:

Listen 80

--enable-v4-mapped를 사용할때 아파치가 만드는 기본 설정파일의 Listen 지시어는 위와 같다. --enable-v4-mapped는 FreeBSD, NetBSD, OpenBSD를 제외한 모든 플래폼에서 기본값이고, 아마도 당신의 아파치도 마찬가지일 것이다.

플래폼과 APR의 지원여부와 관계없이 아파치가 IPv4 연결만을 받도록하려면, 다음 예제와 같이 모든 Listen 지시어에 IPv4 주소를 사용한다:

Listen 0.0.0.0:80
Listen 192.170.2.1:80

IPv4 연결과 IPv6 연결을 서로 다른 소켓으로 받으려면, 컴파일때 구성 옵션 --disable-v4-mapped를 사용하고 다음과 같이 Listen 지시어를 따로 사용한다:

Listen [::]:80
Listen 0.0.0.0:80

--disable-v4-mapped를 사용할때 아파치가 만드는 기본 설정파일의 Listen 지시어는 위와 같다. --disable-v4-mapped는 FreeBSD, NetBSD, OpenBSD에서 기본값이다.

가상호스트와 어떻게 연관되나

Listen은 가상호스트를 만들지 않는다. 이는 단지 주서버가 어떤 주소와 포트를 기다릴지만 알려준다. <VirtualHost> 지시어를 사용하지 않으면, 서버는 받은 모든 요청을 똑같이 처리한다. 그러나 <VirtualHost>로 여러 주소와 포트에 대해 다른 행동을 지정할 수 있다. 가상호스트를 만들려면 먼저 서버에게 사용할 주소와 포트를 알려줘야 한다. 그리고 특정 주소와 포트에 대한 가상호스트의 행동을 지정할 <VirtualHost> 섹션이 필요하다. 주서버가 기다리지않는 주소와 포트를 사용하는 <VirtualHost>는 접근할 수 없음을 주의하라.


다중처리 모듈 (MPM) - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

다중처리 모듈 (MPM)

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 문서는 다중처리 모듈 (Multi-Processing Module)이 무엇이며, 아파치 웹서버가 이를 어떻게 사용하는지 설명한다.

소개

아파치 웹서버는 다양한 환경의 다양한 플래폼에서 동작할 수 있도록 강력하고 유연하게 설계되었다. 다른 플래폼과 다른 환경은 보통 다른 기능을 요구하며, 어떤 기능을 가장 효율적으로 구현하는 방법이 다를 수 있다. 아파치는 모듈화된 설계로 이런 다양한 환경에 항상 적응해왔다. 그래서 웹마스터는 컴파일시 혹은 실행시 어떤 모듈을 읽어들일지 선택하여 서버에 포함할 기능을 결정할 수 있다.

Apache 2.0은 이런 모듈화된 설계를 웹서버의 가장 기본적인 부분에까지 확장했다. 서버는 시스템의 네트웍 포트에 연결하고, 요청을 받아들이며, 받아들인 요청을 처리하기위해 자식들에게 분배하는 다중처리 모듈 (Multi-Processing Modules, MPMs)을 선택할 수 있다.

서버를 이 정도로 모듈화하면 두가지 중요한 장점이 있다:

  • mpm_winnt가 Apache 1.3에서 사용한 POSIX층 대신 자체 네트웍 기능을 사용할 수 있는 등, 아파치는 여러 다양한 운영체제를 더 깔끔하고 효율적으로 지원할 수 있다. 이 장점은 특화된 MPM을 구현한 다른 운영체제에도 적용된다.
  • 서버는 특정 사이트의 요구조건에 더 특화될 수 있다. 예를 들어 높은 확장가능성(scalability)이 필요한 사이트는 worker와 같은 쓰레드 MPM을 사용하고, 안정성과 오래된 소프트웨어와의 호환성이 필요한 사이트는 preforking MPM을 사용할 수 있다. 추가로 다른 사용자아이디로 여러 호스트를 서비스하는 것(perchild)과 같은 특별한 기능도 제공된다.

사용자가 보기에 MPM은 다른 아파치 모듈과 거의 비슷해 보인다. 주된 차이는 서버는 한번에 오직 한 MPM만을 사용해야 한다는 점이다. 사용가능한 MPM 목록은 모듈 목록 페이지에 있다.

MPM 선택하기

MPMs는 구성중에 선택하여 서버에 컴파일되야 한다. 쓰레드를 사용하는 것을 컴파일러가 알면 많은 함수를 최적화할 수 있다. 유닉스에서 몇몇 MPM은 쓰레드를 쓰고 나머지는 아니므로, MPM이 구성중에 선택되어 아파치에 컴파일될때 아파치는 더 빠른 속도를 낸다.

원하는 MPM을 선택하려면 ./configure 스크립트에 with-mpm= NAME 아규먼트를 사용하라. NAME은 원하는 MPM 이름이다.

서버를 컴파일한후 ./httpd -l 명령어로 선택한 MPM을 알 수 있다. 이 명령어는 MPM을 포함하여 서버에 컴파일된 모든 모듈을 알려준다.

MPM 기본값

다음 표는 여러 운영체제의 기본 MPM을 보여준다. 컴파일시 다르게 선택하지 않으면 이 MPM이 선택된다.

BeOS | beos
Netware | mpm_netware
OS/2 | mpmt_os2
유닉스 | prefork
윈도우즈 | mpm_winnt


아파치의 환경변수 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

아파치의 환경변수

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

아파치 웹서버는 환경변수(environment variable)라는 변수에 정보를 저장할 수 있다. 이 정보를 사용하여 로그나 접근제어 등 여러 작업을 조절한다. 또, 환경변수는 CGI 스크립트와 같은 외부 프로그램과 통신하는 수단이 된다. 이 문서는 환경변수를 다루고 사용하는 다양한 방법들을 설명한다.

이 변수들을 환경변수라고 부르지만, 운영체제에서 말하는 환경변수와 다르다. 이 변수는 아파치 내부에 저장되고 사용된다. 환경변수는 CGI 스크립트나 Server Side Include 스크립트로 넘겨질때만 실제 운영체제 환경변수가 된다. 서버를 실행하는 운영체제 환경을 수정하고 싶다면 운영체제 쉘에서 환경을 수정해야 한다.

환경변수 설정하기

관련된 모듈 관련된 지시어
  • mod_env
  • mod_rewrite
  • mod_setenvif
  • mod_unique_id
  • BrowserMatch
  • BrowserMatchNoCase
  • PassEnv
  • RewriteRule
  • SetEnv
  • SetEnvIf
  • SetEnvIfNoCase
  • UnsetEnv

기본적인 환경설정

아파치에서 환경변수를 설정하는 가장 기본적인 방법은 무조건적인 SetEnv 지시어를 사용하는 것이다. PassEnv 지시어를 사용하여 서버를 시작한 쉘에서 환경변수를 가져올 수도 있다.

요청에 따른 조건부 설정

더 유연하게, mod_setenvif가 제공하는 지시어는 요청마다 요청의 특징에 따라 환경변수를 설정한다. 예를 들어, 특정 브라우저로 (User-Agent) 요청하거나 특정 Referer (맞춤법이 틀리지 않았다) 헤더가 있는 경우에만 변수를 설정할 수 있다. 심지어 mod_rewrite에 있는 RewriteRule의 [E=...] 옵션을 사용하여 더 유연하게 환경변수를 설정할 수도 있다.

유일한 식별자

마지막으로 mod_unique_id는 각 요청에 대해 어떤 경우에도 "모든" 요청중에 확실히 유일한(겹치지않은) 값으로 UNIQUE_ID 환경변수를 설정한다.

표준 CGI 변수

CGI 스크립트와 SSI 문서는 아파치 설정에서 설정하였거나 쉘에서 가져온 환경변수 외에 추가로 CGI 규약이 규정한 요청에 대한 정보를 알려주는 환경변수들을 받는다.

주의할 점

  • 환경설정 지시어를 사용하여 표준 CGI 변수를 무시하거나 수정할 수 없다.
  • suexec가 CGI 스크립트를 실행하는 경우, 시작하기전에 CGI 스크립트의 환경은 안전한 변수들만 가지도록 청소된다. 안전한 변수 목록은 컴파일시 suexec.c에 정의된다.
  • 포팅을 위해 환경변수 이름에는 오직 문자, 숫자, 밑줄문자만 사용하는 것이 좋다. 또, 첫번째 문자로 숫자를 사용하지않는 것이 좋다. CGI 스크립트나 SSI 페이지에 넘어갈때 이외의 문자는 밑줄로 대체된다.

환경변수 사용하기

관련된 모듈 관련된 지시어
  • mod_access
  • mod_cgi
  • mod_ext_filter
  • mod_headers
  • mod_include
  • mod_log_config
  • mod_rewrite
  • Allow
  • CustomLog
  • Deny
  • ExtFilterDefine
  • Header
  • LogFormat
  • RewriteCond
  • RewriteRule

CGI 스크립트

환경변수의 주된 용도중 하나는 CGI 스크립트와 정보를 교환하는 것이다. 앞에서 설명했듯이 아파치 설정에서 설정한 변수외에 요청에 대한 표준 정보를 가진 변수가 CGI 스크립트로 넘어간다. 더 자세한 내용은 CGI 투토리얼을 참고하라.

SSI 페이지

mod_include의 INCLUDES 필터가 처리하는 서버파싱 (SSI) 문서는 echo 요소를 사용하여 환경변수를 출력할 수 있고, 환경변수를 사용하여 요청의 특징에 따라 흐름제어 요소로 페이지의 일부를 변경할 수 있다. 아파치는 또 SSI 문서에게 위에서 설명한 표준 CGI 환경변수를 제공한다. 더 자세한 내용은 SSI 투토리얼을 참고하라.

접근제어

allow from env=과 deny from env= 지시어를 사용하여 환경변수 값에 따라 서버로의 접근을 조절할 수 있다. SetEnvIf와 같이 사용하면 클라이언트의 특징에 따라 자유롭게 서버로의 접근을 제어할 수 있다. 예를 들어, 특정 브라우저의 (User-Agent) 접근을 거부할 수 있다.

조건부 로그

LogFormat의 %e 옵션을 사용하여 환경변수를 접근 로그에 기록할 수 있다. 또, CustomLog 지시어의 조건부 형식을 사용하면 환경변수의 상황에 따라 요청을 로그할지 여부를 결정할 수 있다. SetEnvIf와 같이 사용하여 어떤 요청을 로그할지 자유롭게 결정할 수 있다. 예를 들어, 파일명이 gif로 끝나는 요청은 로그하지 않거나, 외부 네트웍에 있는 클라이언트의 요청만을 로그할 수 있다.

조건부 응답 헤더

Header 지시어는 클라이언트에게 응답을 보낼때 환경변수의 유무에 따라 어떤 HTTP 헤더를 포함할지 결정할 수 있다. 예를 들어, 클라이언트의 요청에 특정 헤더가 있는 경우에만 어떤 응답 헤더를 보낼 수 있다.

외부 필터 실행하기

mod_ext_filter의 ExtFilterDefine 지시어로 설정한 외부 필터를 disableenv=와 enableenv= 옵션을 사용하여 환경변수에 따라 선택적으로 실행할 수 있다.

URL 재작성(Rewriting)

RewriteCond의 TestString에 %{ENV:...} 형식을 사용하면 mod_rewrite의 재작성 엔진이 환경변수에 따라 다르게 행동한다. mod_rewrite에서 앞에 ENV:를 붙이지않고 접근하는 변수는 실제 환경변수가 아님을 주의하라. 그들은 다른 모듈에서 읽을 수 없는 mod_rewrite에 한정된 변수다.

특별한 목적의 환경변수

클라이언트와 원활한 동작하기위해 아파치는 특별한 클라이언트에 대해 자신의 행동을 수정한다. 보통 BrowserMatch에서 환경변수를 정의하여 이런 문제를 해결한다. 그러나 SetEnv와 PassEnv로도 가능하다.

downgrade-1.0

요청이 이후 버전을 사용하더라도 HTTP/1.0 요청으로 처리한다.

force-no-vary

응답을 클라이언트에게 보내기 전에 응답 헤더에서 Vary 필드를 뺀다. 어떤 클라이언트는 이 필드를 제대로 해석하지 못한다 (클라이언트의 이미 알려진 문제점 페이지 참고). 이 변수는 이런 문제를 해결한다. 또한, 이 변수는 force-response-1.0을 가정한다.

force-response-1.0

HTTP/1.0 요청을 하는 클라이언트에게 HTTP/1.0 응답을 강제한다. 원래 AOL 프록시에 문제가 있어서 만들어졌다. 어떤 HTTP/1.0 클라이언트는 HTTP/1.1 응답을 받으면 제대로 동작하지 않으므로, 이 문제를 해결하기위해 사용한다.

gzip-only-text/html

값이 "1"이면 text/html이 아닌 content-type에 대해 mod_deflate의 DEFLATE 출력필터를 사용하지 않는다.

no-gzip

이 옵션을 설정하면 mod_deflate의 DEFLATE 필터를 사용하지 않는다.

nokeepalive

KeepAlive를 무시한다.

prefer-language

이 변수는 mod_negotiation의 행동에 영향을 미친다. 변수가 (en, ja, x-klingon 등) 언어태그를 담고있다면, mod_negotiation는 그 언어로 된 변형을 보내길 시도한다. 그런 변형이 없다면 일반적인 협상 과정을 시작한다.

redirect-carefully

서버가 더 조심히 클라이언트에게 리다이렉션을 보낸다. 보통 리다이렉션을 처리하는데 문제가 있는 클라이언트을 위해 사용한다. 원래 Microsoft의 WebFolders 소프트웨어가 DAV 메써드를 통해 디렉토리 자원의 리다이렉션을 처리하는데 문제가 있어서 만들어졌다.

suppress-error-charset

2.0.40 이후 버전에 있다

아파치가 클라이언트의 요청에 대한 응답으로 리다이렉션을 보낼때 클라이언트가 자동으로 리다이렉션을 따라가지 못하는(혹은 않는) 경우에 대비하여 응답에 사용자에게 보여줄 문구를 포함한다. 아파치는 보통 이 글을 아파치가 사용하는 문자집합인 ISO-8859-1로 표시한다.

그러나 리다이렉션된 페이지가 다른 문자집합을 사용할 경우 어떤 이상한 브라우저 버전은 실제 페이지가 아니라 리다이렉션 페이지의 문자집합을 사용하려고 한다. 예를 들어, 그리스어가 이상하게 보일 수 있다.

이 환경변수는 아파치가 리다이렉션 페이지에 문자집합을 설정하지않도록 하여, 이런 브라우저가 실제 페이지의 문자집합을 올바로 사용하게 만든다.

예제

잘못 동작하는 클라이언트들을 위해 프로토콜 행동 변경하기

클라이언트들의 이미 알려진 문제를 해결하기위해 httpd.conf에 다음 내용을 포함하길 바란다.

#
# 다음 지시어들은 일반적인 HTTP 응답을 변경한다.
# 첫번째 지시어는 Netscape 2.x와 이를 가장한 브라우저에게
# keepalive를 사용하지 않는다. 이들 브라우저 구현에 문제가 있다.
# 두번째 지시어는 HTTP/1.1 구현이 잘못되었고 301이나 302
# (리다이렉션) 응답에 사용한 keepalive를 제대로 지원하지
# 못하는 Microsoft Internet Explorer 4.0b2를 위한 것이다.
#
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0

#
# 다음 지시어는 기본적인 HTTP/1.1 응답을 이해하지 못하여
# HTTP/1.0 규약을 어기는 브라우저에게 HTTP/1.1 응답을 보내지 않는다.
#
BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0

접근 로그에 이미지에 대한 요청을 로그하지 않기

이 예제는 이미지에 대한 요청을 접근 로그에 기록하지 않는다. 특정 디렉토리에 대한 혹은 특정 호스트에서 온 요청을 로그하지 않도록 쉽게 수정할 수 있다.

SetEnvIf Request_URI \.gif image-request
SetEnvIf Request_URI \.jpg image-request
SetEnvIf Request_URI \.png image-request
CustomLog logs/access_log common env=!image-request

"이미지 도둑" 방지

이 예는 현재 서버외의 사용자가 페이지에 서버에 있는 이미지를 포함하지 못하도록 하는 방법을 설명한다. 이 설정을 권장하지는 않으며, 제한된 경우에만 동작한다. 우리는 모든 이미지가 /web/images 디렉토리 안에 있다고 가정한다.

SetEnvIf Referer "^http://www.example.com/" local_referal
# Referer 정보를 보내지 않는 브라우저를 허용한다
SetEnvIf Referer "^$" local_referal
<Directory /web/images>
   Order Deny,Allow
   Deny from all
   Allow from env=local_referal
</Directory>

이 기법에 대한 자세한 설명은 ApacheToday 투토리얼 " Keeping Your Images from Adorning Other Sites"를 참고하라.


아파치에서 핸들러 사용 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

아파치에서 핸들러 사용

이 문서는 아파치에서 핸들러를 사용하는 방법을 설명한다.

핸들러가 무엇인가

관련된 모듈 관련된 지시어
  • mod_actions
  • mod_asis
  • mod_cgi
  • mod_imap
  • mod_info
  • mod_mime
  • mod_negotiation
  • mod_status
  • Action
  • AddHandler
  • RemoveHandler
  • SetHandler

파일을 요청할때 아파치가 내부적으로 수행할 작업을 "핸들러(handler)"라고 한다. 일반적으로 파일은 파일 종류에 따라 암묵적인 핸들러를 가지고 있다. 모든 파일은 보통 간단히 서버가 서비스하지만, 어떤 파일 종류는 따로 "처리된다(handled)".

Apache 1.1부터 핸들러를 명시적으로 사용할 수 있게 되었다. 파일 종류와 관계없이 핸들러를 파일의 확장자나 위치에 따라 지정할 수 있다. 이는 더 훌륭한 방법이고 파일을 종류와 핸들러 둘 모두와 연계할 수 있기때문에 좋다. (여러 확장자를 가진 파일도 참고)

핸들러는 서버나 모듈로 구현하여, Action 지시어로 추가할 수 있다. 표준 배포본에 있는 기본 핸들러는 다음과 같다:

  • default-handler: 정적인 내용을 처리하기위해 기본적으로 사용하는 핸들러 default_handler()를 사용하여 파일을 보낸다. (core)
  • send-as-is: HTTP 헤더가 있는 파일을 그대로 보낸다. (mod_asis)
  • cgi-script: 파일을 CGI로 처리한다. (mod_cgi)
  • imap-file: imagemap 규칙 파일로 처리한다. (mod_imap)
  • server-info: 서버의 설정 정보를 알려준다. (mod_info)
  • server-status: 서버의 상태를 보고한다. (mod_status)
  • type-map: 내용협상에 사용할 type map으로 처리한다. (mod_negotiation)

예제

CGI 스크립트를 사용하여 정적인 내용 수정하기

다음 지시어는 확장자가 html인 파일을 요청할 경우 footer.pl CGI 스크립트를 띄운다.

Action add-footer /cgi-bin/footer.pl
AddHandler add-footer .html

CGI 스크립트는 (PATH_TRANSLATED 환경변수가 지칭하는) 원래 요청한 문서를 적절히 수정한 후 보낸다.

HTTP 헤더를 포함하는 파일

다음 지시어는 HTTP 헤더를 포함하는 파일에 send-as-is 핸들러를 지시한다. /web/htdocs/asis/ 디렉토리 안에 있는 모든 파일은 확장자와 관계없이 send-as-is 핸들러가 처리한다.

<Directory /web/htdocs/asis>
SetHandler send-as-is
</Directory>

프로그래머를 위한 정보

핸들러 기능을 구현하기위해 사용함직한 Apache API가 추가되었다. 특히 request_rec 구조체에 새로운 필드가 추가되었다:

char *handler

모듈이 핸들러를 사용하려면, 요청의 invoke_handler 단계 이전에 r->handler에 핸들러 이름을 지정해주기만 하면 된다. 핸들러는 content type 대신 핸들러 이름을 사용한 것을 제외하고는 전과 같이 구현되었다. 꼭 지킬 필요는 없지만 핸들러 이름에 슬래쉬를 사용하지 않고, 단어들 사이에 빼기 기호를 사용하는 것이 일반적이다. 그래서 핸들러 이름이 media type과 겹치지 않는다.


필터 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

필터

이 문서는 아파치에서 필터를 사용하는 방법을 설명한다.

필터

관련된 모듈 관련된 지시어
  • mod_deflate
  • mod_ext_filter
  • mod_include
  • AddInputFilter
  • AddOutputFilter
  • RemoveInputFilter
  • RemoveOutputFilter
  • ExtFilterDefine
  • ExtFilterOptions
  • SetInputFilter
  • SetOutputFilter

필터(filter)는 서버가 보내거나 받는 자료에 적용되는 작업이다. 클라이언트가 서버에게 보내는 자료는 입력필터(input filter)가 처리하고, 서버가 클라이언트에게 보내는 자료는 출력필터(output filter)가 처리한다. 자료에 여러 필터를 사용할 수 있고, 직접 필터의 순서를 지정할 수 있다.

아파치는 이어받기(byte-range) 요청 등을 처리하기위해 내부적으로 필터를 사용한다. 또, 설정 지시어를 사용하여 선택가능한 필터를 제공하는 모듈도 있다. SetInputFilter, SetOutputFilter, AddInputFilter, AddOutputFilter, RemoveInputFilter, RemoveOutputFilter 지시어로 자료를 처리하는 필터를 조절한다.

현재 아파치 웹서버 배포본은 사용자가 선택할 수 있는 다음과 같은 필터를 제공한다.

INCLUDES
mod_include가 처리하는 Server-Side Includes
DEFLATE
mod_deflate를 사용하여 출력을 클라이언트로 보내기 전에 압축

또, mod_ext_filter 모듈을 사용하여 외부 프로그램을 필터로 사용할 수도 있다.


suEXEC 지원 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

suEXEC 지원

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

suEXEC 기능은 아파치가 CGI와 SSI 프로그램을 웹서버를 실행한 사용자 ID가 아닌 다른 사용자 ID로 실행하도록 한다. 보통 CGI나 SSI 프로그램을 실행하면 웹서버를 실행한 사용자와 같은 사용자로 실행한다.

이 기능을 적절히 사용하면 사용자가 직접 CGI나 SSI 프로그램을 개발하고 실행할때 발생할 수 있는 보안위험을 상당히 줄일 수 있다. 그러나 suEXEC가 부적절하게 설정되면 많은 문제와 컴퓨터에 새로운 보안 허점을 만들 수 있다. 만약 setuid root 프로그램과 이런 프로그램의 보안 문제에 생소하다면 suEXEC를 사용하지않길 진심으로 바란다.

시작하기 전에

시작하기 전에 우선 아파치그룹과 이 문서의 가정을 밝힌다.

먼저 setuid와 setgid 기능이 가능한 유닉스류 운영체제를 사용한다고 가정한다. 모든 명령어 예들도 같은 가정을 한다. suEXEC를 지원하는 다른 플래폼을 사용하다면 설정이 다를 수 있다.

두번째, 당신이 컴퓨터 보안의 기본 개념과 관리에 익숙하다고 가정한다. 여기에는 setuid/setgid 기능과 이들이 시스템과 보안에 미치는 여러 영향에 대한 이해가 포함된다.

세번째, suEXEC 코드의 수정하지않은 버전을 사용한다고 가정한다. 개발자와 여러 베타테스터들은 suEXEC와 관련된 모든 코드를 조심스럽게 조사하고 검사했다. 코드를 간단하게 하고 확실한 안전을 보장하기위해 모든 주의를 기울였다. 이 코드를 수정하면 예상치못한 문제와 새로운 보안 위험이 발생할 수 있다. 보안 프로그래밍에 대해 매우 잘 알고 코드를 살펴보기위해 아파치그룹과 작업을 공유할 의사가 없다면 suEXEC 코드를 수정하지않길 강력히 권한다.

네번째이자 마지막으로, 아파치그룹은 suEXEC를 아파치 기본설치에 포함하지 않기로 결정했다. 결국 관리자가 주의를 기울여서 suEXEC를 설정해야 한다. suEXEC의 여러 설정을 잘 고려한후 관리자는 일반적인 설치방법을 suEXEC를 설치할 수 있다. suEXEC 기능을 사용하는 시스템의 보안을 책임지는 관리자는 이 설정값들을 주의있게 살펴보고 지정해야 한다. 이런 상세한 과정은 suEXEC를 사용할만큼 주의있고 단호한 사람만이 suEXEC를 사용하도록 아파치그룹이 원하기 때문이다.

아직도 사용하길 원하는가? 그런가? 좋다. 이제 시작하자!

suEXEC 보안모델

suEXEC를 구성하고 설치하기 전에 우리는 보안모델을 먼저 설명한다. 이를 통해 정확히 suEXEC 안에서는 무슨 일이 일어나며 시스템의 보안을 위해 무엇을 조심해야 할지 더 잘 이해할 수 있다.

suEXEC는 아파치 웹서버가 부르는 setuid "wrapper" 프로그램을 기반으로 한다. 이 wrapper는 관리자가 주서버와 다른 userid로 실행하도록 설정한 CGI나 SSI 프로그램에 HTTP 요청이 오면 불린다. 이런 요청이 오면 아파치는 suEXEC wrapper에게 프로그램명과 프로그램을 실행할 사용자와 그룹 ID를 제공한다.

그러면 wrapper는 다음 과정을 통해 성공과 실패를 결정한다. 이 조건중 하나라도 실패하면 프로그램은 실패로 기록되고 오류를 내며 종료한다. 실패하지 않으면 과정을 계속한다:

  1. wrapper를 실행하는 사용자가 시스템의 정상적인 사용자인가?

    wrapper를 실행하는 사용자가 실제로 시스템의 사용자인지 확인한다.

  2. 적절한 수의 아규먼트로 wrapper를 실행하는가?

    wrapper는 적절한 수의 아규먼트가 있어야만 실행된다. 아파치 웹서버가 이 개수를 안다. wrapper가 적절한 수의 아규먼트를 받지못하면 해킹되었거나 아파치의 suEXEC에 뭔가 문제가 있는 것이다.

  3. 이 사용자가 wrapper를 실행하도록 허용되었나?

    이 사용자가 wrapper를 실행하도록 허용되었나? 오직 한 사용자(아파치 사용자)만이 이 프로그램을 실행할 수 있다.

  4. 지정한 CGI나 SSI 프로그램이 안전하지않은 계층참조를 가지는가?

    지정한 CGI나 SSI 프로그램이 '/'로 시작하거나 뒷참조 '..'을 가지는가? 이들을 사용할 수 없다. 지정한 CGI/SSI 프로그램은 suEXEC 문서 root (아래 --with-suexec-docroot=DIR 참고) 내에 있어야 한다.

  5. 지정한 사용자명이 유효한가?

    지정한 사용자가 존재하는가?

  6. 지정한 그룹명이 유효한가?

    지정한 그룹이 존재하는가?

  7. 지정한 사용자가 superuser가 아닌가?

    현재 suEXEC는 root가 CGI/SSI 프로그램을 실행할 수 없도록 한다.

  8. 지정한 userid가 최소 ID 숫자보다 큰가?

    설정에서 최소 사용자 ID 숫자를 지정한다. 그래서 CGI/SSI 프로그램을 실행할 수 있는 userid의 최소치를 지정할 수 있다. "시스템용" 계정을 제외할때 유용하다.

  9. 지정한 그룹이 superuser 그룹이 아닌가?

    현재 suEXEC는 root 그룹이 CGI/SSI 프로그램을 실행할 수 없도록 한다.

  10. 지정한 groupid가 최소 ID 숫자보다 큰가?

    설정에서 최소 그룹 ID 숫자를 지정한다. 그래서 CGI/SSI 프로그램을 실행할 수 있는 groupid의 최소치를 지정할 수 있다. "시스템용" 그룹을 제외할때 유용하다.

  11. wrapper가 성공적으로 지정한 사용자와 그룹이 될 수 있는가?

    이 단계에서 프로그램은 setuid와 setgid 호출을 하여 지정한 사용자와 그룹이 된다. 또, 그룹 접근목록은 사용자가 해당된 모든 그룹으로 초기화된다.

  12. CGI/SSI 프로그램이 있는 디렉토리로 디렉토리를 변경할 수 있는가?

    디렉토리가 존재하지 않다면 파일이 있을 수 없다. 이곳으로 디렉토리를 변경할 수 없다면 디렉토리는 존재하지 않을 것이다.

  13. 디렉토리가 아파치 웹공간 안에 있는가?

    서버의 일반적인 부분을 요청할 경우 요청하는 디렉토리가 suEXEC 문서 root 아래 있는가? UserDir을 요청할 경우 요청하는 디렉토리가 suEXEC userdir로 설정한 (suEXEC 설정 옵션 참고) 디렉토리 아래에 있는가?

  14. 다른 누구도 디렉토리에 쓰기권한이 없는가?

    디렉토리를 다른 사람에게 열어두길 원하지않는다. 오직 소유자만이 디렉토리 내용을 변경할 수 있다.

  15. 지정한 CGI/SSI 프로그램이 존재하는가?

    존재하지않다면 실행할 수도 없다.

  16. 다른 누구도 지정한 CGI/SSI 프로그램에 쓰기권한이 없는가?

    소유자외 누구도 CGI/SSI 프로그램을 변경하길 원하지않는다.

  17. 지정한 CGI/SSI 프로그램이 setuid나 setgid가 아닌가?

    우리는 프로그램이 다시 UID/GID를 변경하길 원하지않는다.

  18. 지정한 사용자/그룹이 프로그램의 사용자/그룹과 같은가?

    사용자가 파일의 소유자인가?

  19. 안전한 동작을 위해 프로세스의 환경변수를 청소할 수 있는가?

    suEXEC는 (설정에서 정의한) 안전한 실행 PATH를 잡고, (이것도 설정에서 정의) 안전한 환경변수 목록에 열거된 변수만 남기고 프로세스의 환경변수를 지운다.

  20. 성공적으로 지정한 CGI/SSI 프로그램을 실행할 수 있는가?

    여기서 suEXEC가 끝나고 지정한 CGI/SSI 프로그램이 시작한다.

이것이 suEXEC wrapper 보안모델의 표준 동작이다. 다소 엄격하고 CGI/SSI 설계에 새로운 제한이 되지만, 보안을 염두에 두고 한단계씩 조심스럽게 만들어졌다.

이 보안 모델이 서버 설정에 어떤 제한을 주는지와 적절한 suEXEC 설정으로 어떤 보안 위험을 피할 수 있는지에 대해 이 문서의 "다시 한번 조심하라" 절을 참고하라.

suEXEC 구성과 설치

이제 재미있는 내용이 시작한다.

suEXEC 구성 옵션

--enable-suexec
이 옵션은 기본적으로 설치되거나 활성화되지않는 suEXEC 기능을 활성화한다. APACI가 suEXEC를 받아들이려면 --enable-suexec 옵션외에 --with-suexec-xxxxx 옵션이 최소한 한개 필요하다.
--with-suexec-bin=PATH
suexec 바이너리 경로는 보안상 이유로 서버에 기록되야 한다. 경로 기본값을 무시하려면 이 옵션을 사용한다. 예를 들어 --with-suexec-bin=/usr/sbin/suexec
--with-suexec-caller=UID
보통 아파치를 실행하는 사용자명. 프로그램을 실행할 수 있는 유일한 사용자다.
--with-suexec-userdir=DIR
suEXEC 접근이 허용되는 사용자 홈디렉토리의 하위디렉토리를 지정한다. 이 디렉토리에 있는 모든 실행파일을 사용자의 suEXEC로 실행므로, 모든 프로그램이 "안전해야" 한다. (예를 들어, 값에 "*"이 없는) "간단한" UserDir 지시어를 사용한다면 같은 값을 설정해야 한다. UserDir 지시어가 passwd 파일에 나온 사용자 홈디렉토리와 다르면 suEXEC는 정상적으로 작동하지 않는다. 기본값은 "public_html"이다.
가상호스트들이 각각 다른 UserDir을 사용한다면 모두 한 부모 디렉토리 안에 있도록 정의해야 하고, 그 부모 디렉토리명을 여기 적는다. 이렇게 정의하지 않으면, "~userdir" cgi 요청이 작동하지 않는다!
--with-suexec-docroot=DIR
아파치의 DocumentRoot를 정의한다. 이는 suEXEC가 사용할 수 있는 (UserDirs을 제외한) 유일한 공간이다. 기본 디렉토리는 --datadir 값에 "/htdocs"을 붙인 것이다. 예를 들어 "--datadir=/home/apache"로 구성했다면 suEXEC wrapper는 document root로 "/home/apache/htdocs" 디렉토리를 사용한다.
--with-suexec-uidmin=UID
suEXEC에서 지정가능한 사용자의 최소 UID를 정의한다. 대부분의 시스템에서 500이나 100이 적절하다. 기본값은 100이다.
--with-suexec-gidmin=GID
suEXEC에서 지정가능한 그룹의 최소 GID를 정의한다. 대부분의 시스템에서 100이 적절하므로 이 값이 기본값이다.
--with-suexec-logfile=FILE
모든 suEXEC 작동과 오류를 (감시나 디버깅 목적에 유용한) 기록할 로그파일명을 지정한다. 기본적으로 로그파일의 이름은 "suexec_log"이고 표준 로그파일 디렉토리에 (--logfiledir) 위치한다.
--with-suexec-safepath=PATH
CGI 실행파일에 넘겨질 안전한 PATH 환경변수를 정의한다. 기본값은 "/usr/local/bin:/usr/bin:/bin"이다.

suEXEC wrapper를 컴파일하고 설치하기
--enable-suexec 옵션으로 suEXEC 기능을 가능하게한 경우 make 명령어를 실행하면 suexec 실행파일이 (아파치와 함께) 자동으로 만들어진다.
모든것을 컴파일한 후 make install 명령어를 실행하여 설치할 수 있다. 바이너리파일 suexec는 --sbindir 옵션으로 지정한 디렉토리에 설치된다. 기본 위치는 "/usr/local/apache2/sbin/suexec"이다.
설치 과정에 root 권한이 필요함을 주의하라. wrapper가 사용자 ID를 설정하기위해서는 소유자가 root이고 파일모드로 setuserid 실행비트가 설정되야 한다.

편집증적인 권한설정
suEXEC wrapper는 자신을 실행한 사용자가 구성 옵션 --with-suexec-caller로 지정한 올바른 사용자인지 확인을 하지만, 이 검사 이전에 suEXEC가 사용하는 시스템호출 혹은 라이브러리 함수가 조작되었을 수 있다. 이를 대비하며 일반적으로 좋은 습관이므로 오직 아파치를 실행하는 그룹만이 suEXEC를 실행할 수 있도록 파일시스템 권한을 지정해야 한다.

예를 들어, 웹서버를 다음과 같이 설정하고:

User www
Group webgroup

suexec를 "/usr/local/apache2/sbin/suexec"에 설치하였다면, 다음을 실행해야 한다:

chgrp webgroup /usr/local/apache2/bin/suexec
chmod 4750 /usr/local/apache2/bin/suexec

그러면 오직 아파치를 실행하는 그룹만이 suEXEC wrapper를 실행할 수 있다.

suEXEC 키고 끄기

아파치는 시작할때 --sbindir 옵션으로 지정한 디렉토리에서 suexec 파일을 (기본값 "/usr/local/apache2/sbin/suexec") 찾는다. 아파치가 정상적으로 구성된 suEXEC wrapper를 발견하면 오류 로그(error log)에 다음과 같이 출력한다:

[notice] suEXEC mechanism enabled (wrapper: /path/to/suexec)

서버 시작중에 이런 문구를 없다면 서버는 기대한 장소에서 wrapper 프로그램을 찾지 못했거나, 실행파일이 setuid root로 설치되지않았기 때문일 것이다.

처음으로 suEXEC 기능을 사용하고 싶고 이미 아파치 서버가 실행중이라면, 아파치를 죽이고 다시 시작해야 한다. 간단히 HUP이나 USR1 시그널로 재시작하는 것으로는 충분하지 않다.

suEXEC를 안사용하려면 suexec 파일을 지운후 아파치를 죽이고 재시작해야 한다.

suEXEC 사용하기

CGI 프로그램 요청의 경우 SuexecUserGroup 지시어를 사용한 가상호스트에 요청을 하였거나 mod_userdir이 요청을 처리하는 경우에만 suEXEC wrapper를 호출한다.

가상호스트:
suEXEC wrapper를 사용하는 한가지 방법은 VirtualHost 정의에 SuexecUserGroup 지시어를 사용하는 것이다. 이 지시어를 주서버 사용자 ID와 다르게 설정하면 CGI 자원의 모든 요청이 <VirtualHost>에서 지정한 User와 Group으로 실행된다. 이 지시어들이 <VirtualHost>에 없으면 주서버 userid를 사용한다.

사용자 디렉토리:
mod_userdir이 요청을 처리한다면 suEXEC wrapper를 호출하여, 요청한 사용자 디렉토리에 해당하는 사용자 ID로 CGI 프로그램을 실행한다. 이 기능이 동작하려면 사용자 ID로 CGI를 실행할 수 있고 스크립트가 위의 보안 검사 항목을 만족해야 한다. 구성 옵션 --with-suexec-userdir을 참고하라.

suEXEC 디버깅하기

suEXEC wrapper는 로그 정보를 위에서 다룬 --with-suexec-logfile 옵션으로 지정한 파일에 쓴다. wrapper를 올바로 구성하고 설치했다면 어디서 잘못되었는지 이 로그파일와 서버의 error_log를 살펴봐라.

다시 한번 조심하라: 경고와 예제

주의! 이 섹션은 완전하지 않을 수 있다. 아파치그룹의 온라인 문서에서 이 문서의 최신판을 참고하라.

wrapper가 서버 설정을 제약하는 몇가지 흥미로운 점이 있다. suEXEC와 관련된 "버그"를 보고하기 전에 이들을 살펴보길 바란다.

  • suEXEC 제약 사항
  • 디렉토리 구조 제한

    보안과 효율성을 위해 모든 suEXEC 요청은 가상호스트의 경우 최상위 document root 혹은 userdir 요청의 경우 최상위 개인 document root 안에서 발생해야 한다. 예를 들어, 가상호스트 네개를 설정했다면 가상호스트에서 suEXEC를 이용하기위해 가상호스트의 document root를 주 아파치 문서 계층구조 밖에 설정할 필요가 있다. (예제는 다음에.)

  • suEXEC의 PATH 환경변수

    변경하면 위험할 수 있다. 여기에 포함하는 모든 경로가 믿을 수 있는 디렉토리인지 확인하라. 이 지구상의 누군가가 그곳에 있는 트로이목마를 실행하길 원하지 않을 것이다.

  • suEXEC 코드 수정하기

    반복해서 말하지만, 당신이 무엇을 하는지 모르고 시도한다면 큰 문제가 발생할 수 있다. 어떤 경우에도 수정하지마라.


아파치 성능향상 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

아파치 성능향상

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

아파치 2.0은 기능과 포팅가능성과 성능의 균형이 맞도록 설계한 범용 웹서버이다. 벤치마크 기록을 세우기위해 설계하지 않았지만 아파치 2.0은 실제 많은 경우 높은 성능을 낸다.

아파치 1.3과 비교해서 2.0 버전은 처리량과 확장성(scalability)을 높이기위해 많은 최적화를 했다. 기본값으로 대부분 최적화한 값을 사용한다. 그러나 컴파일시 혹은 실행시 설정이 성능에 큰 영향을 줄 수 있다. 이 문서는 아파치 2.0의 성능을 향상하기위해 서버 관리자가 설정할 수 있는 옵션을 설명한다. 어떤 설정 옵션은 웹서버가 하드웨어와 운영체제의 기능을 더 잘 활용하도록 하는 반면, 어떤 옵션은 속도를 위해 기능을 희생한다.

하드웨어와 운영체제에 대해서

웹서버 성능에 가장 큰 영향을 주는 것은 메모리다. 스왑은 요청당 지연시간을 사용자가 "충분히 빠르다고" 생각하지 못하게 늘리기때문에 웹서버는 스왑을 하면 안된다. 느려지면 사용자는 정지하고 다시 접속하여 부하가 계속 증가한다. MaxClients 지시어를 조절하여 웹서버가 스왑을 할 정도로 많은 자식을 만들지않도록 해야 한다. 방법은 간단하다: top과 같은 도구에서 프로세스 목록을 보고 아파치 프로세스의 평균 메모리 사용량을 알아낸후, 전체 사용가능한 메모리에서 다른 프로세스들이 사용할 공간을 뺀 값에서 나눈다.

나머지는 평범하다: 충분히 빠른 CPU, 충분히 빠른 네트웍카드, 충분히 빠른 디스크, 여기서 "충분히 빠른"은 실험을 해서 결정해야 한다.

운영체제는 보통 각자 알아서 선택할 일이다. 그러나 일반적으로 유용하다고 판명된 몇가지 지침이 있다:

  • 선택한 운영체제의 최신 안정 버전과 패치를 실행한다. 많은 운영체제 제작사는 최근 TCP 스택과 쓰레드 라이브러리에 많은 속도향상을 했다.

  • 운영체제가 sendfile(2) 시스템호출을 지원한다면, 이를 사용하기위한 버전이나 패치를 설치하였는지 확인한다. (예를 들어, 리눅스라면 2.4 이상 버전을 뜻한다. Solaris 8 초기 버전은 패치가 필요하다.) 지원하는 시스템이라면 아파치 2는 sendfile을 사용하여 CPU를 덜 사용하며 정적 파일을 더 빨리 전송할 수 잇다.

실행시 설정에 대해서

관련된 모듈 관련된 지시어
  • mod_dir
  • mpm_common
  • mod_status
  • AllowOverride
  • DirectoryIndex
  • HostnameLookups
  • EnableMMAP
  • EnableSendfile
  • KeepAliveTimeout
  • MaxSpareServers
  • MinSpareServers
  • Options
  • StartServers

HostnameLookups와 DNS에 대해 고려할 점들

아파치 1.3 이전에 HostnameLookups의 기본값은 On이였다. 요청을 마치기전에 DNS 검색이 끝나야 하므로 요청마다 지연이 생겼다. 아파치 1.3에서 이 설정의 기본값이 Off로 변경되었다. 로그파일의 주소를 호스트명으로 변환하려면 여러 로그처리 프로그램중 하나인, 아파치에 포함된 logresolve 프로그램을 사용하라.

로그처리 작업이 서버 성능에 악영향을 미치므로 실제 사용하는 웹서버가 아닌 다른 컴퓨터에서 로그파일을 후처리하길 바란다.

Allow from domain이나 Deny from domain 지시어를 사용한다면 (즉, IP 주소가 아닌 호스트명이나 도메인명을 사용한다면) 부득이 중복-역 DNS 검색을 (역검색을 한후 악의로 변경되었는지 확인하기위해 다시 검색) 해야 한다. 그러므로 성능을 높이기위해 이런 지시어에는 가능하면 이름대신 IP 주소를 사용한다.

<Location /server-status> 섹션 등으로 지시어의 적용범위를 제한할 수 있음을 기억하라. 이 경우 조건에 맞는 요청에만 DNS 조회를 한다. 다음은 .html과 .cgi 파일만 DNS 검색을 하는 예제다:

HostnameLookups off
<Files ~ "\.(html|cgi)$">
HostnameLookups on
 </Files>

그러나 CGI에서 DNS명이 필요할 뿐이라면, 필요한 특정 CGI에서만 gethostbyname 호출을 하도록 고려해볼 수 있다.

FollowSymLinks와 SymLinksIfOwnerMatch

URL 공간에서 Options FollowSymLinks를 사용하지않고 Options SymLinksIfOwnerMatch를 사용하면 아파치는 심볼링크를 검사하기위해 시스템호출을 한번 더 해야 한다. 파일명의 각 부분마다 한번씩 더 호출을 한다. 예를 들어, 설정이 다음과 같고:

DocumentRoot /www/htdocs
<Directory />
Options SymLinksIfOwnerMatch
 </Directory>

/index.html URI에 대한 요청이 있다고 가정하자. 그러면 아파치는 /www, /www/htdocs, /www/htdocs/index.html 각각에 대해 lstat(2)를 호출한다. lstats 결과를 캐싱하지 않기때문에 요청이 들어올 때마다 매번 같은 작업을 한다. 진짜 심볼링크 보안 검사를 원한다면 다음과 같이 할 수 있다:

DocumentRoot /www/htdocs
<Directory />
Options FollowSymLinks
 </Directory>

<Directory /www/htdocs>
Options -FollowSymLinks +SymLinksIfOwnerMatch
 </Directory>

이 경우 최소한 DocumentRoot 경로는 검사하지 않는다. DocumentRoot 밖에 있는 경로로 Alias나 RewriteRule을 사용한 경우에도 위와 비슷한 섹션이 필요하다. 심볼링크 보안을 고려하지 않고 최고의 성능을 얻으려면, FollowSymLinks를 설정하고, SymLinksIfOwnerMatch는 절대로 안된다.

AllowOverride

URL 공간에서 overrides를 허용한다면 (보통 .htaccess 파일) 아파치는 파일명의 각 부분마다 .htaccess를 열길 시도한다. 예를 들어,

DocumentRoot /www/htdocs
<Directory />
AllowOverride all
 </Directory>

/index.html URI에 대한 요청이 있다고 가정하자. 아파치는 /.htaccess, /www/.htaccess, /www/htdocs/.htaccess를 열려고 시도한다. 해결책은 앞의 Options FollowSymLinks 경우와 비슷하다. 최고의 성능을 얻으려면 파일시스템에 대해서 항상 AllowOverride None을 사용한다.

내용협상

가능하고 진짜 조금의 성능향상에도 관심이 있다면 내용협상을 막는다. 실제로 협상의 이득은 성능저하보다 작다. 서버를 빠르게 할 수 있다. 다음과 같이 와일드카드를 사용하는 대신:

DirectoryIndex index

완전한 목록을 사용한다:

DirectoryIndex index.cgi index.pl index.shtml index.html

가장 흔한 것을 앞에 둔다.

또, 디렉토리에서 파일들을 찾는 MultiViews 보다는, 한 파일만 읽으면 필요한 정보를 얻을 수 있는 type-map 파일을 직접 만드는 것이 더 빠름을 명심하라.

사이트에 내용협상이 필요하다면 협상을 위해 Options MultiViews 지시어를 사용하기보다 type-map 파일을 고려하라. 협상방법에 대한 자세한 설명과 type-map 파일을 만드는 방법은 내용협상 문서를 참고하라.

메모리대응 (memory-mapping)

예를 들어, server-side-include를 처리하는 등 아파치 2.0이 전송할 파일을 읽을때 운영체제가 mmap(2) 등을 지원한다면 파일을 메모리대응한다.

여러 플래폼에서 메모리대응을 성능을 향상한다. 그러나 메모리대응이 서버의 성능을 떨어트리고 심지어 안정성을 해치는 경우가 있다:

  • 어떤 운영체제에서 mmap은 CPU 개수가 많아질때 read(2) 만큼 확장성이 좋지 않다. 예를 들어, 다중프로세서 Solaris 서버에서 아파치 2.0은 종종 mmap을 사용하지 않을때 서버가 처리한 파일을 더 빨리 전송한다.

  • NFS 마운트한 파일시스템에 있는 파일을 메모리대응하는 도중에 다른 NFS 클라이언트에 있는 프로세스가 파일을 지우거나 파일크기를 줄이면, 웹서버 프로세스가 다음 번에 메모리대응한 파일내용을 읽을때 bus error가 발생할 수 있다.

위의 조건에 해당하면 전송하는 파일을 메모리대응하지 않도록 EnableMMAP off를 사용해야 한다. (주의: 이 지시어는 디렉토리별로 변경할 수 있다.)

Sendfile

아파치는 운영체제가 sendfile(2)을 지원하면 커널 sendfile을 사용하여 -- 예를 들어, 정적 파일을 서비스할때 -- 전송할 파일을 직접 읽지않을 수 있다.

여러 플래폼에서 sendfile을 사용하면 read와 send를 따로 할 필요가 없어서 빨라진다. 그러나 sendfile을 사용하면 웹서버의 안정성을 해치게되는 경우가 있다:

  • sendfile 지원이 잘못되었고 컴파일 시스템이 이점을 발견하지 못하는 플래폼이 있다. 특히 다른 컴퓨터에서 실행파일을 컴파일하여 sendfile 지원이 잘못된 컴퓨터로 가져온 경우에 가능하다.

  • 커널은 자신의 캐쉬를 사용하여 NFS로 마운트한 파일을 안정적으로 서비스할 수 없는 경우가 있다.

위의 조건에 해당하면 파일을 sendfile 전송하지 않도록 EnableSendfile off를 사용해야 한다. (주의: 이 지시어는 디렉토리별로 변경할 수 있다.)

프로세스 생성

아파치 1.3 이전에는 MinSpareServers, MaxSpareServers, StartServers 설정이 모두 벤치마크 결과에 큰 영향을 미쳤다. 특히 아파치는 작업을 서비스하기위해 충분한 자식수에 다다를 때까지 "도달" 기간이 필요했다. 처음 StartServers개 자식을 만든후, MinSpareServers 설정값까지 초당 자식을 하나씩 만들었다. 그래서 StartServers 기본값이 5인 서버에 클라이언트 100개가 동시에 접속하면 부하를 처리하기에 충분한 자식을 만들기까지 95초가 걸렸다. 자주 재시작하지 않는 실제 서버에서는 잘 동작하지만, 10분간만 실행하는 벤치마크 결과는 매우 나쁘게 나온다.

초당 한개 규칙은 자식을 새로 시작하면서 서버에 무리를 주지 않으려고 정했다. 컴퓨터가 자식을 시작하느라 바쁘면 요청을 서비스할 수 없다. 그러나 이 규칙이 아파치의 체감 성능에 악영향을 주어 변경하였다. 아파치 1.3에서 초당 한개 규칙은 완화되었다. 코드는 자식 한개를 만들고, 1초 쉬고, 두개를 만들고, 1초 쉬고, 네개를 만들고, 이런 식으로 초당 자식을 32개 만들때까지 지수로 증가한다. 자식수가 MinSpareServers 설정에 다다르면 증가를 중단한다.

이 경우 반응속도가 빨라져서 MinSpareServers, MaxSpareServers, StartServers를 거의 설정할 필요가 없다. 일초에 자식을 4개 이상 생성하면 ErrorLog에 기록한다. 이런 오류문이 많이 보이면 이 설정들을 조절하길 바란다. mod_status 결과가 도움이 될 것이다.

프로세스 생성과 관련하여 MaxRequestsPerChild 설정은 프로세스를 종료한다. 기본값은 자식당 처리할 요청수에 제한이 없다는 0이다. 현재 설정이 30과 같이 매우 작은 값으로 설정되있다면, 값을 상당히 높힐 필요가 있다. SunOS나 오래된 Solaris 버전을 사용한다면, 메모리유출때문에 이 값을 10000 정도로 설정하라.

연결유지(keep-alive)를 사용한다면 자식들은 이미 열린 연결에서 추가 요청을 기다리며 아무것도 하지않기때문에 계속 바쁘다. KeepAliveTimeout의 기본값 15 초는 이런 현상을 최소화한다. 네트웍 대역폭과 서버 자원 간의 균형이 맞게 설정한다. 연결유지의 대부분의 이점이 사라지기때문에 어떤 경우에도 이 값을 60 초 이상으로 올리지 마라.

컴파일시 설정에 대해서

MPM 선택

아파치 2.x는 다중처리모듈 (MPMs)이라는 교체할 수 있는 동기화 모델을 지원한다. 아파치를 컴파일할때 MPM을 선택해야 한다. beos, mpm_netware, mpmt_os2, mpm_winnt와 같이 특정 플래폼에서만 사용할 수 있는 MPM도 있다. 일반적인 유닉스류 시스템은 여러 MPM 중에 하나를 선택할 수 있다. 웹서버의 속도와 확장성(scalability)은 어떤 MPM을 선택했냐에 달렸다:

  • worker MPM은 여러 자식 프로세스가 각각 여러 쓰레드를 사용한다. 각 쓰레드는 한번에 한 연결을 담당한다. 일반적으로 worker는 prefork MPM 보다 적은 메모리를 사용하므로 통신량이 많은 서버에 적절하다.
  • prefork MPM은 쓰레드가 한개인 자식 프로세스를 여러개 사용한다. 각 프로세스는 한번에 한 연결을 담당한다. 여러 시스템에서 prefork의 속도는 worker와 비슷하지만, 더 많은 메모리를 사용한다. 다음과 같은 상황에서 쓰레드를 사용하지 않는 prefork 방식이 worker에 비해 이점을 가진다: 쓰레드에 안전하지 (thread-safe) 않은 제삼자가 만든 모듈을 사용할 수 있고, 쓰레드 디버깅 지원이 빈약한 플래폼에서 쉽게 디버깅할 수 있다.

이 MPM들과 다른 MPM에 대해 더 자세한 정보는 MPM 문서를 참고하길 바란다.

모듈

메모리 사용량이 성능에서 가장 중요한 요인이기때문에 실제로 사용하지 않는 모듈을 제거해보자. 모듈을 DSO로 컴파일했다면 간단히 그 모듈에 대한 LoadModule 지시어를 주석처리하면 된다. 그래서 모듈을 제거하고 실행하여 사이트가 모듈없이도 정상적으로 동작하는지 살펴볼 수 있다.

반대로 모듈이 아파치 실행파일에 정적으로 링크되있다면 원하지 않는 모듈을 제거하기위해 아파치를 재컴파일해야 한다.

여기서 당연히 어떤 모듈을 사용하고 사용하지 말지 의문이 생긴다. 정답은 웹사이트마다 다르다. 그러나 아마도 최소한 mod_mime, mod_dir, mod_log_config 모듈은 사용할 것이다. 물론 웹사이트에 로그파일이 필요없다면 mod_log_config는 없어도 된다. 그러나 추천하지 않는다.

Atomic 명령

mod_cache 같은 모듈과 최근 개발중인 worker MPM은 APR의 atomic API를 사용한다. 이 API는 경량급 쓰레드 동기화를 위할 atomic 명령을 제공한다.

기본적으로 APR은 각 운영체제/CPU 플래폼에서 가장 효율적인 방법을 사용하여 이 명령을 구현한다. 예를 들어, 여러 최신 CPU에는 하드웨어로 atomic compare-and-swap (CAS) 연산을 하는 명령어가 있다. 그러나 어떤 플래폼에서 APR은 이런 명령어가 없는 오래된 CPU와 호환성을 위해 더 느린 mutex기반 구현을 기본적으로 사용한다. 이런 플래폼에서 아파치를 컴파일할때 아파치를 최신 CPU에서만 실행할 계획이라면, 아파치를 구성할때 --enable-nonportable-atomics 옵션을 사용하여 더 빠른 atomic 구현을 선택할 수 있다:

./buildconf
./configure --with-mpm=worker --enable-nonportable-atomics=yes

--enable-nonportable-atomics 옵션은 다음과 같은 플래폼에 영향이 있다:

  • SPARC에서 Solaris
    기본적으로 APR은 Solaris/SPARC에서 mutex기반 atomic을 사용한다. 그러나 구성할때 --enable-nonportable-atomics를 사용하면 APR은 빠른 하드웨어 compare-and-swap을 위한 SPARC v8plus 명령어를 사용한다. 이 옵션을 사용하면 atomic 명령이 더 효율적이지만 (CPU를 덜 사용하고 더 높은 동기화가 가능하다), 컴파일한 실행파일은 UltraSPARC 칩에서만 실행할 수 있다.
  • Linux on x86
    기본적으로 APR은 리눅스에서 mutex기반 atomic을 사용한다. 그러나 구성할때 --enable-nonportable-atomics를 사용하면 APR은 빠른 하드웨어 compare-and-swap을 위한 486 명령어를 사용한다. 더 효율적인 atomic 명령이 가능하지만, 컴파일한 실행파일은 486 이상 칩에서만 (386은 안된다) 실행할 수 있다.

mod_status와 ExtendedStatus On

아파치를 컴파일할때 mod_status를 포함하고 실행할때 ExtendedStatus On을 설정하면 아파치는 요청을 받을때마다 gettimeofday(2)(혹은 운영체제에 따라 times(2))를 두번 호출하고 (1.3 이전에는) time(2)도 추가로 여러번 호출한다. 상태 보고서에 동작시간이 필요하기 때문이다. 최상의 성능을 얻으려면 (기본값인) ExtendedStatus off를 설정한다.

accept 직렬화 - 여러 소켓

주의:

아래 문서는 아파치 웹서버 2.0 버전에서 변경된 내용을 담고 있지 않다. 아직도 유효한 정보가 있지만, 주의해서 사용하길 바란다.

유닉스 소켓 API의 단점을 설명한다. 웹서버가 여러 포트 혹은 여러 주소를 기다리기위해 여러 Listen을 사용한다고 가정하자. 연결이 가능한지 각 소켓을 검사하기위해 아파치는 select(2)를 사용한다. select(2)는 소켓에 기다리고 있는 연결이 없는지 혹은 최소한 한개 있는지 알려준다. 아파치에는 여러 자식이 있고, 쉬고 있는 모든 자식은 동시에 새로운 연결을 검사한다. 원래 구현은 다음과 비슷하다 (이 예는 코드에서 가져오지 않았다. 단지 설명하기위한 용도로 만들었다.):

for (;;) {
for (;;) {
fd_set accept_fds;

FD_ZERO (&accept_fds);
for (i = first_socket; i <= last_socket; ++i) {
FD_SET (i, &accept_fds);
 }
rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
if (rc < 1) continue;
new_connection = -1;
for (i = first_socket; i <= last_socket; ++i) {
if (FD_ISSET (i, &accept_fds)) {
new_connection = accept (i, NULL, NULL);
if (new_connection != -1) break;
 }
 }
if (new_connection != -1) break;
 }
process the new_connection;
 }

그러나 위의 단순한 구현에는 심각한 고갈(starvation) 문제가 있다. 여러 자식이 동시에 이 반복문을 실행하면, 요청을 기다리며 모두 select에서 멈춘다. 이때 어떤 소켓에 요청이 하나라도 들어오면 모든 자식이 깨어난다 (깨어나는 자식의 개수는 운영체제와 타이밍에 따라 다르다). 이들은 모두 연결을 accept하길 시도한다. 그러나 (아직도 한 연결만 대기중이라면) 한 자식만 성공하고, 나머지는 accept에서 멈춘다. 그러면 이 자식들은 한 소켓의 요청만을 서비스하도록 묶여서, 그 소켓으로 새로운 요청이 충분히 들어와서 모든 자식을 깨울때까지 정지해있다. 이런 고갈 문제는 PR#467에 처음 보고되었다. 최소한 두가지 해결책이 있다.

한가지는 소켓을 대기하지 않도록 (non-blocking) 만드는 방법이다. 이 경우 자식이 accept를 해도 멈추지 않고, 즉시 진행할 수 있다. 그러나 CPU 시간을 낭비한다. select에서 쉬는 자식이 10개 있고, 새로 연결이 한개 들어왔다고 가정하자. 그러면 이 자식중 9개는 깨어나서 연결을 accept하길 시도하고 실패하면 아무 일도 하지 않고 다시 select를 반복한다. 다시 select로 돌아올 때까지 어떤 자식도 다른 소켓에 들어온 요청을 서비스하지 않는다. (다중프로세서 컴퓨터에서) 쉬는 자식 개수만큼 CPU 개수가 있는 드문 경우가 아니라면 이 해결책은 별로 좋아보이지 않는다.

다른 방법은 아파치가 사용하는 방법으로 내부 반복문에 한 자식만을 들여보낸다. 반복문은 다음과 같다 (차이를 강조했음):

for (;;) {
accept_mutex_on ();
for (;;) {
fd_set accept_fds;

FD_ZERO (&accept_fds);
for (i = first_socket; i <= last_socket; ++i) {
FD_SET (i, &accept_fds);
 }
rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);
if (rc < 1) continue;
new_connection = -1;
for (i = first_socket; i <= last_socket; ++i) {
if (FD_ISSET (i, &accept_fds)) {
new_connection = accept (i, NULL, NULL);
if (new_connection != -1) break;
 }
 }
if (new_connection != -1) break;
 }
accept_mutex_off ();
process the new_connection;
 }

accept_mutex_on과 accept_mutex_off 함수는 mutex 세마포어를 구현한다. 한번에 오직 한 자식만이 mutex를 가질 수 있다. mutex를 구현하는 방법은 여러가지이다. 구현 방법은 (1.3 이전) src/conf.h나 (1.3과 그 이후) src/include/ap_config.h에 정의되있다. 어떤 아키텍쳐는 잠금(locking) 방법을 선택하지 않기때문에, 이런 아키텍쳐에서 여러 Listen 지시어를 사용하면 위험하다.

실행시 AcceptMutex 지시어를 사용하여 mutex 구현을 변경할 수 있다.

AcceptMutex flock

이 방법은 잠금파일을 잠그기위해 flock(2) 시스템호출을 사용한다 (잠금파일 위치는 LockFile 지시어로 지정).

AcceptMutex fcntl

이 방법은 잠금파일을 잠그기위해 fcntl(2) 시스템호출을 사용한다 (잠금파일 위치는 LockFile 지시어로 지정).

AcceptMutex sysvsem

(1.3과 그 이후) 이 방법을 SysV식 세마포어를 사용하여 mutex를 구현한다. 불행히도 SysV식 세마포어는 나쁜 부작용이 있다. 하나는 아파치가 세마포어를 정리하지 않고 죽을 수 있는 점이다 (ipcs(8) manpage 참고). 다른 하나는 웹서버와 동일한 uid로 실행하는 CGI가 (즉, suexec나 cgiwrapper를 사용하지않는 한 모든 CGI) 세마포어 API를 사용하여 서비스거부공격을 할 수 있는 점이다. 이런 이유때문에 IRIX를 제외한 아키텍쳐에서 이 방법을 사용하지 않는다 (대부분의 IRIX 컴퓨터에서 앞의 두 방법은 지나치게 버겁다).

AcceptMutex pthread

(1.3과 그 이후) 이 방법은 POSIX mutex를 사용하기때문에 POSIX 쓰레드 규약을 완전히 구현한 아키텍쳐라면 모두 사용가능하지만, (2.5 이후) Solaris에서만 그것도 특정 구성에서만 동작하는 듯하다. 이 방법을 시도해본다면 서버가 멈춰서 응답을 안하는지 살펴봐야 한다. 정적 내용만 서비스하는 서버는 잘 동작하는 것 같다.

AcceptMutex posixsem

(2.0과 그 이후) 이 방법은 POSIX 세마포어를 사용한다. mutex를 가진 프로세스의 쓰레드가 죽는다면(segfault) 세마포어 소유권이 회복되지 않아서 웹서버가 멈춘다.

시스템에 위 목록에 없는 직렬화(serialization) 방법이 있다면 그 방법을 사용하는 코드를 APR에 추가할 가치가 있다.

고려는 해봤지만 구현하지않은 다른 방법은 부분적으로 반복문을 직렬화하는 방법이다. 즉, 프로세서를 몇개만 들여보내는 것이다. 이 방법은 여러 자식을 동시에 실행할 수 있어서 직렬화때문에 전체 대역폭을 활용하지 못하는 다중프로세서 컴퓨터에서만 관심을 가져볼 수 있다. 앞으로 살펴볼 부분이지만, 매우 병렬화된 웹서버가 흔하지 않아서 우선순위가 낮다.

최상의 성능을 얻기위해서는 여러 Listen 문을 사용하지 않는 것이 이상적이다. 그러나 계속 설명한다.

accept 직렬화 - 소켓 한개

앞의 설명은 다중소켓 서버에는 좋지만, 소켓이 한개인 서버는 어떤가? 연결이 도착할때까지 모든 자식이 accept(2)에서 멈춰있기때문에 이론상 같은 문제가 발생하지 않고, 고갈 문제도 없다. 그러나 실제로는 앞에서 말한 대기하지 않는 (non-blocking) 방법에서 발생하는 "공회전(spinning)" 현상을 감추고 있다. 대부분의 TCP 스택은 연결이 도착하면 커널이 accept에서 멈춰있는 모든 자식을 깨우도록 구현되있다. 프로세스중 한개가 연결을 얻고 사용자영역으로 돌아가고, 나머지는 커널에서 공회전하여 연결이 없음을 발견하면 다시 잠을 잔다. 사용자영역 코드에서는 이런 공회전을 알 수 없지만, 분명히 존재한다. 그래서 다중소켓의 대기하지 않는 방법과 동일하게 부하를 높이는 불필요한 행동이 일어난다.

그래서 우리는 여러 아키텍쳐에서 소켓이 한개인 경우에도 직렬화하면 더 "잘" 동작함을 발견했다. 그래서 거의 대부분의 경우 기본적으로 직렬화를 사용한다. 리눅스에서 (커널 2.0.30, 128Mb 메모리에 듀얼 Pentium pro) 실험한 결과 소켓 한개를 직렬화하면 하지 않은 경우에 비해 초당 요청이 3% 미만 줄어들었다. 그러나 직렬화를 하지 않은 경우 요청당 100ms 지연이 발생했다. 이 지연은 아마도 LAN에서 발생하는 긴 연결선때문일 것이다. 소켓이 한개인 경우 직렬화를 사용하지 않으려면 SINGLE_LISTEN_UNSERIALIZED_ACCEPT를 정의한다.

Close 지연(lingering)

draft-ietf-http-connection-00.txt 8절에서 설명하듯이 안정적인 웹서버가 되려면, 통신의 양 방향을 독립적으로 닫을 수 있어야 한다 (TCP 연결은 쌍방향이고, 방향은 서로 독립적이다). 이점을 다른 서버에서는 자주 간과하지만, 아파치는 1.2부터 정확히 구현해왔다.

이 기능을 부주의하게 아파치에 추가했을때 여러 유닉스 버전에서 많은 문제가 발생했다. TCP 규약은 FIN_WAIT_2에 타임아웃이 있다고 정하지 않았지만, 금지하지도 않았다. 타임아웃이 없는 시스템에서 아파치 1.2는 많은 소켓을 영원히 FIN_WAIT_2 상태로 만들었다. 많은 경우 이 문제는 제작사가 제공하는 최신 TCP/IP 패치를 적용하여 해결할 수 있다. 그러나 제작사가 패치를 발표하지 않는 경우가 (즉, SunOS4 -- 소스 라이선스가 있는 사람은 직접 패치할 수 있지만) 있기때문에 이 기능을 사용하지 않기로 결정했다.

방법은 두가지다. 하나는 소켓 옵션 SO_LINGER를 사용하는 방법이다. 그러나 불행히도 대부분의 TCP/IP 스택은 이 옵션을 올바로 구현하지 않았다. 올바로 구현한 스택에서 조차도 (즉, 리눅스 2.0.31) 이 방법은 다음 방법보다 더 cpu를 잡아먹는다.

아파치는 보통 (http_main.c에 있는) lingering_close라는 함수를 사용한다. 이 함수는 대충 다음과 같다:

void lingering_close (int s)
{
char junk_buffer[2048];

/* shutdown the sending side */
shutdown (s, 1);

signal (SIGALRM, lingering_death);
alarm (30);

for (;;) {
select (s for reading, 2 second timeout);
if (error) break;
if (s is ready for reading) {
if (read (s, junk_buffer, sizeof (junk_buffer)) <= 0) {
break;
 }
/* just toss away whatever is here */
 }
 }

close (s);
 }

이 코드는 연결을 닫을때 더 CPU를 사용하지만, 안정적인 구현을 위해 필요하다. HTTP/1.1이 더 널리 퍼지고 모든 연결을 유지한다면(persistent), 연결을 받는 비용은 여러 요청을 처리하면서 상쇄될 것이다. 위험하게도 NO_LINGCLOSE를 정의하여 이 기능을 사용하지 않을 수 있지만, 절대로 권하지 않는다. 특히 HTTP/1.1 파이프라인 (역주; 연결유지 상태에서 응답을 기다리지 않고 여러 요청을 보내는 기술) 연결유지에는 lingering_close가 필수적이다 (그리고 파이프라인 연결이 더 빠르기때문에 사용하길 바랄 것이다).

Scoreboard 파일

아파치의 부모와 자식은 scoreboard라는 것을 통해 서로 통신한다. 이상적으로는 scoreboard를 공유메모리로 구현해야 한다. 우리 개발자가 해당 운영체제에 접근할 수 있거나 상세한 포팅 결과를 받은 경우 보통 공유메모리를 사용하여 구현한다. 나머지는 디스크에 있는 파일을 사용하여 구현한다. 디스크에 있는 파일은 느리고 신뢰도가 떨어진다 (기능도 더 적다). src/main/conf.h 파일에서 사용하는 아키텍쳐를 찾아서 USE_MMAP_SCOREBOARD 혹은 USE_SHMGET_SCOREBOARD인지 확인한다. 둘중 하나를 (각각 함께 사용할 HAVE_MMAP이나 HAVE_SHMGET도 같이) 정의하면 공유메모리 코드를 사용한다. 시스템이 다른 종류의 공유메모리를 사용한다면 src/main/http_main.c 파일을 수정하여 아파치에서 공유메모리를 사용할 수 있도록 훅(hook)을 추가하라. (또한 패치를 우리에게 보내주길 바란다.)

역사적 설명: 아파치의 리눅스 버전은 아파치 1.2 버전부터 공유메모리를 사용하기 시작했다. 리눅스에서 초기 아파치 버전이 느리고 신뢰도가 떨어졌기 때문이다.

DYNAMIC_MODULE_LIMIT

모듈을 동적으로 읽어들이지 않는다면 (가능한 조금이라도 성능을 높이기위해 이 글을 읽는다면 아마도 모듈을 동적으로 읽어들이지 않을 것이다), 서버를 컴파일할때 -DDYNAMIC_MODULE_LIMIT=0을 추가한다. 그러면 모듈을 동적으로 읽어들이기위해 할당하는 메모리를 절약한다.

부록: 시스템호출 기록을 자세히 분석하기

다음은 Solaris 8에서 worker MPM을 사용한 아파치 2.0.38의 시스템호출 기록(trace)이다. 아래 명령어를 사용하여 기록을 얻었다:

truss -l -p httpd_child_pid.

-l 옵션을 사용하면 truss는 시스템호출을 하는 LWP (lightweight process, 경량급 프로세스--Solaris의 커널수준 쓰레드) ID를 같이 기록한다.

다른 시스템에는 strace, ktrace, par 같은 시스템호출 추적 도구가 있다. 결과는 비슷하다.

클라이언트는 웹서버에게 크기가 10KB인 정적 파일을 요청한다. 정적인 파일을 요청하지 않거나 내용협상하는 요청을 한 경우 기록이 매우 다르다 (때로는 매우 알아보기 힘들다).

/67:    accept(3, 0x00200BEC, 0x00200C0C, 1) (sleeping...)
/67:    accept(3, 0x00200BEC, 0x00200C0C, 1)            = 9

위에서 연결대기(listener) 쓰레드가 LWP #67에서 실행됨을 알 수 있다.

accept(2) 직렬화를 사용하지 않음을 주목하라. 여러 포트를 기다리지않는 경우 이 플래폼의 worker MPM은 기본적으로 직렬화하지 않은 accept를 사용한다.
/65:    lwp_park(0x00000000, 0)                         = 0
/67:    lwp_unpark(65, 1)                               = 0

연결은 받아들이고(accept) 연결대기 쓰레드는 worker 쓰레드를 깨워서 요청을 처리하게 한다. 아래 기록에서 요청을 처리하는 worker 쓰레드가 LWP #65임을 알 수 있다.

/65:    getsockname(9, 0x00200BA4, 0x00200BC4, 1)       = 0

가상호스트를 구현하기위해 아파치는 연결을 받아들인 지역(local) 소켓 주소를 알아야 한다. (가상호스트를 사용하지 않거나 Listen 지시어에 와일드카드 주소를 사용하지 않은 경우 등) 많은 경우 이 호출을 없앨 수 있다. 그러나 아직 이런 최적화 작업이 안되있다.

/65:    brk(0x002170E8)                                 = 0
/65:    brk(0x002190E8)                                 = 0

brk(2) 호출은 힙(heap)에서 메모리를 할당한다. 웹서버는 대부분의 요청 처리시 자체 메모리 할당자(apr_pool과 apr_bucket_alloc)를 사용하기때문에 시스템호출 기록에서 이 시스템호출을 보기가 드물다. 이 기록에서 웹서버는 시작하자마자 자체 메모리 할당자가 사용할 메모리블록을 얻기위해 malloc(3)을 호출한다.

/65:    fcntl(9, F_GETFL, 0x00000000)                   = 2
/65:    fstat64(9, 0xFAF7B818)                          = 0
/65:    getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B910, 2190656) = 0
/65:    fstat64(9, 0xFAF7B818)                          = 0
/65:    getsockopt(9, 65535, 8192, 0xFAF7B918, 0xFAF7B914, 2190656) = 0
/65:    setsockopt(9, 65535, 8192, 0xFAF7B918, 4, 2190656) = 0
/65:    fcntl(9, F_SETFL, 0x00000082)                   = 0

다음 worker 쓰레드는 클라이언트의 연결(파일기술자 9)을
    대기안함(non-blocking) 상태로 바꾼다. setsockopt(2)와
    getsockopt(2) 호출은 Solaris의 libc가 소켓에
    대한 fcntl(2)을 어떻게 처리하는지 보여준다.

/65:    read(9, " G E T   / 1 0 k . h t m".., 8000)     = 97

worker 쓰레드는 클라이언트로 부터 요청을 읽는다.

/65:    stat("/var/httpd/apache/httpd-8999/htdocs/10k.html", 0xFAF7B978) = 0
/65:    open("/var/httpd/apache/httpd-8999/htdocs/10k.html", O_RDONLY) = 10

웹서버 설정은 Options FollowSymLinks와 AllowOverride None이다. 그래서 요청한 파일경로의 각 디렉토리에 대해 lstat(2)하거나 .htaccess 파일을 검사할 필요가 없다. 파일을 검사하기위해, 1) 파일이 있는지, 2) 디렉토리가 아닌 일반파일인지, stat(2) 호출만 하면 된다.

/65:    sendfilev(0, 9, 0x00200F90, 2, 0xFAF7B53C)      = 10269

이 경우 웹서버는 한번의 sendfilev(2) 시스템호출로
    HTTP 응답헤더와 요청한 파일을 전송할 수 있다. Sendfile 지원여부는
    운영체제마다 다르다. 다른 시스템이라면 sendfile(2)을
    호출하기 전에 헤더를 보내기위해 write(2)나
    writev(2) 호출을 한다.

/65:    write(4, " 1 2 7 . 0 . 0 . 1   -  ".., 78)      = 78

write(2) 호출은 접근로그(access log)에 요청을 기록한다. 이 기록에 time(2) 호출이 없음을 주목하라. 아파치 1.3과 달리 아파치 2.0은 시간을 알기위해 gettimeofday(3)를 사용한다. gettimeofday를 최적화한 리눅스와 Solaris 같은 몇몇 운영체제에서는 일반적인 시스템호출 부담이 없다.

/65:    shutdown(9, 1, 1)                               = 0
/65:    poll(0xFAF7B980, 1, 2000)                       = 1
/65:    read(9, 0xFAF7BC20, 512)                        = 0
/65:    close(9)                                        = 0

worker 쓰레드는 연결을 지연닫기(lingering close)한다.

/65:    close(10)                                       = 0
/65:    lwp_park(0x00000000, 0)         (sleeping...)

마지막으로 worker 쓰레드는 방금 전송한 파일을 닫고, 연결대기(listener) 쓰레드가 다른 연결을 할당할 때까지 정지한다.

/67:    accept(3, 0x001FEB74, 0x001FEB94, 1) (sleeping...)

그동안 연결대기 쓰레드는 연결을 (모든 worker가 작업중이면 연결대기 쓰레드를 멈추는 worker MPM의 흐름제어 기능에 따라) worker 쓰레드에 할당하자마자 다른 연결을 받아들일 수 있다. 이 기록에는 나오지 않지만, worker 쓰레드가 방금 받은 연결을 처리하는 동안 다음 accept(2)가 (요청이 매우 많은 경우 항상) 일어날 수 있다.


URL 재작성 지침서 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

URL 재작성 지침서

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

원저자
Ralf S. Engelschall <rse@apache.org>
1997년 12월

이 문서는 mod_rewrite 참조 문서를 보충한다. 이 문서는 웹관리자가 실제 작업에서 부딪치게되는 전형적인 URL관련 문제를 해결하기위해서 어떻게 아파치 mod_rewrite를 사용하는지 설명한다. URL 재작성 규칙을 설정하여 문제를 해결하는 방법을 자세히 설명한다.

mod_rewrite 소개

아파치 mod_rewrite 모듈은 굉장하다. 즉, URL을 조작할 수 있는 강력하고 실로 정교한 모듈이다. 상상해왔던 거의 모든 종류의 URL 조작이 가능하다. 그러나 그 대가로 사용하기 복잡하다. mod_rewrite의 최대 단점은 초보자가 이해하고 사용하기 쉽지 않다는 점이다. 심지어 아파치 전문가도 종종 mod_rewrite의 새로운 용도를 발견한다.

다른 말로: mod_rewrite에 대해 당신은 처음에 겁을 먹고 절대로 다시 사용하지 않거나, 강력함에 매료되어 앞으로 삶 동안 사랑에 빠질 것이다. 이 글은 첫번째 경우를 막기위해 이미 알려진 몇가지 성공사례를 소개하려고 한다.

실용적인 해결책

이제 내가 직접 만들었거나 다른 사람들이 만든 많은 실용적인 해결책이 나온다. 예제에서 URL 재작성의 흑마술을 마음껏 배우길 바란다.

주의: 서버 설정에 따라 상황에 맞게 예제를 조금 수정해야 할 경우가 있다. 예를 들어, 추가로 mod_alias, mod_userdir 등을 사용한다면 [PT] 플래그를 추가한다. 혹은 주서버설정/가상호스트 사용장소가 아닌 .htaccess 사용장소에 알맞게 규칙을 수정할 수도 있다. 사용하기 전에 항상 규칙이 어떤 기능을 하는지 이해하도록 해라. 그러면 문제를 피할 수 있다.

URL 구조

기준이 되는 URL

상황설명:

한 리소스에 대해 여러 URL을 가지는 웹서버가 있다. 보통 (실제 사용하고 알려져야 할) 기준이 되는 URL과, 단축 혹은 내부 용도의 URL이 있다. 사용자가 요청에 어떤 URL을 사용하던지 기준이 되는 URL만을 보여줘야 한다.

해결책:

기준이 되지않는 모든 URL을 브라우저가 알도록 고치기위해 외부 HTTP 리다이렉션한다. 예를 들어 아래 규칙은 /~user를 기준이 되는 /u/user로 대체하고, /u/user 마지막에 슬래쉬가 없다면 추가한다.

RewriteRule   ^/~([^/]+)/?(.*)    /u/$1/$2  [R]
RewriteRule   ^/([uge])/([^/]+)$  /$1/$2/   [R]

기준이 되는 호스트명

상황설명:
이 규칙은 동일한 사이트에 도달할 수 있는 다른 호스트명 대신 특정 호스트명을 사용하도록 강제한다. 예를 들어, example.com 대신 www.example.com을 사용하도록 강제하고 싶다면 다음과 같은 규칙을 사용할 수 있다.
해결책:
# 80번이 아닌 포트에서 실행하는 사이트용
RewriteCond %{HTTP_HOST}   !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST}   !^$
RewriteCond %{SERVER_PORT} !^80$
RewriteRule ^/(.*)         http://fully.qualified.domain.name:%{SERVER_PORT}/$1 [L,R]

# 그리고, 80번 포트에서 실행하는 사이트용
RewriteCond %{HTTP_HOST}   !^fully\.qualified\.domain\.name [NC]
RewriteCond %{HTTP_HOST}   !^$
RewriteRule ^/(.*)         http://fully.qualified.domain.name/$1 [L,R]

DocumentRoot를 옮긴 경우

상황설명:

웹서버의 DocumentRoot는 보통 URL "/"과 직접 관련있다. 그러나 이곳에 모든 자료가 있지 않고, 자료가 다른 여러 곳에 흩어져있는 경우가 있다. 예를 들어 인트라넷 사이트에 (외부를 위한 홈페이지) /e/www/와 (인트라넷을 위한 홈페이지) /e/sww/가 있다고 하자. 이제 DocumentRoot가 /e/www/이기때문에, 요청에서 페이지에 포함된 그림 등을 이곳에서 가져와야 한다.

해결책:

우리는 URL /를 /e/www/로 리다이렉션만 하면 된다. 사소해 보이지만 실제로 mod_rewrite를 사용해서만 가능하다. (mod_alias 등이 제공하는) URL Alias 같은 전형적인 방법은 앞부분만 찾는다. DocumentRoot가 모든 URL의 앞부분이기때문에 이 방법을 사용하여 리다이렉션을 할 수 없다. mod_rewrite를 사용하면 진짜 간단하다:

RewriteEngine on
RewriteRule   ^/$  /e/www/  [R]

마지막 슬래쉬 문제

상황설명:

디렉토리를 지칭하는 URL의 마지막 슬래쉬 문제가 없다면 모든 웹관리자는 환호할 것이다. 슬래쉬가 없다면, 즉 /~quux/foo/ 대신 /~quux/foo를 사용하면 서버가 foo라는 파일을 찾기때문에 오류가 발생한다. 파일이 디렉토리이기때문에 받아들이지 않는다. 대부분의 경우 보통 서버가 자동으로 URL을 고치지만, 가끔 직접 해줘야 할 경우가 있다. 예를 들어, CGI 스크립트 등으로 복잡한 URL 재작성을 한 후에 그러하다.

해결책:

이 미묘한 문제의 해결방법은 서버가 자동으로 마지막 슬래쉬를 추가하는 것이다. 브라우저가 나머지 그림 등을 올바로 요청할 수 있도록, 외부 리다이렉션을 해야 한다. 내부 리다이렉션을 한다면 디렉토리 페이지에만 동작하여 이 페이지가 상대 URL로 포함하는 그림을 브라우저가 요청할때 찾을 수 없다. 예를 들어, 외부 리다이렉션을 사용하지 않을때 /~quux/foo/index.html에서 image.gif를 요청하면 /~quux/image.gif를 요청하게 된다!

그래서 이를 해결하기위해 다음과 같이 설정한다:

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo$  foo/  [R]

홈디렉토리의 최상위 .htaccess 파일에 다음과 같이 설정할 수도 있다. 그러나 처리하는데 부담이 된다.

RewriteEngine  on
RewriteBase    /~quux/
RewriteCond    %{REQUEST_FILENAME}  -d
RewriteRule    ^(.+[^/])$           $1/  [R]

일관된 URL 구조로 만든 웹클러스터

상황설명:

인트라넷 웹서버군의 모든 웹서버에 동일하고 일관된 URL 구조를 만들고 싶다. 즉, 모든 (정의상 서버에 속하여 서버에 의존적인!) URL을 서버 독립적으로 만든다! 웹 이름공간에 서버독립적인 동일한 구조를 부여해야 한다: URL은 실제 서버를 지칭하면 안된다. 서버군이 자동으로 실제 서버로 유도한다.

해결책:

먼저 사용자, 그룹, 독립체의 위치 정보를 저장한 (분산된) 외부맵에 실제 서버 정보를 얻어온다. 외부맵은 다음과 같은 형식이다

user1  server_of_user1
user2  server_of_user2
:      :

우리는 이 정보를 각각 map.xxx-to-host 파일에 저장했다. 다음으로 모든 서버에서 URL이 서버에 없다면 다음과 같은 URL을,

/u/user/anypath
/g/group/anypath
/e/entity/anypath

다음과 같이 리다이렉션한다

http://physical-host/u/user/anypath
http://physical-host/g/group/anypath
http://physical-host/e/entity/anypath

아래 규칙은 맵파일을 사용하여 이 작업을 한다 (server0은 맵에 항목이 없는 경우 사용할 기본서버라고 가정한다):

RewriteEngine on

RewriteMap      user-to-host   txt:/path/to/map.user-to-host
RewriteMap     group-to-host   txt:/path/to/map.group-to-host
RewriteMap    entity-to-host   txt:/path/to/map.entity-to-host

RewriteRule   ^/u/([^/]+)/?(.*)   http://${user-to-host:$1|server0}/u/$1/$2
RewriteRule   ^/g/([^/]+)/?(.*)  http://${group-to-host:$1|server0}/g/$1/$2
RewriteRule   ^/e/([^/]+)/?(.*) http://${entity-to-host:$1|server0}/e/$1/$2

RewriteRule   ^/([uge])/([^/]+)/?$          /$1/$2/.www/
RewriteRule   ^/([uge])/([^/]+)/([^.]+.+)   /$1/$2/.www/$3\

홈디렉토리를 다른 웹서버로 이전

상황설명:

많은 웹관리자는 웹서버의 모든 홈디렉토리를 다른 웹서버로 이전한 경우 해결책을 물어본다. 이 방법은 이전 서버를 대체할 새로운 서버를 구성하는데 시간이 걸리는 경우에 필요하다.

해결책:

mod_rewrite를 사용하면 간단하다. 이전 웹서버는 모든 /~user/anypath URL을 http://newserver/~user/anypath로 리다이렉션하면 된다.

RewriteEngine on
RewriteRule   ^/~(.+)  http://newserver/~$1  [R,L]

홈디렉토리 구조 만들기

상황설명:

사용자가 수천명인 사이트는 보통 홈디렉토리 구조를 만든다. 즉, 예를 들어 이름이 사용자명의 첫번째 문자인 하위디렉토리에 홈디렉토리를 둔다. 그래서, /~foo/anypath는 /home/f/foo/.www/anypath이고, /~bar/anypath는 /home/b/bar/.www/anypath이다.

해결책:

물결표시가 있는 URL을 위와 같은 구조로 변환하기위해 다음 규칙을 사용한다.

RewriteEngine on
RewriteRule   ^/~(([a-z])[a-z0-9]+)(.*)  /home/$2/$1/.www$3

파일시스템 재구성

상황설명:

이 예는 실로 하드코어적이다: 디렉토리별 RewriteRules를 매우 많이 사용하여 자료 자체는 그대로 둔체로 웹에 자료를 자연스럽게 브라우징하도록 한다. 배경: 나는 1992년 부터 자유롭게 사용할 수 있는 유닉스 소프트웨어들을 net.sw에 모아두고 있었다. 이는 내가 컴퓨터과학을 공부하면서 여러해동안 여가시간에 시스템 관리자와 네트웍 관리자를 해왔기때문에 내 취미이자 일이다. 매주마다 새로 소프트웨어가 추가될 때마다 디렉토리를 깊게 만들어왔다:

drwxrwxr-x   2 netsw  users    512 Aug  3 18:39 Audio/
drwxrwxr-x   2 netsw  users    512 Jul  9 14:37 Benchmark/
drwxrwxr-x  12 netsw  users    512 Jul  9 00:34 Crypto/
drwxrwxr-x   5 netsw  users    512 Jul  9 00:41 Database/
drwxrwxr-x   4 netsw  users    512 Jul 30 19:25 Dicts/
drwxrwxr-x  10 netsw  users    512 Jul  9 01:54 Graphic/
drwxrwxr-x   5 netsw  users    512 Jul  9 01:58 Hackers/
drwxrwxr-x   8 netsw  users    512 Jul  9 03:19 InfoSys/
drwxrwxr-x   3 netsw  users    512 Jul  9 03:21 Math/
drwxrwxr-x   3 netsw  users    512 Jul  9 03:24 Misc/
drwxrwxr-x   9 netsw  users    512 Aug  1 16:33 Network/
drwxrwxr-x   2 netsw  users    512 Jul  9 05:53 Office/
drwxrwxr-x   7 netsw  users    512 Jul  9 09:24 SoftEng/
drwxrwxr-x   7 netsw  users    512 Jul  9 12:17 System/
drwxrwxr-x  12 netsw  users    512 Aug  3 20:15 Typesetting/
drwxrwxr-x  10 netsw  users    512 Jul  9 14:08 X11/

1996년 7월 이 저장소를 멋있는 웹 인터페이스를 통해 세상에 공개하기로 결정햇다. "멋있다"는 말은, 최상위 디렉토리에 CGI 스크립트를 두지 않고도, 저장소 계층구조를 직접 브라우질하길 바란다는 뜻이다. 왜? 저장소를 나중에 FTP로도 접근할 수 있도록 만들 예정이였기때문에 웹이나 CGI와 관련된 내용을 같이 두기 싫었다.

해결책:

해결책은 두 부분으로 나뉜다: 먼저 디렉토리 수준에서 필요한 모든 페이지를 동적으로 만드는 CGI 스크립트가 필요하다. 나는 이 스크립트들을 다음과 같이 /e/netsw/.www/에 두었다:

-rw-r--r--   1 netsw  users    1318 Aug  1 18:10 .wwwacl
drwxr-xr-x  18 netsw  users     512 Aug  5 15:51 DATA/
-rw-rw-rw-   1 netsw  users  372982 Aug  5 16:35 LOGFILE
-rw-r--r--   1 netsw  users     659 Aug  4 09:27 TODO
-rw-r--r--   1 netsw  users    5697 Aug  1 18:01 netsw-about.html
-rwxr-xr-x   1 netsw  users     579 Aug  2 10:33 netsw-access.pl
-rwxr-xr-x   1 netsw  users    1532 Aug  1 17:35 netsw-changes.cgi
-rwxr-xr-x   1 netsw  users    2866 Aug  5 14:49 netsw-home.cgi
drwxr-xr-x   2 netsw  users     512 Jul  8 23:47 netsw-img/
-rwxr-xr-x   1 netsw  users   24050 Aug  5 15:49 netsw-lsdir.cgi
-rwxr-xr-x   1 netsw  users    1589 Aug  3 18:43 netsw-search.cgi
-rwxr-xr-x   1 netsw  users    1885 Aug  1 17:41 netsw-tree.cgi
-rw-r--r--   1 netsw  users     234 Jul 30 16:35 netsw-unlimit.lst

DATA/ 하위디렉토리에 위에서 말한 저장소가 있다. 실제 net.sw의 내용은 보통 rdist를 사용하여 자동으로 가져온다. 두번째 부분이 남았다: 어떻게 이 두 구조를 하나의 자연스러운 URL 구조로 연결하는가? 사용자에게 DATA/ 디렉토리를 감추고, URL마다 적절한 CGI 스크립트를 실행하고 싶다. 해결책은 다음과 같다: 먼저 서버의 DocumentRoot에서 공개된 URL /net.sw/를 내부 경로 /e/netsw로 재작성하기위해 디렉토리별 설정파일에 다음과 같이 설정한다:

RewriteRule  ^net.sw$       net.sw/        [R]
RewriteRule  ^net.sw/(.*)$  e/netsw/$1

첫번째 규칙은 마지막에 슬래쉬가 없는 요청을 위해서 사용했다! 두번째 규칙이 실제 작업을 한다. 그리고 디렉토리별 설정파일 /e/netsw/.www/.wwwacl에 결정적인 설정이 나온다:

Options       ExecCGI FollowSymLinks Includes MultiViews

RewriteEngine on

#  앞 부분이 /net.sw/ 로 접근한다
RewriteBase   /net.sw/

#  먼저 최상위 디렉토리를
#  cgi 스크립트로 재작성한다
RewriteRule   ^$                       netsw-home.cgi     [L]
RewriteRule   ^index\.html$            netsw-home.cgi     [L]

#  브라우저가 디렉토리별 페이지를 요청한 경우
#  하위디렉토리를 추출한다
RewriteRule   ^.+/(netsw-[^/]+/.+)$    $1                 [L]

#  이제 재작성을 마친다
RewriteRule   ^netsw-home\.cgi.*       -                  [L]
RewriteRule   ^netsw-changes\.cgi.*    -                  [L]
RewriteRule   ^netsw-search\.cgi.*     -                  [L]
RewriteRule   ^netsw-tree\.cgi$        -                  [L]
RewriteRule   ^netsw-about\.html$      -                  [L]
RewriteRule   ^netsw-img/.*$           -                  [L]

#  다른 cgi 스크립트가 처리할
#  하위디렉토리가 남았다
RewriteRule   !^netsw-lsdir\.cgi.*     -                  [C]
RewriteRule   (.*)                     netsw-lsdir.cgi/$1

해석을 위한 힌트:

  1. 네번째 부분에서 대체 필드('-')가 없고 L (last) 플래그가 있음을 주목하라
  2. 마지막 부분에서 첫번째 규칙에 ! (not) 문자와 C (chain) 플래그를 주목하라
  3. 마지막 규칙에서 기타 해당하지 않는 모든 경우를 잡아내는 패턴을 주목하라

NCSA imagemap을 아파치 mod_imap으로

상황설명:

사람들은 NCSA 웹서버에서 현대적인 아파치 웹서버로 자연스럽게 옮겨가길 바란다. 그래서 오래된 NCSA imagemap 프로그램을 사용한 페이지를 현대적인 아파치 mod_imap로 처리하길 바란다. 문제는 imagemap 프로그램을 /cgi-bin/imagemap/path/to/page.map과 같이 참조하는 하이퍼링크가 많다는 것이다. 아파치는 /path/to/page.map과 같은 요청을 받아야 한다.

해결책:

모든 요청에서 앞부분을 동적으로 제거하는 전역 규칙을 사용한다:

RewriteEngine  on
RewriteRule    ^/cgi-bin/imagemap(.*)  $1  [PT]

여러 디렉토리에서 페이지 검색

상황설명:

가끔 웹서버가 여러 디렉토리에서 파일을 찾아야 할 때가 있다. 이 경우 MultiViews나 다른 방법은 도움이 안된다.

해결책:

여러 디렉토리에서 파일을 찾는 규칙을 직접 프로그램한다.

RewriteEngine on

#   먼저 custom/에서 찾길 시도하고...
#   ...찾으면 끝!
RewriteCond         /your/docroot/dir1/%{REQUEST_FILENAME}  -f
RewriteRule  ^(.+)  /your/docroot/dir1/$1  [L]

#   두번째로 pub/에서 찾길 시도한다...
#   ...찾으면 끝!
RewriteCond         /your/docroot/dir2/%{REQUEST_FILENAME}  -f
RewriteRule  ^(.+)  /your/docroot/dir2/$1  [L]

#   못찾으면 다른 Alias나 ScriptAlias 지시어 등으로 진행한다.
RewriteRule   ^(.+)  -  [PT]

URL에 따라 환경변수를 설정한다

상황설명:

요청들간에 상태정보를 유지하기위해 URL에 정보를 인코딩하는 방법도 있다. 그러나 단지 이 정보를 제거하기위해 모든 페이지에 CGI wrapper를 사용하고 싶지 않다.

해결책:

재작성 규칙을 사용하여 상태정보를 추출하고, 추출한 정보를 나중에 XSSI나 CGI에서 사용하기위해 환경변수에 저장한다. 그래서 URL /foo/S=java/bar/는 /foo/bar/로 변환되고 STATUS라는 환경변수 값을 "java"로 설정한다.

RewriteEngine on
RewriteRule   ^(.*)/S=([^/]+)/(.*)    $1/$3 [E=STATUS:$2]

가상 사용자 호스트

상황설명:

가상호스트를 사용하지 않고 같은 컴퓨터로 DNS A 레코드를 설정하여 www.username.host.domain.com을 사용자의 홈페이지로 제공하고 싶다.

해결책:

HTTP/1.0 요청의 경우 방법이 없지만, Host: HTTP 헤더를 포함한 HTTP/1.1 요청은 다음 규칙을 사용하여 내부적으로 http://www.username.host.com/anypath를 /home/username/anypath로 재작성할 수 있다:

RewriteEngine on
RewriteCond   %{HTTP_HOST}                 ^www\.[^.]+\.host\.com$
RewriteRule   ^(.+)                        %{HTTP_HOST}$1          [C]
RewriteRule   ^www\.([^.]+)\.host\.com(.*) /home/$1$2

홈디렉토리를 외부 서버로 리다이렉션

상황설명:

지역 도메인 ourdomain.com 밖에서 요청이 들어오면 홈디렉토리 URL을 다른 웹서버 www.somewhere.com으로 리다리렉션하길 바란다. 종종 가상호스트 사용장소에서 사용한다.

해결책:

재작성 조건을 사용하면 된다:

RewriteEngine on
RewriteCond   %{REMOTE_HOST}  !^.+\.ourdomain\.com$
RewriteRule   ^(/~.+)         http://www.somewhere.com/$1 [R,L]

실패한 URL을 다른 웹서버로 리다이렉션

상황설명:

URL 재작성에 대해서 웹서버 A에 해당 파일이 없는 경우 웹서버 B로 요청을 리다이렉션하는 방법을 자주 물어본다. 보통 Perl로 작성한 ErrorDocument CGI 스크립트를 사용하지만, mod_rewrite를 사용하는 방법도 있다. 그러나 성능은 ErrorDocument CGI 스크립트보다 떨어짐을 명심하라!

해결책:

첫번째 방법은 빠르지만 유연성이 떨어지고 완전하지 않다:

RewriteEngine on
RewriteCond   /your/docroot/%{REQUEST_FILENAME} !-f
RewriteRule   ^(.+)                             http://webserverB.dom/$1

이 방법의 단점은 DocumentRoot 안에 있는 페이지만 가능하다는 점이다. (예를 들어 홈디렉토리 등을 위해) 조건을 추가할 수 있지만, 더 좋은 방법이 있다:

RewriteEngine on
RewriteCond   %{REQUEST_URI} !-U
RewriteRule   ^(.+)          http://webserverB.dom/$1

mod_rewrite의 URL 전방참조(look-ahead)를 사용한다. 그래서 모든 URL에 동작하고 안전하다. 그러나 모든 요청마다 내부 하위요청을 한번 더 하기때문에 웹서버 성능에 악영향을 준다. 그래서 강력한 CPU에서 웹서버를 실행한다면 사용하라. 컴퓨터가 느리다면 첫번째 방법이나 더 나은 ErrorDocument CGI 스크립트를 사용하라.

확장 리다이렉션

상황설명:

가끔 리다이렉션하는 URL을 더 조절할 필요가 있다. 아파치 내부 URL escape 함수는 "url#anchor" 같은 URL의 anchor도 escape한다. 아파치의 uri_escape() 함수는 우물정자(#)도 같이 escape하므로 사용할 수 없다. 그러면 어떻게 이런 URL로 리다이렉션할 수 있나?

해결책:

직접 리다이렉션하는 NPH-CGI 스크립트를 사용한 해결책이 필요하다. escape를 하지 않기때문이다 (NPH=non-parseable headers). 먼저 다음 서버설정을 하여 (재작성 규칙의 끝부분에 사용해야 한다) 새로운 URL scheme xredirect:를 도입한다:

RewriteRule ^xredirect:(.+) /path/to/nph-xredirect.cgi/$1 \
            [T=application/x-httpd-cgi,L]

그러면 xredirect:로 시작하는 모든 URL은 nph-xredirect.cgi 프로그램을 통하게 된다. 프로그램은 다음과 같다:

#!/path/to/perl
##
##  nph-xredirect.cgi -- NPH/CGI script for extended redirects
##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
##

$| = 1;
$url = $ENV{'PATH_INFO'};

print "HTTP/1.0 302 Moved Temporarily\n";
print "Server: $ENV{'SERVER_SOFTWARE'}\n";
print "Location: $url\n";
print "Content-type: text/html\n";
print "\n";
print "<html>\n";
print "<head>\n";
print "<title>302 Moved Temporarily (EXTENDED)</title>\n";
print "</head>\n";
print "<body>\n";
print "<h1>Moved Temporarily (EXTENDED)</h1>\n";
print "The document has moved <a HREF=\"$url\">here</a>.<p>\n";
print "</body>\n";
print "</html>\n";

##EOF##

그러면 mod_rewrite가 직접 받지못하는 모든 URL scheme으로 리다이렉션할 수 있다. 예를 들어, 다음과 같이 news:newsgroup으로 리다이렉션할 수 있다

RewriteRule ^anyurl  xredirect:news:newsgroup
주의: 위의 특별한 "통과" 규칙을 사용하여 xredirect:를 마지막에 확장해야 하기때문에 규칙에 [R]이나 [R,L]을 사용하면 안된다.

저장소 접근 중계(multiplexer)

상황설명:

http://www.perl.com/CPAN에 있는 대단한 CPAN (Comprehensive Perl Archive Network)을 아는가? 이 주소는 세계에 흩어진 여러 CPAN 미러 FTP 서버중 클라이언트에 가까이 있는 서버로 리다이렉션한다. 이를 FTP 접근 중계 서비스라고 한다. CPAN은 CGI 스크립트를 사용하지만, mod_rewrite를 사용하여 비슷하게 만들 수 있을까?

해결책:

먼저 mod_rewrite 3.0.0 버전부터 리다이렉션에 "ftp:" scheme을 사용할 수 있다. 다음으로 클라이언트의 최상위 도메인을 RewriteMap과 같이 사용하여 위치를 추정할 수 있다. 복잡히 엮인 규칙에서 최상위 도메인을 중계맵의 키로 사용한다.

RewriteEngine on
RewriteMap    multiplex                txt:/path/to/map.cxan
RewriteRule   ^/CxAN/(.*)              %{REMOTE_HOST}::$1                 [C]
RewriteRule   ^.+\.([a-zA-Z]+)::(.*)$  ${multiplex:$1|ftp.default.dom}$2  [R,L]

##
##  map.cxan -- Multiplexing Map for CxAN
##

de        ftp://ftp.cxan.de/CxAN/
uk        ftp://ftp.cxan.uk/CxAN/
com       ftp://ftp.cxan.com/CxAN/
 :
##EOF##

시간에 따른 재작성

상황설명:

시간에 따라 다른 내용을 서비스하는 경우 많은 웹관리자는 잠시 특별한 페이지로 리다이렉션하기위해 CGI 스크립트를 사용한다. mod_rewrite로는 어떻게 할 수 있는가?

해결책:

재작성 조건에서 사용할 수 있는 여러 TIME_xxx 변수가 있다. 변수와 특별한 사전순서 비교 <STRING, >STRING, =STRING을 사용하여 시간에 따라 리다이렉션할 수 있다:

RewriteEngine on
RewriteCond   %{TIME_HOUR}%{TIME_MIN} >0700
RewriteCond   %{TIME_HOUR}%{TIME_MIN} <1900
RewriteRule   ^foo\.html$             foo.day.html
RewriteRule   ^foo\.html$             foo.night.html

URL foo.html을 요청하면 07:00-19:00 동안 foo.day.html 내용을 서비스하고, 나머지 시간 동안 foo.night.html 내용을 서비스한다. 홈페이지에서 사용하기 좋은 기능이다...

YYYY를 XXXX로 이전한 경우 역호환

상황설명:

여러 .html 파일을 .phtml로 변환하는 등 document.YYYY를 document.XXXX로 이전한후 역호환(backward compatibility) URL을 (가상적으로 존재하게) 만들 수 있나?

해결책:

이름을 기본이름으로 재작성한후 새로운 확장자를 가진 파일이 있는지 검사한다. 있다면 그 파일명을 사용하고, 없으면 URL을 원래 상태로 재작성한다.

#   문서.html 이 없고
#   문서.phtml 만 있는 경우
#   문서.html 을 문서.phtml 로
#   재작성하는 역호환 규칙
RewriteEngine on
RewriteBase   /~quux/
#   기본이름을 찾고, 찾았다는 사실을 기억한다
RewriteRule   ^(.*)\.html$              $1      [C,E=WasHTML:yes]
#   파일이 있다면 문서.phtml 로 재작성한다
RewriteCond   %{REQUEST_FILENAME}.phtml -f
RewriteRule   ^(.*)$ $1.phtml                   [S=1]
#   아니면 앞에서 찾은 기본이름을 되돌린다
RewriteCond   %{ENV:WasHTML}            ^yes$
RewriteRule   ^(.*)$ $1.html

컨텐츠 다루기

새로 이전 (감추기)

상황설명:

최근 foo.html을 bar.html로 변경하고 역호환성을 위해 이전 URL을 계속 제공하고 싶다고 가정하자. 사용자는 이전 URL이 변경되었다는 사실을 눈치채지 못한다.

해결책:

다음 규칙으로 이전 URL을 내부적으로 새로운 URL로 재작성한다:

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo\.html$  bar.html

새로 이전 (알리기)

상황설명:

다시 foo.html을 bar.html로 변경하고 역호환성을 위해 이전 URL을 계속 제공하고 싶다고 가정하자. 그러나 이제는 이전 URL을 사용하면 사용자에게 새로운 URL을 힌트로 알려준다. 즉, 브라우저 주소창이 변한다.

해결책:

새로운 URL로 HTTP 리다이렉션하다. 그러면 브라우저가 새로운 URL를 보이고 변경사실을 사용자가 알게된다:

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo\.html$  bar.html  [R]

브라우저에 따른 내용

상황설명:

최소한 중요한 최상위 페이지는 브라우저에 최적화된 내용으로 서비스해야할 경우가 있다. 즉, 최신 Netscape 브라우저에게는 최상의 버전을, Lynx 브라우저에게는 최저 버전을, 나머지 브라우저에는 평균적인 버전을 제공한다.

해결책:

브라우저가 내용협상을 위해 자신의 종류에 대한 정보를 제공하지 않기때문에 내용협상을 사용할 수 없다. 대신 HTTP "User-Agent" 헤더를 사용한다. 다음 규칙은 HTTP "User-Agent" 헤더가 "Mozilla/3"으로 시작하면 foo.html 페이지를 foo.NS.html로 재작성하고 재작성을 중단한다. 브라우저가 "Lynx"나 "Mozilla" 버전 1 혹은 2라면 URL은 foo.20.html이 된다. 나머지 브라우저는 foo.32.html 페이지를 받는다. 아래 규칙이 이 작업을 한다:

RewriteCond %{HTTP_USER_AGENT}  ^Mozilla/3.*
RewriteRule ^foo\.html$         foo.NS.html          [L]

RewriteCond %{HTTP_USER_AGENT}  ^Lynx/.*         [OR]
RewriteCond %{HTTP_USER_AGENT}  ^Mozilla/[12].*
RewriteRule ^foo\.html$         foo.20.html          [L]

RewriteRule ^foo\.html$         foo.32.html          [L]

동적 미러

상황설명:

외부 호스트에 우리 사이트로 가져오고 싶은 좋은 웹페이지가 있다고 가정하자. FTP 서버의 경우 직접 외부 자료의 최신복사본을 유지하는 mirror 프로그램을 사용할 수 있고, 웹서버라면 HTTP로 비슷한 작업을 하는 webcopy 프로그램을 사용할 수 있다. 그러나 두 방법 모두 단점이 있다: 복사본은 가끔씩 프로그램을 실행해줄 때만 최신판으로 유지된다. 직접 구성해야하는 정적인 미러가 아니라면 좋겠다. 대신 (외부 호스트에서 자료가 갱신되면) 필요할때 자동으로 자료를 갱신하는 동적 미러가 필요하다.

해결책:

이를 위해 Proxy Throughput 기능을 (플래그 [P]) 사용하여 외부 웹페이지 혹은 외부 웹공간 전체를 우리 이름공간으로 대응한다:

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^hotsheet/(.*)$  http://www.tstimpreso.com/hotsheet/$1  [P]

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^usa-news\.html$   http://www.quux-corp.com/news/index.html  [P]

동적 역미러

상황설명:
...
해결책:
RewriteEngine on
RewriteCond   /mirror/of/remotesite/$1           -U
RewriteRule   ^http://www\.remotesite\.com/(.*)$ /mirror/of/remotesite/$1

없는 자료를 인트라넷에서 가져오기

상황설명:

실제 자료를 방화벽이 보호하는 (내부) 인트라넷 웹서버에 (www2.quux-corp.dom) 저장하면서, 기업의 (외부) 인터넷 웹서버를 (www.quux-corp.dom) 실행하는 것처럼 보이게 한다. 외부 웹서버는 요청한 자료를 내부 웹서버에서 가져온다.

해결책:

먼저 방화벽이 내부 웹서버를 보호하고 외부 웹서버만이 내부 웹서버에서 자료를 얻을 수 있게 한다. 다음과 같이 패킷필터링 방화벽을 설정한다:

ALLOW Host www.quux-corp.dom Port >1024 --> Host www2.quux-corp.dom Port 80
DENY  Host *                 Port *     --> Host www2.quux-corp.dom Port 80

실제 설정문법에 알맞게 고쳐라. 없는 자료를 내부적으로 proxy throughput 기능을 통해 요청하는 mod_rewrite 규칙을 작성한다:

RewriteRule ^/~([^/]+)/?(.*)          /home/$1/.www/$2
RewriteCond %{REQUEST_FILENAME}       !-f
RewriteCond %{REQUEST_FILENAME}       !-d
RewriteRule ^/home/([^/]+)/.www/?(.*) http://www2.quux-corp.dom/~$1/pub/$2 [P]

로드밸런싱 (부하 분산하기)

상황설명:

www.foo.com의 통신량을 www[0-5].foo.com (총 서버 6대)으로 분산하고 싶다. 어떻게 하는가?

해결책:

매우 다양한 방법으로 이 문제를 해결할 수 있다. 먼저 DNS를 사용한 잘 알려진 방법을 설명하고, mod_rewrite를 사용하는 경우를 살펴보자:

  1. DNS Round-Robin

    가장 간단한 로드밸런싱 방법은 BIND의 DNS round-robin 방식을 사용하는 것이다. 다음과 같이 DNS A(address) 레코드에 www[0-9].foo.com을 설정한다.

    www0   IN  A       1.2.3.1
www1   IN  A       1.2.3.2
www2   IN  A       1.2.3.3
www3   IN  A       1.2.3.4
www4   IN  A       1.2.3.5
www5   IN  A       1.2.3.6

    그리고 다음 항목을 추가한다:

    www    IN  CNAME   www0.foo.com.
       IN  CNAME   www1.foo.com.
       IN  CNAME   www2.foo.com.
       IN  CNAME   www3.foo.com.
       IN  CNAME   www4.foo.com.
       IN  CNAME   www5.foo.com.
       IN  CNAME   www6.foo.com.

    잘못된 것처럼 보이지만, 실제로 BIND의 의도된 기능이다. 이제 www.foo.com을 찾으면, BIND는 매번 순서를 조금씩 바꿔가며 www0-www6을 반환한다. 그래서 클라이언트들을 여러 서버로 분산한다. 그러나 DNS 검색 결과가 네트웍의 다른 네임서버에 캐쉬되여 www.foo.com을 찾은 결과가 특정 wwwN.foo.com이면 클라이언트의 다음 요청들도 같은 wwwN.foo.com으로 보내지기때문에 완벽한 로드밸런싱 기법이 아님을 주의하라. 그러나 크게 보면 요청이 여러 웹서버에 분산되므로 효과가 좋다.

  2. DNS 로드밸런싱

    http://www.stanford.edu/~schemers/docs/lbnamed/lbnamed.html에 있는 lbnamed 프로그램을 사용하여 정교한 DNS기반 로드밸런싱을 할 수 있다. DNS가 실제 로드밸런싱을 하도록 만드는 여러 도구와 Perl 5 프로그램이다.

  3. Proxy Throughput Round-Robin

    이 방법은 mod_rewrite와 proxy throughput 기능을 사용한다. 먼저 DNS에 다음 항목을 사용하여 www0.foo.com이 실제 www.foo.com을 전담하게 한다

    www    IN  CNAME   www0.foo.com.

    그리고 www0.foo.com을 프록시전용 서버로 변경한다. 즉, URL을 받으면 서버는 내부 프록시를 통해 다른 5대 서버중 (www1-www5) 한대로 보내기만 한다. 이를 위해 먼저 모든 URL을 로드밸런싱 스크립트 lb.pl로 보내는 규칙을 만든다.

    RewriteEngine on
RewriteMap    lb      prg:/path/to/lb.pl
RewriteRule   ^/(.+)$ ${lb:$1}           [P,L]

    lb.pl을 작성한다:

    #!/path/to/perl
##
##  lb.pl -- 로드밸런싱 스크립트
##

$| = 1;

$name   = "www";     # 기본 호스트명
$first  = 1;         # 첫번째 서버 (자신이 0이기 때문에, 0을 사용하지 않는다)
$last   = 5;         # round-robin에서 마지막 서버
$domain = "foo.dom"; # 도메인명

$cnt = 0;
while (<STDIN>) {
    $cnt = (($cnt+1) % ($last+1-$first));
    $server = sprintf("%s%d.%s", $name, $cnt+$first, $domain);
    print "http://$server/$_";
}

##EOF##
    마지막 주의: 왜 이 방법이 유용한가? www0.foo.com에 부담이 가지않는가? 물론, 부담이 된다. 그러나 단순한 proxy throughput 요청만 하기때문에 괜찮다! 모든 SSI, CGI, ePerl 등은 전적으로 다른 서버가 처리한다. 이것이 핵심이다.
  4. 하드웨어/TCP Round-Robin

    하드웨어를 사용한 해결책도 있다. Cisco는 TCP/IP 수준에서 로드밸런싱을 하는 LocalDirector라는 괴물을 판다. 실제로는 웹서버군 앞단에 위치하는 일종의 회로수준 게이트웨이다. 자금이 충분하고 고성능 해결책이 필요하다면 이것을 사용하라.

새로운 MIME-type, 새로운 서비스

상황설명:

네트웍에는 멋진 CGI 프로그램들이 많다. 그러나 사용하기 번거러워서 많은 웹관리자가 사용하지 않는다. 아파치의 MIME-type에 따른 Action 핸들러 기능도 CGI 프로그램이 특별한 URL을 (정확히 PATH_INFO와 QUERY_STRINGS) 프로그램의 입력으로 사용하지 않을 때만 적절하다. 먼저, 확장자가 (secure CGI를 줄여) .scgi인 파일을 유명한 cgiwrap 프로그램으로 처리하기위해 새로운 type을 설정한다. 문제는 (위에서 본) 일관된 URL 구조를 사용하는 경우 사용자 홈디렉토리가 /u/user/foo/bar.scgi같은 URL인 점이다. cgiwrap는 /~user/foo/bar.scgi/ 형식의 URL을 원하기때문이다. 다음 규칙이 문제를 해결한다:

RewriteRule ^/[uge]/([^/]+)/\.www/(.+)\.scgi(.*) ...
... /internal/cgi/user/cgiwrap/~$1/$2.scgi$3  [NS,T=application/x-http-cgi]

이제 다른 멋진 프로그램, (URL 하위트리에 대한 access.log를 출력하는) wwwlog와 (URL 하위트리에 Glimpse를 실행하는) wwwidx가 있다고 가정하자. 우리는 프로그램에게 작업할 대상인 URL 영역을 알려줘야 한다. 그러나 요청할때마다 항상 적어줘야 하기때문에 깔끔하지 않다. 즉, 보통 /u/user/foo/에 대해 swwidx 프로그램을 실행한다면 다음과 같은 링크를 사용한다

/internal/cgi/user/swwidx?i=/u/user/foo/

깔끔하지 않다. 링크에 영역의 위치와 CGI 위치를 모두 적어야 하기때문이다. 영역을 재구성한다면 여러 하이퍼링크를 수정하는데 많은 시간이 걸릴 것이다.

해결책:

해결책은 자동으로 적절한 CGI를 실행하는 새로운 특별한 URL 형식을 만드는 것이다. 다음과 같이 설정한다:

RewriteRule   ^/([uge])/([^/]+)(/?.*)/\*  /internal/cgi/user/wwwidx?i=/$1/$2$3/
RewriteRule   ^/([uge])/([^/]+)(/?.*):log /internal/cgi/user/wwwlog?f=/$1/$2$3

이제 /u/user/foo/을 검색하는 링크는 다음과 같다

HREF="*"
/u/user/foo/* (???)

내부적으로 다음과 같이 자동변환된다

/internal/cgi/user/wwwidx?i=/u/user/foo/

같은 방법으로 링크 뒤에 :log를 사용하여 접근 로그 CGI 프로그램을 실행할 수 있다.

정적에서 동적으로

상황설명:

어떻게 브라우저와 사용자가 모르게 자연스럽게 정적 페이지 foo.html을 동적인 foo.cgi로 변경할 수 있나.

해결책:

URL을 CGI 스크립트로 재작성하고, MIME-type을 수정하여 CGI 스크립트로 실행하게 한다. 그래서 /~quux/foo.html를 요청하면 내부적으로 /~quux/foo.cgi를 실행하게 된다.

RewriteEngine  on
RewriteBase    /~quux/
RewriteRule    ^foo\.html$  foo.cgi  [T=application/x-httpd-cgi]

즉석 컨텐츠 재생성

상황설명:

이 방법은 실로 비기이다: 동적으로 페이지를 생성하지만, 정적으로 페이지를 서비스한다. 즉, 페이지는 순수하게 (파일시스템에서 읽은 내용을 그대로) 정적 페이지로 전달되지만, 없을 경우 웹서버가 동적으로 생성한다. 그러면 누가 (혹은 cron 작업이) 정적 컨텐츠를 지우지않는 한 CGI가 생성한 페이지를 정적으로 서비스한다. 컨텐츠를 지우면 내용을 갱신한다.

해결책:
다음 규칙을 사용한다:
RewriteCond %{REQUEST_FILENAME}   !-s
RewriteRule ^page\.html$          page.cgi   [T=application/x-httpd-cgi,L]

여기서 page.html를 요청할때 page.html이 없거나 파일크기가 0인 경우 내부적으로 page.cgi를 실행한다. 여기서 비결은 page.cgi가 일반적인 CGI 스크립트와 같이 STDOUT에 출력하고, 추가로 출력을 page.html 파일에 적는다. 한번 실행한후 서버는 page.html의 정보를 보낸다. 웹관리자가 강재로 내용을 갱신하고 싶다면, (보통 cron 작업이) page.html을 지우기만 하면 된다.

자동으로 새로 고침하는 문서

상황설명:

복잡한 웹페이지를 만들때 편집자가 내용을 수정할 때마다 자동으로 페이지를 새로 고침하는 웹브라우저가 있으면 얼마나 좋을까? 불가능한가?

해결책:

가능하다! MIME multipart 기능과 웹서버 NPH 기능, mod_rewrite의 URL 조작 능력을 결합하면 된다. 먼저, 새로운 URL 기능을 만든다: URL에 :refresh를 추가하기만 하면 파일시스템에서 수정될 때마다 새로 고침한다.

RewriteRule   ^(/[uge]/[^/]+/?.*):refresh  /internal/cgi/apache/nph-refresh?f=$1

이제 다음 URL에 접근하면

/u/foo/bar/page.html:refresh

다음 URL을 내부적으로 부른다

/internal/cgi/apache/nph-refresh?f=/u/foo/bar/page.html

이제 NPH-CGI 스크립트만 남았다. 보통 "독자에게 연습으로 남겨둠"이라고 말하지만 ;-) 나는 이것도 제공한다.

#!/sw/bin/perl
##
##  nph-refresh -- NPH/CGI script for auto refreshing pages
##  Copyright (c) 1997 Ralf S. Engelschall, All Rights Reserved.
##
$| = 1;

#   split the QUERY_STRING variable
@pairs = split(/&/, $ENV{'QUERY_STRING'});
foreach $pair (@pairs) {
    ($name, $value) = split(/=/, $pair);
    $name =~ tr/A-Z/a-z/;
    $name = 'QS_' . $name;
    $value =~ s/%([a-fA-F0-9][a-fA-F0-9])/pack("C", hex($1))/eg;
    eval "\$$name = \"$value\"";
}
$QS_s = 1 if ($QS_s eq '');
$QS_n = 3600 if ($QS_n eq '');
if ($QS_f eq '') {
    print "HTTP/1.0 200 OK\n";
    print "Content-type: text/html\n\n";
    print "&lt;b&gt;ERROR&lt;/b&gt;: No file given\n";
    exit(0);
}
if (! -f $QS_f) {
    print "HTTP/1.0 200 OK\n";
    print "Content-type: text/html\n\n";
    print "&lt;b&gt;ERROR&lt;/b&gt;: File $QS_f not found\n";
    exit(0);
}

sub print_http_headers_multipart_begin {
    print "HTTP/1.0 200 OK\n";
    $bound = "ThisRandomString12345";
    print "Content-type: multipart/x-mixed-replace;boundary=$bound\n";
    &print_http_headers_multipart_next;
}

sub print_http_headers_multipart_next {
    print "\n--$bound\n";
}

sub print_http_headers_multipart_end {
    print "\n--$bound--\n";
}

sub displayhtml {
    local($buffer) = @_;
    $len = length($buffer);
    print "Content-type: text/html\n";
    print "Content-length: $len\n\n";
    print $buffer;
}

sub readfile {
    local($file) = @_;
    local(*FP, $size, $buffer, $bytes);
    ($x, $x, $x, $x, $x, $x, $x, $size) = stat($file);
    $size = sprintf("%d", $size);
    open(FP, "&lt;$file");
    $bytes = sysread(FP, $buffer, $size);
    close(FP);
    return $buffer;
}

$buffer = &readfile($QS_f);
&print_http_headers_multipart_begin;
&displayhtml($buffer);

sub mystat {
    local($file) = $_[0];
    local($time);

    ($x, $x, $x, $x, $x, $x, $x, $x, $x, $mtime) = stat($file);
    return $mtime;
}

$mtimeL = &mystat($QS_f);
$mtime = $mtime;
for ($n = 0; $n &lt; $QS_n; $n++) {
    while (1) {
        $mtime = &mystat($QS_f);
        if ($mtime ne $mtimeL) {
            $mtimeL = $mtime;
            sleep(2);
            $buffer = &readfile($QS_f);
            &print_http_headers_multipart_next;
            &displayhtml($buffer);
            sleep(5);
            $mtimeL = &mystat($QS_f);
            last;
        }
        sleep($QS_s);
    }
}

&print_http_headers_multipart_end;

exit(0);

##EOF##

대량의 가상호스트

상황설명:

가상호스트가 몇개만 있다면 아파치의 <VirtualHost> 기능이 잘 동작한다. 그러나 가상호스트가 수백개 있는 ISP라면 이 기능이 최선은 아니다.

해결책:

이 기능을 제공하려면 Proxy Throughput 기능을 (플래그 [P]) 사용하여 외부 웹페이지 혹은 전체 외부 웹영역을 우리의 이름공간에 대응한다:

##
##  vhost.map
##
www.vhost1.dom:80  /path/to/docroot/vhost1
www.vhost2.dom:80  /path/to/docroot/vhost2
     :
www.vhostN.dom:80  /path/to/docroot/vhostN

##
##  httpd.conf
##
    :
#   리다이렉트할때 정규 호스트명을 사용한다.
UseCanonicalName on

    :
#   가상호스트를 CLF 형식 앞에 추가한다
CustomLog  /path/to/access_log  "%{VHOST}e %h %l %u %t \"%r\" %>s %b"
    :

#   주서버에서 재작성 엔진을 사용한다
RewriteEngine on

#   두 맵을 정의한다: 하나는 URL을 고치고,
#   다른 하나는 가상호스트별 DocumentRoot를
#   정의한다.
RewriteMap    lowercase    int:tolower
RewriteMap    vhost        txt:/path/to/vhost.map

#   이제 크고 복잡한 규칙 한개를 사용하여
#   가상호스트로 대응한다.
#
#   1. 가상호스트들이 같이 사용하는 위치는 대응하지 않는다
RewriteCond   %{REQUEST_URI}  !^/commonurl1/.*
RewriteCond   %{REQUEST_URI}  !^/commonurl2/.*
    :
RewriteCond   %{REQUEST_URI}  !^/commonurlN/.*
#
#   2. 우리가 현재 사용하는 방법이 Host 헤더를
#      가상호스트를 지원하므로
#      Host 헤더가 있는지 확인한다
RewriteCond   %{HTTP_HOST}  !^$
#
#   3. 호스트명을 소문자로 만든다
RewriteCond   ${lowercase:%{HTTP_HOST}|NONE}  ^(.+)$
#
#   4. vhost.map에서 호스트명을 찾고
#      경로일때만 기억한다
#      (위에서 "NONE"은 아니다)
RewriteCond   ${vhost:%1}  ^(/.*)$
#
#   5. 마지막으로 URL을 문서 위치로 대응하고
#      로그에 남기기위해 가상호스트를 기억해 둔다
RewriteRule   ^/(.*)$   %1/$1  [E=VHOST:${lowercase:%{HTTP_HOST}}]
    :

접근 제한

로봇 막기

상황설명:

어떻게 하면 특정 웹공간의 페이지를 긁어모으는 귀찮은 로봇을 막을 수 있나? "Robot Exclusion Protocol" 항목을 저장한 /robots.txt 파일은 보통 이런 로봇을 막는데 충분하지 않다.

해결책:

(아마도 디렉토리가 깊어서 로봇이 돌아다니면 서버에 부담이 큰 경우) 웹공간 /~quux/foo/arc/에 있는 URL들을 거부하는 규칙을 사용한다. 우리는 특정 로봇의 접근을 막아야 한다. 즉, 로봇을 실행하는 호스트를 막는 것으로는 불충분하며, 그 호스트의 사용자도 막아버리게 된다. User-Agent HTTP 헤더 정보도 비교한다.

RewriteCond %{HTTP_USER_AGENT}   ^NameOfBadRobot.*
RewriteCond %{REMOTE_ADDR}       ^123\.45\.67\.[8-9]$
RewriteRule ^/~quux/foo/arc/.+   -   [F]

그림 퍼가기 방지

상황설명:

http://www.quux-corp.de/~quux/에 있는 페이지들이 GIF 그림을 포함한다고 가정하자. 이 그림이 멋있어서, 다른 사람들이 자신의 페이지에 직접 링크를 건다. 서버에 불필요한 부담이 되므로 막고 싶다.

해결책:

그림을 100% 보호할 수는 없지만, 최소한 브라우저가 HTTP Referer 헤더를 보내는 경우 제한할 수 있다.

RewriteCond %{HTTP_REFERER} !^$
RewriteCond %{HTTP_REFERER} !^http://www.quux-corp.de/~quux/.*$ [NC]
RewriteRule .*\.gif$        -                                    [F]

RewriteCond %{HTTP_REFERER}         !^$
RewriteCond %{HTTP_REFERER}         !.*/foo-with-gif\.html$
RewriteRule ^inlined-in-foo\.gif$   -                        [F]

호스트 거부

상황설명:

어떻게 외부에서 서버에 접근할 수 없는 호스트 목록을 설정할 수 있나?

해결책:

아파치 >= 1.3b6에서:

RewriteEngine on
RewriteMap    hosts-deny  txt:/path/to/hosts.deny
RewriteCond   ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND} !=NOT-FOUND [OR]
RewriteCond   ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND} !=NOT-FOUND
RewriteRule   ^/.*  -  [F]

아파치 <= 1.3b6에서:

RewriteEngine on
RewriteMap    hosts-deny  txt:/path/to/hosts.deny
RewriteRule   ^/(.*)$ ${hosts-deny:%{REMOTE_HOST}|NOT-FOUND}/$1
RewriteRule   !^NOT-FOUND/.* - [F]
RewriteRule   ^NOT-FOUND/(.*)$ ${hosts-deny:%{REMOTE_ADDR}|NOT-FOUND}/$1
RewriteRule   !^NOT-FOUND/.* - [F]
RewriteRule   ^NOT-FOUND/(.*)$ /$1

##
##  hosts.deny
##
##  주의! 이것은 목록처럼 보이지만 목록이 아니라 맵이다.
##        mod_rewrite는 이 정보를 키/값 쌍으로 해석하기때문에,
##        각 항목의 값 자리에 최소한 "-"가 필요하다.
##

193.102.180.41 -
bsdti1.sdm.de  -
192.76.162.40  -

프록시 거부

상황설명:

어떻게 특정 호스트 혹은 특정 호스트의 사용자가 아파치 프록시를 사용할 수 없도록 하나?

해결책:

먼저 아파치 웹서버를 컴파일할때 구성파일에서 mod_rewrite가 mod_proxy 아래에(!) 있어야 한다. 그러면 mod_rewrite는 mod_proxy 이전에 불린다. 이제 다음과 같이 특정 호스트를 거부하도록 설정한다...

RewriteCond %{REMOTE_HOST} ^badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]

...그리고 다음은 user@host에 따라 거부한다:

RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST}  ^badguy@badhost\.mydomain\.com$
RewriteRule !^http://[^/.]\.mydomain.com.*  - [F]

특별한 인증 방식

상활설명:

가끔 매우 특별한 인증이 필요할 때가 있다. 예를 들어, 미리 설정해둔 사용자인지 검사한다. 이들에게만 (mod_auth의 Basic Auth를 사용한 경우와 달리) 별다른 물음없이 접근을 허용한다.

해결책:

친구만 접근이 가능하도록 재작성 규칙들을 사용한다:

RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend1@client1.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend2@client2.quux-corp\.com$
RewriteCond %{REMOTE_IDENT}@%{REMOTE_HOST} !^friend3@client3.quux-corp\.com$
RewriteRule ^/~quux/only-for-friends/      -                                 [F]

Referer기반 변환기(deflector)

상황설명:

"Referer" HTTP 헤더에 따라 원하는대로 참조페이지를 설정할 수 있는 유연한 URL 변환기를 만들 수 있는가?

해결책:

다음과 같이 복잡한 규칙을...

RewriteMap  deflector txt:/path/to/deflector.map

RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}} ^-$
RewriteRule ^.* %{HTTP_REFERER} [R,L]

RewriteCond %{HTTP_REFERER} !=""
RewriteCond ${deflector:%{HTTP_REFERER}|NOT-FOUND} !=NOT-FOUND
RewriteRule ^.* ${deflector:%{HTTP_REFERER}} [R,L]

... 재작성 맵과 같이 사용한다:

##
##  deflector.map
##

http://www.badguys.com/bad/index.html    -
http://www.badguys.com/bad/index2.html   -
http://www.badguys.com/bad/index3.html   http://somewhere.com/

그러면 요청을 자동으로 (맵에서 값으로 "-"를 사용한 경우) 참조페이지나 (URL이 맵에 있는 경우 두번째 아규먼트로) 특정 URL로 리다이렉션한다.

기타

외부 재작성 엔진

상황설명:

FAQ: 어떻게 이런저런 잡다한 문제를 풀 수 있는가? mod_rewrite로는 해결책이 안보인다...

해결책:

외부 RewriteMap을 사용하라. 즉, 프로그램이 RewriteMap 역할을 한다. 프로그램은 아파치가 시작할때 시작하여 STDIN에서 요청한 URL을 받고, (같은 순서로!) 결과 (보통 재작성된) URL을 STDOUT에 출력한다.

RewriteEngine on
RewriteMap    quux-map       prg:/path/to/map.quux.pl
RewriteRule   ^/~quux/(.*)$  /~quux/${quux-map:$1}

#!/path/to/perl

#   아파치 서버가 멈추지 않도록
#   입출력 버퍼를 사용하지 않는다
$| = 1;

#   stdin에서 한줄씩 URL을 읽고
#   stdout에 변환한 URL을 출력한다
while (<>) {
    s|^foo/|bar/|;
    print $_;
}

설명하기위해 모든 /~quux/foo/... URL을 /~quux/bar/...로 재작성하는 스크립트를 예로 들었다. 실제로 마음대로 프로그래밍할 수 있다. 그러나 일반 사용자가 이런 맵을 사용할 수 있다고 하더라고, 오직 시스템 관리자만이 맵을 정의해야 함을 주의하라.


아파치 가상호스트 문서 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

아파치 가상호스트 문서

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

가상호스트 (Virtual Host)는 한 컴퓨터에서 여러 웹사이트를 (예를 들어, www.company1.com과 www.company2.com) 서비스함을 뜻한다. 가상호스트에는 각 웹사이트마다 다른 IP 주소를 사용하는 "IP기반 (IP-based)" 방식과 한 IP 주소당 여러 이름을 가지는 "이름기반 (name-based)" 방식이 있다. 여러 사이트들이 같은 서버에서 돌고있다는 사실을 웹사용자는 눈치채지 못한다.

아파치는 기본으로 IP기반 가상호스트를 지원한 초창기 서버들중 하나다. 아파치 버전 1.1 이상은 IP기반과 이름기반 가상호스트를 모두 지원한다. 이름기반 가상호스트를 호스트기반 (host-based) 또는 비IP 가상호스트 (non-IP virtual hosts)라고도 부른다.

다음은 아파치 버전 1.3 이상의 가상호스트 지원을 자세히 설명한 문서들이다.

참고

  • mod_vhost_alias
  • 이름기반 가상호스트
  • IP기반 가상호스트
  • 가상호스트 예
  • 파일기술자 한계
  • 대량의 가상호스트
  • 가상호스트 찾기에 대한 자세한 설명

가상호스트 지원

  • 이름기반 가상호스트 (IP 주소당 여러 웹사이트)
  • IP기반 가상호스트 (각 웹사이트마다 IP 주소)
  • 일반적인 가상호스트 예
  • 파일기술자(file descriptor) 한계 (즉, 너무 많은 로그파일)
  • 대량의 가상호스트를 동적으로 설정하기
  • 가상호스트 찾기에 대한 자세한 설명

설정 지시어

  • <VirtualHost>
  • NameVirtualHost
  • ServerName
  • ServerAlias
  • ServerPath

가상호스트 설정을 테스트할때 아파치의 -S 명령행 옵션이 유용하다. 즉, 다음과 같이 실행한다:

/usr/local/apache2/bin/httpd -S

이 명령어는 아파치가 읽은 설정파일에 대한 정보를 출력한다. IP 주소와 서버명을 자세히 살펴보면 설정에서 실수를 발견하는데 도움이 될 것이다. (다른 명령행 옵션들은 httpd 프로그램 문서를 참고하라.)


이름기반 가상호스트 지원 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 가상호스트

이름기반 가상호스트 지원

이 문서는 이름기반 가상호스트를 사용하는 경우와 방법을 설명한다.

참고

  • IP기반 가상호스트 지원
  • 가상호스트 찾기에 대한 자세한 설명
  • 대량의 가상호스트를 동적으로 설정하기
  • 일반적인 가상호스트 예
  • ServerPath 설정 예

이름기반 대 IP기반 가상호스트

IP기반 가상호스트는 연결한 IP 주소를 가지고 서비스할 가상호스트를 결정한다. 그래서 각 호스트는 서로 다른 IP 주소를 가져야 한다. 이름기반 가상호스트의 경우 서버는 클라이언트가 HTTP 헤더로 호스트명을 알려주길 바란다. 이런 방법으로 한 IP 주소로 여러 다른 호스트를 서비스할 수 있다.

이름기반 가상호스트는 DNS 서버가 각 호스트명이 올바른 IP 주소로 대응하도록 가상호스트를 설정하고, 다른 호스트명을 구별할 수 있도록 아파치 웹서버를 설정하기만 하면되므로 더 간단하다. 이름기반 가상호스트는 또 여러 IP 주소가 필요없다. 그러므로 특별히 IP기반 가상호스트를 선택할 이유가 없다면 이름기반 가상호스트를 사용해야 한다. IP기반 가상호스트를 사용해야할 이유로는:

  • 이름기반 가상호스트를 지원하지않는 오래된 클라이언트들이 있다. 이름기반 가상호스트를 사용하려면 클라이언트가 HTTP Host 헤더를 보내야 한다. 이는 HTTP/1.1에서는 필수이고, 최근 모든 HTTP/1.0 브라우저들도 확장으로 지원한다. 만약 이름기반 가상호스트를 사용하면서 오래된 클라이언트를 지원해야 한다면 이 문서 끝에 있는 방법을 살펴봐라.
  • SSL 프로토콜의 성격상 SSL 보안서버에서 이름기반 가상호스트를 사용할 수 없다.
  • 어떤 운영체제나 네트웍 장치는 다른 IP 주소를 사용하지 않으면 호스트를 구별하지 못하는 네트웍 사용량(bandwidth) 관리기술을 사용한다.

이름기반 가상호스트 사용하기

관련된 모듈 관련된 지시어
  • core
  • DocumentRoot
  • NameVirtualHost
  • ServerAlias
  • ServerName
  • ServerPath
  • <VirtualHost>

이름기반 가상호스트를 사용하려면 서버는 연결을 받을 IP 주소를 (아마 포트도) 정해야 한다. 이는 NameVirtualHost 지시어로 가능하다. 일반적으로 서버의 모든 IP 주소를 사용한다면 NameVirtualHost의 아규먼트로 *를 사용한다. 여러 포트를 사용할 (예를 들어, SSL을 사용할) 계획이라면 *:80과 같이 아규먼트에 포트를 추가해야 한다. NameVirtualHost 지시어에 IP 주소를 적어주었다고 서버가 자동으로 그 IP 주소를 기다리지 않음을 주의하라. 자세한 내용은 아파치가 사용할 주소와 포트 설정하기를 참고하라. 또, 여기서 지정한 IP 주소는 서버의 네트웍 인터페이스이어야 한다.

다음 단계는 서비스하려는 호스트별로 <VirtualHost> 블록을 만드는 일이다. <VirtualHost>> 지시어의 아규먼트는 NameVirtualHost 지시어의 아규먼트(예를 들어, IP 주소나 모든 주소를 뜻하는 *)와 같아야 한다. <VirtualHost>> 블록 안에는 최소한 서비스할 호스트를 지정하는 ServerName 지시어와 호스트의 내용이 파일시스템 어디에 있는지를 지정하는 DocumentRoot 지시어가 필요하다.

주 호스트가 없어진다

기존에 사용하던 웹서버에 가상호스트를 추가한다면 기존에 사용하던 호스트에 대한 <VirtualHost> 블록도 추가해야 한다. 이 블록에 포함하는 ServerName과 DocumentRoot는 전체 ServerName과 DocumentRoot와 같아야 한다. 설정파일에서 이 가상호스트를 가장 먼저 적으면 기본 호스트가 된다.

예를 들어 www.domain.tld 도메인을 서비스하고 있었는데 같은 IP 주소에 www.otherdomain.tld란 가상호스트를 추가하고 싶다고 가정하자. httpd.conf에 다음과 같이 추가하면 된다:

NameVirtualHost *:80

<VirtualHost *:80>
ServerName www.domain.tld
ServerAlias domain.tld *.domain.tld
DocumentRoot /www/domain
 </VirtualHost>

<VirtualHost *:80>
ServerName www.otherdomain.tld
DocumentRoot /www/otherdomain
 </VirtualHost>

NameVirtualHost와 <VirtualHost> 지시어 둘 모두 * 대신 직접 IP 주소를 지정할 수도 있다. 예를 들어, 이런식으로 한 IP 주소에 여러 이름기반 가상호스트들을 돌리고, 다른 주소에 IP기반 혹은 이름기반 가상호스트들을 돌릴 수 있다.

어떤 서버는 여러 이름으로 접속할 수 있길 바란다. 이는 <VirtualHost> 섹션 안에 ServerAlias 지시어를 사용하여 가능하다. 예를 들어 위의 첫번째 <VirtualHost> 블록에서 ServerAlias 지시어를 사용하면 열거한 이름으로 같은 웹사이트를 볼 수 있다:

ServerAlias domain.tld *.domain.tld

domain.tld 도메인에 있는 모든 호스트에 대한 요청을 www.domain.tld 가상호스트가 서비스한다. 이름을 줄때 와일드카드 문자 *와 ?를 사용할 수 있다. 물론 ServerName이나 ServerAlias에 이름을 적어주었다고 끝이 아니다. 먼저 이 이름들이 서버의 IP 주소로 대응하도록 DNS 서버를 알맞게 설정해야 한다.

마지막으로 <<VirtualHost>> 안에 다른 지시어들을 사용하여 가상호스트를 자세히 설정할 수 있다. 대부분의 지시어를 사용할 수 있으며, 관련된 가상호스트의 설정만을 변경한다. 어떤 지시어가 사용가능한지 알려면 지시어의 사용장소를 확인하라. (<<VirtualHost>> 안이 아닌) 주서버설정에서 지정한 설정 지시어는 가상호스트에 같은 설정 지시어가 없는 경우에만 사용된다.

요청을 받으면 서버는 먼저 NameVirtualHost에서 지정한 IP 주소인지 검사한다. 그렇다면 그 IP 주소를 가진 <VirtualHost> 섹션들에서 요청한 호스트명과 일치하는 ServerName이나 ServerAlias를 찾는다. 찾으면 그 설정을 사용한다. 적절한 가상호스트를 찾지못하면, IP 주소에 해당하는 가상호스트들중 첫번째 것을 사용한다.

결과적으로 처음에 나온 가상호스트가 기본 가상호스트가 된다. IP 주소가 NameVirtualHost 지시어에 해당하면, 주서버의 DocumentRoot는 절대로 사용하지 않는다. 특정 가상호스트에 해당하지않는 요청을 설정하려면 설정을 <VirtualHost>에 담고 설정파일에서 먼저 나오도록 하면 된다.

오래된 브라우저와 호환

이미 적었듯이 이름기반 가상호스트가 올바로 동작하기위해 필요한 정보를 보내지않는 클라이언트가 있다. 이런 클라이언트는 항상 요청한 IP 주소에 대해 첫번째로 나오는 가상호스트 (최초의 이름기반 가상호스트)가 서비스한다.

얼마나 오래된 것을 말하는가?

여기서 오래되었음은 실제로 상당히 오래된 것을 뜻한다. 오늘날 이런 브라우저를 사용할 일은 거의없다. 요즘 브라우저는 모두 이름기반 가상호스트에 필요한 Host 헤더를 보낸다.

이 문제는 약간 거추장스럽지만 ServerPath 지시어로 해결할 수 있다:

설정 예:

NameVirtualHost 111.22.33.44

<VirtualHost 111.22.33.44>
ServerName www.domain.tld
ServerPath /domain
DocumentRoot /web/domain
 </VirtualHost>

이게 무슨 뜻인가? "/domain"로 시작하는 URI에 대한 요청은 가상호스트 www.domain.tld가 서비스한다. 즉, Host: 헤더를 보내는 클라이언트는 http://www.domain.tld/만으로도 접근할 수 있지만, http://www.domain.tld/domain/으로는 모든 클라이언트가 페이지에 접근할 수 있다.

이를 위해 최초의 가상호스트에 있는 페이지에 http://www.domain.tld/domain/으로 가는 링크를 넣는다. 그리고 가상호스트 페이지에서는 상대링크 (예를 들어, "file.html" 이나 "../icons/image.gif") 혹은 ("http://www.domain.tld/domain/misc/file.html"이나 "/domain/misc/file.html"과 같이) 앞에 /domain/이 붙은 링크만을 사용한다.

조금 규칙이 필요하지만 이 규칙을 따르면 대부분의 경우 요즘 것이나 오래된 것이나 관계없이 모든 브라우저로 페이지를 볼 수 있다.


아파치 IP기반 가상호스트 지원 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 가상호스트

아파치 IP기반 가상호스트 지원

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

참고

  • 이름기반 가상호스트 지원

시스템 요구사항

IP기반이란 말이 의미하듯이 서버는 IP기반 가상호스트 각각에 대해 다른 IP 주소를 가져야한다. 이는 컴퓨터를 물리적으로 여러 네트웍에 연결하거나, 최근 운영체제에서 지원하는 가상 인터페이스를 (자세한 내용은 시스템 문서를 참고하라. 흔히 "ip aliases"라고 하며, 보통 "ifconfig" 명령어로 만든다) 사용하여 가능하다.

아파치 설정방법

여러 호스트를 지원하도록 아파치를 설정하는 방법은 두가지다. 하나는 각 호스트마다 별도의 웹서버를 실행하는 법이고, 다른 하나는 모든 가상호스트를 지원하는 서버 한개를 실행하는 방법이다.

언제 여러 서버를 사용하나:

  • 회사2의 사용자가 웹이외의 방법으로 회사1의 자료를 읽을 수 없게 하는 등 보안상 구분이 필요한 경우. 이 경우 두 서버를 각각 다른 User, Group, Listen, ServerRoot 설정으로 실행해야 한다.
  • 충분한 메모리가 있고, 컴퓨터의 모든 IP를 기다리기위한 파일기술자(file descriptor) 요구사항도 만족한다. "와일드카드"나 특정 주소를 Listen할 수만 있다. 그래서 어떤 이유에서건 특정 주소를 기다릴 필요가 있다면, (한 웹서버가 한 주소를 제외한 모든 주소를 기다리고 다른 한 웹서버가 제외한 주소를 기다릴 수 있지만) 지정한 주소 모두를 기다려야 한다.

언제 서버 한개를 사용하나:

  • 가상호스트들의 웹서버 설정을 공유할 수 있는 경우.
  • 컴퓨터가 매우 많은 요청을 서비스한다면 여러 서버를 실행하기에 속도 손실이 클 수 있다.

여러 서버를 실행하기

각 가상호스트별로 웹서버를 설치한다. 설정파일의 Listen 지시어에 서버가 서비스할 IP 주소(혹은 가상호스트)를 적어준다. 예를 들면,

Listen www.smallco.com:80

호스트명 보다는 IP 주소를 사용하길 바란다. (DNS 문제 참고)

서버 하나로 가상호스트 실행하기

이 경우 웹서버 한개로 주서버와 모든 가상호스트에 대한 요청을 서비스한다. 설정파일의 VirtualHost 지시어에 가상호스트마다 다른 ServerAdmin, ServerName, DocumentRoot, ErrorLog, TransferLog, CustomLog 지시어 값을 설정한다. 예를 들면,

<VirtualHost www.smallco.com>
ServerAdmin webmaster@mail.smallco.com
DocumentRoot /groups/smallco/www
ServerName www.smallco.com
ErrorLog /groups/smallco/logs/error_log
TransferLog /groups/smallco/logs/access_log
</VirtualHost>

<VirtualHost www.baygroup.org>
ServerAdmin webmaster@mail.baygroup.org
DocumentRoot /groups/baygroup/www
ServerName www.baygroup.org
ErrorLog /groups/baygroup/logs/error_log
TransferLog /groups/baygroup/logs/access_log
</VirtualHost>

호스트명 보다는 IP 주소를 사용하길 바란다. (DNS 문제 참고)

VirtualHost 지시어 안에서는 프로세스 생성과 기타 몇몇 지시어를 제외하고 거의 모든 설정지시어를 사용할 수 있다. VirtualHost 지시어 안에서 지시어를 사용할 수 있는지 알려면 지시어 목록에서 사용장소를 확인하라.

suEXEC 프로그램을 사용한다면 VirtualHost 지시어 안에 User와 Group을 사용할 수 있다.

보안: 서버를 실행하는 사용자외에 다른 사람에게 로그파일이 있는 디렉토리의 쓰기권한이 있다면 보안 문제를 조심하라. 자세한 내용은 보안 팁을 참고하라.


대량의 가상호스트를 동적으로 설정하기 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 가상호스트

대량의 가상호스트를 동적으로 설정하기

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 문서는 아파치 1.3에서 대량의 가상호스트를 효율적으로 서비스하는 방법을 설명한다.

동기

당신의 httpd.conf에 다음과 같이 서로 비슷한 <VirtualHost> 섹션들을 많이 있다면 여기서 설명하는 방법이 도움이 될 것이다:

NameVirtualHost 111.22.33.44
<VirtualHost 111.22.33.44>
ServerName www.customer-1.com
DocumentRoot /www/hosts/www.customer-1.com/docs
ScriptAlias /cgi-bin/ /www/hosts/www.customer-1.com/cgi-bin
 </VirtualHost>
<VirtualHost 111.22.33.44>
ServerName www.customer-2.com
DocumentRoot /www/hosts/www.customer-2.com/docs
ScriptAlias /cgi-bin/ /www/hosts/www.customer-2.com/cgi-bin
 </VirtualHost>
# 바보 바보 바보
<VirtualHost 111.22.33.44>
ServerName www.customer-N.com
DocumentRoot /www/hosts/www.customer-N.com/docs
ScriptAlias /cgi-bin/ /www/hosts/www.customer-N.com/cgi-bin
 </VirtualHost>

기본 개념은 정적인 <VirtualHost> 설정 모두를 동적으로 처리하도록 대체하는 것이다. 그러면 많은 장점이 있다:

  1. 설정파일이 작아져서 아파치가 빨리 시작하고 메모리를 적게 사용한다.
  2. 가상호스트를 추가하기위해 파일시스템에 적당한 디렉토리를 만들고 DNS에 항목을 추가하기만 하면된다. 즉, 아파치를 재설정하고 재시작할 필요가 없다.

단점은 각 가상호스트별로 다른 로그파일을 사용할 수 없다는 점이다. 그러나 매우 많은 가상호스트를 사용한다면 파일기술자를 다 써버리기때문에 서로 다른 로그파일을 사용할 수 없다. 파이프나 fifo로 로그를 보내고, 받는 편에서 로그를 처리하여 나누는 방법이 (통계 등을 모을 수도 있다) 더 낫다.

개요

가상호스트는 IP 주소와 HTTP 요청의 Host: 헤더 정보로 정의한다. 기본적으로 대량의 동적 가상호스트 기술은 자동으로 가상호스트 정보를 요청의 파일경로에 포함한다. 이는 대부분 mod_vhost_alias를 사용하여 쉽게 해결할 수 있지만, 아파치 1.3.6 이하를 사용한다면 mod_rewrite를 사용해야 한다. 이 두 모듈 모두 기본적으로 서버에 포함되지 않는다. 이 방법을 사용하려면 아파치를 구성하고 컴파일할때 포함해야 한다.

동적 가상호스트를 일반적인 가상호스트처럼 보이게하려면 여러가지를 `속여야' 한다. 가장 중요한 것은 아파치가 자기참조 URL 등을 만들때 사용할 서버명이다. 서버명은 ServerName 지시어로 설정하며, CGI에는 SERVER_NAME 환경변수로 주어진다. 실행중 실제 서버명은 UseCanonicalName 설정에 달렸다. UseCanonicalName Off이면 요청의 Host: 헤더 내용이 서버명이 된다. UseCanonicalName DNS이면 가상호스트의 IP 주소를 역DNS 검색하여 서버명을 알아낸다. 전자는 이름기반 동적 가상호스트에서 사용하고, 후자는 IP기반 가상호스트에서 사용한다. Host: 헤더가 없거나 DNS 검색이 실패하여 아파치가 서버명을 알아내지 못하면 ServerName으로 설정한 값을 대신 사용한다.

다른 `속일' 것은 (DocumentRoot로 설정하며, CGI에는 DOCUMENT_ROOT 환경변수로 주어지는) 문서루트이다. 일반적인 경우 core 모듈이 이 설정을 사용하여 URI에 해당하는 파일명을 찾지만, 서버를 동적 가상호스팅을 할때는 다른 모듈이 (mod_vhost_alias나 mod_rewrite) 다른 방법으로 이런 작업을 한다. 두 모듈 모두 DOCUMENT_ROOT 환경변수를 사용하지 않으므로 CGI나 SSI 문서가 이 값을 사용한다면 잘못된 결과를 얻을 수 있다.

간단한 동적 가상호스트

위 동기 절의 가상호스트 설정을 mod_vhost_alias를 사용하여 더 일반적으로 구현했다.

# Host: 헤더에서 서버명을 알아낸다
UseCanonicalName Off

# 첫번째 필드를 사용하여 이 로그를 가상호스트별로 나눌 수 있다
LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

# 요청을 처리하기위해 파일명에 서버명을 포함한다
VirtualDocumentRoot /www/hosts/%0/docs
VirtualScriptAlias /www/hosts/%0/cgi-bin

이 설정에서 UseCanonicalName Off를 UseCanonicalName DNS로 변경하기만 하면 IP기반 가상호스트가 된다. 가상호스트의 IP 주소를 가지고 파일명에 추가할 서버명을 알 수 있다.

가상으로 호스트하는 홈페이지 시스템

ISP 홈페이지 서버를 위해 위의 설정을 수정했다. 조금 더 복잡한 설정을 사용하면 www.user.isp.com의 문서를 /home/user/에 두는 식으로 서버명의 일부를 가지고 파일명을 만들 수 있다. 이 설정은 cgi-bin을 각 가상호스트가 따로 가지지않고 모든 가상호스트가 같이 사용한다.

# 기본적인 내용은 위와 같다. 그리고

# 파일명에 서버명의 일부를 포함한다
VirtualDocumentRoot /www/hosts/%2/docs

# 하나의 cgi-bin 디렉토리
ScriptAlias /cgi-bin/ /www/std-cgi/

mod_vhost_alias 문서에는 더 복잡한 VirtualDocumentRoot 설정의 예가 있다.

한 서버에 여러 가상호스트 시스템 사용하기

더 복잡한 설정의 예로 아파치의 일반적인 <VirtualHost> 지시어를 사용하여 여러 가상호스트 설정의 범위를 조절할 수 있다. 예를 들어, 다음과 같은 설정은 홈페이지 고객에 IP 주소 한개, 상업적인 고객에게 다른 IP 주소 한개를 부여한다. 물론 이전처럼 <VirtualHost> 설정 섹션에 모두 묶을 수도 있다.

UseCanonicalName Off

LogFormat "%V %h %l %u %t \"%r\" %s %b" vcommon

<Directory /www/commercial>
Options FollowSymLinks
AllowOverride All
 </Directory>

<Directory /www/homepages>
Options FollowSymLinks
AllowOverride None
 </Directory>

<VirtualHost 111.22.33.44>
ServerName www.commercial.isp.com

CustomLog logs/access_log.commercial vcommon

VirtualDocumentRoot /www/commercial/%0/docs
VirtualScriptAlias /www/commercial/%0/cgi-bin
 </VirtualHost>

<VirtualHost 111.22.33.45>
ServerName www.homepages.isp.com

CustomLog logs/access_log.homepages vcommon

VirtualDocumentRoot /www/homepages/%0/docs
ScriptAlias /cgi-bin/ /www/std-cgi/
 </VirtualHost>

더 효율적인 IP기반 가상호스트

첫번째 예에서 나는 설정을 간단히 IP기반 가상호스트로 바꿀 수 있다고 말했다. 불행히도 그런 설정은 매 요청마다 DNS를 찾아야하므로 매우 비효율적이다. 이름대신 IP 주소로 파일시스템을 구성하고 같은 방식으로 로그를 수정하면 문제를 해결할 수 있다. 아파치는 서버명을 다룰 필요가 없어지고, DNS 검색도 하지 않게 된다.

# IP 주소를 역DNS 검색하여 서버명을 알아낸다
UseCanonicalName DNS

# 로그를 나눌 수 있도록 IP 주소를 포함한다
LogFormat "%A %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

# 파일명에 IP 주소를 포함한다
VirtualDocumentRootIP /www/hosts/%0/docs
VirtualScriptAliasIP /www/hosts/%0/cgi-bin

아파치 이전 버전 사용하기

위 예들은 아파치 버전 1.3.6 이후에 포함된 mod_vhost_alias을 사용한다. mod_vhost_alias가 없는 아파치 버전을 사용한다면 이미 말했듯이 mod_rewrite를 사용하여, 단 Host:-헤더기반 가상호스트만을, 구현할 수 있다.

또 로그에 관하여 주의할 점이 있다. 아파치 1.3.6에서 로그형식 지시어 %V가 포함되었고, 버전 1.3.0 - 1.3.3에서 이 기능을 %v 옵션이 대신 했다. 그러나 버전 1.3.4에는 이런 기능이 없다. 어떤 아파치 버전에서도 .htaccess 파일에서 UseCanonicalName 지시어를 사용할 수 있으므로 로그에 이상한 내용이 기록될 수 있다. 그러므로 가장 좋은 방법은 %{Host}i 지시어를 사용하여 Host: 헤더를 직접 로그에 남기는 것이다. 또, 이 방법은 %V는 포함하지않는 :port를 뒤에 추가할 수 있다.

mod_rewrite를 사용한 간단한 동적 가상호스트

다음은 첫번째 예와 같은 일을 하는 httpd.conf 예이다. 처음 절반은 첫번째 예와 거의 비슷하지만, 이전 버전과의 호환성과 mod_rewrite의 적절한 동작을 위해 수정되었다. 나머지 절반은 실제 작업을 하는 mod_rewrite를 설정한다.

특별히 주의해야 할 사항이 있다. 기본적으로 mod_rewrite는 (mod_alias 등) 다른 URI 번역 모듈 이전에 실행된다. 그래서 다른 URI 번역 모듈들과 같이 동작할 것을 고려하여 mod_rewrite를 설정해야 한다. 또, 동적 가상호스트에서 ScriptAlias과 같은 기능을 위해서는 특별한 작업이 필요하다.

# Host: 헤더에서 서버명을 얻는다
UseCanonicalName Off

# splittable logs
LogFormat "%{Host}i %h %l %u %t \"%r\" %s %b" vcommon
CustomLog logs/access_log vcommon

<Directory /www/hosts>
# ScriptAlias 식으로 CGI 실행을 강제할 수 없기때문에
# 여기에 ExecCGI를 사용한다
Options FollowSymLinks ExecCGI
 </Directory>

# 이제 어려운 부분이다

RewriteEngine On

# Host: 헤더에서 가져온 서버명에는 대소문자가 뒤섞여있을 수 있다
RewriteMap lowercase int:tolower

## 일반 문서를 먼저 처리한다:
# Alias /icons/ 가 동작하도록 - 다른 alias에 대해서도 반복
RewriteCond %{REQUEST_URI} !^/icons/
# CGI가 동작하도록
RewriteCond %{REQUEST_URI} !^/cgi-bin/
# 특별한 작업
RewriteRule ^/(.*)$ /www/hosts/${lowercase:%{SERVER_NAME}}/docs/$1

## 이제 CGI를 처리한다 - MIME type을 강제해야 한다
RewriteCond %{REQUEST_URI} ^/cgi-bin/
RewriteRule ^/(.*)$ /www/hosts/${lowercase:%{SERVER_NAME}}/cgi-bin/$1 [T=application/x-httpd-cgi]

# 끝!

mod_rewrite를 사용한 홈페이지 시스템

다음은 두번째 예와 같은 일을 한다.

RewriteEngine on

RewriteMap lowercase int:tolower

# CGI가 동작하도록
RewriteCond %{REQUEST_URI} !^/cgi-bin/

# RewriteRule이 동작하도록 호스트명이 올바른지 검사한다
RewriteCond ${lowercase:%{SERVER_NAME}} ^www\.[a-z-]+\.isp\.com$

# 가상호스트명을 URI 앞에 붙인다
# [C]는 이 결과를 가지고 다음 재작성을 수행함을 뜻한다
RewriteRule ^(.+) ${lowercase:%{SERVER_NAME}}$1 [C]

# 이제 실제 파일명을 만든다
RewriteRule ^www\.([a-z-]+)\.isp\.com/(.*) /home/$1/$2

# 전체 CGI 디렉토리를 정의한다
ScriptAlias /cgi-bin/ /www/std-cgi/

별도의 가상호스트 설정파일 사용하기

다음은 mod_rewrite의 고급 기능을 사용하여 별도의 설정파일을 가지고 가상호스트의 문서루트를 알아낸다. 더 유연하지만 더 복잡한 설정이 필요하다.

vhost.map 파일은 다음과 같다:

www.customer-1.com /www/customers/1
www.customer-2.com /www/customers/2
# ...
www.customer-N.com /www/customers/N

http.conf는 다음과 같다:

RewriteEngine on

RewriteMap lowercase int:tolower

# 대응파일을 정의한다
RewriteMap vhost txt:/www/conf/vhost.map

# 위와 같이 alias들을 처리한다
RewriteCond %{REQUEST_URI} !^/icons/
RewriteCond %{REQUEST_URI} !^/cgi-bin/
RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
# 파일 내용을 가지고 찾는다
RewriteCond ${vhost:%1} ^(/.*)$
RewriteRule ^/(.*)$ %1/docs/$1

RewriteCond %{REQUEST_URI} ^/cgi-bin/
RewriteCond ${lowercase:%{SERVER_NAME}} ^(.+)$
RewriteCond ${vhost:%1} ^(/.*)$
RewriteRule ^/(.*)$ %1/cgi-bin/$1


가상호스트 예 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 가상호스트

가상호스트 예

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 문서는 자주 문의되는 가상호스트 질문에 답을 하려고 쓰여졌다. 상황은 이름기반이나 IP기반 가상호스트를 통해 한 서버에서 여러 웹사이트를 서비스하려는 경우이다. 한 프록시 서버 뒤에서 여러 서버를 사용하여 사이트를 운영하는 경우를 다룬 문서도 곧 나올 것이다.

IP 주소 한개에 여러 이름기반 웹사이트 운영하기.

서버에 IP 주소가 한개 있고, DNS에서 여러 주소(CNAMES)가 이 컴퓨터를 가리킨다. 이 컴퓨터에서 www.example1.com과 www.example2.org의 웹서버를 실행하고 싶다.

Note

아파치 서버에 가상호스트 설정을 한다고 그 호스트명에 대한 DNS 항목이 자동이로 생성되지 않는다. 반드시 DNS에 IP 주소를 가리키는 이름이 있어야 한다. 안그러면 아무도 웹사이트를 볼 수 없다. 검사해보기 위해 hosts 파일에 항목을 추가할 수 있지만, 이는 hosts 항목을 가진 컴퓨터에만 반영된다.

서버 설정

# 아파치가 포트 80을 기다린다
Listen 80

# 모든 IP 주소에서 가상호스트 요청을 기다린다
NameVirtualHost *:80

<VirtualHost *:80>
DocumentRoot /www/example1
ServerName www.example1.com

# 다른 지시어들도 있다

 </VirtualHost>

<VirtualHost *:80>
DocumentRoot /www/example2
ServerName www.example2.org

# 다른 지시어들도 있다

 </VirtualHost>

별표는 모든 주소를 가리키므로, 주서버는 어떤 요청도 서비스하지 않는다. www.example1.com이 설정파일에 처음으로 나오므로 가장 높은 우선순위를 가지며, 기본혹은 초기 서버가 된다. 어떤 ServerName 지시어에도 해당되지않는 요청은 첫번째 VirtualHost가 서비스한다.

주의

원한다면 * 대신 시스템의 실제 IP 주소를 사용할 수 있다. 이 경우 VirtualHost의 아규먼트는 NameVirtualHost의 아규먼트와 일치해야 한다:

NameVirtualHost 172.20.30.40

<VirtualHost 172.20.30.40>
# 생략 ...

그러나 ISP에서 동적으로 IP 주소를 가져오는 등 IP 주소를 모르는 경우에는 *를 사용하는 것이 유용하다. *는 모든 IP 주소에 해당하므로, IP 주소가 변경되어도 설정을 변경할 필요가 없다.

거의 대부분의 이름기반 가상호스트 설정은 위와 같다. 예외는 다른 IP 주소나 포트로 다른 내용을 서비스하려는 경우이다.

여러 IP 주소에서 이름기반 호스트.

주의

여기서 설명한 방법은 IP 주소가 몇개라도 적용가능하다.

서버는 IP 주소가 두개있다. 하나에서 (172.20.30.40) "주" 서버 server.domain.com을 서비스하고, 다른 하나에서 (172.20.30.50) 여러 가상호스트를 서비스할 것이다.

서버 설정

Listen 80

# 172.20.30.40에서 실행하는 "주"서버이다
ServerName server.domain.com
DocumentRoot /www/mainserver

# 다른 주소다
NameVirtualHost 172.20.30.50

<VirtualHost 172.20.30.50>
DocumentRoot /www/example1
ServerName www.example1.com

# 다른 지시어들도 있다 ...

 </VirtualHost>

<VirtualHost 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example2.org

# 다른 지시어들도 있다 ...

 </VirtualHost>

172.20.30.50이 아닌 주소에 대한 요청은 주서버가 서비스한다. 호스트명 없이, 즉 Host: 헤더없이 172.20.30.50로 요청하면 www.example1.com이 서비스한다.

(내부와 외부 주소와 같이) 다른 IP 주소로 같은 내용을 서비스하기.

서버 컴퓨터에 IP 주소가 두개 (192.168.1.1과 172.20.30.40) 있다. 컴퓨터는 내부 (인트라넷) 네트웍과 외부 (인터넷) 네트웍 사이에 위치한다. 네트웍 밖에서 server.example.com은 외부 주소를 (172.20.30.40) 의미하고, 네트웍 내부에서 같은 이름을 내부 주소로 (192.168.1.1) 사용한다.

서버는 VirtualHost 섹션 한개로 내부와 외부 응답에 같은 내용을 서비스할 수 있다.

서버 설정

NameVirtualHost 192.168.1.1
NameVirtualHost 172.20.30.40

<VirtualHost 192.168.1.1 172.20.30.40>
DocumentRoot /www/server1
ServerName server.example.com
ServerAlias server
 </VirtualHost>

이제 두 네트웍에서 들어온 요청을 같은 VirtualHost에서 서비스한다.

주의:

내부 네트웍에서는 완전한 호스트명 server.example.com 대신 이름 server도 가능하다.

또한 위의 예에서 IP 주소 대신 *을 사용하여 서버가 모든 주소에 동일하게 동작할 수 있다.

여러 포트에서 서로 다른 사이트 운영하기.

같은 IP의 여러 포트에서 서로 다른 도메인을 서비스한다고 가정하자. 이는 "NameVirtualHost" 태그에 포트를 정의하면 가능하다. NameVirtualHost name:port없이 <VirtualHost name:port>만 혹은 Listen 지시어만 사용하면 안된다.

서버 설정

Listen 80
Listen 8080

NameVirtualHost 172.20.30.40:80
NameVirtualHost 172.20.30.40:8080

<VirtualHost 172.20.30.40:80>
ServerName www.example1.com
DocumentRoot /www/domain-80
 </VirtualHost>

<VirtualHost 172.20.30.40:8080>
ServerName www.example1.com
DocumentRoot /www/domain-8080
 </VirtualHost>

<VirtualHost 172.20.30.40:80>
ServerName www.example2.org
DocumentRoot /www/otherdomain-80
 </VirtualHost>

<VirtualHost 172.20.30.40:8080>
ServerName www.example2.org
DocumentRoot /www/otherdomain-8080
 </VirtualHost>

IP기반 가상호스트

서버는 각각 www.example1.com과 www.example2.org에 해당하는 두 IP 주소를 (172.20.30.40과 172.20.30.50) 가진다.

서버 설정

Listen 80

<VirtualHost 172.20.30.40>
DocumentRoot /www/example1
ServerName www.example1.com
 </VirtualHost>

<VirtualHost 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example2.org
 </VirtualHost>

<VirtualHost> 지시어로 지정한 주소에 해당하지않는 주소로 (예를 들어, localhost) 요청이 들어오면 주서버가 있는 경우 주서버가 서비스한다.

포트기반과 ip기반이 혼합된 가상호스트

서버는 각각 www.example1.com과 www.example2.org에 해당하는 두 IP 주소를 (172.20.30.40과 172.20.30.50) 가진다. 각 IP의 80번과 8080번 포트에 가상호스트를 돌린다.

서버 설정

Listen 172.20.30.40:80
Listen 172.20.30.40:8080
Listen 172.20.30.50:80
Listen 172.20.30.50:8080

<VirtualHost 172.20.30.40:80>
DocumentRoot /www/example1-80
ServerName www.example1.com
 </VirtualHost>

<VirtualHost 172.20.30.40:8080>
DocumentRoot /www/example1-8080
ServerName www.example1.com
 </VirtualHost>

<VirtualHost 172.20.30.50:80>
DocumentRoot /www/example2-80
ServerName www.example1.org
 </VirtualHost>

<VirtualHost 172.20.30.50:8080>
DocumentRoot /www/example2-8080
ServerName www.example2.org
 </VirtualHost>

이름기반과 IP기반이 혼합된 가상호스트

주소중 몇몇은 이름기반 가상호스트로, 다른 것은 IP기반 가상호스트로 서비스하고 싶다.

서버 설정

Listen 80

NameVirtualHost 172.20.30.40

<VirtualHost 172.20.30.40>
DocumentRoot /www/example1
ServerName www.example1.com
 </VirtualHost>

<VirtualHost 172.20.30.40>
DocumentRoot /www/example2
ServerName www.example2.org
 </VirtualHost>

<VirtualHost 172.20.30.40>
DocumentRoot /www/example3
ServerName www.example3.net
 </VirtualHost>

# IP-기반
<VirtualHost 172.20.30.50>
DocumentRoot /www/example4
ServerName www.example4.edu
 </VirtualHost>

<VirtualHost 172.20.30.60>
DocumentRoot /www/example5
ServerName www.example5.gov
 </VirtualHost>

_default_ 가상호스트 사용하기

모든 포트에 대한 _default_ 가상호스트

어떤 가상호스트에도 해당하지않은 IP 주소와 포트에 대한 모든 요청을 처리하기.

서버 설정

<VirtualHost _default_:*>
DocumentRoot /www/default
 </VirtualHost>

default(기본) 가상호스트의 포트로 와일드카드를 사용하여 어떤 요청도 주서버로 못가도록 만든다.

default 가상호스트는 절대로 이름기반 가상호스트가 사용하는 주소/포트로의 요청을 서비스하지 않는다. 알 수 없거나 Host: 헤더가 생략된 요청은 항상 최초의 이름기반 가상호스트(설정파일에서 주소/포트가 처음으로 나온 가상호스트)가 서비스한다.

AliasMatch나 RewriteRule을 사용하여 어떤 요청을 특정 페이지(혹은 스크립트)로 재작성할(rewrite) 수 있다.

여러 포트에 대한 _default_ 가상호스트

위의 경우와 같지만, 서버는 여러 포트를 기다리고 80번 포트에 대해서 추가로 _default_ 가상호스트를 사용하고 싶다.

서버 설정

<VirtualHost _default_:80>
DocumentRoot /www/default80
# ...
 </VirtualHost>

<VirtualHost _default_:*>
DocumentRoot /www/default
# ...
 </VirtualHost>

80번 포트에 대한 default 가상호스트는 (반드시 와일드카드 포트를 가진 기본 가상호스트 이전에 나와야 한다) 지정하지않은 IP 주소로 보내진 모든 요청을 서비스한다. 주서버는 절대로 요청을 서비스하지 못한다.

한 포트에 대한 _default_ 가상호스트

80번 포트에 대해서만 default 가상호스트를 만들고 싶다.

서버 설정

<VirtualHost _default_:80>
DocumentRoot /www/default
...
</VirtualHost>

포트 80번에 지정하지않은 주소에 대한 요청은 기본 가상호스트가 서비스하고, 다른 지정하지않은 주소와 포트를 가진 요청은 주 서버가 서비스한다.

이름기반 가상호스트를 IP기반 가상호스트로 옮기기

(이름기반의 첫번째 예에서) 호스트명 www.example2.org에 대한 이름기반 가상호스트는 자신의 IP 주소를 가져야 한다. 이름기반 가상호스트의 이전 IP 주소를 캐싱하는 네임서버나 프록시와의 문제를 피하기위해 옮기는 동안 둘 모두를 서비스하고 싶다.
방법은 VirtualHost 지시어에 새 IP 주소만을 (172.20.30.50) 추가하면되므로 쉽다.

서버 설정

Listen 80
ServerName www.example1.com
DocumentRoot /www/example1

NameVirtualHost 172.20.30.40

<VirtualHost 172.20.30.40 172.20.30.50>
DocumentRoot /www/example2
ServerName www.example2.org
# ...
 </VirtualHost>

<VirtualHost 172.20.30.40>
DocumentRoot /www/example3
ServerName www.example3.net
ServerAlias *.example3.net
# ...
 </VirtualHost>

이제 (IP기반 가상호스트를 통한) 새로운 주소와 (이름기반 가상호스트를 통한) 이전 주소 모두 가상호스트에 접근할 수 있다.

ServerPath 지시어 사용하기

두 이름기반 가상호스트를 가진 서버가 있다. 올바른 가상호스트를 선택하기위해 클라이언트는 올바른 Host: 헤더를 보내야 한다. 오래된 HTTP/1.0 클라이언트가 이 헤더를 보내지 못하면 아파치는 클라이언트가 어떤 가상호스트를 보려고하는지 알 수 없다 (그래서 최초의 가상호스트가 요청을 서비스한다). 오래된 브라우저와 가능한 호환을 유지하기위해 최초의 가상호스트를 만들고, 여기에 이름기반 가상호스트의 URL 접두사를 포함하는 링크 목록 페이지를 둔다.

서버 설정

NameVirtualHost 172.20.30.40

<VirtualHost 172.20.30.40>
# primary vhost
DocumentRoot /www/subdomain
RewriteEngine On
RewriteRule ^/.* /www/subdomain/index.html
# ...
 </VirtualHost>

<VirtualHost 172.20.30.40>
DocumentRoot /www/subdomain/sub1
ServerName www.sub1.domain.tld
ServerPath /sub1/
RewriteEngine On
RewriteRule ^(/sub1/.*) /www/subdomain$1
# ...
 </VirtualHost>

<VirtualHost 172.20.30.40>
DocumentRoot /www/subdomain/sub2
ServerName www.sub2.domain.tld
ServerPath /sub2/
RewriteEngine On
RewriteRule ^(/sub2/.*) /www/subdomain$1
# ...
 </VirtualHost>

ServerPath 지시어때문에 URL http://www.sub1.domain.tld/sub1/에 대한 요청은 항상 subl-가상호스트가 서비스한다.
클라이언트가 올바른 Host: 헤더를 보낸다면, URL http://www.sub1.domain.tld/에 대한 요청은 subl-가상호스트에서만 서비스한다. 만약 Host: 헤더를 보내지않으면 클라이언트는 최초의 호스트에 있는 정보페이지를 보게된다.
여기에 문제가 있음을 주의하라: 클라이언트가 Host: 헤더를 보내지않으면 http://www.sub2.domain.tld/sub1/에 대한 요청도 subl-가상호스트가 서비스한다.
RewriteRule 지시어를 사용하여 올바른 Host: 헤더를 보내는 클라이언트는 (예를 들어, URL 전치사가 있거나 없는) 두 URL을 모두 사용할 수 있다.


가상호스트 찾기에 대한 자세한 설명 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 가상호스트

가상호스트 찾기에 대한 자세한 설명

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

가상호스트 코드는 아파치 1.3에서 거의 다시 작성되었다. 이 문서는 아파치가 요청을 받으면 어떤 가상호스트가 서비스할지 결정하는 방법을 설명한다. 새로운 NameVirtualHost 지시어를 사용하여 가상호스트 설정이 1.3 버전 이전보다 더 쉽고 안전해졌다.

어떻게 동작하는지 이해하지않고 단지 동작하게만 하고 싶다면, 예제들을 참고하라.

설정파일 읽기

<VirtualHost> 설정을 제외한 설정이 주서버를 만든다. <VirtualHost> 섹션으로 정의한 부분을 가상호스트라고 부른다.

Listen, ServerName, ServerPath, ServerAlias 지시어는 서버 정의 어느곳에서도 사용할 수 있다. 그러나 같은 지시어가 여러번 나오면 (그 서버에서) 마지막 지시어만이 유효하다.

주서버 Listen의 기본값은 80이다. 주서버의 ServerPath나 ServerAlias에는 기본값은 없다. ServerName의 기본값은 서버의 IP 주소이다.

주서버의 Listen 지시어는 두가지 기능을 한다. 첫째는 아파치가 연결할 기본 네트웍 포트를 지정하는 일이다. 둘째는 리다이렉션할 절대 URI에 사용할 포트 번호를 지정하는 일이다.

주서버와 달리 가상호스트의 포트는 아파치가 연결을 기다리는 포트에 영향을 주지 않는다.

VirtualHost 지시어에 포트를 지정할 수 있다. 포트를 지정하지않으면 주서버의 가장 최근 Listen 값을 사용한다. 특별한 포트 *는 어떤 포트라도 지칭하는 와일드카드이다. (DNS 검색 결과의 여러 A 레코드를 포함하여) 가상호스트의 주소를 모두 총칭하여 가상호스트의 주소집합(address set)이라고 부른다.

특정 IP 주소에 대한 NameVirtualHost 지시어가 없다면 그 주소를 포함하는 첫번째 가상호스트를 IP기반 가상호스트로 취급한다. IP 주소에 와일드카드 *를 사용할 수도 있다.

이름기반 가상호스트를 사용한다면 이름기반 가상호스트에 사용할 IP 주소를 NameVirtualHost 지시어에 사용해야 한다. 즉, 설정파일의 NameVirtualHost 지시어에 이름기반 가상호스트의 호스트별명(CNAME)에 해당하는 IP 주소를 지정해야 한다.

특정 IP:포트 쌍에 대해 오직 한 NameVirtualHost 지시어만을 사용한다면, 여러 NameVirtualHost 지시어와 VirtualHost 지시어를 섞어서 사용할 수 있다.

NameVirtualHost와 VirtualHost 지시어의 순서는 중요하지 않기때문에 다음 두 예는 같다 (오직 한 주소집합에 대한 VirtualHost의 순서가 중요하다. 아래 참고):

NameVirtualHost 111.22.33.44
<VirtualHost 111.22.33.44>
# 서버 A
...
</VirtualHost>
<VirtualHost 111.22.33.44>
# 서버 B
...
</VirtualHost>

NameVirtualHost 111.22.33.55
<VirtualHost 111.22.33.55>
# 서버 C
...
</VirtualHost>
<VirtualHost 111.22.33.55>
# 서버 D
...
</VirtualHost>

<VirtualHost 111.22.33.44>
# 서버 A
</VirtualHost>
<VirtualHost 111.22.33.55>
# 서버 C
...
</VirtualHost>
<VirtualHost 111.22.33.44>
# 서버 B
...
</VirtualHost>
<VirtualHost 111.22.33.55>
# 서버 D
...
</VirtualHost>

NameVirtualHost 111.22.33.44
NameVirtualHost 111.22.33.55

(왼쪽 설정이 더 읽기 편하다.)

VirtualHost 지시어를 읽을 다음, 가상호스트 서버는 VirtualHost 지시어에 지정한 포트를 기본 Listen으로 한다.

VirtualHost 지시어의 이름이 모두 같은 주소집합에 속한다면 ServerAlias와 같이 취급한다 (그러나 다른 ServerAlias의 영향을 받지 않는다). 가상호스트에 추가로 사용한 Listen은 주소집합이 지정한 포트에 영향을 주지 않음을 주의하라.

시작할때 IP 주소 목록을 만들어 해쉬테이블에 추가한다. NameVirtualHost 지시어에 IP 주소를 사용하면 목록은 그 IP 주소에 대한 모든 이름기반 가상호스트를 포함한다. 그 주소에 대한 가상호스트가 없다면 NameVirtualHost 지시어를 무시하고 로그에 오류를 기록한다. IP기반 가상호스트는 해쉬테이블에 목록을 추가하지 않는다.

빠른 해쉬함수를 사용하기때문에 요청시 IP 주소를 해싱하는 부담은 거의 없다. 또 해쉬테이블은 IP 주소의 마지막 부분의 차이에 최적화되있다.

가상호스트에 여러 기본값이 설정된다. 특히:

  1. 가상호스트에 ServerAdmin, ResourceConfig, AccessConfig, Timeout, KeepAliveTimeout, KeepAlive, MaxKeepAliveRequests, SendBufferSize 지시어가 없다면 주서버에서 해당 값을 가져온다. (즉, 주서버의 설정값을 사용한다.)
  2. 가상호스트의 디렉토리 기본권한을 정의하는 "참조 기본값(lookup defaults)"은 주서버의 설정과 합쳐진다. 모듈의 디렉토리당 설정(per-directory configuration)도 여기에 해당된다.
  3. 각 모듈의 서버당 설정(per-server config)은 주서버의 설정과 가상호스트의 설정을 합친다.

기본적으로 주서버는 가상호스트를 만드는 "기본" 혹은 "기반"이 된다. 그러나 설정파일에서 주서버를 정의하는 위치는 관계없다. 마지막으로 설정을 합치기 전에 주서버의 모든 설정을 읽어들인다. 그래서 주서버 정의가 가상호스트 정의 뒤에 나와도 가상호스트 정의에 영향을 준다.

주서버에 ServerName이 없다면 웹서버를 실행하는 컴퓨터의 호스트명을 대신 사용한다. 주서버의 ServerName을 DNS 겁색하여 얻은 IP 주소들을 주서버 주소집합이라고 부른다.

이름기반 가상호스트의 ServerName을 정의하지 않으면 가상호스트를 정의하는 VirtualHost에서 처음으로 나온 주소를 기본값으로 사용한다.

특별한 _default_ 와일트카드를 포함하는 가상호스트는 주서버와 같은 ServerName을 가진다.

가상호스트 찾기

서버는 아래와 같은 방법으로 어떤 가상호스트가 요청을 처리할지 결정한다:

해쉬테이블 찾기

클라이언트가 처음 연결하면 연결한 IP 주소를 내부 IP 해쉬테이블에서 찾는다.

IP 주소를 찾을 수 없고 클라이언트가 요청을 보낸 포트에 해당하는 가상호스트가 있다면, _default_ 가상호스트가 요청을 서비스한다. _default_ 가상호스트가 없다면 주서버가 요청을 서비스한다.

해쉬테이블에 IP 주소가 없지만 포트 번호가 NameVirtualHost *에 해당할 수 있다. 이 경우 이름기반 가상호스트처럼 처리한다.

찾았다면 (목록에서 IP 주소에 해당하는 항목을 찾으면), IP기반 가상호스트인지 이름기반 가상호스트인지 결정한다.

IP기반 가상호스트

찾은 항목에 이름 목록이 없다면 IP기반 가상호스트이다. 더 이상 작업이 필요없고, 그 가상호스트가 요청을 처리한다.

이름기반 가상호스트

이름 목록에 한개 이상의 가상호스트 구조가 포함되면 이름기반 가상호스트이다. 이 목록에서 가상호스트들은 설정파일의 VirtualHost 순서대로 위치한다.

목록에서 첫번째 가상호스트(설정파일에서 해당 IP 주소를 포함하는 첫번째 가상호스트)는 가장 높은 우선순위를 가지며, 서버명을 알 수 없거나 Host: 헤더가 없는 요청을 처리한다.

클라이언트가 Host: 헤더를 주면, 목록에서 첫번째로 ServerName이나 ServerAlias가 대응하는 가상호스트가 요청을 서비스한다. Host: 헤더에 포트 번호가 나올 수 있지만, 아파치는 항상 클라이언트가 요청을 보낸 실제 포트를 찾는다.

클라이언트가 Host: 헤더없이 HTTP/1.0 요청을 하면 클라이언트가 어떤 서버에 연결하려는지 알 수 없기때문에 요청의 URI에 해당하는 ServerPath가 있는지 찾는다. 목록에서 제일 먼저 찾은 경로를 사용하고, 그 가상호스트가 요청을 서비스한다.

대응하는 가상호스트를 찾을 수 없다면, (이미 앞에 말했듯이) 클라이언트가 연결한 IP에 대한 목록에서 일치하는 포트 번호를 포함하는 첫번째 가상호스트가 요청을 서비스한다.

지속 연결

IP는 위에서 설명한데로 특정 TCP/IP 세션당 한번만 찾지만, 이름은 KeepAlive/지속 연결동안 매 요청때마다 찾는다. 즉, 클라이언트는 지속 연결동안 여러 이름기반 가상호스트의 페이지를 요청할 수 있다.

절대 URI

요청의 URI가 절대 URI이고 클라이언트가 보낸 요청의 호스트명과 포트가 주서버나 특정 가상호스트에 해당하면, 그 주서버 혹은 가상호스트는 URI 앞의 스킴/호스트명/포트 부분을 제외한 나머지 상대 URI를 서비스한다. 해당하는 주서버나 가상호스트가 없다면 URI를 그대로 두고 요청을 프록시 요청으로 처리한다.

주의

  • 이름기반 가상호스트와 IP기반 가상호스트는 서로에게 영향을 주지 않는다. IP기반 가상호스트를 자신의 이름집합 IP 주소외에 어떤 주소로도 접근할 수 없다. 이름기반 가상호스트도 마찬가지다. 이름기반 가상호스트는 NameVirtualHost 지시어로 정의한 주소집합의 IP 주소를 통해서만 접근할 수 있다.
  • IP기반 가상호스트는 ServerAlias와 ServerPath를 절대로 검사하지 않는다.
  • 설정파일에서 이름기반 가상호스트, IP기반 가상호스트, _default_ 가상호스트, NameVirtualHost 지시어의 순서는 중요하지 않다. 특정 주소집합에 대한 이름기반 가상호스트들의 순서만이 중요하다. 설정파일에서 앞에 나오는 이름기반 가상호스트는 자신이 속한 주소집합에서 가장 높은 우선순위를 가진다.
  • 보안을 위해 Host: 헤더에 포함된 포트 번호는 절대로 사용하지 않는다. 아파치는 항상 클라이언트가 요청을 보낸 실제 포트를 사용한다.
  • (둘 사이를 구별할 Host: 헤더가 없다고 가정하면,) ServerPath 지시어가 설정파일에서 뒤에 나오는 다른 ServerPath 지시어의 앞부분을 지칭하는 경우 항상 앞에 나온 지시어를 사용한다.
  • 두 IP기반 가상호스트가 같은 주소를 가지면, 항상 설정파일에서 앞에 나오는 가상호스트를 사용한다. 이런 일은 아무도 모르게 일어날 수 있다. 서버가 이런 상황을 발견하면 오류 로그파일에 경고를 기록한다.
  • _default_ 가상호스트는 요청의 IP 주소와 포트 번호에 해당하는 가상호스트가 없을때만 요청을 처리한다. 클라이언트가 요청을 보낸 포트 번호가 _default_ 가상호스트의 포트 번호(기본값은 Listen)와 같을때만 요청을 처리한다. 어떤 포트의 요청이라도 잡기위해 (예를 들어, _default_:*) 와일드카드 포트를 사용할 수 있다. NameVirtualHost * 가상호스트도 마찬가지다.
  • 주서버는 클라이언트가 연결한 IP 주소와 포트 번호에 해당하는 (_default_ 가상호스트를 포함하여) 가상호스트가 없을때만 요청을 서비스한다. 즉, 주서버는 (그 포트에 해당하는 _default_ 가상호스트가 없다면) 지정하지않은 주소/포트 쌍에 대한 요청만을 처리한다.
  • 클라이언트가 (예를 들어, NameVirtualHost 지시어에서) 이름기반 가상호스트 주소(와 포트)에 연결한 경우 Host: 헤더를 알 수 없거나 헤더가 없는 요청을 보내면 요청은 절대로 _default_ 가상호스트나 주서버에서 처리하지 않는다.
  • 시작할때 서버가 DNS를 의존하지 않으려면 절대로 VirtualHost 지시어에 DNS 이름을 사용하지마라. 게다가 열거한 모든 도메인의 DNS를 통제하지 않는다면 보안상 위험도 있다. 이에 대한 정보가 있다.
  • 각 가상호스트마다 ServerName를 항상 정의해야 한다. 안그러면 가상호스트마다 DNS를 찾게 된다.

팁

DNS 문제 페이지의 팁에 추가로 아래에 팁이 있다:

  • 모든 주서버 정의를 VirtualHost 정의 앞에 두어라. (그러면 설정을 읽기 편하다. 안그러면 나중에 설정이 합쳐질때 가상호스트들 사이에 섞인 정의가 모든 가상호스트에 영향을 줄 수 있기때문에 혼란스럽다.)
  • 읽기 편하도록 설정에서 해당하는 NameVirtualHost과 VirtualHost 정의들을 묶어라.
  • ServerPath가 다른 ServerPath의 앞부분을 지칭하는 경우를 피하라. 피할 수 없다면 설정파일에서 앞부분이 더 긴 (더 자세한) 가상호스트를 짧은 (덜 자세한) 가상호스트보다 앞에 두어라. (예를 들어, "ServerPath /abc"는 "ServerPath /abc/def" 다음에 두어야 한다.


파일기술자(file descriptor) 한계 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 가상호스트

파일기술자(file descriptor) 한계

가상호스트를 많이 사용하고 각 가상호스트에 서로 다른 로그파일을 지정하면, 아파치가 사용가능한 파일기술자(file descriptor, 흔히 파일핸들(file handle)이라고 부름)를 다 써버릴 수 있다. 아파치가 사용하는 파일기술자의 총 개수는 오류 로그파일당 한개, 다른 로그파일 지시어당 한개, 추가로 내부용도로 10-20개를 더한 수다. 유닉스 운영체제는 프로세스가 사용할 수 있는 파일기술자 개수를 제한한다. 이 한계는 보통 64개로, 보통 이보다 큰 hard-limit까지 늘릴 수 있다.

아파치는 이 한계를 필요한만큼 늘리려고 하지만, 실패하는 경우가 있다:

  1. 시스템이 setrlimit() 시스템호출을 제공하지 않는다.
  2. (Solaris 2.3과 같이) 시스템에서 setrlimit(RLIMIT_NOFILE) 함수가 동작하지 않는다.
  3. 필요한 파일기술자 개수가 hard limit 보다 많다.
  4. (Solaris 2) 시스템이 stdio 스트림을 256이하의 파일기술자만을 사용하도록 제한하는 등 파일기술자에 제약을 가한다.

이 경우 해결책은:

  • 로그파일 개수를 줄인다. <VirtualHost> 섹션에서 로그파일을 지정하지 않고 주 로그파일을 사용한다. (더 자세한 방법은 아래 로그파일 나누기를 참고하라.)
  • 사용하는 시스템이 (위의) 1번째나 2번째 경우에 해당한다면, 다음과 같은 스크립트로 아파치를 시작하기 전에 파일기술자 한계를 늘린다.

    #!/bin/sh
    ulimit -S -n 100
    exec httpd

파일기술자 문제와 각 운영체제에서의 해결방법에 대한 자세한 내용은 파일기술자와 아파치 문서를 참고하라.

로그파일 나누기

여러 가상호스트가 같은 로그파일을 사용한다면 나중에 각 가상호스트의 통계분석을 위해 로그파일을 나누고 싶을 것이다. 이 작업은 다음과 같이 할 수 있다.

먼저 로그 항목에 가상호스트 정보를 추가한다. 이를 위해 LogFormat 지시어와 %v 변수를 사용한다. 이 변수를 로그 형식문자열 앞에 추가한다:

LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost
CustomLog logs/multiple_vhost_log vhost

그러면 common 로그형식 앞에 (ServerName 지시어에 나오는) 정규 가상호스트를 포함하여 로그파일을 기록한다. (로그파일 사용자정의에 관한 내용은 사용자정의 로그형식을 참고하라.)

로그파일을 (가상호스트당 한 파일씩) 나누고 싶다면 split-logfile 프로그램을 사용한다. 이 프로그램은 아파치 배포본의 support 디렉토리에 있다.

다음과 같이 프로그램을 실행한다:

split-logfile < /logs/multiple_vhost_log

가상호스트 로그파일을 가지고 이 프로그램을 실행하면 로그파일에 나오는 각 가상호스트당 파일을 하나씩 만든다. 각각의 파일명은 hostname.log이다.


DNS와 아파치와 관련된 사항 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

DNS와 아파치와 관련된 사항

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 문서를 한 문장으로 요약할 수 있다. 아파치가 설정파일을 읽을때 DNS를 의존하지않도록 하라. 아파치가 설정파일을 읽는데 DNS가 필요하다면 서버는 신뢰성 문제 (시작이 안될 수도 있다) 혹은 서비스거부 공격과 (사용자가 다른 사용자에 대한 접근을 가로채는 것을 포함하여) 서비스도둑(theft of service) 공격에 시달릴 수 있다.

간단한 예제

<VirtualHost www.abc.dom>
ServerAdmin webgirl@abc.dom
DocumentRoot /www/abc
</VirtualHost>

아파치가 정상적으로 동작하기위해서는 각 가상호스트에 대해 두가지 정보가 절대적으로 필요하다. 이 정보는 ServerName과 서버가 기다리고 응답할 최소 한개의 IP 주소이다. 이 예는 IP 주소가 없기때문에, 아파치는 DNS를 사용하여 www.abc.dom의 주소를 찾아야 한다. 서버가 설정파일을 읽을때 어떤 이유에서건 DNS를 사용할 수 없다면 가상호스트를 만들 수 없다. 이 가상호스트는 요청에 응답할 수 없다. (아파치 1.2 이전 버전에서는 심지어 서버가 부팅도 안한다.)

www.abc.dom의 주소가 10.0.0.1이라고 가정하자. 그리고 다음 설정을 보라:

<VirtualHost 10.0.0.1>
ServerAdmin webgirl@abc.dom
DocumentRoot /www/abc
</VirtualHost>

이제 아파치는 이 가상호스트의 ServerName을 찾기위해 역DNS를 사용해야 한다. 역찾기가 실패하면 아파치는 가상호스트를 부분적으로 끈다. (아파치 1.2 이전 버전에서는 심지어 서버가 부팅도 안한다.) 즉, 이 경우 이름기반 가상호스트라면 가상호스트는 완전히 동작하지않고, ip기반이라면 대부분 동작한다. 그러나 아파치가 서버명을 포함하여 서버의 전체 URL을 만들어야 한다면 정상적인 URL을 만들지 못한다.

아래 경우 이 두가지 문제가 없다.

<VirtualHost 10.0.0.1>
ServerName www.abc.dom
ServerAdmin webgirl@abc.dom
DocumentRoot /www/abc
</VirtualHost>

서비스거부 (Denial of Service)

(최소한) 두가지 종류의 서비스거부가 발생할 수 있다. 아파치 1.2 이전 버전의 경우 어떤 가상호스트에서라도 위에서 말한 두 DNS 검색이 실패하면 서버가 켜지지도 않는다. DNS가 당신의 권한 밖의 문제일 수도 있다. 예를 들어, abc.dom이 고객 사이트이고 고객이 자신의 DNS를 관리한다면, www.abc.dom 레코드를 지우기만 해도 (1.2 이전) 서버는 시작하지 못한다.

훨씬 더 교활한 방법도 있다. 다음 설정을 살펴보자:

<VirtualHost www.abc.dom>
  ServerAdmin webgirl@abc.dom
  DocumentRoot /www/abc
</VirtualHost>

<VirtualHost www.def.dom>
  ServerAdmin webguy@def.dom
  DocumentRoot /www/def
</VirtualHost>

당신이 www.abc.dom에 10.0.0.1, www.def.dom에 10.0.0.2를 할당했다고 하자. 또, def.dom은 자체 DNS를 사용한다고 가정하자. 이 설정과 함께 def.dom을 abc.dom으로 가는 모든 통신을 가로챌 수 있는 장소에 두었다. 그렇다면 그들은 www.def.dom을 10.0.0.1로 설정하기만 하면 된다. 그들이 자체 DNS를 사용하기때문에 당신은 그들이 원하는데로 www.def.dom 레코드를 설정하는 것을 막을 수 없다.

(사용자가 http://www.abc.dom/whatever 형식의 URL을 입력하는 경우를 포함하여) 10.0.0.1로 오는 모든 요청을 def.dom 가상호스트가 서비스하게 된다. 왜 이런 일이 일어나는지 이해하려면 아파치가 어떻게 가상호스트로 오는 요청을 처리하는지에 대한 설명이 필요하다. 여기에 대강 설명되있다.

"주서버" 주소

아파치 1.1에서 이름기반 가상호스트 지원이 포함되었기때문에 아파치는 웹서버를 실행하는 호스트의 IP 주소(들)를 알 필요가 생겼다. 이 주소는 (있다면) 전역 ServerName 혹은 C 함수 gethostname으로 (명령프롬프트에 "hostname"을 입력했을때와 같은 결과) 얻는다. 그러면 이 주소로 DNS 검색을 한다. 현재 이 검색은 피할 수 없다.

DNS 서버가 죽어서 이 검색이 실패할 것 같다면 /etc/hosts에 호스트명을 집어넣을 수 있다. (컴퓨터가 정상적으로 부팅되었다면 아마 이미 들어있을 것이다.) 그리고 DNS가 실패하면 서버가 /etc/hosts를 사용하는지 확인하라. 사용하는 운영체제에 따라 /etc/resolv.conf 혹은 /etc/nsswitch.conf를 수정하면 될 것이다.

서버가 어떤 이유에서건 DNS를 검색하면 안된다면 HOSTRESORDER 환경변수를 "local"로 설정하고 아파치를 실행할 수 있다. mod_env를 사용하여 환경을 변경하지 않는다면 이 환경변수는 CGI에도 영향을 준다. 운영체제의 manpage나 FAQ를 참고하는 것이 좋다.

이 문제를 피하기위한 팁

  • VirtualHost에 IP 주소를 사용하라
  • Listen에 IP 주소를 사용하라
  • 모든 가상호스트는 명시적으로 ServerName을 가지게 하라
  • 어떤 페이지도 서비스하지않는 <VirtualHost _default_:*> 서버를 만들어라

부록: 앞으로는

DNS와 관련된 상황은 매우 바람직하지 못하다. 아파치 1.2에서 우리는 DNS가 실패한 경우에도 최소한 서버가 켜지도록 노력했지만 결과는 나빴다. 어쨌든 설정파일에 직접 IP 주소를 요구하는 것은 번호를 다시 설정해야할 요즘 인터넷에 매우 바람직하지 못하다.

위에서 설명한 서비스도둑 공격을 막는 한가지 방법은 검색한 IP 주소에 다시 역DNS 검색을 하여 두 이름을 비교하는 것이다. 서로 다른 경우 가상호스트를 가동하지 않을 수 있다. 이 방법은 역DNS가 올바로 설정되야 한다. (FTP 서버나 TCP wrapper가 "중복-역" DNS 검색을 자주 사용하기때문에 대부분의 관리자에게 익숙할 것이다.)

어쨌든 IP 주소를 사용하지않으면 DNS가 실패한 경우 가상호스트 웹서버를 믿을 수 있게 시작할 수 없다. 설정의 일부를 무시하는 것과 같은 부분적인 해결책은 웹서버 전체를 시작하지않는 것보다 더 나쁠 수도 있다.

HTTP/1.1이 나왔고 브라우저와 프록시가 Host 헤더를 보내기 시작했으므로 IP기반 가상호스트를 완전히 사용하지않는 것이 가능해질 것이다. 그러면 웹서버는 설정중에서 DNS 검색을 할 필요가 없어진다. 그러나 1997년 3월에는 중요한 웹서버에 포함할 정도로 이름기반 가상호스트가 널리 사용되지 않았다.


자주 물어보는 질문 (FAQ) - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

자주 물어보는 질문 (FAQ)

FAQ 최신판은 아파치 웹사이트 <http://httpd.apache.org/docs-2.0/faq/>에서 볼 수 있다. 또, 검색하고 출력하기 편하게 FAQ를 한 페이지로 볼 수 있다.

아파치 2.0이 나온지 얼마 안되서 우리는 아직 자주 물어보는 질문 (FAQ)이 무엇인지 모른다. 내용이 채워질 때까지 여기에 해답이 없다면 아파치 1.3 FAQ도 참고하라.

주제

지원
문제가 생기면 어떻게 해결하나?
오류문
이 오류문이 무슨 뜻인가?


지원 - 자주 물어보는 질문 (FAQ) - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > FAQ

지원 - 자주 물어보는 질문 (FAQ)

지원

  • "왜 ... 안되나? 왜 ... 동작하지 않는가?" 문제가 생기면 할일
  • 도움을 얻으려면 누구에게 연락하나?

"왜 ... 안되나? 왜 ... 동작하지 않는가?" 문제가 생기면 할일

아파치 서버 소프트웨어에 문제가 생기면 다음과 같은 단계를 따른다:

오류 로그(errorlog)를 확인하라!
아파치 서버는 문제가 생기면 도움을 주려고 노력한다. 많은 경우 서버 오류 로그에 자세한 내용을 기록한다. 이것만으로도 직접 (파일권한 등) 문제를 발견하고 고칠 수 있는 경우가 많다. 오류 로그의 기본 위치는 /usr/local/apache2/logs/error_log이지만, 정확한 위치는 설정파일의 ErrorLog 지시어를 참고하라.
FAQ를 확인하라!
아파치 웹사이트에서 항상 아파치 FAQ 최신판을 볼 수 있다.
아파치 버그 데이터베이스를 확인하라
아파치그룹(The Apache Group)에 보고된 대부분의 문제는 버그 데이터베이스에 기록된다. 새로 버그를 추가하기 전에, 이미 알려졌거나(open) 해결된(closed) 버그가 있는지 확인하길 바란다. 이미 문제가 보고되었다면 "나도 이런 문제가 있다고" 보고하지 않길 바란다. 아직 해결되지 않았다면 주기적으로 상황을 확인하길 바란다. 또, 데이터베이스에 기록되지 않고 이메일 교환으로 진행된 사항이 있을 수 있으니 처음 문제를 보고한 사람에게 연락해볼 수도 있다.
사용자 지원 공간에 문의한다

아파치에 대한 지식을 공유하길 원하는 활발한 사용자 공동체들이 있다. 일반적으로 이런 공동체에 참여하는 것이 문제의 답을 얻는 가장 좋고 빠른 방법이다.

사용자 메일링리스트

USENET 뉴스그룹:

  • comp.infosystems.www.servers.unix [news] [google]
  • comp.infosystems.www.servers.ms-windows [news] [google]
  • comp.infosystems.www.authoring.cgi [news] [google]
위의 방법이 모두 실패하면 버그 데이터베이스에 문제를 보고한다

위의 단계를 모두 시도하고도 해결책이 없다면, 버그를 보고하여 웹서버 개발자들에게 문제를 알리길 바란다.

core dump를 만들며 서버가 죽는 경우라면 (가능하면) backtrace(역주; 문제가 실행파일의 정확히 어떤 지점에서 발생하였고, 프로그램이 그 지점까지 어떤 경로로 실행되었는지를 알려주는 정보)를 포함하길 바란다. 예를 들어,

# cd ServerRoot
# dbx httpd core
(dbx) where

(ServerRoot, httpd, core 파일의 실제 위치를 대신 사용하라. dbx 대신 gdb를 사용해야 할 수도 있다.)

도움을 얻으려면 누구에게 연락하나?

40명 가량의 자발적으로 참여한 개발자만으로는 수백만의 사용자에게 아파치에 대해 일일이 지원할 수 없다. 무료 지원을 얻으려면 사용자 공간에 참여하길 권한다.

아파치에 대한 직업적인 유료 지원은 여러 회사에서 제공한다.


오류문 - 자주 물어보는 질문 (FAQ) - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > FAQ

오류문 - 자주 물어보는 질문 (FAQ)

오류문

  • Invalid argument: core_output_filter: writing data to the network
  • AcceptEx failed
  • Premature end of script headers

Invalid argument: core_output_filter: writing data to the network

플래폼이 sendfile 시스템호출을 지원한다면, 아파치는 응답의 속도를 빠르게하기위해 이 시스템호출을 사용한다. 불행히도 어떤 시스템에서 아파치는 컴파일할때 sendfile이 정상적으로 작동하지 않는데도 정상적으로 작동한다고 오판한다. 이 문제는 네트웍 파일시스템이나 비표준 파일시스템을 사용할때 자주 발생한다.

이 문제의 증상은 오류 로그(error log)에 위의 문구를 기록하거나 크기가 0이 아닌 파일에 대해 크기가 0인 응답을 하는 경우이다. 동적으로 내용을 생성할때는 sendfile을 사용하지 않기때문에 일반적으로 정적인 파일을 요청할때만 문제가 발생한다.

문제를 해결하려면 서버가 sendfile을 사용하지 않도록 EnableSendfile 지시어를 사용한다. 또, 이와 유사한 문제에 대해 EnableMMAP을 참고하라.

AcceptEx Failed

win32에서 AcceptEx 시스템호출에 대한 오류문을 나오면, Win32DisableAcceptEx 지시어를 참고하라.

Premature end of script headers

보통 CGI 스크립트에 문제가 있으면 브라우저에게 Internal Server Error를 보내고 오류로그에 이 문구를 기록한다. 이런 문제를 디버깅할때 CGI 투토리얼이 도움이 될 수 있다.


Apache SSL/TLS Encryption - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

Apache SSL/TLS Encryption

The Apache HTTP Server module mod_ssl provides an interface to the OpenSSL library, which provides Strong Encryption using the Secure Sockets Layer and Transport Layer Security protocols. The module and this documentation are based on Ralf S. Engelschall's mod_ssl project.

Documentation

  • Introduction
  • Compatibility
  • How-To
  • Frequently Asked Questions
  • Glossary

mod_ssl

Extensive documentation on the directives and environment variables provided by this module is provided in the mod_ssl reference documentation.


SSL/TLS Strong Encryption: An Introduction - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > SSL/TLS

SSL/TLS Strong Encryption: An Introduction

The nice thing about standards is that there are so many to choose from. And if you really don't like all the standards you just have to wait another year until the one arises you are looking for.

-- A. Tanenbaum, "Introduction to Computer Networks"

As an introduction this chapter is aimed at readers who are familiar with the Web, HTTP, and Apache, but are not security experts. It is not intended to be a definitive guide to the SSL protocol, nor does it discuss specific techniques for managing certificates in an organization, or the important legal issues of patents and import and export restrictions. Rather, it is intended to provide a common background to mod_ssl users by pulling together various concepts, definitions, and examples as a starting point for further exploration.

The presented content is mainly derived, with permission by the author, from the article Introducing SSL and Certificates using SSLeay from Frederick J. Hirsch, of The Open Group Research Institute, which was published in Web Security: A Matter of Trust, World Wide Web Journal, Volume 2, Issue 3, Summer 1997. Please send any positive feedback to Frederick Hirsch (the original article author) and all negative feedback to Ralf S. Engelschall (the mod_ssl author).

Cryptographic Techniques

Understanding SSL requires an understanding of cryptographic algorithms, message digest functions (aka. one-way or hash functions), and digital signatures. These techniques are the subject of entire books (see for instance [AC96]) and provide the basis for privacy, integrity, and authentication.

Cryptographic Algorithms

Suppose Alice wants to send a message to her bank to transfer some money. Alice would like the message to be private, since it will include information such as her account number and transfer amount. One solution is to use a cryptographic algorithm, a technique that would transform her message into an encrypted form, unreadable except by those it is intended for. Once in this form, the message may only be interpreted through the use of a secret key. Without the key the message is useless: good cryptographic algorithms make it so difficult for intruders to decode the original text that it isn't worth their effort.

There are two categories of cryptographic algorithms: conventional and public key.

Conventional cryptography
also known as symmetric cryptography, requires the sender and receiver to share a key: a secret piece of information that may be used to encrypt or decrypt a message. If this key is secret, then nobody other than the sender or receiver may read the message. If Alice and the bank know a secret key, then they may send each other private messages. The task of privately choosing a key before communicating, however, can be problematic.
Public key cryptography
also known as asymmetric cryptography, solves the key exchange problem by defining an algorithm which uses two keys, each of which may be used to encrypt a message. If one key is used to encrypt a message then the other must be used to decrypt it. This makes it possible to receive secure messages by simply publishing one key (the public key) and keeping the other secret (the private key).

Anyone may encrypt a message using the public key, but only the owner of the private key will be able to read it. In this way, Alice may send private messages to the owner of a key-pair (the bank), by encrypting it using their public key. Only the bank will be able to decrypt it.

Message Digests

Although Alice may encrypt her message to make it private, there is still a concern that someone might modify her original message or substitute it with a different one, in order to transfer the money to themselves, for instance. One way of guaranteeing the integrity of Alice's message is to create a concise summary of her message and send this to the bank as well. Upon receipt of the message, the bank creates its own summary and compares it with the one Alice sent. If they agree then the message was received intact.

A summary such as this is called a message digest, one-way function or hash function. Message digests are used to create short, fixed-length representations of longer, variable-length messages. Digest algorithms are designed to produce unique digests for different messages. Message digests are designed to make it too difficult to determine the message from the digest, and also impossible to find two different messages which create the same digest -- thus eliminating the possibility of substituting one message for another while maintaining the same digest.

Another challenge that Alice faces is finding a way to send the digest to the bank securely; when this is achieved, the integrity of the associated message is assured. One way to do this is to include the digest in a digital signature.

Digital Signatures

When Alice sends a message to the bank, the bank needs to ensure that the message is really from her, so an intruder does not request a transaction involving her account. A digital signature, created by Alice and included with the message, serves this purpose.

Digital signatures are created by encrypting a digest of the message, and other information (such as a sequence number) with the sender's private key. Though anyone may decrypt the signature using the public key, only the signer knows the private key. This means that only they may have signed it. Including the digest in the signature means the signature is only good for that message; it also ensures the integrity of the message since no one can change the digest and still sign it.

To guard against interception and reuse of the signature by an intruder at a later date, the signature contains a unique sequence number. This protects the bank from a fraudulent claim from Alice that she did not send the message -- only she could have signed it (non-repudiation).

Certificates

Although Alice could have sent a private message to the bank, signed it, and ensured the integrity of the message, she still needs to be sure that she is really communicating with the bank. This means that she needs to be sure that the public key she is using corresponds to the bank's private key. Similarly, the bank also needs to verify that the message signature really corresponds to Alice's signature.

If each party has a certificate which validates the other's identity, confirms the public key, and is signed by a trusted agency, then they both will be assured that they are communicating with whom they think they are. Such a trusted agency is called a Certificate Authority, and certificates are used for authentication.

Certificate Contents

A certificate associates a public key with the real identity of an individual, server, or other entity, known as the subject. As shown in Table 1, information about the subject includes identifying information (the distinguished name), and the public key. It also includes the identification and signature of the Certificate Authority that issued the certificate, and the period of time during which the certificate is valid. It may have additional information (or extensions) as well as administrative information for the Certificate Authority's use, such as a serial number.

Table 1: Certificate Information

Subject | Distinguished Name, Public Key
Issuer | Distinguished Name, Signature
Period of Validity | Not Before Date, Not After Date
Administrative Information | Version, Serial Number
Extended Information | Basic Constraints, Netscape Flags, etc.

A distinguished name is used to provide an identity in a specific context -- for instance, an individual might have a personal certificate as well as one for their identity as an employee. Distinguished names are defined by the X.509 standard [X509], which defines the fields, field names, and abbreviations used to refer to the fields (see Table 2).

Table 2: Distinguished Name Information

DN Field | Abbrev. | Description | Example
Common Name | CN | Name being certified | CN=Joe Average
Organization or Company | O | Name is associated with this organization | O=Snake Oil, Ltd.
Organizational Unit | OU | Name is associated with this organization unit, such as a department | OU=Research Institute
City/Locality | L | Name is located in this City | L=Snake City
State/Province | ST | Name is located in this State/Province | ST=Desert
Country | C | Name is located in this Country (ISO code) | C=XZ

A Certificate Authority may define a policy specifying which distinguished field names are optional, and which are required. It may also place requirements upon the field contents, as may users of certificates. As an example, a Netscape browser requires that the Common Name for a certificate representing a server has a name which matches a wildcard pattern for the domain name of that server, such as *.snakeoil.com.

The binary format of a certificate is defined using the ASN.1 notation [X208] [PKCS]. This notation defines how to specify the contents, and encoding rules define how this information is translated into binary form. The binary encoding of the certificate is defined using Distinguished Encoding Rules (DER), which are based on the more general Basic Encoding Rules (BER). For those transmissions which cannot handle binary, the binary form may be translated into an ASCII form by using Base64 encoding [MIME]. This encoded version is called PEM encoded (the name comes from "Privacy Enhanced Mail"), when placed between begin and end delimiter lines as illustrated in the following example.

Example of a PEM-encoded certificate (snakeoil.crt)

-----BEGIN CERTIFICATE-----
MIIC7jCCAlegAwIBAgIBATANBgkqhkiG9w0BAQQFADCBqTELMAkGA1UEBhMCWFkx
FTATBgNVBAgTDFNuYWtlIERlc2VydDETMBEGA1UEBxMKU25ha2UgVG93bjEXMBUG
A1UEChMOU25ha2UgT2lsLCBMdGQxHjAcBgNVBAsTFUNlcnRpZmljYXRlIEF1dGhv
cml0eTEVMBMGA1UEAxMMU25ha2UgT2lsIENBMR4wHAYJKoZIhvcNAQkBFg9jYUBz
bmFrZW9pbC5kb20wHhcNOTgxMDIxMDg1ODM2WhcNOTkxMDIxMDg1ODM2WjCBpzEL
MAkGA1UEBhMCWFkxFTATBgNVBAgTDFNuYWtlIERlc2VydDETMBEGA1UEBxMKU25h
a2UgVG93bjEXMBUGA1UEChMOU25ha2UgT2lsLCBMdGQxFzAVBgNVBAsTDldlYnNl
cnZlciBUZWFtMRkwFwYDVQQDExB3d3cuc25ha2VvaWwuZG9tMR8wHQYJKoZIhvcN
AQkBFhB3d3dAc25ha2VvaWwuZG9tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKB
gQDH9Ge/s2zcH+da+rPTx/DPRp3xGjHZ4GG6pCmvADIEtBtKBFAcZ64n+Dy7Np8b
vKR+yy5DGQiijsH1D/j8HlGE+q4TZ8OFk7BNBFazHxFbYI4OKMiCxdKzdif1yfaa
lWoANFlAzlSdbxeGVHoT0K+gT5w3UxwZKv2DLbCTzLZyPwIDAQABoyYwJDAPBgNV
HRMECDAGAQH/AgEAMBEGCWCGSAGG+EIBAQQEAwIAQDANBgkqhkiG9w0BAQQFAAOB
gQAZUIHAL4D09oE6Lv2k56Gp38OBDuILvwLg1v1KL8mQR+KFjghCrtpqaztZqcDt
2q2QoyulCgSzHbEGmi0EsdkPfg6mp0penssIFePYNI+/8u9HT4LuKMJX15hxBam7
dUHzICxBVC1lnHyYGjDuAMhe396lYAn8bCld1/L4NMGBCQ==
-----END CERTIFICATE-----

Certificate Authorities

By first verifying the information in a certificate request before granting the certificate, the Certificate Authority assures the identity of the private key owner of a key-pair. For instance, if Alice requests a personal certificate, the Certificate Authority must first make sure that Alice really is the person the certificate request claims.

Certificate Chains

A Certificate Authority may also issue a certificate for another Certificate Authority. When examining a certificate, Alice may need to examine the certificate of the issuer, for each parent Certificate Authority, until reaching one which she has confidence in. She may decide to trust only certificates with a limited chain of issuers, to reduce her risk of a "bad" certificate in the chain.

Creating a Root-Level CA

As noted earlier, each certificate requires an issuer to assert the validity of the identity of the certificate subject, up to the top-level Certificate Authority (CA). This presents a problem: Since this is who vouches for the certificate of the top-level authority, which has no issuer? In this unique case, the certificate is "self-signed", so the issuer of the certificate is the same as the subject. As a result, one must exercise extra care in trusting a self-signed certificate. The wide publication of a public key by the root authority reduces the risk in trusting this key -- it would be obvious if someone else publicized a key claiming to be the authority. Browsers are preconfigured to trust well-known certificate authorities.

A number of companies, such as Thawte and VeriSign have established themselves as Certificate Authorities. These companies provide the following services:

  • Verifying certificate requests
  • Processing certificate requests
  • Issuing and managing certificates

It is also possible to create your own Certificate Authority. Although risky in the Internet environment, it may be useful within an Intranet where the organization can easily verify the identities of individuals and servers.

Certificate Management

Establishing a Certificate Authority is a responsibility which requires a solid administrative, technical, and management framework. Certificate Authorities not only issue certificates, they also manage them -- that is, they determine how long certificates are valid, they renew them, and they keep lists of certificates that have already been issued but are no longer valid (Certificate Revocation Lists, or CRLs). Say Alice is entitled to a certificate as an employee of a company. Say too, that the certificate needs to be revoked when Alice leaves the company. Since certificates are objects that get passed around, it is impossible to tell from the certificate alone that it has been revoked. When examining certificates for validity, therefore, it is necessary to contact the issuing Certificate Authority to check CRLs -- this is not usually an automated part of the process.

Note

If you use a Certificate Authority that is not configured into browsers by default, it is necessary to load the Certificate Authority certificate into the browser, enabling the browser to validate server certificates signed by that Certificate Authority. Doing so may be dangerous, since once loaded, the browser will accept all certificates signed by that Certificate Authority.

Secure Sockets Layer (SSL)

The Secure Sockets Layer protocol is a protocol layer which may be placed between a reliable connection-oriented network layer protocol (e.g. TCP/IP) and the application protocol layer (e.g. HTTP). SSL provides for secure communication between client and server by allowing mutual authentication, the use of digital signatures for integrity, and encryption for privacy.

The protocol is designed to support a range of choices for specific algorithms used for cryptography, digests, and signatures. This allows algorithm selection for specific servers to be made based on legal, export or other concerns, and also enables the protocol to take advantage of new algorithms. Choices are negotiated between client and server at the start of establishing a protocol session.

Table 4: Versions of the SSL protocol

Version | Source | Description | Browser Support
SSL v2.0 | Vendor Standard (from Netscape Corp.) [SSL2] | First SSL protocol for which implementations exists | - NS Navigator 1.x/2.x - MS IE 3.x - Lynx/2.8+OpenSSL
SSL v3.0 | Expired Internet Draft (from Netscape Corp.) [SSL3] | Revisions to prevent specific security attacks, add non-RSA ciphers, and support for certificate chains | - NS Navigator 2.x/3.x/4.x - MS IE 3.x/4.x - Lynx/2.8+OpenSSL
TLS v1.0 | Proposed Internet Standard (from IETF) [TLS1] | Revision of SSL 3.0 to update the MAC layer to HMAC, add block padding for block ciphers, message order standardization and more alert messages. | - Lynx/2.8+OpenSSL

There are a number of versions of the SSL protocol, as shown in Table 4. As noted there, one of the benefits in SSL 3.0 is that it adds support of certificate chain loading. This feature allows a server to pass a server certificate along with issuer certificates to the browser. Chain loading also permits the browser to validate the server certificate, even if Certificate Authority certificates are not installed for the intermediate issuers, since they are included in the certificate chain. SSL 3.0 is the basis for the Transport Layer Security [TLS] protocol standard, currently in development by the Internet Engineering Task Force (IETF).

Session Establishment

The SSL session is established by following a handshake sequence between client and server, as shown in Figure 1. This sequence may vary, depending on whether the server is configured to provide a server certificate or request a client certificate. Though cases exist where additional handshake steps are required for management of cipher information, this article summarizes one common scenario: see the SSL specification for the full range of possibilities.

Note

Once an SSL session has been established it may be reused, thus avoiding the performance penalty of repeating the many steps needed to start a session. For this the server assigns each SSL session a unique session identifier which is cached in the server and which the client can use on forthcoming connections to reduce the handshake (until the session identifer expires in the cache of the server).

Figure 1: Simplified SSL Handshake Sequence

The elements of the handshake sequence, as used by the client and server, are listed below:

  1. Negotiate the Cipher Suite to be used during data transfer
  2. Establish and share a session key between client and server
  3. Optionally authenticate the server to the client
  4. Optionally authenticate the client to the server

The first step, Cipher Suite Negotiation, allows the client and server to choose a Cipher Suite supportable by both of them. The SSL3.0 protocol specification defines 31 Cipher Suites. A Cipher Suite is defined by the following components:

  • Key Exchange Method
  • Cipher for Data Transfer
  • Message Digest for creating the Message Authentication Code (MAC)

These three elements are described in the sections that follow.

Key Exchange Method

The key exchange method defines how the shared secret symmetric cryptography key used for application data transfer will be agreed upon by client and server. SSL 2.0 uses RSA key exchange only, while SSL 3.0 supports a choice of key exchange algorithms including the RSA key exchange when certificates are used, and Diffie-Hellman key exchange for exchanging keys without certificates and without prior communication between client and server.

One variable in the choice of key exchange methods is digital signatures -- whether or not to use them, and if so, what kind of signatures to use. Signing with a private key provides assurance against a man-in-the-middle-attack during the information exchange used in generating the shared key [AC96, p516].

Cipher for Data Transfer

SSL uses the conventional cryptography algorithm (symmetric cryptography) described earlier for encrypting messages in a session. There are nine choices, including the choice to perform no encryption:

  • No encryption
  • Stream Ciphers
    • RC4 with 40-bit keys
    • RC4 with 128-bit keys
  • CBC Block Ciphers
    • RC2 with 40 bit key
    • DES with 40 bit key
    • DES with 56 bit key
    • Triple-DES with 168 bit key
    • Idea (128 bit key)
    • Fortezza (96 bit key)

Here "CBC" refers to Cipher Block Chaining, which means that a portion of the previously encrypted cipher text is used in the encryption of the current block. "DES" refers to the Data Encryption Standard [AC96, ch12], which has a number of variants (including DES40 and 3DES_EDE). "Idea" is one of the best and cryptographically strongest available algorithms, and "RC2" is a proprietary algorithm from RSA DSI [AC96, ch13].

Digest Function

The choice of digest function determines how a digest is created from a record unit. SSL supports the following:

  • No digest (Null choice)
  • MD5, a 128-bit hash
  • Secure Hash Algorithm (SHA-1), a 160-bit hash

The message digest is used to create a Message Authentication Code (MAC) which is encrypted with the message to provide integrity and to prevent against replay attacks.

Handshake Sequence Protocol

The handshake sequence uses three protocols:

  • The SSL Handshake Protocol for performing the client and server SSL session establishment.
  • The SSL Change Cipher Spec Protocol for actually establishing agreement on the Cipher Suite for the session.
  • The SSL Alert Protocol for conveying SSL error messages between client and server.

These protocols, as well as application protocol data, are encapsulated in the SSL Record Protocol, as shown in Figure 2. An encapsulated protocol is transferred as data by the lower layer protocol, which does not examine the data. The encapsulated protocol has no knowledge of the underlying protocol.

Figure 2: SSL Protocol Stack

The encapsulation of SSL control protocols by the record protocol means that if an active session is renegotiated the control protocols will be transmitted securely. If there were no session before, then the Null cipher suite is used, which means there is no encryption and messages have no integrity digests until the session has been established.

Data Transfer

The SSL Record Protocol, shown in Figure 3, is used to transfer application and SSL Control data between the client and server, possibly fragmenting this data into smaller units, or combining multiple higher level protocol data messages into single units. It may compress, attach digest signatures, and encrypt these units before transmitting them using the underlying reliable transport protocol (Note: currently all major SSL implementations lack support for compression).

Figure 3: SSL Record Protocol

Securing HTTP Communication

One common use of SSL is to secure Web HTTP communication between a browser and a webserver. This case does not preclude the use of non-secured HTTP. The secure version is mainly plain HTTP over SSL (named HTTPS), but with one major difference: it uses the URL scheme https rather than http and a different server port (by default 443). This mainly is what mod_ssl provides to you for the Apache webserver...

References

[AC96]
Bruce Schneier, Applied Cryptography, 2nd Edition, Wiley, 1996. See http://www.counterpane.com/ for various other materials by Bruce Schneier.
[X208]
ITU-T Recommendation X.208, Specification of Abstract Syntax Notation One (ASN.1), 1988. See for instance http://www.itu.int/rec/recommendation.asp?type=items&lang=e&parent=T-REC-X.208-198811-I.
[X509]
ITU-T Recommendation X.509, The Directory - Authentication Framework. See for instance http://www.itu.int/rec/recommendation.asp?type=folders&lang=e&parent=T-REC-X.509.
[PKCS]
Public Key Cryptography Standards (PKCS), RSA Laboratories Technical Notes, See http://www.rsasecurity.com/rsalabs/pkcs/.
[MIME]
N. Freed, N. Borenstein, Multipurpose Internet Mail Extensions (MIME) Part One: Format of Internet Message Bodies, RFC2045. See for instance http://ietf.org/rfc/rfc2045.txt.
[SSL2]
Kipp E.B. Hickman, The SSL Protocol, 1995. See http://www.netscape.com/eng/security/SSL_2.html.
[SSL3]
Alan O. Freier, Philip Karlton, Paul C. Kocher, The SSL Protocol Version 3.0, 1996. See http://www.netscape.com/eng/ssl3/draft302.txt.
[TLS1]
Tim Dierks, Christopher Allen, The TLS Protocol Version 1.0, 1999. See http://ietf.org/rfc/rfc2246.txt.


SSL/TLS Strong Encryption: Compatibility - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > SSL/TLS

SSL/TLS Strong Encryption: Compatibility

All PCs are compatible. But some of them are more compatible than others.

-- Unknown

Here we talk about backward compatibility to other SSL solutions. As you perhaps know, mod_ssl is not the only existing SSL solution for Apache. Actually there are four additional major products available on the market: Ben Laurie's freely available Apache-SSL (from where mod_ssl were originally derived in 1998), Red Hat's commercial Secure Web Server (which is based on mod_ssl), Covalent's commercial Raven SSL Module (also based on mod_ssl) and finally C2Net's commercial product Stronghold (based on a different evolution branch named Sioux up to Stronghold 2.x and based on mod_ssl since Stronghold 3.x).

The idea in mod_ssl is mainly the following: because mod_ssl provides mostly a superset of the functionality of all other solutions we can easily provide backward compatibility for most of the cases. Actually there are three compatibility areas we currently address: configuration directives, environment variables and custom log functions.

Configuration Directives

For backward compatibility to the configuration directives of other SSL solutions we do an on-the-fly mapping: directives which have a direct counterpart in mod_ssl are mapped silently while other directives lead to a warning message in the logfiles. The currently implemented directive mapping is listed in Table 1. Currently full backward compatibility is provided only for Apache-SSL 1.x and mod_ssl 2.0.x. Compatibility to Sioux 1.x and Stronghold 2.x is only partial because of special functionality in these interfaces which mod_ssl (still) doesn't provide.

Table 1: Configuration Directive Mapping

Old Directive | mod_ssl Directive | Comment
Apache-SSL 1.x & mod_ssl 2.0.x compatibility:
SSLEnable | SSLEngine on | compactified
SSLDisable | SSLEngine off | compactified
SSLLogFile file | SSLLog file | compactified
SSLRequiredCiphers spec | SSLCipherSuite spec | renamed
SSLRequireCipher c1 ... | SSLRequire %{SSL_CIPHER} in {"c1", ...} | generalized
SSLBanCipher c1 ... | SSLRequire not (%{SSL_CIPHER} in {"c1", ...}) | generalized
SSLFakeBasicAuth | SSLOptions +FakeBasicAuth | merged
SSLCacheServerPath dir | - | functionality removed
SSLCacheServerPort integer | - | functionality removed
Apache-SSL 1.x compatibility:
SSLExportClientCertificates | SSLOptions +ExportCertData | merged
SSLCacheServerRunDir dir | - | functionality not supported
Sioux 1.x compatibility:
SSL_CertFile file | SSLCertificateFile file | renamed
SSL_KeyFile file | SSLCertificateKeyFile file | renamed
SSL_CipherSuite arg | SSLCipherSuite arg | renamed
SSL_X509VerifyDir arg | SSLCACertificatePath arg | renamed
SSL_Log file | SSLLogFile file | renamed
SSL_Connect flag | SSLEngine flag | renamed
SSL_ClientAuth arg | SSLVerifyClient arg | renamed
SSL_X509VerifyDepth arg | SSLVerifyDepth arg | renamed
SSL_FetchKeyPhraseFrom arg | - | not directly mappable; use SSLPassPhraseDialog
SSL_SessionDir dir | - | not directly mappable; use SSLSessionCache
SSL_Require expr | - | not directly mappable; use SSLRequire
SSL_CertFileType arg | - | functionality not supported
SSL_KeyFileType arg | - | functionality not supported
SSL_X509VerifyPolicy arg | - | functionality not supported
SSL_LogX509Attributes arg | - | functionality not supported
Stronghold 2.x compatibility:
StrongholdAccelerator dir | - | functionality not supported
StrongholdKey dir | - | functionality not supported
StrongholdLicenseFile dir | - | functionality not supported
SSLFlag flag | SSLEngine flag | renamed
SSLSessionLockFile file | SSLMutex file | renamed
SSLCipherList spec | SSLCipherSuite spec | renamed
RequireSSL | SSLRequireSSL | renamed
SSLErrorFile file | - | functionality not supported
SSLRoot dir | - | functionality not supported
SSL_CertificateLogDir dir | - | functionality not supported
AuthCertDir dir | - | functionality not supported
SSL_Group name | - | functionality not supported
SSLProxyMachineCertPath dir | - | functionality not supported
SSLProxyMachineCertFile file | - | functionality not supported
SSLProxyCACertificatePath dir | - | functionality not supported
SSLProxyCACertificateFile file | - | functionality not supported
SSLProxyVerifyDepth number | - | functionality not supported
SSLProxyCipherList spec | - | functionality not supported

Environment Variables

When you use ``SSLOptions +CompatEnvVars'' additional environment variables are generated. They all correspond to existing official mod_ssl variables. The currently implemented variable derivation is listed in Table 2.

Table 2: Environment Variable Derivation

Old Variable | mod_ssl Variable | Comment
SSL_PROTOCOL_VERSION | SSL_PROTOCOL | renamed
SSLEAY_VERSION | SSL_VERSION_LIBRARY | renamed
HTTPS_SECRETKEYSIZE | SSL_CIPHER_USEKEYSIZE | renamed
HTTPS_KEYSIZE | SSL_CIPHER_ALGKEYSIZE | renamed
HTTPS_CIPHER | SSL_CIPHER | renamed
HTTPS_EXPORT | SSL_CIPHER_EXPORT | renamed
SSL_SERVER_KEY_SIZE | SSL_CIPHER_ALGKEYSIZE | renamed
SSL_SERVER_CERTIFICATE | SSL_SERVER_CERT | renamed
SSL_SERVER_CERT_START | SSL_SERVER_V_START | renamed
SSL_SERVER_CERT_END | SSL_SERVER_V_END | renamed
SSL_SERVER_CERT_SERIAL | SSL_SERVER_M_SERIAL | renamed
SSL_SERVER_SIGNATURE_ALGORITHM | SSL_SERVER_A_SIG | renamed
SSL_SERVER_DN | SSL_SERVER_S_DN | renamed
SSL_SERVER_CN | SSL_SERVER_S_DN_CN | renamed
SSL_SERVER_EMAIL | SSL_SERVER_S_DN_Email | renamed
SSL_SERVER_O | SSL_SERVER_S_DN_O | renamed
SSL_SERVER_OU | SSL_SERVER_S_DN_OU | renamed
SSL_SERVER_C | SSL_SERVER_S_DN_C | renamed
SSL_SERVER_SP | SSL_SERVER_S_DN_SP | renamed
SSL_SERVER_L | SSL_SERVER_S_DN_L | renamed
SSL_SERVER_IDN | SSL_SERVER_I_DN | renamed
SSL_SERVER_ICN | SSL_SERVER_I_DN_CN | renamed
SSL_SERVER_IEMAIL | SSL_SERVER_I_DN_Email | renamed
SSL_SERVER_IO | SSL_SERVER_I_DN_O | renamed
SSL_SERVER_IOU | SSL_SERVER_I_DN_OU | renamed
SSL_SERVER_IC | SSL_SERVER_I_DN_C | renamed
SSL_SERVER_ISP | SSL_SERVER_I_DN_SP | renamed
SSL_SERVER_IL | SSL_SERVER_I_DN_L | renamed
SSL_CLIENT_CERTIFICATE | SSL_CLIENT_CERT | renamed
SSL_CLIENT_CERT_START | SSL_CLIENT_V_START | renamed
SSL_CLIENT_CERT_END | SSL_CLIENT_V_END | renamed
SSL_CLIENT_CERT_SERIAL | SSL_CLIENT_M_SERIAL | renamed
SSL_CLIENT_SIGNATURE_ALGORITHM | SSL_CLIENT_A_SIG | renamed
SSL_CLIENT_DN | SSL_CLIENT_S_DN | renamed
SSL_CLIENT_CN | SSL_CLIENT_S_DN_CN | renamed
SSL_CLIENT_EMAIL | SSL_CLIENT_S_DN_Email | renamed
SSL_CLIENT_O | SSL_CLIENT_S_DN_O | renamed
SSL_CLIENT_OU | SSL_CLIENT_S_DN_OU | renamed
SSL_CLIENT_C | SSL_CLIENT_S_DN_C | renamed
SSL_CLIENT_SP | SSL_CLIENT_S_DN_SP | renamed
SSL_CLIENT_L | SSL_CLIENT_S_DN_L | renamed
SSL_CLIENT_IDN | SSL_CLIENT_I_DN | renamed
SSL_CLIENT_ICN | SSL_CLIENT_I_DN_CN | renamed
SSL_CLIENT_IEMAIL | SSL_CLIENT_I_DN_Email | renamed
SSL_CLIENT_IO | SSL_CLIENT_I_DN_O | renamed
SSL_CLIENT_IOU | SSL_CLIENT_I_DN_OU | renamed
SSL_CLIENT_IC | SSL_CLIENT_I_DN_C | renamed
SSL_CLIENT_ISP | SSL_CLIENT_I_DN_SP | renamed
SSL_CLIENT_IL | SSL_CLIENT_I_DN_L | renamed
SSL_EXPORT | SSL_CIPHER_EXPORT | renamed
SSL_KEYSIZE | SSL_CIPHER_ALGKEYSIZE | renamed
SSL_SECKEYSIZE | SSL_CIPHER_USEKEYSIZE | renamed
SSL_SSLEAY_VERSION | SSL_VERSION_LIBRARY | renamed
SSL_STRONG_CRYPTO | - | Not supported by mod_ssl
SSL_SERVER_KEY_EXP | - | Not supported by mod_ssl
SSL_SERVER_KEY_ALGORITHM | - | Not supported by mod_ssl
SSL_SERVER_KEY_SIZE | - | Not supported by mod_ssl
SSL_SERVER_SESSIONDIR | - | Not supported by mod_ssl
SSL_SERVER_CERTIFICATELOGDIR | - | Not supported by mod_ssl
SSL_SERVER_CERTFILE | - | Not supported by mod_ssl
SSL_SERVER_KEYFILE | - | Not supported by mod_ssl
SSL_SERVER_KEYFILETYPE | - | Not supported by mod_ssl
SSL_CLIENT_KEY_EXP | - | Not supported by mod_ssl
SSL_CLIENT_KEY_ALGORITHM | - | Not supported by mod_ssl
SSL_CLIENT_KEY_SIZE | - | Not supported by mod_ssl

Custom Log Functions

When mod_ssl is built into Apache or at least loaded (under DSO situation) additional functions exist for the Custom Log Format of mod_log_config as documented in the Reference Chapter. Beside the ``%{varname}x'' eXtension format function which can be used to expand any variables provided by any module, an additional Cryptography ``%{name}c'' cryptography format function exists for backward compatibility. The currently implemented function calls are listed in Table 3.

Table 3: Custom Log Cryptography Function

Function Call | Description
%...{version}c | SSL protocol version
%...{cipher}c | SSL cipher
%...{subjectdn}c | Client Certificate Subject Distinguished Name
%...{issuerdn}c | Client Certificate Issuer Distinguished Name
%...{errcode}c | Certificate Verification Error (numerical)
%...{errstr}c | Certificate Verification Error (string)


SSL/TLS Strong Encryption: How-To - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > SSL/TLS

SSL/TLS Strong Encryption: How-To

The solution of this problem is trivial and is left as an exercise for the reader.

-- Standard textbook cookie

How to solve particular security constraints for an SSL-aware webserver is not always obvious because of the coherences between SSL, HTTP and Apache's way of processing requests. This chapter gives instructions on how to solve such typical situations. Treat it as a first step to find out the final solution, but always try to understand the stuff before you use it. Nothing is worse than using a security solution without knowing its restrictions and coherences.

Cipher Suites and Enforced Strong Security

  • SSLv2 only server
  • strong encryption only server
  • server gated cryptography
  • stronger per-directory requirements

How can I create a real SSLv2-only server?

The following creates an SSL server which speaks only the SSLv2 protocol and its ciphers.

httpd.conf

SSLProtocol -all +SSLv2
SSLCipherSuite SSLv2:+HIGH:+MEDIUM:+LOW:+EXP

How can I create an SSL server which accepts strong encryption only?

The following enables only the seven strongest ciphers:

httpd.conf

SSLProtocol all
SSLCipherSuite HIGH:MEDIUM

How can I create an SSL server which accepts strong encryption only, but allows export browsers to upgrade to stronger encryption?

This facility is called Server Gated Cryptography (SGC) and details you can find in the README.GlobalID document in the mod_ssl distribution. In short: The server has a Global ID server certificate, signed by a special CA certificate from Verisign which enables strong encryption in export browsers. This works as following: The browser connects with an export cipher, the server sends its Global ID certificate, the browser verifies it and subsequently upgrades the cipher suite before any HTTP communication takes place. The question now is: How can we allow this upgrade, but enforce strong encryption. Or in other words: Browser either have to initially connect with strong encryption or have to upgrade to strong encryption, but are not allowed to keep the export ciphers. The following does the trick:

httpd.conf

# allow all ciphers for the initial handshake,
# so export browsers can upgrade via SGC facility
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

<Directory /usr/local/apache2/htdocs>
# but finally deny all browsers which haven't upgraded
SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128
</Directory>

How can I create an SSL server which accepts all types of ciphers in general, but requires a strong ciphers for access to a particular URL?

Obviously you cannot just use a server-wide SSLCipherSuite which restricts the ciphers to the strong variants. But mod_ssl allows you to reconfigure the cipher suite in per-directory context and automatically forces a renegotiation of the SSL parameters to meet the new configuration. So, the solution is:

# be liberal in general
SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL

<Location /strong/area>
# but https://hostname/strong/area/ and below
# requires strong ciphers
SSLCipherSuite HIGH:MEDIUM
</Location>

Client Authentication and Access Control

  • simple certificate-based client authentication
  • selective certificate-based client authentication
  • particular certificate-based client authentication
  • intranet vs. internet authentication

How can I authenticate clients based on certificates when I know all my clients?

When you know your user community (i.e. a closed user group situation), as it's the case for instance in an Intranet, you can use plain certificate authentication. All you have to do is to create client certificates signed by your own CA certificate ca.crt and then verify the clients against this certificate.

httpd.conf

# require a client certificate which has to be directly
# signed by our CA certificate in ca.crt
SSLVerifyClient require
SSLVerifyDepth 1
SSLCACertificateFile conf/ssl.crt/ca.crt

How can I authenticate my clients for a particular URL based on certificates but still allow arbitrary clients to access the remaining parts of the server?

For this we again use the per-directory reconfiguration feature of mod_ssl:

httpd.conf

SSLVerifyClient none
SSLCACertificateFile conf/ssl.crt/ca.crt

<Location /secure/area>
SSLVerifyClient require
SSLVerifyDepth 1
</Location>

How can I authenticate only particular clients for a some URLs based on certificates but still allow arbitrary clients to access the remaining parts of the server?

The key is to check for various ingredients of the client certificate. Usually this means to check the whole or part of the Distinguished Name (DN) of the Subject. For this two methods exists: The mod_auth based variant and the SSLRequire variant. The first method is good when the clients are of totally different type, i.e. when their DNs have no common fields (usually the organisation, etc.). In this case you've to establish a password database containing all clients. The second method is better when your clients are all part of a common hierarchy which is encoded into the DN. Then you can match them more easily.

The first method:

httpd.conf

SSLVerifyClient      none
<Directory /usr/local/apache2/htdocs/secure/area>

SSLVerifyClient      require
SSLVerifyDepth       5
SSLCACertificateFile conf/ssl.crt/ca.crt
SSLCACertificatePath conf/ssl.crt
SSLOptions           +FakeBasicAuth
SSLRequireSSL
AuthName             "Snake Oil Authentication"
AuthType             Basic
AuthUserFile         /usr/local/apache2/conf/httpd.passwd
require              valid-user
</Directory>

httpd.passwd

/C=DE/L=Munich/O=Snake Oil, Ltd./OU=Staff/CN=Foo:xxj31ZMTZzkVA
/C=US/L=S.F./O=Snake Oil, Ltd./OU=CA/CN=Bar:xxj31ZMTZzkVA
/C=US/L=L.A./O=Snake Oil, Ltd./OU=Dev/CN=Quux:xxj31ZMTZzkVA

The second method:

httpd.conf

SSLVerifyClient      none
<Directory /usr/local/apache2/htdocs/secure/area>

  SSLVerifyClient      require
  SSLVerifyDepth       5
  SSLCACertificateFile conf/ssl.crt/ca.crt
  SSLCACertificatePath conf/ssl.crt
  SSLOptions           +FakeBasicAuth
  SSLRequireSSL
  SSLRequire       %{SSL_CLIENT_S_DN_O}  eq "Snake Oil, Ltd." \
               and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"}
</Directory>

How can I require HTTPS with strong ciphers and either basic authentication or client certificates for access to a subarea on the Intranet website for clients coming from the Internet but still allow plain HTTP access for clients on the Intranet?

Let us assume the Intranet can be distinguished through the IP network 192.160.1.0/24 and the subarea on the Intranet website has the URL /subarea. Then configure the following outside your HTTPS virtual host (so it applies to both HTTPS and HTTP):

httpd.conf

SSLCACertificateFile conf/ssl.crt/company-ca.crt

<Directory /usr/local/apache2/htdocs>
#   Outside the subarea only Intranet access is granted
Order                deny,allow
Deny                 from all
Allow                from 192.168.1.0/24
</Directory>

<Directory /usr/local/apache2/htdocs/subarea>
#   Inside the subarea any Intranet access is allowed
#   but from the Internet only HTTPS + Strong-Cipher + Password
#   or the alternative HTTPS + Strong-Cipher + Client-Certificate

#   If HTTPS is used, make sure a strong cipher is used.
#   Additionally allow client certs as alternative to basic auth.
SSLVerifyClient      optional
SSLVerifyDepth       1
SSLOptions           +FakeBasicAuth +StrictRequire
SSLRequire           %{SSL_CIPHER_USEKEYSIZE} >= 128

#   Force clients from the Internet to use HTTPS
RewriteEngine        on
RewriteCond          %{REMOTE_ADDR} !^192\.168\.1\.[0-9]+$
RewriteCond          %{HTTPS} !=on
RewriteRule          .* - [F]

#   Allow Network Access and/or Basic Auth
Satisfy              any

#   Network Access Control
Order                deny,allow
Deny                 from all
Allow                192.168.1.0/24

#   HTTP Basic Authentication
AuthType             basic
AuthName             "Protected Intranet Area"
AuthUserFile         conf/protected.passwd
Require              valid-user
</Directory>


SSL/TLS Strong Encryption: FAQ - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > SSL/TLS

SSL/TLS Strong Encryption: FAQ

The wise man doesn't give the right answers, he poses the right questions.

-- Claude Levi-Strauss

This chapter is a collection of frequently asked questions (FAQ) and corresponding answers following the popular USENET tradition. Most of these questions occurred on the Newsgroup comp.infosystems.www.servers.unix or the mod_ssl Support Mailing List modssl-users@modssl.org. They are collected at this place to avoid answering the same questions over and over.

Please read this chapter at least once when installing mod_ssl or at least search for your problem here before submitting a problem report to the author.

About The Module

  • What is the history of mod_ssl?
  • mod_ssl and Year 2000?
  • mod_ssl and Wassenaar Arrangement?

What is the history of mod_ssl?

The mod_ssl v1 package was initially created in April 1998 by Ralf S. Engelschall via porting Ben Laurie's Apache-SSL 1.17 source patches for Apache 1.2.6 to Apache 1.3b6. Because of conflicts with Ben Laurie's development cycle it then was re-assembled from scratch for Apache 1.3.0 by merging the old mod_ssl 1.x with the newer Apache-SSL 1.18. From this point on mod_ssl lived its own life as mod_ssl v2. The first publicly released version was mod_ssl 2.0.0 from August 10th, 1998.

After US export restrictions on cryptographic software were loosened, mod_ssl became part of the Apache HTTP Server with the release of Apache httpd 2.

Is mod_ssl affected by the Wassenaar Arrangement?

First, let us explain what Wassenaar and its Arrangement on Export Controls for Conventional Arms and Dual-Use Goods and Technologies is: This is a international regime, established in 1995, to control trade in conventional arms and dual-use goods and technology. It replaced the previous CoCom regime. Further details on both the Arrangement and its signatories are available at http://www.wassenaar.org/.

In short, the aim of the Wassenaar Arrangement is to prevent the build up of military capabilities that threaten regional and international security and stability. The Wassenaar Arrangement controls the export of cryptography as a dual-use good, that is, something that has both military and civilian applications. However, the Wassenaar Arrangement also provides an exemption from export controls for mass-market software and free software.

In the current Wassenaar List of Dual Use Goods and Technologies And Munitions, under GENERAL SOFTWARE NOTE (GSN) it says The Lists do not control "software" which is either: 1. [...] 2. "in the public domain". And under DEFINITIONS OF TERMS USED IN THESE LISTS we find In the public domain defined as "technology" or "software" which has been made available without restrictions upon its further dissemination. Note: Copyright restrictions do not remove "technology" or "software" from being "in the public domain".

So, both mod_ssl and OpenSSL are in the public domain for the purposes of the Wassenaar Arrangement and its List of Dual Use Goods and Technologies And Munitions List, and thus not affected by its provisions.

Installation

  • Why do I get permission errors related to SSLMutex when I start Apache?
  • Why does mod_ssl stop with the error "Failed to generate temporary 512 bit RSA private key", when I start Apache?

Why do I get permission errors related to SSLMutex when I start Apache?

Errors such as ``mod_ssl: Child could not open SSLMutex lockfile /opt/apache/logs/ssl_mutex.18332 (System error follows) [...] System: Permission denied (errno: 13)'' are usually caused by overly restrictive permissions on the parent directories. Make sure that all parent directories (here /opt, /opt/apache and /opt/apache/logs) have the x-bit set for, at minimum, the UID under which Apache's children are running (see the User directive).

Why does mod_ssl stop with the error "Failed to generate temporary 512 bit RSA private key", when I start Apache?

Cryptographic software needs a source of unpredictable data to work correctly. Many open source operating systems provide a "randomness device" that serves this purpose (usually named /dev/random). On other systems, applications have to seed the OpenSSL Pseudo Random Number Generator (PRNG) manually with appropriate data before generating keys or performing public key encryption. As of version 0.9.5, the OpenSSL functions that need randomness report an error if the PRNG has not been seeded with at least 128 bits of randomness.

To prevent this error, mod_ssl has to provide enough entropy to the PRNG to allow it to work correctly. This can be done via the SSLRandomSeed directives.

Configuration

  • Is it possible to provide HTTP and HTTPS from the same server?
  • Which port does HTTPS use?
  • How do I speak HTTPS manually for testing purposes?
  • Why does the connection hang when I connect to my SSL-aware Apache server
  • Why do I get ``Connection Refused'' errors, when trying to access my newly installed Apache+mod_ssl server via HTTPS?
  • Why are the SSL_XXX variables not available to my CGI & SSI scripts?
  • How can I switch between HTTP and HTTPS in relative hyperlinks?

Is it possible to provide HTTP and HTTPS from the same server?

Yes. HTTP and HTTPS use different server ports (HTTP binds to port 80, HTTPS to port 443), so there is no direct conflict between them. You can either run two separate server instances bound to these ports, or use Apache's elegant virtual hosting facility to create two virtual servers over one instance of Apache - one responding to requests on port 80 and speaking HTTP and the other responding to requests on port 443 speaking HTTPS.

Which port does HTTPS use?

You can run HTTPS on any port, but the standards specify port 443, which is where any HTTPS compliant browser will look by default. You can force your browser to look on a different port by specifying it in the URL like this (for port 666): https://secure.server.dom:666/

How do I speak HTTPS manually for testing purposes?

While you usually just use

$ telnet localhost 80
GET / HTTP/1.0

for simple testing of Apache via HTTP, it's not so easy for HTTPS because of the SSL protocol between TCP and HTTP. With the help of OpenSSL's s_client command, however, you can do a similar check for HTTPS:

$ openssl s_client -connect localhost:443 -state -debug
GET / HTTP/1.0

Before the actual HTTP response you will receive detailed information about the SSL handshake. For a more general command line client which directly understands both HTTP and HTTPS, can perform GET and POST operations, can use a proxy, supports byte ranges, etc. you should have a look at the nifty cURL tool. Using this, you can check that Apache is responding correctly on ports 80 and 443 as follows:

$ curl http://localhost/
$ curl https://localhost/

Why does the connection hang when I connect to my SSL-aware Apache server?

Because you connected with HTTP to the HTTPS port, i.e. you used an URL of the form ``http://'' instead of ``https://''. This also happens the other way round when you connect via HTTPS to a HTTP port, i.e. when you try to use ``https://'' on a server that doesn't support SSL (on this port). Make sure you are connecting to a virtual server that supports SSL, which is probably the IP associated with your hostname, not localhost (127.0.0.1).

Why do I get ``Connection Refused'' messages, when trying to access my newly installed Apache+mod_ssl server via HTTPS?

This can happen for various reasons. The most common mistakes include starting Apache with just apachectl start (or httpd) instead of apachectl startssl (or httpd -DSSL). Your configuration may also be incorrect. Please make sure that your Listen directives match your <VirtualHost> directives. If all else fails, please start afresh, using the default configuration provided by mod_ssl.

Why are the SSL_XXX variables not available to my CGI & SSI scripts?

Please make sure you have ``SSLOptions +StdEnvVars'' enabled for the context of your CGI/SSI requests.

How can I switch between HTTP and HTTPS in relative hyperlinks?

Usually, to switch between HTTP and HTTPS, you have to use fully-qualified hyperlinks (because you have to change the URL scheme). Using mod_rewrite however, you can manipulate relative hyperlinks, to achieve the same effect.

RewriteEngine on
RewriteRule ^/(.*):SSL$ https://%{SERVER_NAME}/$1 [R,L]
RewriteRule ^/(.*):NOSSL$ http://%{SERVER_NAME}/$1 [R,L]

This rewrite ruleset lets you use hyperlinks of the form <a href="document.html:SSL">, to switch to HTTPS in a relative link.

Certificates

  • What are RSA Private Keys, CSRs and Certificates?
  • Is there a difference on startup between the original Apache and an SSL-aware Apache?
  • How do I create a self-signed SSL Certificate for testing purposes?
  • How do I create a real SSL Certificate?
  • How do I create and use my own Certificate Authority (CA)?
  • How can I change the pass-phrase on my private key file?
  • How can I get rid of the pass-phrase dialog at Apache startup time?
  • How do I verify that a private key matches its Certificate?
  • Why do connections fail with an "alert bad certificate" error?
  • Why does my 2048-bit private key not work?
  • Why is client authentication broken after upgrading from SSLeay version 0.8 to 0.9?
  • How can I convert a certificate from PEM to DER format?
  • Why can't I find the getca or getverisign programs mentioned by Verisign, for installing my Verisign certificate?
  • Can I use the Server Gated Cryptography (SGC) facility (aka Verisign Global ID) with mod_ssl?
  • Why do browsers complain that they cannot verify my Verisign Global ID server certificate?

What are RSA Private Keys, CSRs and Certificates?

An RSA private key file is a digital file that you can use to decrypt messages sent to you. It has a public component which you distribute (via your Certificate file) which allows people to encrypt those messages to you.

A Certificate Signing Request (CSR) is a digital file which contains your public key and your name. You send the CSR to a Certifying Authority (CA), who will convert it into a real Certificate, by signing it.

A Certificate contains your RSA public key, your name, the name of the CA, and is digitally signed by the CA. Browsers that know the CA can verify the signature on that Certificate, thereby obtaining your RSA public key. That enables them to send messages which only you can decrypt.

See the Introduction chapter for a general description of the SSL protocol.

Is there a difference on startup between the original Apache and an SSL-aware Apache?

Yes. In general, starting Apache with mod_ssl built-in is just like starting Apache without it. However, if you have a passphrase on your SSL private key file, a startup dialog will pop up which asks you to enter the pass phrase.

Having to manually enter the passphrase when starting the server can be problematic - for example, when starting the server from the system boot scripts. In this case, you can follow the steps below to remove the passphrase from your private key.

How do I create a self-signed SSL Certificate for testing purposes?

  1. Make sure OpenSSL is installed and in your PATH.

  2. Run the following command, to create server.key and server.crt files:
    $ openssl req -new -x509 -nodes -out server.crt -keyout server.key
    These can be used as follows in your httpd.conf file:
                 SSLCertificateFile    /path/to/this/server.crt
             SSLCertificateKeyFile /path/to/this/server.key
  3. It is important that you are aware that this server.key does not have any passphrase. To add a passphrase to the key, you should run the following command, and enter & verify the passphrase as requested.

    $ openssl rsa -des3 -in server.key -out server.key.new
    $ mv server.key.new server.key

    Please backup the server.key file, and the passphrase you entered, in a secure location.

How do I create a real SSL Certificate?

Here is a step-by-step description:

  1. Make sure OpenSSL is installed and in your PATH.

  2. Create a RSA private key for your Apache server (will be Triple-DES encrypted and PEM formatted):

    $ openssl genrsa -des3 -out server.key 1024

    Please backup this server.key file and the pass-phrase you entered in a secure location. You can see the details of this RSA private key by using the command:

    $ openssl rsa -noout -text -in server.key

    If necessary, you can also create a decrypted PEM version (not recommended) of this RSA private key with:

    $ openssl rsa -in server.key -out server.key.unsecure

  3. Create a Certificate Signing Request (CSR) with the server RSA private key (output will be PEM formatted):

    $ openssl req -new -key server.key -out server.csr

    Make sure you enter the FQDN ("Fully Qualified Domain Name") of the server when OpenSSL prompts you for the "CommonName", i.e. when you generate a CSR for a website which will be later accessed via https://www.foo.dom/, enter "www.foo.dom" here. You can see the details of this CSR by using

    $ openssl req -noout -text -in server.csr

  4. You now have to send this Certificate Signing Request (CSR) to a Certifying Authority (CA) to be signed. Once the CSR has been signed, you will have a real Certificate, which can be used by Apache. You can have a CSR signed by a commercial CA, or you can create your own CA to sign it.
    Commercial CAs usually ask you to post the CSR into a web form, pay for the signing, and then send a signed Certificate, which you can store in a server.crt file. For more information about commercial CAs see the following locations:

    1. Verisign
      http://digitalid.verisign.com/server/apacheNotice.htm
    2. Thawte
      http://www.thawte.com/
    3. CertiSign Certificadora Digital Ltda.
      http://www.certisign.com.br
    4. IKS GmbH
      http://www.iks-jena.de/leistungen/ca/
    5. Uptime Commerce Ltd.
      http://www.uptimecommerce.com
    6. BelSign NV/SA
      http://www.belsign.be
    For details on how to create your own CA, and use this to sign a CSR, see below.
    Once your CSR has been signed, you can see the details of the Certificate as follows:

    $ openssl x509 -noout -text -in server.crt
  5. You should now have two files: server.key and server.crt. These can be used as follows in your httpd.conf file:
           SSLCertificateFile    /path/to/this/server.crt
       SSLCertificateKeyFile /path/to/this/server.key
    The server.csr file is no longer needed.

How do I create and use my own Certificate Authority (CA)?

The short answer is to use the CA.sh or CA.pl script provided by OpenSSL. Unless you have a good reason not to, you should use these for preference. If you cannot, you can create a self-signed Certificate as follows:

  1. Create a RSA private key for your server (will be Triple-DES encrypted and PEM formatted):

    $ openssl genrsa -des3 -out server.key 1024

    Please backup this host.key file and the pass-phrase you entered in a secure location. You can see the details of this RSA private key by using the command:
    $ openssl rsa -noout -text -in server.key

    If necessary, you can also create a decrypted PEM version (not recommended) of this RSA private key with:

    $ openssl rsa -in server.key -out server.key.unsecure

  2. Create a self-signed Certificate (X509 structure) with the RSA key you just created (output will be PEM formatted):

    $ openssl req -new -x509 -nodes -sha1 -days 365 -key server.key -out server.crt

    This signs the server CSR and results in a server.crt file.
    You can see the details of this Certificate using:

    $ openssl x509 -noout -text -in server.crt

How can I change the pass-phrase on my private key file?

You simply have to read it with the old pass-phrase and write it again, specifying the new pass-phrase. You can accomplish this with the following commands:

$ openssl rsa -des3 -in server.key -out server.key.new
$ mv server.key.new server.key

The first time you're asked for a PEM pass-phrase, you should enter the old pass-phrase. After that, you'll be asked again to enter a pass-phrase - this time, use the new pass-phrase. If you are asked to verify the pass-phrase, you'll need to enter the new pass-phrase a second time.

How can I get rid of the pass-phrase dialog at Apache startup time?

The reason this dialog pops up at startup and every re-start is that the RSA private key inside your server.key file is stored in encrypted format for security reasons. The pass-phrase is needed decrypt this file, so it can be read and parsed. Removing the pass-phrase removes a layer of security from your server - proceed with caution!

  1. Remove the encryption from the RSA private key (while keeping a backup copy of the original file):

    $ cp server.key server.key.org
    $ openssl rsa -in server.key.org -out server.key

  2. Make sure the server.key file is only readable by root:

    $ chmod 400 server.key

Now server.key contains an unencrypted copy of the key. If you point your server at this file, it will not prompt you for a pass-phrase. HOWEVER, if anyone gets this key they will be able to impersonate you on the net. PLEASE make sure that the permissions on this file are such that only root or the web server user can read it (preferably get your web server to start as root but run as another user, and have the key readable only by root).

As an alternative approach you can use the ``SSLPassPhraseDialog exec:/path/to/program'' facility. Bear in mind that this is neither more nor less secure, of course.

How do I verify that a private key matches its Certificate?

A private key contains a series of numbers. Two of these numbers form the "public key", the others are part of the "private key". The "public key" bits are included when you generate a CSR, and subsequently form part of the associated Certificate.

To check that the public key in your Certificate matches the public portion of your private key, you simply need to compare these numbers. To view the Certificate and the key run the commands:

$ openssl x509 -noout -text -in server.crt
$ openssl rsa -noout -text -in server.key

The `modulus' and the `public exponent' portions in the key and the Certificate must match. As the public exponent is usually 65537 and it's difficult to visually check that the long modulus numbers are the same, you can use the following approach:

$ openssl x509 -noout -modulus -in server.crt | openssl md5
$ openssl rsa -noout -modulus -in server.key | openssl md5

This leaves you with two rather shorter numbers to compare. It is, in theory, possible that these numbers may be the same, without the modulus numbers being the same, but the chances of this are overwhelmingly remote.

Should you wish to check to which key or certificate a particular CSR belongs you can perform the same calculation on the CSR as follows:

$ openssl req -noout -modulus -in server.csr | openssl md5

Why do connections fail with an "alert bad certificate" error?

Errors such as OpenSSL: error:14094412: SSL routines:SSL3_READ_BYTES:sslv3 alert bad certificate in the SSL logfile, are usually caused a browser which is unable to handle the server certificate/private-key. For example, Netscape Navigator 3.x is unable to handle RSA key lengths not equal to 1024 bits.

Why does my 2048-bit private key not work?

The private key sizes for SSL must be either 512 or 1024 bits, for compatibility with certain web browsers. A keysize of 1024 bits is recommended because keys larger than 1024 bits are incompatible with some versions of Netscape Navigator and Microsoft Internet Explorer, and with other browsers that use RSA's BSAFE cryptography toolkit.

Why is client authentication broken after upgrading from SSLeay version 0.8 to 0.9?

The CA certificates under the path you configured with SSLCACertificatePath are found by SSLeay through hash symlinks. These hash values are generated by the `openssl x509 -noout -hash' command. However, the algorithm used to calculate the hash for a certificate changed between SSLeay 0.8 and 0.9. You will need to remove all old hash symlinks and create new ones after upgrading. Use the Makefile provided by mod_ssl.

How can I convert a certificate from PEM to DER format?

The default certificate format for SSLeay/OpenSSL is PEM, which is simply Base64 encoded DER, with header and footer lines. For some applications (e.g. Microsoft Internet Explorer) you need the certificate in plain DER format. You can convert a PEM file cert.pem into the corresponding DER file cert.der using the following command: $ openssl x509 -in cert.pem -out cert.der -outform DER

Why can't I find the getca or getverisign programs mentioned by Verisign, for installing my Verisign certificate?

Verisign has never provided specific instructions for Apache+mod_ssl. The instructions provided are for C2Net's Stronghold (a commercial Apache based server with SSL support).

To install your certificate, all you need to do is to save the certificate to a file, and give the name of that file to the SSLCertificateFile directive. You will also need to give it the key file. For more information, see the SSLCertificateKeyFile directive.

Can I use the Server Gated Cryptography (SGC) facility (aka Verisign Global ID) with mod_ssl?

Yes. mod_ssl has included support for the SGC facility since version 2.1. No special configuration is required - just use the Global ID as your server certificate. The step up of the clients is then automatically handled by mod_ssl at run-time.

Why do browsers complain that they cannot verify my Verisign Global ID server certificate?

Verisign uses an intermediate CA certificate between the root CA certificate (which is installed in the browsers) and the server certificate (which you installed on the server). You should have received this additional CA certificate from Verisign. If not, complain to them. Then, configure this certificate with the SSLCertificateChainFile directive. This ensures that the intermediate CA certificate is sent to the browser, filling the gap in the certificate chain.

The SSL Protocol

  • Why do I get lots of random SSL protocol errors under heavy server load?
  • Why does my webserver have a higher load, now that it serves SSL encrypted traffic?
  • Why do HTTPS connections to my server sometimes take up to 30 seconds to establish a connection?
  • What SSL Ciphers are supported by mod_ssl?
  • Why do I get ``no shared cipher'' errors, when trying to use Anonymous Diffie-Hellman (ADH) ciphers?
  • Why do I get a 'no shared ciphers' error when connecting to my newly installed server?
  • Why can't I use SSL with name-based/non-IP-based virtual hosts?
  • Why is it not possible to use Name-Based Virtual Hosting to identify different SSL virtual hosts?
  • When I use Basic Authentication over HTTPS the lock icon in Netscape browsers stays unlocked when the dialog pops up. Does this mean the username/password is being sent unencrypted?
  • Why do I get I/O errors when connecting via HTTPS to an Apache+mod_ssl server with Microsoft Internet Explorer (MSIE)?
  • Why do I get I/O errors, or the message "Netscape has encountered bad data from the server", when connecting via HTTPS to an Apache+mod_ssl server with Netscape Navigator?

Why do I get lots of random SSL protocol errors under heavy server load?

There can be a number of reasons for this, but the main one is problems with the SSL session Cache specified by the SSLSessionCache directive. The DBM session cache is the most likely source of the problem, so using the SHM session cache (or no cache at all) may help.

Why does my webserver have a higher load, now that it serves SSL encrypted traffic?

SSL uses strong cryptographic encryption, which necessitates a lot of number crunching. When you request a webpage via HTTPS, everything (even the images) is encrypted before it is transferred. So increased HTTPS traffic leads to load increases.

Why do HTTPS connections to my server sometimes take up to 30 seconds to establish a connection?

This is usually caused by a /dev/random device for SSLRandomSeed which blocks the read(2) call until enough entropy is available to service the request. More information is available in the reference manual for the SSLRandomSeed directive.

What SSL Ciphers are supported by mod_ssl?

Usually, any SSL ciphers supported by the version of OpenSSL in use, are also supported by mod_ssl. Which ciphers are available can depend on the way you built OpenSSL. Typically, at least the following ciphers are supported:

  1. RC4 with MD5
  2. RC4 with MD5 (export version restricted to 40-bit key)
  3. RC2 with MD5
  4. RC2 with MD5 (export version restricted to 40-bit key)
  5. IDEA with MD5
  6. DES with MD5
  7. Triple-DES with MD5

To determine the actual list of ciphers available, you should run the following:

$ openssl ciphers -v

Why do I get ``no shared cipher'' errors, when trying to use Anonymous Diffie-Hellman (ADH) ciphers?

By default, OpenSSL does not allow ADH ciphers, for security reasons. Please be sure you are aware of the potential side-effects if you choose to enable these ciphers.

In order to use Anonymous Diffie-Hellman (ADH) ciphers, you must build OpenSSL with ``-DSSL_ALLOW_ADH'', and then add ``ADH'' into your SSLCipherSuite.

Why do I get a 'no shared ciphers' error when connecting to my newly installed server?

Either you have made a mistake with your >SSLCipherSuite directive (compare it with the pre-configured example in httpd.conf-dist) or you chose to use DSA/DH algorithms instead of RSA when you generated your private key and ignored or overlooked the warnings. If you have chosen DSA/DH, then your server cannot communicate using RSA-based SSL ciphers (at least until you configure an additional RSA-based certificate/key pair). Modern browsers like NS or IE can only communicate over SSL using RSA ciphers. The result is the "no shared ciphers" error. To fix this, regenerate your server certificate/key pair, using the RSA algorithm.

Why can't I use SSL with name-based/non-IP-based virtual hosts?

The reason is very technical, and a somewhat "chicken and egg" problem. The SSL protocol layer stays below the HTTP protocol layer and encapsulates HTTP. When an SSL connection (HTTPS) is established Apache/mod_ssl has to negotiate the SSL protocol parameters with the client. For this, mod_ssl has to consult the configuration of the virtual server (for instance it has to look for the cipher suite, the server certificate, etc.). But in order to go to the correct virtual server Apache has to know the Host HTTP header field. To do this, the HTTP request header has to be read. This cannot be done before the SSL handshake is finished, but the information is needed in order to complete the SSL handshake phase. Bingo!

Why is it not possible to use Name-Based Virtual Hosting to identify different SSL virtual hosts?

Name-Based Virtual Hosting is a very popular method of identifying different virtual hosts. It allows you to use the same IP address and the same port number for many different sites. When people move on to SSL, it seems natural to assume that the same method can be used to have lots of different SSL virtual hosts on the same server.

It comes as rather a shock to learn that it is impossible.

The reason is that the SSL protocol is a separate layer which encapsulates the HTTP protocol. So the SSL session is a separate transaction, that takes place before the HTTP session has begun. The server receives an SSL request on IP address X and port Y (usually 443). Since the SSL request does not contain any Host: field, the server has no way to decide which SSL virtual host to use. Usually, it will just use the first one it finds, which matches the port and IP address specified.

You can, of course, use Name-Based Virtual Hosting to identify many non-SSL virtual hosts (all on port 80, for example) and then have a single SSL virtual host (on port 443). But if you do this, you must make sure to put the non-SSL port number on the NameVirtualHost directive, e.g.

NameVirtualHost 192.168.1.1:80

Other workaround solutions include:

Using separate IP addresses for different SSL hosts. Using different port numbers for different SSL hosts.

How do I get SSL compression working?

Although SSL compression negotiation was defined in the specification of SSLv2 and TLS, it took until May 2004 for RFC 3749 to define DEFLATE as a negotiable standard compression method.

OpenSSL 0.9.8 started to support this by default when compiled with the zlib option. If both the client and the server support compression, it will be used. However, most clients still try to initially connect with an SSLv2 Hello. As SSLv2 did not include an array of prefered compression algorithms in its handshake, compression cannot be negotiated with these clients. If the client disables support for SSLv2, either an SSLv3 or TLS Hello may be sent, depending on which SSL library is used, and compression may be set up. You can verify whether clients make use of SSL compression by logging the %{SSL_COMPRESS_METHOD}x variable.

When I use Basic Authentication over HTTPS the lock icon in Netscape browsers stays unlocked when the dialog pops up. Does this mean the username/password is being sent unencrypted?

No, the username/password is transmitted encrypted. The icon in Netscape browsers is not actually synchronized with the SSL/TLS layer. It only toggles to the locked state when the first part of the actual webpage data is transferred, which may confuse people. The Basic Authentication facility is part of the HTTP layer, which is above the SSL/TLS layer in HTTPS. Before any HTTP data communication takes place in HTTPS, the SSL/TLS layer has already completed its handshake phase, and switched to encrypted communication. So don't be confused by this icon.

Why do I get I/O errors when connecting via HTTPS to an Apache+mod_ssl server with Microsoft Internet Explorer (MSIE)?

The first reason is that the SSL implementation in some MSIE versions has some subtle bugs related to the HTTP keep-alive facility and the SSL close notify alerts on socket connection close. Additionally the interaction between SSL and HTTP/1.1 features are problematic in some MSIE versions. You can work around these problems by forcing Apache not to use HTTP/1.1, keep-alive connections or send the SSL close notify messages to MSIE clients. This can be done by using the following directive in your SSL-aware virtual host section:

SetEnvIf User-Agent ".*MSIE.*" \
nokeepalive ssl-unclean-shutdown \
downgrade-1.0 force-response-1.0

Further, some MSIE versions have problems with particular ciphers. Unfortunately, it is not possible to implement a MSIE-specific workaround for this, because the ciphers are needed as early as the SSL handshake phase. So a MSIE-specific SetEnvIf won't solve these problems. Instead, you will have to make more drastic adjustments to the global parameters. Before you decide to do this, make sure your clients really have problems. If not, do not make these changes - they will affect all your clients, MSIE or otherwise.

The next problem is that 56bit export versions of MSIE 5.x browsers have a broken SSLv3 implementation, which interacts badly with OpenSSL versions greater than 0.9.4. You can accept this and require your clients to upgrade their browsers, you can downgrade to OpenSSL 0.9.4 (not advised), or you can work around this, accepting that your workaround will affect other browsers too:

SSLProtocol all -SSLv3

will completely disables the SSLv3 protocol and allow those browsers to work. A better workaround is to disable only those ciphers which cause trouble.

SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP

This also allows the broken MSIE versions to work, but only removes the newer 56bit TLS ciphers.

Another problem with MSIE 5.x clients is that they refuse to connect to URLs of the form https://12.34.56.78/ (where IP-addresses are used instead of the hostname), if the server is using the Server Gated Cryptography (SGC) facility. This can only be avoided by using the fully qualified domain name (FQDN) of the website in hyperlinks instead, because MSIE 5.x has an error in the way it handles the SGC negotiation.

And finally there are versions of MSIE which seem to require that an SSL session can be reused (a totally non standard-conforming behaviour, of course). Connecting with those MSIE versions only work if a SSL session cache is used. So, as a work-around, make sure you are using a session cache (see the SSLSessionCache directive).

Why do I get I/O errors, or the message "Netscape has encountered bad data from the server", when connecting via HTTPS to an Apache+mod_ssl server with Netscape Navigator?

This usually occurs when you have created a new server certificate for a given domain, but had previously told your browser to always accept the old server certificate. Once you clear the entry for the old certificate from your browser, everything should be fine. Netscape's SSL implementation is correct, so when you encounter I/O errors with Netscape Navigator it is usually caused by the configured certificates.

mod_ssl Support

  • What information resources are available in case of mod_ssl problems?
  • What support contacts are available in case of mod_ssl problems?
  • What information should I provide when writing a bug report?
  • I had a core dump, can you help me?
  • How do I get a backtrace, to help find the reason for my core dump?

What information resources are available in case of mod_ssl problems?

The following information resources are available. In case of problems you should search here first.

Answers in the User Manual's F.A.Q. List (this)
http://httpd.apache.org/docs/2.1/ssl/ssl_faq.html
First check the F.A.Q. (this text). If your problem is a common one, it may have been answered several times before, and been included in this doc.
Postings from the modssl-users Support Mailing List http://www.modssl.org/support/
Search for your problem in the archives of the modssl-users mailing list. You're probably not the first person to have had this problem!

What support contacts are available in case of mod_ssl problems?

The following lists all support possibilities for mod_ssl, in order of preference. Please go through these possibilities in this order - don't just pick the one you like the look of.

  1. Send a Problem Report to the modssl-users Support Mailing List
    modssl-users@modssl.org
    This is the preferred way of submitting your problem report, because this way, others can see the problem, and learn from any answers. You must subscribe to the list first, but you can then easily discuss your problem with both the author and the whole mod_ssl user community.
  2. Send a Problem Report to the Apache httpd Users Support Mailing List
    users@httpd.apache.org
    This is the second way of submitting your problem report. Again, you must subscribe to the list first, but you can then easily discuss your problem with the whole Apache httpd user community.
  3. Write a Problem Report in the Bug Database
    http://httpd.apache.org/bug_report.html
    This is the last way of submitting your problem report. You should only do this if you've already posted to the mailing lists, and had no success. Please follow the instructions on the above page carefully.

What information should I provide when writing a bug report?

You should always provide at least the following information:

Apache and OpenSSL version information
The Apache version can be determined by running httpd -v. The OpenSSL version can be determined by running openssl version. Alternatively, if you have Lynx installed, you can run the command lynx -mime_header http://localhost/ | grep Server to gather this information in a single step.
The details on how you built and installed Apache+mod_ssl+OpenSSL
For this you can provide a logfile of your terminal session which shows the configuration and install steps. If this is not possible, you should at least provide the configure command line you used.
In case of core dumps please include a Backtrace
If your Apache+mod_ssl+OpenSSL dumps its core, please attach a stack-frame ``backtrace'' (see below for information on how to get this). Without this information, the reason for your core dump cannot be found
A detailed description of your problem
Don't laugh, we really mean it! Many problem reports don't include a description of what the actual problem is. Without this, it's very difficult for anyone to help you. So, it's in your own interest (you want the problem be solved, don't you?) to include as much detail as possible, please. Of course, you should still include all the essentials above too.

I had a core dump, can you help me?

In general no, at least not unless you provide more details about the code location where Apache dumped core. What is usually always required in order to help you is a backtrace (see next question). Without this information it is mostly impossible to find the problem and help you in fixing it.

How do I get a backtrace, to help find the reason for my core dump?

Following are the steps you will need to complete, to get a backtrace:

  1. Make sure you have debugging symbols available, at least in Apache. On platforms where you use GCC/GDB, you will have to build Apache+mod_ssl with ``OPTIM="-g -ggdb3"'' to get this. On other platforms at least ``OPTIM="-g"'' is needed.
  2. Start the server and try to reproduce the core-dump. For this you may want to use a directive like ``CoreDumpDirectory /tmp'' to make sure that the core-dump file can be written. This should result in a /tmp/core or /tmp/httpd.core file. If you don't get one of these, try running your server under a non-root UID. Many modern kernels do not allow a process to dump core after it has done a setuid() (unless it does an exec()) for security reasons (there can be privileged information left over in memory). If necessary, you can run /path/to/httpd -X manually to force Apache to not fork.
  3. Analyze the core-dump. For this, run gdb /path/to/httpd /tmp/httpd.core or a similar command. In GDB, all you have to do then is to enter bt, and voila, you get the backtrace. For other debuggers consult your local debugger manual.


How-To / 투토리얼 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

How-To / 투토리얼

How-To / 투토리얼

인증

인증(authentication)은 자신이 누구라고 주장하는 사람을 확인하는 절차이다. 권한부여(authorization)는 가고 싶은 곳으로 가도록 혹은 원하는 정보를 얻도록 허용하는 과정이다.

참고: 인증, 권한부여, 접근제어

CGI를 사용한 동적 페이지 생성

CGI (Common Gateway Interface)는 웹서버가 보통 CGI 프로그램 혹은 CGI 스크립트하고 부르는, (웹페이지 내용을 만드는) 외부 프로그램과 상호작용하는 방법을 정의한다. 웹사이트에서 동적인 페이지를 만드는 가장 흔하고 간단한 방법이다. 이 문서는 아파치 웹서버에 CGI를 구성하는 방법을 소개하고, CGI 프로그램을 작성해본다.

참고: CGI: 동적 페이지 생성

.htaccess 파일

.htaccess 파일을 사용하여 디렉토리별로 설정을 변경할 수 있다. 여러 설정 지시어가 있는 파일을 특정 문서 디렉토리에 두면, 그 디렉토리와 모든 하위디렉토리에 지시어를 적용한다.

참고: .htaccess 파일

Server Side Includes 소개

SSI (Server Side Includes)는 HTML 페이지에 사용하는 지시어로, 페이지를 서비스할때 서버가 처리한다. SSI를 사용하면 CGI 프로그램이나 다른 동적인 기술로 페이지 전체를 만들어서 서비스하지 않고도 HTML 페이지에 동적으로 생성한 내용을 추가할 수 있다.

참고: Server Side Includes (SSI)

사용자별 웹디렉토리

여러 사용자가 있는 시스템에서 UserDir 지시어를 사용하면 각 사용자는 자신의 홈디렉토리 안에 웹사이트를 만들 수 있다. URL http://example.com/~username/에 접근하면 사용자 "username"의 홈디렉토리에서 UserDir 지시어로 지정한 하위디렉토리에 있는 페이지를 가져오게 된다.

참고: 사용자 웹디렉토리 (public_html)


인증(Authentication), 권한부여(Authorization), 접근제어(Access Control) - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > How-To / Tutorials

인증(Authentication), 권한부여(Authorization), 접근제어(Access Control)

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

인증(authentication)은 자신이 누구라고 주장하는 사람을 확인하는 절차이다. 권한부여(authorization)는 가고 싶은 곳으로 가도록 혹은 원하는 정보를 얻도록 허용하는 과정이다.

관련 모듈과 지시어

관련된 모듈 관련된 지시어
  • mod_auth
  • mod_access
  • Allow
  • AuthGroupFile
  • AuthName
  • AuthType
  • AuthUserFile
  • Deny
  • Options
  • Require

소개

당신의 웹사이트에 있는 정보가 소수의 사람들만의 비밀이거나 이들만을 위한 정보라면, 이 글에서 설명하는 기법을 사용하여 당신이 보길 원하는 사람만 페이지를 보도록 할 수 있다.

이 글은 웹사이트의 일부를 보호하기위해 많은 사람들이 사용하는 "표준적인" 방법을 다룬다.

기본 지식

이 글에서 다루는 지시어는 서버의 주설정파일(일반적으로 <Directory> 섹션)이나 디렉토리별 설정파일(.htaccess 파일)에서 사용한다.

.htaccess 파일을 사용하려면 이 파일에 있는 인증 지시어를 허용하도록 서버를 설정해야 한다. 이를 위해 디렉토리별 설정파일에 어떤 지시어를 사용할 수 있는지를 결정하는 AllowOverride 지시어를 사용한다.

여기서는 인증을 다루기 때문에, 다음과 같은 AllowOverride 지시어가 필요하다.

AllowOverride AuthConfig

혹은 지시어를 직접 서버 주설정파일에 적는다면, 그 파일에 쓰기 권한이 물론 있어야 한다.

그리고 보호할 파일이 어디있는지 알기위해 서버의 디렉토리 구조에 대해 조금 알아야한다. 이 일은 어렵지않고, 적당한 때에 자세히 설명할 것이다.

기본적인 설정하기

이제 서버의 디렉토리를 암호로 보호하는 기본적인 방법을 설명한다.

먼저 암호파일을 만들어야 한다. 이 파일은 웹에서 접근할 수 없는 곳에 있어야 한다. 다른사람이 암호파일을 다운로드하지 못하게하기 위해서다. 예를 들어, 문서들이 /usr/local/apache/htdocs에 있다면 암호파일(들)은 /usr/local/apache/passwd에 둔다.

아파치에 포함된 htpasswd 도구를 사용하여 암호파일을 만든다. 이 프로그램은 아파치를 설치한 곳의 bin 디렉토리에 있다. 파일을 만들려면 다음과 같이 입력한다.

htpasswd -c /usr/local/apache/passwd/passwords rbowen

htpasswd는 암호를 물어보고, 확인을 위해 암호를 다시 입력하라고 요청한다.

# htpasswd -c /usr/local/apache/passwd/passwords rbowen
New password: mypassword
Re-type new password: mypassword
Adding password for user rbowen

물론 htpasswd이 실행파일 경로에 없다면 실행파일의 전체 경로를 입력해야 한다. 내가 사용하는 서버에서는 /usr/local/apache/bin/htpasswd에 실행파일이 있다.

다음으로 서버가 암호를 요청하도록 설정하고, 서버에게 어떤 사용자의 접근을 허용할지 알려줘야 한다. httpd.conf를 편집하거나 .htaccess 파일을 사용하여 설정한다. 예를 들어, /usr/local/apache/htdocs/secret 디렉토리를 보호하려면, 아래 지시어를 /usr/local/apache/htdocs/secret/.htaccess 파일이나 httpd.conf의 <Directory /usr/local/apache/apache/htdocs/secret> 섹션에 적어야 한다.

AuthType Basic
AuthName "Restricted Files"
AuthUserFile /usr/local/apache/passwd/passwords
Require user rbowen

지시어를 하나씩 살펴보자. AuthType 지시어는 사용자를 인증할 방법을 선택한다. 가장 일반적인 방법은 Basic으로, mod_auth가 구현한다. 그러나 Basic 인증은 브라우저가 서버로 암호를 암호화하지 않고 보낸다. 그러므로 기밀 자료를 보호하기위해 이 방법을 사용하면 안된다. 아파치는 AuthType Digest라는 인증 방법도 지원한다. 이 방법은 mod_auth_digest가 구현하며, 매우 안전하다. 가장 최근 클라이언트들만이 Digest 인증을 지원한다고 한다.

AuthName 지시어는 인증에 사용할 영역(realm)을 지정한다. 영역은 두가지 역할을 한다. 첫번째는 클라이언트가 보통 이 정보를 암호 대화창에 보여준다. 두번째는 영역 정보를 사용하여 클라이언트가 특정 인증구역에 어떤 암호를 보낼지 결정한다.

예를 들어, 일단 클라이언트가 "Restricted Files" 영역에 인증이 성공하였다면, 클라이언트는 자동으로 같은 서버에서 "Restricted Files" 영역으로 표시된 구역에 대해 동일한 암호를 시도한다. 그래서 여러 제한 구역이 같은 영역을 공유하면 사용자가 여러번 암호를 입력하지 않아도 된다. 물론 보안상 이유로 클라이언트는 서버의 호스트명이 다르면 항상 새로 암호를 물어본다.

AuthUserFile 지시어는 우리가 방금 htpasswd로 만든 암호파일의 경로를 설정한다. 사용자가 많다면 요청마다 매번 사용자를 인증하기위해 일반 문서파일을 검색하는데 시간이 상당히 많이 걸릴 수 있다. 아파치는 빠른 데이타베이스 파일에 사용자 정보를 저장할 수 있다. mod_auth_dbm 모듈은 AuthDBMUserFile 지시어를 제공한다. dbmmanage 프로그램을 사용하여 암호파일을 만들고 다룬다. 아파치 모듈 데이타베이스에는 여러 다른 인증 방식을 제공하는 제삼자가 만든 모듈들이 있다.

마지막으로 Require 지시어는 서버의 특정 영역에 접근할 수 있는 사용자를 지정하여 권한부여를 한다. 다음 절은 require 지시어를 사용하는 다양한 방법을 설명한다.

여러명을 들여보내기

위의 지시어는 디렉토리로 (사용자명이 rbowen인) 한 사람만을 들여보낸다. 대부분의 경우 여러 사람을 들여보내고 싶을 것이다. 이제 AuthGroupFile을 사용할 때다.

여러 사람을 들여보내고 싶다면 그룹명과 그 그룹에 어떤 사용자들이 있는지 알려주는 그룹파일이 필요하다. 이 파일의 형식은 매우 간단하여, 아무 편집기로나 만들 수 있다. 파일내용은 다음과 같다.

GroupName: rbowen dpitts sungo rshersey

그냥 공백으로 구분한 긴 그룹 구성원 목록일 뿐이다.

기존의 암호파일에 사용자를 추가하려면 다음과 같이 입력한다

htpasswd /usr/local/apache/passwd/passwords dpitts

전과 같지만, 새로 파일을 만들지 않고 기존 파일에 사용자를 추가한다. (-c 옵션은 새로 암호파일을 만든다).

이제 .htaccess 파일을 다음과 같이 수정한다.

AuthType Basic
AuthName "By Invitation Only"
AuthUserFile /usr/local/apache/passwd/passwords
AuthGroupFile /usr/local/apache/passwd/groups
Require group GroupName

그러면 GroupName 그룹에 속하며 password 파일에 항목이 있는 사용자가 올바른 암호를 입력하면 접근을 허용한다.

여러 일반 사용자를 들여보내는 다른 방법이 있다. 그룹파일을 만들 필요없이 다음 지시어를 사용하기만 하면 된다.

Require valid-user

Require user rbowen 대신 이 지시어를 사용하면 암호파일에 있는 누구라도 올바른 암호를 입력하기만 하면 접근을 허용한다. 그룹별로 다른 암호파일을 사용하여 그룹과 비슷한 효과를 얻을 수도 있다. 이 경우 아파치가 파일 두개(암호파일과 그룹파일)가 아닌 파일 한개(암호파일)만 검사하면 된다는 것이 장점이다. 그러나 여러 암호파일을 관리해야 하고, AuthUserFile 지시어에 정확한 암호파일을 지정해야 하는 것은 단점이다.

발생할 수 있는 문제점

Basic 인증 방식은 서버에서 문서를 요청할 때마다 사용자명과 암호를 확인한다. 심지어 같은 페이지를 새로 고침할 때도 페이지와 (그림이 암호로 보호하는 디렉토리에 있는 경우) 페이지에 있는 모든 그림에 대해 다시 확인한다. 짐작하듯이 속도가 조금 느려진다. 암호파일을 열어서 사용자명을 찾을 때까지 사용자 목록을 살펴봐야 하기때문에 암호파일 크기가 커질 수록 더 느려진다. 그리고 이 작업을 페이지를 요청할 때마다 진행한다.

그래서 현실적으로 한 암호파일에 저장할 수 있는 사용자수에는 한계가 있다. 이 한계는 사용하는 서버의 성능에 따라 다르지만, 항목이 수백개가 넘는다면 느려진다고 생각하고 다른 인증 방법을 고려해야 한다.

다른 방법도 가능한가?

사용자명과 암호를 사용한 인증이 다가 아니다. 종종 접속한 장소와 같은 다른 정보를 가지고 사용자를 들여보내고 싶을 때가 있다.

Allow와 Deny 지시어는 문서를 요청한 컴퓨터의 호스트명 혹은 호스트 주소를 가지고 접근을 허용하거나 거부한다. Order 지시어는 이 두 지시어와 같이 사용하여, 아파치에게 어떤 순서로 규칙을 적용할지 알린다.

이들 지시어 사용법은 다음과 같다.

Allow from address

여기서 address는 IP 주소(혹은 IP 주소 일부)나 완전한 도메인명(혹은 도메인명 일부)이다. 원한다면 여러 주소나 도메인명을 사용할 수 있다.

예를 들어, 누군가가 게시판에 광고를 올리고 있다면 다음과 같이 접근을 막을 수 있다.

Deny from 205.252.46.165

그 주소에서 들어오는 방문자는 이 지시어가 보호하는 페이지를 볼 수 없다. IP 주소 대신 다음과 같이 컴퓨터명을 사용할 수도 있다.

Deny from host.example.com

또, 전체 도메인의 접근을 막으려면 주소나 도메인명의 일부를 사용한다.

Deny from 192.101.205
Deny from cyberthugs.com moreidiots.com
Deny from ke

Order를 Deny와 Allow 지시어와 같이 사용하여 실제로 원하는 대상을 막을 수 있다.

Order deny,allow
Deny from all
Allow from dev.example.com

Allow 지시어만 사용하면, 해당 호스트의 사용자를 허용하고 거기에 추가로 모든 사람을 허용하므로 원하는 결과를 얻지 못한다. 당신은 특정 사람만 허용하길 원한다.

더 많은 정보

mod_auth와 mod_access 문서에 접근제어가 동작하는 방법에 대한 더 많은 정보가 있다.


아파치 투토리얼: CGI를 사용한 동적 페이지 생성 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > How-To / Tutorials

아파치 투토리얼: CGI를 사용한 동적 페이지 생성

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

소개

관련된 모듈 관련된 지시어
  • mod_alias
  • mod_cgi
  • AddHandler
  • Options
  • ScriptAlias

CGI (Common Gateway Interface)는 웹서버가 보통 CGI 프로그램 혹은 CGI 스크립트라고 부르는, (웹페이지 내용을 만드는) 외부 프로그램과 통신하는 방법을 정의한다. 웹사이트에서 동적인 페이지를 만드는 가장 흔하고 간단한 방법이다. 이 문서는 아파치 웹서버에 CGI를 구성하는 방법을 소개하고, CGI 프로그램을 작성해본다.

CGI를 허용하도록 아파치 설정하기

CGI 프로그램이 올바로 동작하려면 CGI 실행이 가능하도록 아파치를 설정해야 한다. 설정하는 방법은 여러가지다.

ScriptAlias

ScriptAlias 지시어를 사용하면 아파치는 특정 디렉토리를 CGI 프로그램용으로 둔다. 아파치는 이 디렉토리에 있는 모든 파일이 CGI 프로그램이라고 가정하여 클라이언트가 자원을 요청하면 자원을 실행하려고 시도한다.

ScriptAlias 지시어는 다음과 같이 사용한다.

ScriptAlias /cgi-bin/ /usr/local/apache2/cgi-bin/

위 예제는 아파치를 기본 장소에 설치한 경우 httpd.conf 설정파일에 있는 내용이다. ScriptAlias 지시어는 Alias 지시어와 같이 URL 앞부분을 특정 디렉토리로 대응한다. Alias와 ScriptAlias는 보통 DocumentRoot 디렉토리 밖에 있는 디렉토리에 사용한다. Alias와 ScriptAlias의 차이점은 ScriptAlias가 추가로 URL 앞부분으로 시작하는 모든 파일을 CGI 프로그램으로 취급하는 점이다. 그래서 위의 설정은 아파치에게 /cgi-bin/으로 시작하는 자원을 요청하면 /usr/local/apache2/cgi-bin/ 디렉토리에서 찾아서 CGI 프로그램으로 처리하라고 알린다.

예를 들어, URL http://www.example.com/cgi-bin/test.pl을 요청하면 아파치는 /usr/local/apache2/cgi-bin/test.pl 파일을 실행하여 결과를 반환한다. 물론 파일이 존재하고 실행가능하며 어떤 방법으로든 출력을 해야 한다. 그렇지 않으면 아파치는 오류문을 보낸다.

ScriptAlias 디렉토리 밖에 있는 CGI

보통 보안상 이유때문에 CGI 프로그램은 ScriptAlias한 디렉토리에 한정한다. 그래서 관리자는 누가 CGI 프로그램을 사용할 수 있는지 엄격히 감독할 수 있다. 그러나 적당한 보안조치를 취했다면 아무 디렉토리에서나 CGI 프로그램을 실행하지 않을 이유가 없다. 예를 들어, UserDir 지시어를 사용하여 사용자가 자신의 홈디렉토리에 웹페이지를 가지는 경우를 가정하자. 사용자가 자신의 CGI 프로그램을 사용하고 싶은데 cgi-bin 디렉토리에 접근권한이 없다면, 다른 곳에서라도 CGI 프로그램을 실행하고 싶을 것이다.

아무 디렉토리에서나 CGI 실행을 허용하려면 두 과정이 필요하다. 먼저, AddHandler나 SetHandler 지시어를 사용하여 cgi-script 핸들러를 작동해야 한다. 두번째로, Options 지시어에 ExecCGI를 지정해야 한다.

Options를 사용하여 명시적으로 CGI 실행을 허용하기

서버의 주설정파일에 직접 Options 지시어를 사용하여 특정 디렉토리에서 CGI 실행을 허용할 수 있다.

<Directory /usr/local/apache2/htdocs/somedir>
Options +ExecCGI
 </Directory>

위 지시어로 아파치는 CGI 파일의 실행을 허용한다. 어떤 파일이 CGI 파일인지도 서버에게 알려야 한다. 다음 AddHandler 지시어는 서버에게 확장자가 cgi나 pl인 파일은 모두 CGI 프로그램이라고 알린다.

AddHandler cgi-script .cgi .pl

.htaccess 파일

.htaccess 투토리얼은 httpd.conf에 접근권한이 없는 경우에 CGI 프로그램을 사용할 수 있는 방법을 알려준다.

사용자 디렉토리

아래 설정을 사용하면 사용자 디렉토리에서 .cgi로 끝나는 파일을 CGI 프로그램으로 실행한다.

<Directory /home/*/public_html>
Options +ExecCGI
AddHandler cgi-script .cgi
 </Directory>

다음을 사용하면 사용자 디렉토리의 cgi-bin 하위디렉토리에 있는 모든 파일을 CGI 프로그램으로 인식한다.

<Directory /home/*/public_html/cgi-bin>
Options ExecCGI
SetHandler cgi-script
 </Directory>

CGI 프로그램 작성하기

``일반적인'' 프로그래밍과 CGI 프로그래밍 사이에는 두가지 주된 차이점이 있다.

첫번째 차이는 CGI 프로그램은 다른 출력을 하기전에 먼저 MIME-type 헤더를 출력해야 한다는 점이다. HTTP 헤더는 클라이언트에게 클라이언트가 어떤 내용을 받게될지 미리 알린다. 보통 다음과 같다.

Content-type: text/html

두번째 차이는 HTML 혹은 브라우저가 보여줄 수 있는 형식으로 출력해야 한다는 점이다. 대부분의 경우 HTML을 출력하지만, 때때로 gif 그림과 같이 HTML이 아닌 내용을 출력하는 CGI 프로그램을 작성하는 경우도 있다.

두가지를 제외하고는 CGI 프로그램 작성은 이미 만들어 보았을 다른 프로그램들과 매우 비슷하다.

처음으로 만든 CGI 프로그램

다음은 브라우저에 한 줄을 찍는 CGI 프로그램 예제다. 그대로 first.pl이라는 파일에 저장하고, cgi-bin 디렉토리에 복사한다.

#!/usr/bin/perl
print "Content-type: text/html\n\n";
print "Hello, World.";

Perl에 익숙하지 않더라도 무슨 일이 일어나는지 알 수 있다. 첫번째 줄은 아파치(혹은 사용하는 쉘)에게 /usr/bin/perl 위치에 있는 인터프리터을 사용하여 이 프로그램 파일을 실행하라고 알린다. 두번째 줄은 방금 말한 content-type 선언을 출력하고 carriage-return 줄바꿈을 두번 출력한다. 그러면 헤더 뒤에 HTTP 헤더의 끝을 뜻하는 빈줄이 생기고, 본문이 시작한다. 세번째 줄은 "Hello, World." 문자열을 출력한다. 이것으로 끝이다.

브라우저를 실행하고 주소를 입력한다

http://www.example.com/cgi-bin/first.pl

파일 장소를 입력하면, 브라우저창에 Hello, World. 한 줄이 보인다. 흥분되지는 않지만, 한번 동작하는 것을 보았으니 이제 다른 것을 시도해 볼 수 있다.

그러나 아직 동작하지 않아요!

웹에서 CGI 프로그램에 접근할때 브라우저에 나올 수 있는 내용은 기본적으로 네가지다.

CGI 프로그램의 출력
좋다! 모든 것이 잘 동작한다는 뜻이다. 출력은 정확하지만 브라우저가 올바로 처리하지 못한다면, CGI 프로그램에서 올바른 Content-Type을 설정하였는지 확인한다.
CGI 프로그램 소스코드 혹은 "POST Method Not Allowed" 문구
CGI 프로그램을 실행하도록 아파치를 적절히 설정하지 않았다는 뜻이다. 아파치 설정하기 절을 다시 읽고 빼먹은 부분이 있는지 찾아봐라.
"Forbidden"으로 시작하는 문구
권한 문제가 있다는 뜻이다. 아파치 오류 로그와 아래 파일권한 절을 확인하라.
"Internal Server Error"라는 문구
아파치 오류 로그를 보면 아마도 CGI 프로그램이 출력한 오류문과 함께 "Premature end of script headers"가 보일 것이다. 이 경우 아래 내용들을 하나씩 확인하여 어떤 이유로 CGI 프로그램이 적절한 HTTP 헤더를 출력하지 못했는지 알아본다.

파일권한

서버는 당신과 동일한 계정으로 동작하지 않음을 명심하라. 즉, 서버가 시작하면 서버는 비특권 사용자 권한(보통 nobody나 www)으로 동작한다. 그래서 당신이 소유한 파일을 실행하려면 권한이 필요하다. 파일에 nobody가 실행하기에 충분한 권한을 주기위해 보통 모두에게 파일의 실행 권한을 준다.

chmod a+x first.pl

또, 프로그램이 다른 파일을 읽거나 쓴다면 이 파일에도 적절한 권한이 필요하다.

경로 정보와 환경

명령행에서 프로그램을 실행하면 자동으로 어떤 정보가 쉘로 전달된다. 예를 들어, PATH는 쉘에게 당신이 말한 파일을 찾을 장소를 알려준다.

웹서버가 프로그램을 CGI 프로그램으로 실행할때는 PATH가 다를 수 있다. (예를 들어, sendmail 같이) CGI 프로그램 안에서 실행하는 명령어는 완전한 경로로 명시해야 쉘이 명령어를 찾을 수 있다.

경로 문제는 다음과 같이 CGI 프로그램 첫번째 줄에 나오는 스크립트 인터프리터 (보통 perl) 경로에서 자주 발생한다.

#!/usr/bin/perl

실제로 인터프리터의 경로인지 확인한다.

또, CGI 프로그램이 다른 환경변수를 사용한다면 아파치가 이 변수들을 프로그램에게 전달해야 한다.

프로그램 오류

CGI 프로그램이 실패하는 경우 대부분 프로그램 자체 문제때문이다. 특히 위의 두가지 실수를 하지 않았고 이 글을 계속 보고 있다면 더더욱 그렇다. 먼저 웹서버에서 실행하기 전에 명령행에서 프로그램을 실행해본다. 예를 들어, 다음과 같이 실행한다.

cd /usr/local/apache2/cgi-bin
./first.pl

(perl 인터프리터를 실행하지 마라. 쉘과 아파치는 스크립트 첫번째 줄에 있는 경로 정보를 사용하여 인터프리터를 찾아야 한다.)

프로그램은 제일 먼저 Content-Type을 포함한 HTTP 헤더들을 출력하고 빈 줄을 출력해야 한다. 다른 것을 출력한다면 웹서버에서 실행할 경우 아파치는 Premature end of script headers를 반환한다. 자세한 내용은 위의 CGI 프로그램 작성하기를 참고하라.

오류 로그

오류 로그는 당신 편이다. 무언가 잘못되면 오류 로그에 문구가 생긴다. 오류 로그를 제일 먼저 살펴봐야 한다. 웹사이트를 호스팅하는 곳에서 오류 로그를 보지 못하게 한다면, 아마도 다른 업체를 알아봐야 한다. 오류 로그를 보는 방법을 익히면, 대부분의 문제를 빨리 파악하여 해결할 수 있다.

Suexec

suexec 지원 프로그램을 사용하면 어떤 가상호스트 혹은 어떤 사용자 디렉토리에 있는지에 따라 CGI 프로그램을 다른 사용자 권한으로 실행할 수 있다. Suexec는 매우 엄격하게 권한을 검사하며, 검사를 하나라도 통과하지 못하면 CGI 프로그램을 실행하지 않고 Premature end of script headers를 반환한다.

suexec를 사용하고 있는지 알려면 apachectl -V를 실행하여 SUEXEC_BIN 위치를 확인한다. 아파치가 시작할때 그 장소에서 suexec 실행파일을 발견하면, suexec를 사용할 수 있다.

suexec를 완전히 이해하지 못했다면 사용해서는 안된다. suexec를 사용하지 않으려면 SUEXEC_BIN 위치에 있는 suexec 실행파일을 지우고 (혹은 파일명을 바꾸고) 서버를 재시작하면 된다. suexec에 대해 읽은 다음 그래도 사용하고 싶다면, suexec -V를 실행하여 suexec 로그파일 위치를 알아내고 로그파일에서 당신이 어떤 규칙을 어기고 있는지 찾는다.

뒤에서는 무슨 일이 벌어지는가?

CGI 프로그래밍에 익숙해질수록 뒤에서 벌어지는 일을 이해하면 도움이 된다. 구체적으로 브라우저와 서버가 서로 통신하는 방법을 말하는 것이다. 몰라도 "Hello, World."를 출력하는 프로그램을 작성할 수 있지만 이런 프로그램은 별로 쓸모가 없기때문이다.

환경변수

환경변수는 당신이 컴퓨터를 사용하는 동안 당신 주위를 떠다니는 값이다. 환경변수는 path (컴퓨터가 당신이 입력한 명령어에 해당하는 실제 파일을 찾는 장소), 사용자명, 터미널 종류와 같이 유용한 정보다. 일반적인 환경변수를 모두 보려면 명령행 프롬프트에서 env를 입력한다.

CGI를 실행할때도 서버와 브라우저는 각자의 환경변수를 서로 교환한다. 이 정보에는 브라우저 종류 (Netscape, IE, Lynx), 서버 종류 (아파치, IIS, WebSite), 실행하는 CGI 프로그램명 등이 있다.

CGI 프로그래머는 이런 변수들을 사용할 수 있고, 환경변수는 클라이언트-서버 통신에는 일부분을 차지한다. 전체 필수 변수 목록은 http://hoohoo.ncsa.uiuc.edu/cgi/env.html에 있다.

아래 간단한 Perl CGI 프로그램은 자신에게 전달된 모든 환경변수를 보여준다. 아파치 배포본의 cgi-bin 디렉토리에 이와 비슷한 프로그램이 두개 있다. 몇몇 변수는 필수이고 나머지는 선택적이다. 그래서 공식 목록에 없는 변수도 보인다. 또, 아파치는 기본적으로 제공하는 환경변수 외에 여러가지 방법으로 직접 환경변수를 추가할 수 있다.

#!/usr/bin/perl
print "Content-type: text/html\n\n";
foreach $key (keys %ENV) {
print "$key --> $ENV{$key}<br>";
 }

STDIN과 STDOUT

또, 서버와 클라이언트는 표준입력(STDIN)과 표준출력(STDOUT)으로 통신한다. 일상적인 경우 STDIN은 키보드나 프로그램이 처리하는 파일을 나타내고, STDOUT은 보통 콘솔이나 화면을 뜻한다.

CGI 프로그램에게 웹 양식(form)을 POST하면 양식에 입력한 자료를 특별한 형식으로 묶어서 CGI 프로그램의 STDIN으로 전달한다. 그러면 프로그램은 키보드나 파일에서 얻은 자료를 처리하듯이 자료를 처리할 수 있다.

"특별한 형식"은 매우 간단하다. 항목 이름과 값을 등호(=)로 연결하고, 항목 이름과 값의 쌍들을 서로 앤퍼샌드(&)로 연결한다. 공백, 앰퍼샌드, 등호 같은 부자연스러운 문자는 혼동하지 않도록 16진수로 변환한다. 완전한 자료 문자열은 다음과 같이 생겼다.

name=Rich%20Bowen&city=Lexington&state=KY&sidekick=Squirrel%20Monkey

종종 URL 뒤에서 이런 문자열을 보게 된다. 이 경우 서버는 문자열을 QUERY_STRING이라는 환경변수에 저장한다. 이를 GET 요청이라고 한다. FORM 태그의 METHOD 속성을 지정하여 HTML 양식(form)이 자료를 GET할지 POST할지 결정한다.

이제 프로그램은 이런 문자열을 유용한 정보로 쪼개야 한다. 다행히도 이런 자료 처리를 돕고 CGI 프로그램의 다른 여러 면을 살피는 라이브러리와 모듈들이 있다.

CGI 모듈/라이브러리

CGI 프로그램을 작성할때 지루한 작업을 대신해주는 코드 라이브러리 혹은 모듈을 사용할지 고려해봐야 한다. 이런 것을 사용하면 버그가 줄고 더 빨리 프로그램을 개발할 수 있다.

Perl로 CGI 프로그램을 작성한다면 CPAN에서 관련 모듈들을 찾을 수 있다. CGI 개발에 가장 널리 사용되는 모듈은 CGI.pm이다. 대부분의 프로그램에 충분한 최소 기능을 구현한 CGI::Lite도 고려해 볼 수 있다.

C로 CGI 프로그램을 작성한다면 선택의 여지가 많다. 이중 하나가 http://www.boutell.com/cgic/에 있는 CGIC 라이브러리다.

더 많은 정보...

웹에 매우 많은 CGI 정보가 있다. 뉴스그룹 comp.infosystems.www.authoring.cgi에서 여러 사람들과 CGI 문제를 논의할 수 있다. HTML Writers Guild의 -servers 메일링리스트는 질문에 대한 답을 찾기에 훌륭한 장소다. http://www.hwg.org/lists/hwg-servers/에서 더 많은 것을 알 수 있다.

그리고 물론 CGI 프로그램 동작에 대한 모든 내용을 설명한 CGI 규약을 읽어야 할지도 모른다. NCSA에 원본 문서가 있고, 수정한 초안은 Common Gateway Interface RFC 프로젝트에 있다.

메일링리스트나 뉴스그룹에 현재 격고 있는 CGI 문제에 대해 질문할때는 발생한 현상과 원래 기대한 결과, 실제로 발생한 현상이 어떻게 다른지, 사용하는 서버, CGI 프로그램을 작성한 언어, 가능하면 해당 코드를 자세히 적어라. 그러면 해결책을 찾기 쉬워진다.

아파치 소스코드가 잘못되었다고 확신하지 않는 한 CGI 질문을 아파치 버그 데이터베이스에 올리면 절대로 안된다.


아파치 투토리얼: Server Side Includes 소개 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > How-To / Tutorials

아파치 투토리얼: Server Side Includes 소개

Server-side includes를 사용하여 HTML 문서에 동적인 내용을 추가할 수 있다.

소개

관련된 모듈 관련된 지시어
  • mod_include
  • mod_cgi
  • mod_expires
  • Options
  • XBitHack
  • AddType
  • SetOutputFilter
  • BrowserMatchNoCase

이 글은 보통 SSI라고 부르는 Server Side Includes를 설명한다. SSI가 가능하도록 서버를 설정하는 방법과 HTML 페이지에 동적인 내용을 추가하는 기본적인 SSI 사용법을 소개한다.

이 글의 뒷부분은 SSI 지시어 조건문과 같은 고급기법을 설명한다.

SSI가 무엇인가?

SSI (Server Side Includes)는 HTML 페이지에 사용하는 지시어로, 페이지를 서비스할때 서버가 처리한다. SSI를 사용하면 CGI 프로그램이나 다른 동적인 기술로 페이지 전체를 만들어서 서비스하지 않고도 HTML 페이지에 동적으로 생성한 내용을 추가할 수 있다.

SSI를 사용할지 아니면 프로그램으로 페이지 전체를 생성할지 결정은 페이지에서 정적인 부분이 많은지와 페이지를 서비스할 때마다 어느정도를 다시 계산해야할지에 달렸다. SSI는 현재 시간과 같이 적은 정보를 추가하는데 좋다. 그러나 페이지를 서비스할때 페이지의 대부분을 생성해야 한다면 다른 방법을 찾아봐야 한다.

SSI가 가능하도록 서버 설정하기

서버가 SSI를 처리하려면 httpd.conf 파일이나 .htaccess 파일에서 다음 지시어를 사용해야 한다.

Options +Includes

그러면 아파치는 파일에서 SSI 지시어를 처리한다. 설정에는 보통 여러 Options 지시어가 있고, 이 지시어들은 서로 덮어써서 무효로 만들다. 그래서 지시어를 맨마지막에 처리하기위해 보통 SSI를 원하는 특정 디렉토리에서 Options를 사용한다.

모든 파일에서 SSI 지시어를 처리하는 것은 아니다. 아파치에게 어떤 파일을 처리할지 알려줘야 한다. 두가지 방법이 있다. 하나는 다음과 같은 지시어로 .shtml과 같은 특정 파일 확장자를 가진 파일을 처리하는 방법이다.

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

이 방법의 단점은 이미 있는 페이지에 SSI 지시어를 추가하는 경우 SSI 지시어를 처리하기위해 .shtml 확장자를 부여하기때문에 파일명과 이 페이지의 모든 링크를 변경해야 하는 점이다.

다른 방법은 XBitHack 지시어를 사용하는 방법이다.

XBitHack on

XBitHack는 실행권한이 있는 파일에서 SSI 지시어를 처리한다. 그래서 이미 있는 페이지에 SSI 지시어를 추가한다면 파일명을 변경하지 않고 chmod로 파일에 실행권한을 주면 된다.

chmod +x pagename.html

하지 말아야 할 것 하나. 가끔 .shtml 파일명에 골치를 앓지말고 모든 .html 파일을 SSI 처리하라고 충고하는 사람이 있다. 이 사람들은 아마도 XBitHack에 대해 모르는 것 같다. 명심할 점은 이렇게 하면 아파치는 파일에 SSI 지시어가 없더라도 클라이언트로 보내는 모든 파일을 살펴봐야 한다는 것이다. 성능이 매우 느려질 수 있으며, 좋은 생각이 아니다.

물론 윈도우즈에서는 실행권한이란 것이 없기때문에 후자를 사용할 수 없다.

내용이 동적이여서 계산하기 어렵기때문에 아파치 기본 설정은 SSI 페이지의 최근수정일과 content length HTTP 헤더를 보내지 않는다. 그래서 문서를 캐쉬하지 못하고 클라이언트가 느끼는 성능이 떨어진다. 두가지 해결방법이 있다.

  1. XBitHack Full 설정은 사용한다. 그러면 아파치는 포함하는(include) 파일들의 수정일은 무시한체 원래 요청한 파일의 날짜만 보고 최근수정일을 알아낸다.
  2. mod_expires에 있는 지시어를 사용하여 파일에 직접 만기일을 설정하면 브라우저와 프록시가 문서를 캐쉬할 수 있다.

기본 SSI 지시어

SSI 지시어의 사용법은 다음과 같다.

<!--#element attribute=value attribute=value ... -->

HTML 주석같이 생겼기때문에 SSI 기능을 가동하지 않아도 HTML 소스에는 나오지만 브라우저는 무시한다. SSI를 올바로 설정하면 지시어를 결과값으로 바꾼다.

element는 다음중 하나다. 다음 회에 더 자세히 설명할 것이다. 지금은 SSI로 할 수 있는 몇가지 예를 보인다

오늘 날짜

<!--#echo var="DATE_LOCAL" -->

echo element는 변수값을 그대로 출력한다. CGI 프로그램에 제공하는 환경변수들 외에도 여러 표준 변수가 있다. 또, set element를 사용하여 직접 변수를 정의할 수도 있다.

날짜 출력 형식이 마음에 들지 않는다면, 다음과 같이 config element의 timefmt attribute를 사용한다.

<!--#config timefmt="%A %B %d, %Y" -->
Today is <!--#echo var="DATE_LOCAL" -->

파일의 수정일

이 문서는 <!--#flastmod file="index.html" -->에 마지막으로 수정되었다

이 element도 timefmt 형식 설정에 달렸다.

CGI 프로그램 결과를 포함하기

일반적인 SSI 사용법중 하나로, 많이들 애용하는 ``방문수 카운터'' 같은 CGI 프로그램 결과를 출력한다.

<!--#include virtual="/cgi-bin/counter.pl" -->

추가 예제

다음은 HTML 문서에 사용할 수 있는 몇가지 SSI 예제다.

이 문서가 언제 마지막으로 수정되었나?

앞에서 SSI를 사용하여 사용자에게 문서의 최근수정일을 알릴 수 있다고 말했다. 그러나 실제 방법은 알려주지 않았다. 다음 코드를 HTML 문서에 사용하면 페이지에 시간 기록을 남긴다. 물론 위에서 설명한대로 SSI가 올바로 작동해야 한다.

<!--#config timefmt="%A %B %d, %Y" -->
이 문서는 <!--#flastmod file="ssi.shtml" -->에 마지막으로 수정되었다;

물론 ssi.shtml대신 원하는 실제 파일명을 사용한다. 아무 페이지에라도 붙여넣을 수 있는 범용코드를 원한다면, 파일명 대신 LAST_MODIFIED 변수를 사용한다.

<!--#config timefmt="%D" -->
This file last modified <!--#echo var="LAST_MODIFIED" -->

timefmt 형식에 대한 자세한 정보는 검색엔진에서 strftime을 찾아봐라. 문법은 같다.

표준 페이지 하단을 포함하기

여러 페이지가 있는 사이트를 관리한다면 페이지 전체를 수정하는 것은, 특히 페이지들이 표준 외관을 가지도록 수정하는 것은 정말로 괴롭다.

페이지 상단(header)과 하단(footer)을 파일로 포함하여 이런 수정의 부담을 덜 수 있다. 모든 페이지에서 include SSI 명령어를 사용하여 페이지 하단 파일 하나를 포함하면 된다. include element의 file attribute나 virtual attribute로 포함할 파일을 지정한다. file attribute는 현재 디렉토리에 상대적인 파일경로다. 즉, (/로 시작하는) 절대파일경로나 경로 안에 ../를 사용할 수 없다. 아마도 서비스하는 문서의 상대 URL을 지정할 수 있는 virtual attribute가 더 유용할 것이다. 경로를 /로 시작할 수 있지만, 포함하려는 파일이 서비스하는 파일과 같은 서버에 있어야 한다.

<!--#include virtual="/footer.html" -->

나는 보통 이 두가지를 합쳐서 포함할 페이지 하단 파일에 LAST_MODIFIED 지시어를 넣는다. 포함하려는 파일에도 SSI 지시어가 나올 수 있으며, 이렇게 포함한 파일이 다른 파일을 포함하는 식으로 여러번 계속 포함할 수도 있다.

이외에 설정할 수 있는 것은?

시간 형식 config(설정) 외에 두가지를 더 config(설정)할 수 있다.

보통 SSI 지시어가 잘못되면 다음과 같은 문구가 나온다

[an error occurred while processing this directive]

이 문구를 변경하고 싶다면 config element의 errmsg attribute를 사용하여 변경한다.

<!--#config errmsg="[It appears that you don't know how to use SSI]" -->

사이트를 서비스하기 전에 모든 SSI 지시어 문제를 해결하여 사용자가 이런 문구를 보지 않길 바란다. (그렇지?)

그리고 sizefmt attribute가 반환하는 파일크기 형식을 config(설정)할 수 있다. 바이트로 크기를 보여주려면 bytes, 적절히 Kb나 Mb로 크기를 보여주려면 abbrev를 사용한다.

명령어 실행하기

나는 다음 달에 작은 CGI 프로그램과 SSI를 같이 사용하는 글을 쓸 예정이다. 지금은 exec element로 할 수 있는 다른 것들을 설명할 것이다. SSI는 실제 쉘을 (정확히는 /bin/sh나 Win32를 사용한다면 DOS 쉘) 사용하여 명령어를 실행한다. 예를 들어, 다음은 디렉토리 목록을 보여준다.

<pre>
<!--#exec cmd="ls" -->
</pre>

or, on Windows

<pre>
<!--#exec cmd="dir" -->
</pre>

dir 출력에 브라우저가 혼동할 ``<dir>'' 문자열이 포함되있기때문에, 윈도우즈에서 이 지시어를 사용하면 결과가 조금 이상할 것이다.

이 기능은 exec 태그에 사용한 어떤 명령어라도 실행할 수 있기때문에 매우 위험하다. ``방명록''과 같이 사용자가 웹페이지 내용을 수정할 수 있는 환경이라면, 이 기능을 절대로 사용해선 안된다. Options 지시어에 IncludesNOEXEC 아규먼트를 사용하여 SSI를 허용하지만 exec 기능을 막을 수 있다.

고급 SSI 기법

내용을 출력하는 기능 외에 아파치 SSI는 변수 설정이 가능하고, 비교문과 조건문에 이 변수를 사용할 수 있다.

경고

이 글에서 설명하는 대부분의 기능은 아파치 1.2 이후부터 사용할 수 있다. 물론, 아파치 1.2 이상을 사용하지 않는다면 아마도 빨리 업그레이드해야 한다. 해라. 지금 해라. 기다릴 것이다.

변수 설정

set 지시어를 사용하여 나중에 사용할 변수를 설정할 수 있다. 앞으로 변수가 필요하기때문에 먼저 설명한다. 문법은 다음과 같다.

<!--#set var="name" value="Rich" -->

다음과 같이 값을 문자그대로 설정하지 않고 환경변수나 위에서 설명한 변수(예를 들어, LAST_MODIFIED)와 같이 다른 변수를 사용하여 변수값을 설정할 수도 있다. 이때 변수명 앞에 달러 표시($)를 붙여서 문자열이 아닌 변수임을 표시한다.

<!--#set var="modified" value="$LAST_MODIFIED" -->

변수값에 달러 문자를 그대로 입력하려면 달러 표시 앞에 백슬래쉬를 사용한다.

<!--#set var="cost" value="\$100" -->

마지막으로 긴 문자열 중간에 변수를 사용하는데 뒤에 있는 문자도 변수명으로 오인하여 혼동되는 경우, 변수명을 대괄호로 묶어서 확실히 한다. (좋은 예를 찾기 힘들지만, 무슨 말인지 이해하길 바란다.)

<!--#set var="date" value="${DATE_LOCAL}_${DATE_GMT}" -->

조건 표현식

변수를 설정하고 비교할 수 있으니 조건문이 가능하다. 이제 SSI가 일종의 간단한 프로그래밍언어가 된다. mod_include는 조건문을 만드는 if, elif, else, endif 구조를 제공한다. 실제 한 페이지로 여러 논리적인 페이지를 만들 수 있다.

조건문 구조는 다음과 같다.

<!--#if expr="test_condition" -->
<!--#elif expr="test_condition" -->
<!--#else -->
<!--#endif -->

test_condition에는 어떤 논리비교라도 사용할 수 있다. 값을 다른 값과 비교하거나, 특정 값이 ``참''인지 검사한다. (문자열이 비어있지 않으면 참이다.) 사용가능한 비교 연산자를 모두 보려면, mod_include 문서를 참고하라. 다음은 조건문을 사용한 몇가지 예제다.

설정파일에 다음 줄을 추가한다.

BrowserMatchNoCase macintosh Mac
BrowserMatchNoCase MSIE InternetExplorer

클라이언트가 맥킨토시에서 실행하는 Internet Explorer라면 환경변수 ``Mac''과 ``InternetExplorer'' 모두 참으로 설정한다.

그리고 SSI 문서에 다음과 같이 적는다.

<!--#if expr="${Mac} && ${InternetExplorer}" -->
여기에 사과문가 나온다
<!--#else -->
여기에 멋진 JavaScript 코드가 나온다
<!--#endif -->

내가 매킨토시 IE에 반감이 있는 것은 아니다. 나는 단지 저번주에 다른 곳에서는 문제가 없는 JavaScript 코드가 매킨토시 IE에서는 동작하지 않아서 몇시간을 고생했다. 위는 임시 해결책이다.

(직접 정의하였건 일반 환경변수이건) 어떤 변수라도 조건문에 사용할 수 있다. 아라치는 SetEnvIf나 다른 관련 지시어로 환경변수를 설정할 수 있기때문에 CGI 없이도 멋지게 동적인 내용을 만들 수 있다.

결론

SSI는 확실히 CGI나 동적인 웹페이지를 생성하는 다른 기술을 대체할 수 없다. 그러나 많은 추가 작업없이 페이지에 동적인 내용을 조금 추가하기에는 훌륭한 방법이다.


아파치 투토리얼: .htaccess 파일 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > How-To / Tutorials

아파치 투토리얼: .htaccess 파일

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

.htaccess 파일을 사용하여 디렉토리별로 설정을 변경할 수 있다.

.htaccess 파일

관련된 모듈 관련된 지시어
  • core
  • mod_auth
  • mod_cgi
  • mod_include
  • mod_mime
  • AccessFileName
  • AllowOverride
  • Options
  • AddHandler
  • SetHandler
  • AuthType
  • AuthName
  • AuthUserFile
  • AuthGroupFile
  • Require

무엇이며/어떻게 사용하는가

.htaccess 파일(혹은 "분산 설정파일")을 사용하면 디렉토리별로 설정을 변경할 수 있다. 여러 설정 지시어가 있는 파일을 특정 문서 디렉토리에 두면, 그 디렉토리와 모든 하위디렉토리에 지시어를 적용한다.

주의:

.htaccess 파일명을 다르게 사용하고 싶다면, AccessFileName 지시어를 사용하여 변경할 수 있다. 예를 들어, .config 파일명을 사용하려면 서버 설정파일에 다음과 같이 추가한다.

AccessFileName .config

일반적으로 .htaccess 파일은 주설정파일과 문법이 같다. AllowOverride 지시어가 이 파일에 나올 수 있는 내용을 결정한다. 이 지시어는 .htaccess 파일에서 허용하는 지시어 분류를 지정한다. 지시어를 .htaccess 파일에서 사용할 수 있다면, 해당 지시어 문서의 Override 항목은 지시어를 허용하기위해 AllowOverride에 사용할 값을 알려준다.

예를 들어, AddDefaultCharset 지시어 문서를 보면 이 지시어를 .htaccess 파일에서 사용할 수 있다. (지시어 요약에서 사용장소 항목을 보라.) Override 줄에 FileInfo가 있다. 그래서 이 지시어를 .htaccess 파일에서 사용하기위해서는 최소한 AllowOverride FileInfo가 필요하다.

예제:

사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override: | FileInfo

특정 지시어를 .htaccess 파일에서 사용할 수 있는지 궁금하면 지시어 문서의 사용장소 항목에 ".htaccess"가 있는지 확인한다.

언제 .htaccess 파일을 사용하나 (혹은 사용하지 않나)

일반적으로 주서버파일에 접근할 수 없는 경우가 아니라면 .htaccess 파일을 사용하면 안된다. 예를 들어, 사용자 인증이 항상 .htaccess 파일에 있어야 한다는 것은 잘못 알려진 오해다. 이는 사실이 아니다. 주서버설정에 사용자 인증 설정을 적을 수 있고, 사실 이러길 권한다.

.htaccess 파일은 컨텐츠 제공자가 디렉토리별로 서버 설정을 다르게하고 싶지만 서버 시스템에 root 권한이 없는 경우에 사용한다. 서버 관리자가 설정을 자주 변경하고 싶지 않은 경우 일반 사용자가 직접 .htaccess 파일을 수정하도록 허용하는 것이 바람직하다. 예를 들어, 한 컴퓨터에 여러 사용자 사이트를 서비스하는 ISP에서 사용자가 자신의 설정을 변경하고 싶은 경우가 그러하다.

그러나 일반적으로 .htaccess 파일은 가급적 피해야 한다. .htaccess 파일에서 허용하는 지시어는 주설정파일의 <Directory> 섹션과 같은 효과가 있다.

다음 두가지 큰 이유때문에 .htaccess 파일 사용을 피해야 한다.

첫번째는 성능이다. AllowOverride가 .htaccess 파일을 사용하도록 허용하면, 아파치는 디렉토리마다 .htaccess 파일을 찾는다. 그래서 .htaccess 파일을 허용하면 실제로 파일을 사용하지 않는 경우에도 성능이 떨어진다! 또, .htaccess 파일은 문서를 요청할때마다 읽어들인다.

게다가 적용해야 하는 전체 지시어를 모으기위해 아파치는 모든 상위 디렉토리에서 .htaccess 파일을 찾는다. (어떻게 지시어를 적용하나 절을 참고.) 그래서 /www/htdocs/example 디렉토리에 있는 파일을 요청하면, 아파치는 다음 파일들을 찾아야 한다.

/.htaccess
/www/.htaccess
/www/htdocs/.htaccess
/www/htdocs/example/.htaccess

그래서 그 디렉토리에 있는 파일을 접근할 때마다 설정파일이 전혀 없어도 파일시스템을 4번 더 접근해야 한다. (/에서도 .htaccess 파일을 허용한 경우를 말한다. 보통은 허용하지 않는다.)

두번째 이유는 보안이다. 사용자에게 서버설정 변경 권한을 주면 당신이 감당할 수 없는 변화가 일어날 수 있다. 사용자에게 이런 권한을 줄지 곰곰이 생각하라. 또, 사용자가 원하는 것보다 적은 권한을 주면 기술지원요청이 들어온다. 사용자에게 가능한 권한 수준을 명확히 알려라. 사용자에게 AllowOverride를 어떻게 설정하였는지 정확히 알리고 관련 문서를 제공하면 앞으로 혼란을 피할 수 있다.

지시어를 /www/htdocs/example 디렉토리의 .htaccess 파일을 두는 것과 주서버설정의 <Directory /www/htdocs/example> Directory 설정에 두는 것은 완전히 같다.

/www/htdocs/example에 있는 .htaccess 섹션:

/www/htdocs/example에 있는 .htaccess 파일 내용

AddType text/example .exm

httpd.conf 파일에 있는 섹션

<Directory /www/htdocs/example>
AddType text/example .exm
 </Directory>

그러나 파일을 요청할 때마다 설정을 읽지않고 아파치가 시작할때 한번만 설정을 읽기때문에 같은 설정을 서버설정파일에 사용하면 성능이 더 빠르다.

AllowOverride 지시어를 none으로 설정하면 .htaccess 파일을 완전히 사용할 수 없다.

AllowOverride None

어떻게 지시어를 적용하나

.htaccess 파일을 발견한 디렉토리와 그 디렉토리의 모든 하위디렉토리에 .htaccess 파일에 있는 설정 지시어를 적용한다. 그래서 상위디렉토리의 .htaccess 파일을 주의해야 한다. 발견한 순서로 지시어를 적용한다. 특정 디렉토리에 있는 .htaccess 파일은 상위디렉토리에 있는 .htaccess 파일의 지시어를 무효로 만들 수 있고, 상위디렉토리에 있는 지시어는 더 상위디렉토리 혹은 주설정파일에 있는 지시어를 무효로 만들 수 있다.

예제:

/www/htdocs/example1 디렉토리에 다음과 같은 .htaccess 파일이 있다.

Options +ExecCGI

(주의: .htaccess 파일에 "Options" 지시어를 사용하려면 "AllowOverride Options"가 필요하다.)

/www/htdocs/example1/example2 디렉토리에는 다음과 같은 .htaccess 파일이 있다.

Options Includes

이 두번째 .htaccess 파일의 Options Includes가 이전 설정을 완전히 무효로 만들기때문에 /www/htdocs/example1/example2 디렉토리는 CGI 실행을 허용하지 않는다.

인증 예제

인증 방법을 알기위해 바로 이곳부터 읽는다면 주의할 것이 있다. 암호 인증을 하려면 .htaccess 파일이 필요하다는 오해가 널리 퍼져있다. 이는 사실이 아니다. 주설정파일의 <Directory> 섹션에 인증 지시어를 두는 것이 더 권장하는 방법이고, 서버의 주설정파일을 수정할 수 없는 경우에만 .htaccess 파일을 사용해야 한다. 언제 .htaccess 파일을 사용해야 하는지와 사용하지 말아야 하는지는 위에서 설명하였다.

앞에서 말했지만 아직도 .htaccess 파일이 필요하다고 생각되면 아래 설정이 도움이 될 것이다.

이 지시어가 동작하려면 "AllowOverride AuthConfig"가 있어야 한다.

.htaccess 파일 내용.

AuthType Basic
AuthName "Password Required"
AuthUserFile /www/passwords/password.file
AuthGroupFile /www/passwords/group.file
Require Group admins

이 지시어가 동작하기위해서는 AllowOverride AuthConfig 지시어가 필요함을 명심하라.

인증과 권한부여에 대한 자세한 설명은 인증 투토리얼을 보길 바란다.

Server Side Includes 예제

또다른 일반적인 .htaccess 파일의 용도는 특정 디렉토리에서 Server Side Includes를 가능하게 만드는 것이다. 원하는 디렉토리의 .htaccess 파일에 다음과 같은 설정 지시어를 사용하면 된다.

Options +Includes
AddType text/html shtml
AddHandler server-parsed shtml

이 지시어가 동작하려면 AllowOverride Options와 AllowOverride FileInfo가 모두 필요함을 명심하라.

server-side includes에 대한 자세한 설명은 SSI 투토리얼을 보길 바란다.

CGI 예제

마지막으로 .htaccess 파일을 사용하여 특정 디렉토리에서 CGI 프로그램 실행을 허용하고 싶다면, 다음과 같은 설정을 사용한다.

Options +ExecCGI
AddHandler cgi-script cgi pl

혹은 이 디렉토리에 있는 모든 파일을 CGI 프로그램으로 처리하고 싶다면 다음과 같은 설정도 가능하다.

Options +ExecCGI
SetHandler cgi-script

이 지시어가 동작하려면 AllowOverride Options와 AllowOverride FileInfo가 모두 필요함을 명심하라.

CGI 프로그래밍과 설정에 대한 자세한 설명은 CGI 투토리얼을 보길 바란다.

문제해결

.htaccess 파일에 둔 설정 지시어가 원하는 기능을 하지 않는 경우 여러가지 이유가 있을 수 있다.

가장 일반적인 문제는 설정 지시어를 가능하게 만드는 AllowOverride를 설정하지 않은 경우다. 문제가 되는 파일 영역에 AllowOverride None이 없는지 확인한다. .htaccess 파일을 아무렇게나 적은 다음 페이지를 다시 접근하여 쉽게 검사해볼 수 있다. 서버 오류가 나오지 않으면 거의 확실히 AllowOverride None을 사용한 경우다.

반대로 문서에 접근할때 서버 오류가 발생하면 아파치 오류로그를 살펴봐라. 아마도 .htaccess 파일에 있는 지시어를 허용하지 않는다고 할 것이다. 아니고 문법 오류가 있다면 오류를 고친다.


사용자별 웹디렉토리 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > How-To / Tutorials

사용자별 웹디렉토리

여러 사용자가 있는 시스템에서 UserDir 지시어를 사용하면 각 사용자는 자신의 홈디렉토리 안에 웹사이트를 만들 수 있다. URL http://example.com/~username/에 접근하면 사용자 "username"의 홈디렉토리에서 UserDir 지시어로 지정한 하위디렉토리에 있는 페이지를 가져오게 된다.

참고

  • URL을 파일시스템에 대응

사용자별 웹디렉토리

관련된 모듈 관련된 지시어
  • mod_userdir
  • UserDir
  • DirectoryMatch
  • AllowOverride

UserDir로 파일경로 지정하기

UserDir 지시어는 사용자별 페이지를 가져올 디렉토리를 지정한다. 이 지시어의 사용법은 여러가지다.

슬래쉬로 시작하지않는 경로를 지정하면 각 사용자의 홈디렉토리에 상대적인 디렉토리 경로로 처리한다. 예를 들어, 아래 설정의 경우:

UserDir public_html

URL http://example.com/~rbowen/file.html은 파일 경로 /home/rbowen/public_html/file.html을 뜻한다.

슬래쉬로 시작하는 경로를 지정하면 지정한 디렉토리에 사용자명을 더한 디렉토리 경로를 사용한다. 예를 들어, 아래 설정의 경우:

UserDir /var/html

URL http://example.com/~rbowen/file.html은 파일 경로 /var/html/rbowen/file.html을 뜻한다.

별표 (*)를 포함한 경로를 지정하면 별표를 사용자명으로 대체한 경로를 사용한다. 예를 들어, 아래 설정의 경우:

UserDir /var/www/*/docs

URL http://example.com/~rbowen/file.html은 파일 경로 /var/www/rbowen/docs/file.html을 뜻한다.

기능을 이용할 사용자 제한하기

UserDir 문서에 있는 문법을 사용하여 사용자별 웹디렉토리 기능을 이용할 수 있는 사용자를 제한할 수 있다:

UserDir enabled
UserDir disabled root jro fish

위 설정은 disabled 문장에 열거한 사람을 제외하고 모든 사용자에게 웹디렉토리 기능을 허락한다. 또, 다음과 같이 몇몇 사용자를 제외하고 기능을 허락하지 않을 수도 있다:

UserDir disabled
UserDir enabled rbowen krietz

UserDir 문서에 있는 다른 예들도 참고하라.

각 사용자별 cgi 디렉토리 지정하기

사용자마다 cgi-bin 디렉토리를 부여하려면 <Directory> 지시어를 사용하여 사용자 홈디렉토리의 특정 하위디렉토리를 cgi 가능하게 만든다.

<Directory /home/*/public_html/cgi-bin/>
Options ExecCGI
SetHandler cgi-script
</Directory>

UserDir이 public_html이라고 가정하면, 다음과 같이 그 안에 있는 cgi 프로그램 example.cgi를 실행할 수 있다.

http://example.com/~rbowen/cgi-bin/example.cgi

사용자가 설정을 변경할 수 있도록 만들기

사용자가 자신의 웹공간에 대한 웹서버 설정을 수정하려면, .htaccess 파일을 사용할 수 있어야 한다. AllowOverride를 사용자가 수정할 수 있는 지시어에 적합한 값으로 설정하라. 어떻게 동작하는지에 대한 자세한 졍보는 .htaccess 투토리얼을 참고하라.


Apache Tutorials - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

Apache Tutorials

Warning:

This document has not been fully updated to take into account changes made in the 2.0 version of the Apache HTTP Server. Some of the information may still be relevant, but please use it with care.

The following documents give you step-by-step instructions on how to accomplish common tasks with the Apache HTTP server. Many of these documents are located at external sites and are not the work of the Apache Software Foundation. Copyright to documents on external sites is owned by the authors or their assignees. Please consult the official Apache Server documentation to verify what you read on external sites.

Installation & Getting Started

  • Getting Started with Apache 1.3 (ApacheToday)
  • Configuring Your Apache Server Installation (ApacheToday)
  • Getting, Installing, and Running Apache (on Unix) (O'Reilly Network Apache DevCenter)
  • Maximum Apache: Getting Started (CNET Builder.com)
  • How to Build the Apache of Your Dreams (Developer Shed)

Basic Configuration

  • An Amble Through Apache Configuration (O'Reilly Network Apache DevCenter)
  • Using .htaccess Files with Apache (ApacheToday)
  • Setting Up Virtual Hosts (ApacheToday)
  • Maximum Apache: Configure Apache (CNET Builder.com)
  • Getting More Out of Apache (Developer Shed)

Security

  • Security and Apache: An Essential Primer (LinuxPlanet)
  • Using User Authentication (Apacheweek)
  • DBM User Authentication (Apacheweek)
  • An Introduction to Securing Apache (Linux.com)
  • Securing Apache - Access Control (Linux.com)
  • Apache Authentication Part 1 - Part 2 - Part 3 - Part 4 (ApacheToday)
  • mod_access: Restricting Access by Host (ApacheToday)

Logging

  • Log Rhythms (O'Reilly Network Apache DevCenter)
  • Gathering Visitor Information: Customising Your Logfiles (Apacheweek)
  • Apache Guide: Logging Part 1 - Part 2 - Part 3 - Part 4 - Part 5 (ApacheToday)

CGI and SSI

  • Dynamic Content with CGI (ApacheToday)
  • The Idiot's Guide to Solving Perl CGI Problems (CPAN)
  • Executing CGI Scripts as Other Users (LinuxPlanet)
  • CGI Programming FAQ (Web Design Group)
  • Introduction to Server Side Includes Part 1 - Part 2 (ApacheToday)
  • Advanced SSI Techniques (ApacheToday)
  • Setting up CGI and SSI with Apache (CNET Builder.com)

Other Features

  • Content Negotiation Explained (Apacheweek)
  • Using Apache Imagemaps (Apacheweek)
  • Keeping Your Images from Adorning Other Sites (ApacheToday)
  • Language Negotiation Notes (Alan J. Flavell)

If you have a pointer to an accurate and well-written tutorial not included here, please let us know by submitting it to the Apache Bug Database.


플래폼별 설명 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

플래폼별 설명

Microsoft Windows

아파치 사용법

이 문서는 Microsoft Windows에서 아파치 2.0을 설치, 설정, 실행하는 방법을 설명한다.

문서: Microsoft Windows에서 아파치 사용법

아파치 컴파일

아파치를 컴파일하기 전에 주의할 점이 많다. 이 문서는 이점을 설명한다.

문서: Microsoft Windows용 아파치 컴파일

기타 플래폼

Novell NetWare

이 문서는 Novell NetWare 5.1 이상에서 아파치 2.0을 설치, 설정, 실행하는 방법을 설명한다.

문서: Novell NetWare에서 아파치 사용하기

EBCDIC

아파치 웹서버는 1.3 버전때 처음으로 EBCDIC 문자집합을 기본 문자집합으로 사용하는 (비-ASCII) 메인플레임 컴퓨터로 포팅되었다.

경고: 이 문서는 아파치 웹서버 2.0 버전에서 변경된 내용을 담고있지 않다. 아직도 유효한 정보가 있지만, 주의해서 사용하길 바란다.

문서: 아파치 EBCDIC 포팅


Microsoft Windows에서 아파치 사용법 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Platform Specific Notes

Microsoft Windows에서 아파치 사용법

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 문서는 Microsoft Windows에서 아파치 2.0을 설치, 설정, 실행하는 방법을 설명한다. 잘못된 부분이 있거나 다른 방법으로 도움을 주려면, 버그 보고 페이지를 사용하길 바란다.

이 문서는 아파치 바이너리 배포본을 설치한다고 가정한다. (아마도 개발 혹은 버그를 찾기위해) 직접 아파치를 컴파일하려면 Microsoft Windows용 아파치 컴파일을 참고하라.

현재 Microsoft Windows 운영체제군의 버전 정책상 이 문서는 다음과 같이 구분한다:

  • Windows NT: Windows NT 커널을 기반으로 하는 모든 Windows 버전을 의미한다. Windows NT, Windows 2000, Windows XP, Windows .Net Server 2003을 지칭한다.
  • Windows 9x: 소비자 중심의 오래된 Windows 버전을 뜻한다. Windows 95 (OSR2 포함), Windows 98, Windows ME를 지칭한다.

운영체제 요구조건

아파치 2.0을 실행하기위한 기본 Windows 플래폼은 Windows NT이다. 바이너리 설치프로그램은 Intel과 AMD와 같은 x86 개열 프로세서에서만 동작한다. 아파치는 Windows 9x에서 충분히 검사하지 않았기때문에 절대로 실제 서비스에 사용하지 않길 바란다.

운영체제에 설치한 TCP/IP 네트워크가 동작해야 한다. Windows 95에서 실행한다면, Winsock 2 업그레이드를 설치해야 한다. Windows 95용 Winsock 2는 여기에서 다운받을 수 있다.

Windows NT 4.0을 사용한다면 서비스팩 4의 TCP/IP 문제와 Winsock 문제가 다음 서비스팩에서 해결되었기때문에, 서비스팩 6을 설치하길 적극 권한다.

Windows용 아파치 다운로드

아파치 웹서버 http://httpd.apache.org/download.cgi에서 아파치 최신 버전에 대한 정보를 얻을 수 있다. 여기에는 최신 발표판과 알파 혹은 베타 테스트버전과, 아파치 웹서버를 다운로드할 수 있는 HTTP 미러와 FTP 미러 목록이 있다. 빠르고 안정하게 다운받으려면 가까운 미러를 사용하길 바란다.

Windows에 설치하려면 확장자가 .msi인 Windows용 아파치 버전을 다운받아야 한다. 이 파일은 막바로 실행할 수 있는 아파치를 저장한 Microsoft 설치파일이다. 따로 소스코드만 묶어둔 .zip 파일이 있다. Microsoft Visual C++ (Visual Studio)을 사용하여 직접 아파치를 컴파일할 수도 있다.

Windows용 아파치 설치하기

설치하려면 Microsoft Installer 1.2 이상 버전이 필요하다. Windows 9x를 사용한다면 여기에서 Microsoft Installer를 2.0 버전으로 업그레이드할 수 있고, Windows NT 4.0과 2000을 사용한다면 여기에서 2.0 버전 업데이트를 구할 수 있다. Windows XP는 업데이트할 필요가 없다.

바이너리 설치파일로는 같은 컴퓨터에 서로 다른 아파치 2.0 버전을 설치할 수 없음을 주의하라. 그러나 1.3 버전과 2.0 버전은 같은 컴퓨터에 아무 문제없이 설치할 수 있다. 같은 컴퓨터에 두가지 다른 2.0 버전을 설치하려면 소스를 컴파일하여 아파치를 설치해야 한다.

위에서 다운받은 아파치 .msi 파일을 실행한다. 설치할때 다음과 같은 것을 물어본다:

  1. 네트워크 도메인 (Network Domain). 등록된 서버의 DNS 도메인을 입력한다. 예를 들어, 서버의 전체 DNS 이름이 server.mydomain.net이라면 여기에 mydomain.net을 입력한다.

  2. 서버명 (Server Name). 서버의 전체 DNS 이름. 위의 경우 여기에 server.mydomain.net을 입력한다.

  3. 관리자 전자우편 주소 (Administrator's Email Address). 여기에 서버 관리자나 웹마스터의 전자우편 주소를 입력한다. 기본적으로 클라이언트에게 보내는 오류문에 이 주소를 기록한다.

  4. 사용자 대상 (For whom to install Apache) 새로 설치하는 아파치가 80번 포트에서 요청을 기다리게 하려면 for All Users, on Port 80, as a Service - Recommended (모든 사용자, 80번 포트, service로 - 추천)를 선택한다. 아파치를 service로 실행한다 (즉, 아파치는 서버에 로그인한 사람이 없어도 실행된다). 개인적으로 테스트해보거나 이미 80번 포트를 사용하는 다른 웹서버가 있다면 only for the Current User, on Port 8080, when started Manually (현재 사용자만, 8080번 포트, 직접 시작)를 선택한다.

  5. 설치 종류 (The installation type). 모듈 개발에 필요한 소스코드와 라이브러리를 제외한 모든 것을 설치하려면 Typical을 선택한다. Custom을 선택하면 설치할 내용을 지정할 수 있다. 전체 설치시 디스크에 빈 공간이 약 13 메가바이트 정도 필요하다. 이 수치는 웹사이트 크기를 제외한 것이다.

  6. 설치 장소 (Where to install). 기본 경로는 C:\Program Files\Apache Group이고, 이곳에 Apache2라는 디렉토리를 만든다.

설치할 동안 아파치는 conf 하위디렉토리에 있는 파일들을 선택한 설치 디렉토리에 맞게 구성한다. 그러나 이 디렉토리에 설정파일이 이미 있다면 그대로 둔다. 대신, 해당 파일의 새로운 복사본에 확장자 .default를 붙인다. 예를 들어, conf\httpd.conf가 이미 있다면 conf\httpd.conf.default로 이름을 변경한다. 설치후 .default 파일의 설정을 직접 살펴보고, 필요하다면 기존 설정파일을 수정해야 한다.

또, 이미 htdocs\index.html이라는 파일이 있다면 그대로 둔다 (index.html.default라고 복사하지도 않는다). 즉, 기존에 아파치가 설치되있더라도 안전하게 아파치를 새로 설치할 수 있다. 물론 설치하기 전에 서버를 중단하고, 설치후 새로운 서버를 시작해야 한다.

아파치 설치후 필요하다면 conf 하위디렉토리에 있는 설정파일을 수정해야 한다. 파일은 아파치를 설치한 디렉토리의 htdocs 하위디렉토리에 있는 문서를 서비스하도록 설정되있다. 실제로 아파치를 사용하기 전에 설정해야 할 옵션이 많다. 그러나 빨리 실행해볼 수 있도록 기본 설정파일로도 동작한다.

Windows용 아파치 설정하기

아파치는 conf 하위디렉토리에 있는 파일로 설정한다. 이 파일은 유닉스용과 같지만, Windows용 아파치 특유의 지시어가 몇개 있다. 사용가능한 모든 지시어를 보려면 지시어 목록을 참고하라.

Windows용 아파치의 주된 차이점은:

  • Windows용 아파치는 다중쓰레드 방식을 사용하기때문에, 유닉스와 달리 요청마다 다른 프로세스를 사용하지 않는다. 대신 아파치 프로세스는 항상, 부모 프로세스와 요청을 처리하는 자식 프로세스, 2개이다. 자식 프로세스에 있는 여러 쓰레드들이 요청들을 처리한다.

    프로세스 관리 지시어도 다르다:

    MaxRequestsPerChild: 유닉스와 같이, 자식 프로세스가 요청을 얼마만큼 처리하고 죽을지를 조정한다. 그러나 유닉스와 달리 프로세스가 한번에 한 요청만을 처리하지않고 한번에 모든 요청을 서비스하기때문에, 설정한다면 매우 큰 값을 설정하길 권한다. 권장하는 기본값 MaxRequestsPerChild 0을 사용하면 자식 프로세스는 죽지않고 영원히 요청을 서비스한다.

    경고: 자식 프로세스는 새로 시작할 때마다 서버설정파일을 새로 읽는다. httpd.conf를 수정했다면, 자식 프로세스가 시작하지 않거나 예기치않은 결과가 발생할 수 있다.

    ThreadsPerChild: 이 지시어는 새로 추가되었다. 이 지시어는 서버가 사용할 쓰레드 개수를 지정한다. 이 값이 서버가 한번에 처리할 수 있는 최대 연결개수이기때문에, 사이트에 접속량이 많다면 충분히 큰 값을 설정해야 한다. 권장하는 기본값은 ThreadsPerChild 50이다.

  • 파일명을 아규먼트로 받는 지시어는 유닉스 파일명이 아닌 Windows 파일명을 사용해야 한다. 그러나 아파치 내부에서 유닉스식 이름을 사용하기때문에 백슬래쉬가 아닌 슬래쉬를 사용해야 한다. 드라이브 문자를 사용할 수 있다. 드라이브를 지정하지 않으면 아파치 실행파일이 있는 드라이브를 사용한다.

  • Windows용 아파치는 서버를 다시 컴파일하지 않고 실행중에 모듈을 읽어들일 수 있다. 기본값으로 아파치를 컴파일하면 \Apache2\modules 디렉토리에 여러 선택가능한 모듈을 설치한다. 이 모듈 혹은 다른 모듈을 사용하려면 새로 생긴 LoadModule 지시어를 사용한다. 예를 들어, status 모듈을 사용한다면 (access.conf에 status관련 지시어와 함께) 아래와 같이 설정한다:

    LoadModule status_module modules/mod_status.so

    읽어들일 수 있는 모듈 만들기에 대한 정보도 있다.

  • 아파치는 Microsoft IIS와 다른 Windows 서버가 사용하는 ISAPI (Internet Server Application Programming Interface) 확장을 (즉, 인터넷 서버 프로그램) 읽어들일 수도 있다. 더 자세한 정보가 있다. 아파치는 ISAPI 필터를 읽어들일 수 없음을 주의하라.

  • CGI 스크립트를 사용한다면 ScriptInterpreterSource 지시어를 사용하여 아파치가 스크립트의 인터프리터를 찾는 방법을 설정할 수 있다.

  • Windows에서 .htaccess와 같은 파일명을 다루기 힘드므로, AccessFilename 지시어를 사용하여 디렉토리별 설정파일 이름을 변경하면 편하다.

  • Windows NT라면 아파치 시작시 발생한 오류를 Windows 이벤트 로그에 기록한다. 그래서 아파치가 보통 사용하는 error.log 파일을 사용할 수 없는 경우에 대비한다. Windows 이벤트 로그는 Windows NT 4.0에서는 이벤트 뷰어 프로그램으로, 최신 Windows 버전에서는 이벤트 뷰어 MMC 스냅인에서 볼 수 있다.

    Windows 9x에는 Windows 이벤트 로그가 없기때문에 시작시 발생한 오류를 기록하지 않는다.

아파치를 Service로 실행하기

Windows NT에서는 아파치를 service로 실행할 수 있다. Windows 9x에는 매우 실험적인 방법으로 비슷한 기능을 지원한다.

설치시 자동으로 아파치를 service로 설치할 수 있다. "모든 사용자"를 선택하면, 아파치 service가 만들어진다. "현재 사용자만"을 선택하더라도 설치후 직접 아파치를 service로 등록할 수 있다. service를 설치하려면 Administrators 그룹의 구성원이어야 한다.

아파치에는 Apache Service Monitor라는 도구가 있다. 이 도구를 사용하면 네트웍에 있는 다른 컴퓨터에 설치된 아파치 상태도 확인하고 관리할 수 있다. monitor로 아파치 service를 관리하려면 먼저 service를 (설치시 자동으로 혹은 직접) 설치해야 한다.

아파치 bin 하위디렉토리에서 명령행 프롬프트에 다음과 같이 입력하면 아파치를 Windows NT service로 설치한다:

apache -k install

설치할 service 이름을 지정하고 싶다면 다음 명령어를 사용한다. 컴퓨터에 아파치가 여러개 설치되있다면 이름을 다르게 주어야 한다.

apache -k install -n "MyServiceName"

service가 사용할 설정파일을 직접 지정하려면 다음과 같이 한다:

apache -k install -n "MyServiceName" -f "c:\files\my.conf"

-k install 외에 다른 파라미터를 사용하지 않으면, service 이름은 Apache2가 되고 설정파일은 conf\httpd.conf가 된다.

아파치 service를 제거하기 쉽다. 간단히:

apache -k uninstall

다음과 같이 제거할 아파치 service를 지정할 수 있다:

apache -k uninstall -n "MyServiceName"

보통 아파치 service 시작, 재시작, 종료는 Apache Service Monitor나 NET START Apache2, NET STOP Apache2 같은 명령어 혹은 Windows 서비스 관리창에서 한다. 어떤 방법을 사용하든지 아파치 service를 시작하기 전에 설정파일을 검사해봐야 한다:

apache -n "MyServiceName" -t

명령행 옵션으로도 아파치 service를 조정할 수 있다. 설치한 아파치 serivce를 시작하려면:

apache -k start

명령행 옵션으로 아파치 service를 종료하려면:

apache -k stop

혹은

apache -k shutdown

실행중인 service를 재시작하여 설정파일을 다시 읽도록 할 수 있다:

apache -k restart

기본적으로 모든 아파치 service는 시스템 사용자 (LocalSystem 계정) 권한으로 실행하도록 등록된다. Windows 보안구조상 LocalSystem 계정은 파일시스템, named pipes, DCOM, secure RPC 등 어떤 방법을 사용하든지 네트웍에 접근할 수 없다. 그러나 해당 컴퓨터에서는 많은 권한을 가진다.

LocalSystem 계정에게 네트웍 권한을 절대로 주지 마라! 아파치가 네트웍 자원에 접근해야 한다면, 아래에서 설명하는 방법으로 아파치를 위한 별도의 계정을 만들어라.

아파치 service를 실행하기위한 별도의 계정을 만들 수도 있다. 특히 아파치가 네트웍 자원에 접근해야 한다면 이 방법을 강력히 권한다.

  1. 일반 도메인 사용자 계정을 만들고 암호를 기억하라.
  2. 새로 만든 계정에 서비스로 로그온와 운영 체제의 일부로 활동 권한을 부여한다. Windows NT 4.0에서는 User Manager for Domains에서 권한을 부여할 수 있고, Windows 2000과 XP에서는 아마도 "그룹 정책"을 사용해야 한다. "로컬 보안 설정" MMC 스냅인에서 직접 설정해줄 수도 있다.
  3. 새로 만든 계정이 Users 그룹에 속하는지 확인한다.
  4. 모든 문서와 스크립트 폴더에 (예를 들어 htdocs와 cgi-bin) 대해 읽기 및 실행 (RX) 권한을 부여한다.
  5. 아파치 logs 디렉토리에 수정 (RWXD) 권한을 부여한다.
  6. Apache.exe 실행파일에 읽기 및 실행 (RX) 권한을 부여한다.
아파치 service를 실행하는 사용자에게 최소한 수정 (RWXD) 권한이 필요한 logs 하위디렉토리를 제외하고 Apache2 디렉토리 전체에 읽기 및 실행 (RX) 권한을 부여하는 것이 좋다.

계정에 "로컬 로그온"과 "서비스로 로그온" 권한이 있다면, 그 계정으로 로그온하여 계정이 스크립트를 실행하고 웹페이지를 읽으며 콘솔창에서 아파치를 시작할 수 있는지 검사해볼 수 있다. 여기서 문제가 없다면 아파치를 service로 실행해도 문제가 없다.

Error code 2186은 아파치가 필요한 네트웍 자원에 접근할 수 없다는 말로 service의 "로그온" 설정을 확인하라. 또, 아파치를 실행하는 계정의 권한을 살펴봐라.

아파치를 service로 실행하면 Windows Service Control Manager에서 오류문을 볼 수 있다. 예를 들어, 제어판에서 "서비스"를 사용하여 아파치를 시작하는 경우 다음과 같은 문구가 나올 수 있다:

Could not start the Apache2 service on \\COMPUTER
Error 1067; The process terminated unexpectedly.

아파치 service를 시작할때 문제가 있으면 일반적인 이런 오류가 나온다. 실제 어디가 문제인지 알려면 아파치를 콘솔 프로그램으로 실행해보라.

Windows 9x에서 아파치는 Windows NT의 service와 비슷한 방법을 지원한다. 그러나 매우 실험적인 기능이다. 실제 서비스에 사용할만큼 안정적이지 않고 앞으로 개선될지 보장할 수도 없다. 위험하므로 혹시나 사용한다면 주의해서 사용해야 한다!

두가지 service의 중요한 차이점은 다음과 같다:

  • 아파치가 성공적으로 시작하면 배경에서 실행한다. 예를 들어, 데스크탑에 바로가기를 만들어서 다음 명령을 실행하는 경우,

    apache -n "MyServiceName" -k start

    service가 성공적으로 시작하면 콘솔창이 생겼다가 금방 사라진다. httpd.conf 설정파일에 잘못된 내용이 있는 등 아파치 시작시 오류가 발생하면 콘솔창을 계속 보인다. 콘솔창은 문제의 원인을 파악하는데 도움을 주는 오류문을 보여준다.

  • Windows 9x는 NET START와 NET STOP 명령어를 지원하지 않는다. 명령프롬프트에서 -k 옵션을 사용하여 아파치 service를 조정해야 한다.

  • 아파치와 Windows 9x는 네트웍 권한을 가진 특정 사용자로 아파치를 실행하지 못한다. 사실 Windows 9x는 보안을 제공하지도 않는다. 이것이 바로 Apache Software Foundation이 Windows 9x 시스템을 공개 웹서버로 사용하길 권하지 않는 이유다. 사용자가 웹 컨텐츠를 개발하고 아파치 서버 학습을 돕기위해, 아니면 안전한 사설 네트웍에 위치할 인트라넷 서버를 위해, Windows 9x를 지원할 뿐이다.

아파치가 콘솔 프로그램으로 동작함을 확인하였다면 Windows NT에서와 같은 명령어로 가상 service를 설치, 조절, 제거할 수 있다. 또, Apache Service Monitor를 사용하여 Windows 9x 가상 service를 관리할 수 있다.

아파치를 콘솔 프로그램으로 실행하기

일반적으로 아파치를 service로 실행하길 권한다. 그러나 명령행에서 실행하는게 편한 경우가 있다 (Windows 9x에서는 service를 안정적으로 지원하지 않기때문에 명령행에서 아파치를 실행하는 방법을 권한다).

아파치를 콘솔 프로그램으로 실행하려면, 명령행에서 다음 명령어를 사용한다:

apache

아파치는 Control-C를 눌러서 정지할 때까지 실행된다.

또, 시작 메뉴 --> 프로그램 --> Apache HTTP Server 2.0.xx --> Control Apache Server에 설치된 Start Apache in Console 바로가기로 아파치를 실행할 수 있다. 바로가기를 실행하면 콘솔창을 열고 그 안에서 아파치를 실행한다. 아파치를 service로 설치하지 않았다면, 아파치를 실행하는 콘솔창에서 Control-C를 눌러 아파치를 중단할때까지 창이 떠있다. 이 경우 서버는 몇초안에 종료한다. 그러나, 아파치를 service로 설치하였다면 바로가기는 service를 시작한다. 아파치 service가 이미 실행중이라면 바로가기는 아무일도 하지 않는다.

다른 콘솔창을 열고 다음과 같이 입력하여 실행중인 아파치를 종료할 수 있다:

apache -k shutdown

이 방법은 아파치가 현재 작업을 마치고 점잖게 종료할 수 있기때문에 Control-C 보다 낫다.

또, 아파치를 재시작할 수 있다. 이 경우 설정파일을 다시 읽는다. 진행중인 작업을 중간에 끊지않고 완료한다. 아파치를 재시작하려면:

apache -k restart

유닉스용 아파치에 익숙한 사람을 위해: 이 명령어는 kill -TERM pid나 kill -USR1 pid의 Windows판이다. 명령행 옵션 -k는 유닉스 kill 명령어 이름을 본따 지었다.

아파치 콘솔창이 즉시 혹은 시작후 갑자기 닫치면 시작 메뉴 --> 프로그램의 명령 프롬프트를 실행한다. 아파치를 설치한 폴더로 가서 apache 명령어를 실행해보고 발생한 오류문을 살펴본다. 그리고 logs 폴더로 가서, 설정파일이 잘못되었는지 error.log 파일을 살펴본다. 아파치를 설치할때 기본값을 사용했다면 다음과 같다:

c:
cd "\Program Files\Apache Group\Apache2\bin"
apache

아파치가 정지할 때까지 기다리거나 Control-C를 누른다. 그리고 다음과 같이 입력한다:

cd ..\logs
more < error.log

아파치를 다룰때 아파치가 어떻게 설정파일을 찾는지 아는 것이 중요하다. 두가지 방법으로 명령행에서 설정파일을 지정할 수 있다:

  • -f는 설정파일의 절대경로 혹은 상대경로를 지정한다:

    apache -f "c:\my server files\anotherconfig.conf"

    혹은

    apache -f files\anotherconfig.conf

  • -n은 아파치 service를 선택하고, 해당 service의 설정파일을 사용한다:

    apache -n "MyServiceName"

두 경우 모두 설정파일이 적절한 ServerRoot를 지정해야 한다.

-f나 -n으로 설정파일을 지정하지 않으면, 아파치는 conf\httpd.conf와 같이 서버에 컴파일된 파일명을 사용한다. 이 기본 경로는 설치 디렉토리에 상대적이다. 다음과 같이 -V 옵션으로 아파치를 실행하면 SERVER_CONFIG_FILE이란 항목에서 서버가 사용할 설정파일을 알 수 있다:

apache -V

아파치는 다음 순서대로 ServerRoot를 찾는다:

  1. -C 명령행 옵션에 사용한 ServerRoot 지시어.
  2. -d 명령행 옵션.
  3. 현재 작업 디렉토리.
  4. 바이너리 설치를 했다면 설치할때 만든 registry 항목.
  5. 서버에 컴파일된 server root. 기본값은 /apache이고, apache -V를 실행하면 HTTPD_ROOT라는 항목에서 확인할 수 있다.

설치할때 윈도우즈 레지스트리에 버전 특유의 레지스트리 키를 만든다. 키의 위치는 설치 종류에 따라 다르다. install Apache for all users를 선택하였다면 HKEY_LOCAL_MACHINE 아래에 다음과 같은 키를 만든다 (물론 버전번호는 아파치 버전마다 다르다):

HKEY_LOCAL_MACHINE\SOFTWARE\Apache Group\Apache\2.0.43

"모든 사용자"를 대상으로 아파치를 설치하였다면 HKEY_CURRENT_USER 아래 키가 생긴다. 내용은 현재 로그온한 사용자에 따라 다르다:

HKEY_CURRENT_USER\SOFTWARE\Apache Group\Apache\2.0.43

키 이름이 서버에 컴파일되기때문에 현재 버전을 건드리지않고 새로운 버전을 설치하여 테스트해볼 수 있다. 물론 새 버전을 다른 버전과 같은 디렉토리에 설치하지않도록 주의해야 한다.

바이너리 설치를 하지 않은 경우 아파치는 레지스트리 키가 없다고 불평할 수 있다. 서버가 다른 방법으로 설정파일을 찾을 수 있다면 이 경고를 무시해도 된다.

키의 값은 ServerRoot 디렉토리이며, 이 디렉토리에 conf라는 하위디렉토리가 있다. 아파치를 시작하면 이 하위디렉토리에서 httpd.conf 파일을 읽는다. 이 파일에 나오는 ServerRoot 지시어가 레지스트리 키에 나온 디렉토리와 다르다면, 아파치는 레지스트리에서 얻은 값을 무시하고 앞으로 설정파일에 나온 디렉토리를 사용한다. 아파치 디렉토리나 설정파일을 다른 장소로 복사하면 반드시 httpd.conf 파일에 있는 ServerRoot 지시어를 그 위치로 수정하라.

정상적으로 설치되었는지 검사하기

(콘솔창이나 service를 통해) 아파치를 시작하면 (설정파일의 Listen 지시어를 수정하거나 아파치를 "현재 사용자만" 대상으로 설치하지 않는 경우) 80번 포트를 기다린다. 브라우저를 시작하고 URL을 입력하여 서버의 기본 페이지에 접근하다:

http://localhost/

아파치는 아파치 설명서 링크가 있는 환영페이지를 보여줘야 한다. 아무 일도 일어나지 않거나 오류가 나오면, logs 하위디렉토리에 있는 error.log 파일을 살펴봐라. 호스트가 네트웍에 연결되있지 않거나 DNS (Domain Name Service) 설정에 문제가 있다면 다음 URL을 사용해야 한다:

http://127.0.0.1/

기본 설치가 동작하면 conf 하위디렉토리에 있는 파일을 적절히 설정한다. 또, Windows NT 아파치 service 설정을 수정한 경우 먼저 명령행에서 아파치를 시작하여 오류가 발생하지않는지 확인해야 한다.

아파치가 다른 TCP/IP 프로그램과 같은 포트를 공유할 수 없기때문에 아파치를 시작하기 전에 다른 서비스를 중단, 제거, 재설정해야 할지도 모른다. 다른 웹서버나 특정 방화벽 서버스와 충돌할 수 있다.


Microsoft Windows용 아파치 컴파일 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Platform Specific Notes

Microsoft Windows용 아파치 컴파일

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

아파치를 컴파일하기 전에 주의할 점이 많다. 미리 Microsoft Windows에서 아파치 사용법을 참고하라.

요구사항

아파치를 컴파일하려면 다음이 정상적으로 설치되야 한다:

  • 디스크 공간

    남은 디스크 공간이 최소한 50 MB는 되야 한다. 아파치 설치후에는 빨리 증가하는 로그와 캐쉬파일을 제외하고 약 10 MB 정도가 필요하다. 실제 디스크 사용량은 선택한 구성과 제삼자가 만든 모듈 혹은 라이브러리에 따라 크게 다르다.

  • Microsoft Visual C++ 5.0 이상.

    아파치는 명령행 도구를 사용하거나 Visual Studio IDE Workbench 안에서 컴파일할 수 있다. 명령행에서 컴파일한다면 vcvars32 배치파일이 설정하는 PATH, INCLUDE, LIB 등 환경변수가 필요하다:

    "c:\Program Files\DevStudio\VC\Bin\vcvars32.bat"

  • Windows Platform SDK.

    어떤 아파치 기능을 사용하려면 Visual C++ 5.0에 추가로 최신 Microsoft Windows Platform SDK가 필요하다. 명령행에서 컴파일한다면 setenv 배치파일이 Platform SDK 환경을 만든다:

    "c:\Program Files\Platform SDK\setenv.bat"

    Visual C++ 6.0 이상에 포함된 Platform SDK 파일은 충분하다. 이 버전을 사용하는 사용자는 이 과정을 생략해도 된다.

    모든 mod_isapi 기능을 사용하려면 최신 Windows Platform SDK가 필요하다. 최신 버전이 아니면 MSVC++ 5.0은 mod_isapi 기능의 일부를 사용할 수 없다고 경고한다. http://msdn.microsoft.com/downloads/sdks/platform/platform.asp에 최신 버전이 있다.

  • awk 도구 (awk, gawk 등).

    컴파일한 시스템에 아파치를 설치하려면 awk.exe 도구를 사용하여 여러 파일을 수정해야 한다. (Perl이나 WSH/VB과 비교하여) 다운받기에 매우 작고 파일 생성 작업이 가능하여 awk를 선택했다. Brian Kernighan의 http://cm.bell-labs.com/cm/cs/who/bwk/ 사이트에 컴파일된 Win32 실행파일 http://cm.bell-labs.com/cm/cs/who/bwk/awk95.exe이 있다. 이름을 awk95.exe 대신 awk.exe로 변경해야 한다.

    Developer Studio IDE는 Tools 메뉴 Options... Directories 탭의 (Developer Studio 7.0이라면 Projects - VC++ Directories pane) Executable files 경로 목록에서만 awk.exe를 찾는다. 이 목록에 awk.exe 경로를 추가하고, 필요하다면 PATH 환경변수에도 추가한다.
    Cygwin을 (http://www.cygwin.com/) 사용한다면 gawk.exe라는 이름으로 awk 도구가 있으며, awk.exe 파일은 gawk.exe 파일의 심볼링크임을 주의하라. Windows 명령 프롬프트가 심볼링크를 인식하지 못하기때문에 InstallBin을 컴파일할때 실패한다. 해결책은 cygwin에서 awk.exe를 삭제하고 gawk.exe 이름을 awk.exe로 바꾼다.

  • [선택적인] OpenSSL 라이브러리 (mod_ssl과 ab.exe의 ssl 지원에 사용)

    주의: 강력한 암호화와 특허가 걸린 지적재산권을 전세계에 배포하는데는 상당한 제약이 있다. OpenSSL은 미국 수출규제법이 규제하며 미국과 기타 지역에서 특허로 보호되는 지적재산권인 강력한 암호화를 포함한다. Apache Software Foundation과 OpenSSL 프로젝트는 OpenSSL 프로젝트가 제공하는 코드를 소유, 사용, 배포하는데 따른 법적 자문을 제공하지 않는다. 직접 법률 상담을 받길 바란다. 당신 행동의 책임은 당신에게 있다.

    mod_ssl이나 (SSL을 지원하는 ab.exe) abs 프로젝트를 컴파일하려면, OpenSSL을 http://www.openssl.org/source/에서 다운받아서 srclib의 openssl이라는 하위디렉토리에 설치해야 한다. release와 debug로 아파치를 컴파일할때 사용하며 0.9.7 버전에 있는 특허가 걸린 기능을 사용하지 않는다면, 아래 컴파일 명령어를 사용한다:

    perl Configure VC-WIN32
    perl util\mkfiles.pl >MINFO
    perl util\mk1mf.pl dll no-asm no-mdc2 no-rc5 no-idea VC-WIN32 >makefile
    perl util\mk1mf.pl dll debug no-asm no-mdc2 no-rc5 no-idea VC-WIN32 >makefile.dbg
    perl util\mkdef.pl 32 libeay no-asm no-mdc2 no-rc5 no-idea >ms\libeay32.def
    perl util\mkdef.pl 32 ssleay no-asm no-mdc2 no-rc5 no-idea >ms\ssleay32.def
    nmake
    nmake -f makefile.dbg

  • [선택적인] zlib 소스 (mod_deflate에 사용)

    Zlib을 srclib의 zlib라는 하위디렉토리에 설치해야 하지만, 소스를 미리 컴파일할 필요는 없다. 컴파일 시스템은 이 압축소스를 mod_deflate 모듈과 같이 컴파일한다. Zlib은 http://www.gzip.org/zlib/에서 구할 수 있다 -- mod_deflate는 1.1.4 버전과 정상적으로 컴파일되었다.

명령행에서 컴파일하기

먼저 적당한 디렉토리에 아파치 배포본 압축을 푼다. 명령행 프롬프트를 열고 그 디렉토리로 cd한다.

Makefile.win 파일에 아파치 makefile 명령이 있다. Windows NT에서 release와 debug 컴파일하는 명령어는 각각 다음과 같다:

nmake /f Makefile.win _apacher

nmake /f Makefile.win _apached

두 명령어 모두 아파치를 컴파일한다. 후자는 결과파일에 디버깅 정보를 포함하여 버그를 찾고 문제를 추적하기 쉽게 한다.

Developer Studio Workspace IDE에서 컴파일하기

VC++의 Visual Studio 개발 환경을 사용하여 아파치를 컴파일할 수도 있다. 과정을 쉽게 하려고 Visual Studio workspace Apache.dsw를 제공한다. 이 workspace는 완전한 아파치 바이너리 배포본에 필요한 .dsp 프로젝트 목록을 담고있다. 또, 알맞은 순서로 컴파일하기위한 프로젝트간 의존성 정보도 포함한다.

Apache.dsw workspace를 열고 InstallBin을 (Release나 Debug 중 원하는 것을) Active Project로 선택한다. InstallBin은 관련된 모든 프로젝트를 컴파일하고, 컴파일된 실행파일과 dll을 옮기는 Makefile.win을 호출한다. InstallBin의 Settings, General 탭, Build command line 항목을 수정하여 INSTDIR=을 변경할 수 있다. INSTDIR= 기본값은 /Apache2 디렉토리이다. (설치하지않고) 테스트로 컴파일만 해보려면 대신 BuildBin 프로젝트를 사용한다.

.dsp 프로젝트 파일은 Visual C++ 6.0 형식이다. Visual C++ 5.0 (97)에서도 이 파일을 사용할 수 있다. Visual C++ 7.0 (.net)은 Apache.dsw와 .dsp 파일들을 Apache.sln과 .msproj 파일들로 변환한다. .dsp 소스파일을 수정하면 반드시 .msproj 파일로 다시 변환하라! 그냥 VC++ 7.0 IDE에서 Apache.dsw를 다시 열기만 하면 된다.

또, Visual C++ 7.0 (.net) 사용자는 Build 메뉴, Configuration Manager 대화창에서 Debug와 Release의 abs, mod_ssl, mod_deflate Solution modules 선택을 해제해야 한다. srclib에 openssl이나 zlib 디렉토리가 있는 경우에만 nmake를 실행하거나 (이 모듈을 명시적으로 컴파일하는) IDE BinBuild 대상을 사용하여 모듈을 컴파일 할 수 있다.

Export한 .mak 파일들이 혼란스럽지만, Visual C++ 5.0 사용자가 mod_ssl, abs (SSL을 지원하는 ab), mod_deflate를 컴파일할때 필요하다. VC++ 7.0 (.net) 사용자에게도 binenv 보다 nmake를 사용하면 컴파일이 더 빠르다. VC++ 5.0이나 6.0 IDE에서 전체 프로젝트를 컴파일하고, Project 메뉴의 Export for all makefiles를 사용하라. 동적으로 자동 생성하는 대상을 모두 컴파일하고 올바른 의존성 정보를 얻기위해서는 먼저 프로젝트를 컴파일해야 한다. 다음 명령어를 사용하여 경로를 수정하면 어떤 경로에서도 컴파일할 수 있다:

perl srclib\apr\build\fixwin32mak.pl

httpd 소스 최상위 디렉토리에서 명령어를 실행해야 한다. 현재 디렉토리와 하위디렉토리에 있는 모든 .mak와 .dep 프로젝트파일을 수정하고, .dsp를 고려하여 파일시간을 수정한다.

프로젝트파일을 다듬어서 패치를 보낸다면, 프로젝트파일을 Visual Studio 6.0 형식으로 만들어야 한다. 변경은 간단하고, VC++ 5.0에서 7.0까지 모든 환경에서 인식하는 최소한의 컴파일 옵션과 링커 옵션을 사용해야 한다.

프로젝트 구성요소

Apache.dsw workspace와 makefile.win nmake 스크립트는 다음 순서대로 아파치 서버 .dsp 프로젝트를 컴파일한다:

  1. srclib\apr\apr.dsp
  2. srclib\apr\libapr.dsp
  3. srclib\apr-util\uri\gen_uri_delims.dsp
  4. srclib\apr-util\xml\expat\lib\xml.dsp
  5. srclib\apr-util\aprutil.dsp
  6. srclib\apr-util\libaprutil.dsp
  7. srclib\pcre\dftables.dsp
  8. srclib\pcre\pcre.dsp
  9. srclib\pcre\pcreposix.dsp
  10. server\gen_test_char.dsp
  11. libhttpd.dsp
  12. Apache.dsp

또, modules\ 하위디렉토리 아래 대부분의 모듈에는 프로젝트파일이 있다.

support\ 디렉토리에는 아파치를 실행하는데 필요하지는 않지만, 관리자가 아파치를 검사하거나 암호파일과 로그파일을 관리하는데 사용할 추가 프로그램들의 프로젝트파일이 있다. Windows 전용 지원 프로그램은 support\win32\ 디렉토리에 따로 있다.

  1. support\ab.dsp
  2. support\htdigest.dsp
  3. support\htpasswd.dsp
  4. support\logresolve.dsp
  5. support\rotatelogs.dsp
  6. support\win32\ApacheMonitor.dsp
  7. support\win32\wintty.dsp

아파치를 컴파일하면 server root 디렉토리에 설치해야 한다. 기본값은 같은 디스크의 \Apache2 디렉토리이다.

컴파일하고 모든 파일을 원하는 폴더 dir에 자동으로 설치하려면 다음 nmake 명령어중 하나를 사용한다:

nmake /f Makefile.win installr INSTDIR=dir

nmake /f Makefile.win installd INSTDIR=dir

INSTDIR의 dir 아규먼트는 설치디렉토리를 뜻한다. 생락하면 \Apache2에 아파치를 설치한다.

다음과 같이 설치한다:

  • dir\bin\Apache.exe - 아파치 실행파일
  • dir\bin\ApacheMonitor.exe - 서비스 감시용 작업표시줄 아이콘 도구
  • dir\bin\htdigest.exe - Digest auth 암호파일 도구
  • dir\bin\htdbm.exe - SDBM auth 데이터베이스 암호파일 도구
  • dir\bin\htpasswd.exe - Basic auth 암호파일 도구
  • dir\bin\logresolve.exe - 로그파일에서 dns 이름을 찾는 도구
  • dir\bin\rotatelogs.exe - 로그파일 순환 도구
  • dir\bin\wintty.exe - 콘솔창 도구
  • dir\bin\libapr.dll - Apache Portable Runtime 공유 라이브러리
  • dir\bin\libaprutil.dll - Apache Utility Runtime 공유 라이브러리
  • dir\bin\libhttpd.dll - Apache Core 라이브러리
  • dir\modules\mod_*.so - 읽어들일 수 있는 아파치 모듈
  • dir\conf - 설정 디렉토리
  • dir\logs - 비어있는 로그 디렉토리
  • dir\include - C 언어 헤더파일
  • dir\lib - 링크 라이브러리파일

개발중인 아파치 버전을 컴파일할때 경고

.dsp 파일은 release마다 새로 만들어진다. 개발자의 시간낭비를 막기위해 .mak 파일은 새로 만들지 않는다. 그러므로 NMAKE 명령어를 사용하여 새로운 .dsp 프로젝트파일을 컴파일할 수 없다. 프로젝트에서 직접 모든 .mak 파일을 export해야 한다. Microsoft Developer Studio 환경에서 컴파일한다면 이 작업이 필요없다.
또, makefile을 export하기 전에 BuildBin 프로젝트를 (혹은 _apacher나 _apached 명령행 대상) 컴파일하면 매우 도움이 된다. 컴파일중에 많은 파일이 자동으로 만들어진다. 전체를 컴파일해야만 정상적으로 컴파일할때 필요한 의존파일을 모두 만든다.

배포용 .mak 파일을 만드려면 항상 .mak (혹은 .dep)에서 Platform SDK 등의 의존성을 점검하라. DevStudio\SharedIDE\bin\ (VC5)나 DevStudio\Common\MSDev98\bin\ (VC6) 디렉토리에는 모든 예외 목록이 담긴 sysincl.dat 파일이 있다. 이 파일에 의존성 정보를 추가한다 (sys/time.h와 sys\time.h와 같이, 경로는 슬래쉬를 사용한 것과 백슬래쉬를 사용한 것 모두를 추가한다). 배포할 .mak 파일에 현재 컴퓨터에만 해당하는 설치경로가 있다면 컴파일이 완전히 실패한다. 그러므로 srclib/apr/build/fixwin32mak.pl을 실행해하여 .mak 파일에 있는 절대경로를 없애야 한다.


Novell NetWare에서 아파치 사용하기 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Platform Specific Notes

Novell NetWare에서 아파치 사용하기

이 문서는 Novell NetWare 6.0 이상에서 아파치 2.0을 설치, 설정, 실행하는 방법을 설명한다. 버그를 찾았거나 다른 방법으로 돕고싶다면, 버그 보고 페이지를 이용하길 바란다.

버그 보고 페이지나 dev-httpd 메일링리스트는 아파치 설정과 실행에 대한 질문을 답하지 않는다. 버그를 보고하기 전에 먼저 이 문서와 자주 물어보는 질문 (FAQ) 페이지, 다른 관련문서를 살펴봐라. 그래도 궁금한 점이나 문제가 있다면, NetWare에서 아파치 사용에 대한 어렵고 새로운 질문을 답해줄 많은 아파치 사용자가 있는 novell.devsup.webserver 뉴스그룹에 글을 올리길 바란다.

이 문서는 바이너리 배포본으로 아파치를 설치했다고 가정한다. (아마도 개발에 도움을 주거나 버그를 찾기위해) 직접 아파치를 컴파일하려면 아래 NetWare에서 아파치 컴파일하기 절을 참고하라.

요구조건

아파치 2.0은 NetWare 6.0 service pack 3 이상에서 동작하도록 설계되었다. SP3보다 낮은 service pack을 사용한다면 최신 NetWare Libraries for C (LibC)를 설치해야 한다.

NetWare service pack은 여기에 있다.

최신 service pack이나 최신 버전 NetWare Libraries for C (LibC)를 설치했다면 NetWare 5.1 환경에서도 NetWare용 아파치 2.0을 실행할 수 있다. 경고: NetWare용 아파치 2.0은 이 환경을 고려하지 않았고 테스트하지 않았다.

NetWare용 아파치 다운받기

아파치 최신 버전에 대한 정보는 http://www.apache.org/에서 (아파치 웹서버) 찾을 수 있다. 여기에는 현재 버전과 최근 알파/베타테스트 버전, 미러 웹사이트와 ftp 사이트 정보가 있다. NetWare용 아파치 2.0의 최신 바이너리 배포본은 여기에서 다운받을 수 있다.

NetWare용 아파치 설치하기

현재 NetWare용 아파치 설치프로그램은 없다. NetWare용 아파치 2.0 소스를 직접 컴파일한다면 파일을 서버로 직접 복사해줘야 한다.

바이너리로 다운받은 NetWare용 아파치를 설치하는 과정은 다음과 같다 (sys:/apache2에 설치한다고 가정한다):

  • 바이너리로 다운받은 압축파일을 SYS: 볼륨 최상위 디렉토리에 푼다 (다른 볼륨에 설치해도 된다)
  • httpd.conf 파일을 수정하여 ServerRoot와 ServerName과 파일경로 값을 서버에 알맞게 지정한다
  • 예를 들어

    SEARCH ADD SYS:\APACHE2

    와 같이 검색경로에 SYS:/APACHE2를 추가한다

직접 소스를 컴파일한 경우 NetWare에 아파치를 설치하는 방법은 다음과 같다 (sys:/apache2에 설치한다고 가정한다):

  • NetWare 볼륨에 Apache2라는 디렉토리를 만든다
  • APACHE2.NLM과 APRLIB.NLM을 SYS:/APACHE2에 복사한다
  • SYS:/APACHE2 아래에 BIN이라는 디렉토리를 만든다
  • HTDIGEST.NLM, HTPASSWD.NLM, HTDBM.NLM, LOGRES.NLM, ROTLOGS.NLM을 SYS:/APACHE2/BIN에 복사한다
  • SYS:/APACHE2 아래에 CONF라는 디렉토리를 만든다
  • HTTPD-STD.CONF 파일을 SYS:/APACHE2/CONF에 복사하고 파일명을 HTTPD.CONF로 변경한다
  • MIME.TYPES, CHARSET.CONV, MAGIC 파일을 SYS:/APACHE2/CONF 디렉토리에 복사한다
  • \HTTPD-2.0\DOCS\ICONS에 있는 모든 파일과 하위디렉토리를 SYS:/APACHE2/ICONS로 복사한다
  • \HTTPD-2.0\DOCS\MANUAL에 있는 모든 파일과 하위디렉토리를 SYS:/APACHE2/MANUAL로 복사한다
  • \HTTPD-2.0\DOCS\ERROR에 있는 모든 파일과 하위디렉토리를 SYS:/APACHE2/ERROR로 복사한다
  • \HTTPD-2.0\DOCS\DICROOT에 있는 모든 파일과 하위디렉토리를 SYS:/APACHE2/HTDOCS로 복사한다
  • 서버에 SYS:/APACHE2/LOGS 디렉토리를 만든다
  • 서버에 SYS:/APACHE2/APACHE2/CGI-BIN이란 디렉토리를 만든다
  • SYS:/APACHE2/MODULES 디렉토리를 만들고 모든 nlm 모듈을 modules 디렉토리로 복사한다
  • HTTPD.CONF 파일의 모든 @@Value@@ 표시를 적절한 설정으로 대체한다

  • SEARCH ADD SYS:\APACHE2

    같이 검색경로에 SYS:/APACHE2를 추가한다

기본 SYS 볼륨이 아닌 다른 볼륨에도 아파치를 설치할 수 있다.

makefile 명령어에 "install" 키워드를 사용하면 컴파일시 자동으로 DIST 하위디렉토리에 완전한 배포본을 만든다. makefile로 만든 배포본을 NetWare 볼륨 최상위 디렉토리로 복사하면 아파치가 설치된다 (아래 NetWare용 아파치 컴파일하기 참고).

NetWare용 아파치 실행하기

아파치를 시작하려면 콘솔에서 apache를 입력하면 된다. 그러면 운영체제 주소영역에 아파치를 읽어들인다. 보호주소영역에 아파치를 읽어들이려면 다음과 같이 load 명령어로 주소영역을 지정한다:

load address space = apache2 apache2

그러면 아파치를 apache2라는 주소영역에 읽어들인다. NetWare는 여러 아파치를 각각 다른 보호주소영역에 읽어들여서 여러 아파치를 동시에 실행할 수 있다.

아파치가 시작하면 (설정파일에서 Listen 지시어를 수정하지 않는한) 포트 80번을 기다린다. 브라우저를 시작하여 서버명 혹은 서버 주소를 입력하면 서버에 접속하여 기본페이지에 접근한다. 아파치 설명서 링크가 있는 환영페이지가 나와야 한다. 아무 일도 없거나 오류가 발생하면 logs 디렉토리에 있는 error_log 파일을 살펴봐라.

기본 설치가 동작하면 conf 디렉토리에 있는 파일을 적절히 설정한다.

운영체제 주소영역에서 실행중인 아파치를 내릴려면 콘솔에 다음과 같이 입력한다:

unload apache2

혹은

apache2 shutdown

보호주소영역에서 아파치를 실행했다면 unload 명령어에 주소영역을 지정한다:

unload address space = apache2 apache2

아파치가 설정파일 위치를 찾는 방법을 알아두어야 한다. 명령행에서 설정파일을 지정하는 방법은 두가지다:

  • -f는 특정 설정파일 경로를 지정한다

apache2 -f "vol:/my server/conf/my.conf"

apache -f test/test.conf

이 경우 설정파일은 올바른 ServerRoot를 설정해야 한다.

-f로 설정파일명을 지정하지 않으면, 아파치는 서버에 컴파일된 파일명을 (보통 conf/httpd.conf) 사용한다. -V 옵션으로 아파치를 시작하면 SERVER_CONFIG_FILE이라는 항목을 보여준다. 아파치는 다음 순서대로 ServerRoot를 찾는다:

  • -C 옵션의 ServerRoot 지시어.
  • 명령행의 -d 옵션.
  • 현재 디렉토리
  • 서버에 컴파일된 server root.

서버에 컴파일된 server root는 보통 sys:/apache2이다. -V 옵션으로 아파치를 시작하면 HTTPD_ROOT라는 항목을 보여준다.

NetWare용 아파치 2.0에는 실행중인 웹서버를 죽이거나 정보를 알려주는 명령행 지시어가 있다. 이들 지시어는 아파치 동작중에만 사용할 수 있다. 지시어 앞에는 APACHE2 키워드를 붙여야 한다.

RESTART
모든 쓰레드가 쉬는 상태일때 아파치를 죽이고, 설정파일을 다시 읽은후 새로운 설정에 따라 worker 쓰레드들을 재시작한다.
VERSION
현재 실행중인 아파치 버전 정보를 출력한다.
MODULES
기본 모듈과 외부 모듈 목록을 출력한다.
DIRECTIVES
모든 지시어 목록을 출력한다.
SETTINGS
콘솔에 쓰레드 상태 표시를 보이거나 없앤다. 상태를 보이면, 아파치 콘솔창에 동작하는 쓰레드들의 상태가 나온다.
SHUTDOWN
실행중인 아파치 웹서버를 죽인다.
HELP
실행 옵션들을 설명한다.

기본적으로 이 지시어들은 운영체제 주소영역에서 실행중인 아파치를 대상으로 한다. 아파치가 보호주소영역에서 실행중이라면, -p와 주소영역 이름을 추가한다. 더 많은 정보를 보려면 명령행에 "apache2 Help"를 입력한다.

NetWare용 아파치 설정하기

아파치는 보통 conf 디렉토리에 있는 설정파일로 설정한다. 이 파일은 유닉스용과 같지만, NetWare용 아파치에는 조금 다른 지시어들이 있다. 사용가능한 모든 지시어에 대해서는 아파치 문서를 참고하라.

NetWare용 아파치의 주된 차이점은:

  • NetWare용 아파치는 다중쓰레드 방식을 사용하기때문에, 유닉스와 같이 요청마다 다른 프로세스를 사용하지 않는다. 대신 여러 쓰레드를 실행한다: 부모 쓰레드와 요청을 처리하는 여러 자식 혹은 worker 쓰레드들.

    그러므로 "프로세스"-관리 지시어가 다르다:

    MaxRequestsPerChild - 유닉스와 같이 worker 쓰레드가 요청을 얼마만큼 처리하고 죽을지를 조정한다. 권장하는 기본값 MaxRequestsPerChild 0을 사용하면 쓰레드는 죽지않고 영원히 요청을 서비스한다. 특별한 이유가 없다면 NetWare에서는 이 지시어를 0으로 설정하길 권한다.

    StartThreads - 이 지시어는 서버가 처음에 시작할 쓰레드 개수를 결정한다. 권장하는 기본값은 StartThreads 50이다.

    MinSpareThreads - 서버는 쉬는(idle) 쓰레드 개수가 이 값보다 적으면 worker 쓰레드를 더 만든다. 권장하는 기본값은 MinSpareThreads 10이다.

    MaxSpareThreads - 서버는 쉬는 쓰레드 개수가 이 값보다 많으면 worker 쓰레드를 죽이기 시작한다. 권장하는 기본값은 MaxSpareThreads 100이다.

    MaxThreads - 이 지시어는 worker 쓰레드의 최대 개수를 제한한다. 권장하는 기본값은 ThreadsPerChild 250이다.

    ThreadStackSize - 한 worker 쓰레드가 사용할 스택 크기를 지시한다. 권장하는 기본값은 ThreadStackSize 65536이다.

  • 아규먼트로 파일명을 받는 지시어에는 유닉스 파일명이 아닌 NetWare 파일명을 사용해야 한다. 그러나 아파치가 내부적으로 유닉스식 파일명을 사용하기때문에 백슬래쉬 대신 슬래쉬를 사용해야 한다. 모든 절대경로에 볼륨명을 포함하길 바란다. 볼륨명을 생략하면 아파치는 SYS: 볼륨이라고 잘못 가정할 수 있다.

  • NetWare용 아파치는 서버를 다시 컴파일하지 않고 실행할때 모듈을 읽어들일 수 있다. 보통 아파치를 컴파일하면 \Apache2\modules 디렉토리에 여러 추가 모듈을 설치한다. 이들 혹은 다른 모듈을 사용하려면 LoadModule 지시어를 사용한다. 예를 들어 status 모듈을 사용한다면:

    LoadModule status_module modules/status.nlm

    읽어들일 수 있는 모듈 만들기에 대한 정보도 있다.

이외의 NetWare 전용 지시어들:

  • CGIMapExtension - CGI 파일 확장자를 스크립트 인터프리터와 연결한다.
  • SecureListen - 특정 포트를 SSL 암호화한다.
  • NWSSLTrustedCerts - 프록시하는 서버에 보안연결할때 사용할 신뢰하는 인증서(certificate)를 추가한다.
  • NWSSLUpgradeable - 특정 주소/포트로 맺어진 연결을 SSL 연결로 변경할 수 있다.

Netware용 아파치 컴파일하기

아파치를 컴파일하려면 MetroWerks CodeWarrior 6.x 이상이 필요하다. 아파치를 컴파일하면 어떤 Netware 볼륨에라도 설치할 수 있다. 기본값은 sys:/Apache2 디렉토리다.

서버를 실행하기 전에 conf 디렉토리를 작성해야 한다. 배포본의 conf 디렉토리에 있는 HTTPD-STD.CONF 파일명을 HTTPD.CONF로 변경한다. HTTPD.CONF 파일에서 @@Value@@ 표시를 찾아서 적절한 설정으로 대체한다. conf/magic과 conf/mime.types 파일도 복사한다. 아니면 makefile을 실행할때 install 키워드를 사용하면 완전한 배포본을 만든다.

요구사항:

NetWare용 아파치 2.0을 컴파일하려면 다음 개발도구가 필요하다:

  • Metrowerks CodeWarrior 6.0 이상과 NetWare PDK 3.0 이상.
  • NetWare Libraries for C (LibC)
  • LDAP Libraries for C
  • ZLIB 압축 라이브러리 소스코드
  • AWK 도구 (awk, gawk 등). AWK는 http://developer.novell.com/ndk/apache.htm에서 다운받을 수 있다. 도구를 awk.exe란 이름으로 윈도우즈 경로에 두어야 한다.
  • makefile을 사용하여 컴파일하려면 http://developer.novell.com/ndk/apache.htm에 있는 GNU make 버전 3.78.1 (GMake)이 필요하다.

NetWare makefile을 사용하여 아파치 컴파일하기:

  • NOVELLLIBC 환경변수를

    Set NOVELLLIBC=c:\novell\ndk\libc

    와 같이 NetWare Libraries for C SDK 위치로 설정한다.
  • METROWERKS 환경변수를

    Set METROWERKS=C:\Program Files\Metrowerks\CodeWarrior

    와 같이 Metrowerks CodeWarrior 컴파일러를 설치한 위치로 설정한다. 기본 위치인 C:\Program Files\Metrowerks\CodeWarrior에 설치하였다면, 환경변수를 설정할 필요는 없다.
  • LDAPSDK 환경변수를

    Set LDAPSDK=c:\Novell\NDK\cldapsdk\NetWare\libc

    와 같이 LDAP Libraries for C를 설치한 위치로 설정한다.
  • ZLIBSDK 환경변수를

    Set ZLIBSDK=D:\NOVELL\zlib

    과 같이 ZLib 라이브러리 소스코드 위치로 설정한다.
  • AP_WORK 환경변수를 \httpd-2.0 디렉토리의 전체 경로로 설정한다.
  • APR_WORK 환경변수를 \httpd-2.0\srclib\apr 디렉토리의 전체 경로로 설정한다.
  • AWK 도구와 GNU make (gmake.exe) 도구가 시스템의 PATH 환경변수에 포함되있는지 확인한다.
  • 소스코드를 다운받아 적당한 디렉토리에 압축을 푼다.
  • \httpd-2.0\srclib\apr-util\uri 디렉토리에서 "gmake -f nwgnumakefile"을 실행하여 GENURI.nlm을 컴파일한다.
  • GENURI.nlm 파일을 NetWare 서버의 SYS: 볼륨으로 복사하고

    SYS:\genuri > sys:\uri_delims.h

    명령을 실행한다.
  • uri_delims.h 파일을 컴파일하는 컴퓨터의 \httpd-2.0\srclib\apr-util\uri 디렉토리로 복사한다.
  • \httpd-2.0\srclib\apr 디렉토리에서 "gmake -f nwgnumakefile"을 실행하여 APR을 컴파일한다.
  • \httpd-2.0\srclib\pcre 디렉토리에서 "gmake -f nwgnumakefile"을 실행하여 DFTABLES.nlm을 컴파일한다.
  • \httpd-2.0\server 디렉토리에서 "gmake -f nwgnumakefile"을 실행하여 GENCHARS.nlm을 컴파일한다.
  • 각 디렉토리의 GENCHARS.nlm과 DFTABLES.nlm 파일을 NetWare 서버의 SYS: 볼륨으로 복사하고 다음과 같이 실행한다:

    SYS:\genchars > sys:\test_char.h
    SYS:\dftables > sys:\chartables.c

  • test_char.h와 chartables.c 파일을 컴파일하는 컴퓨터의 \httpd-2.0\os\netware 디렉토리로 복사한다.
  • \httpd-2.0 디렉토리에서 "gmake -f nwgnumakefile"을 실행하여 아파치를 컴파일한다.

    gmake -f nwgnumakefile install

    과 같이 install 파라미터를 추가하면 배포용 디렉토리를 만들 수 있다.

추가 make 옵션

  • gmake -f nwgnumakefile

    일반 실행파일을 컴파일하여 \release 디렉토리로 복사한다.

  • gmake -f nwgnumakefile DEBUG=1

    디버그용 실행파일을 컴파일하여 \debug 디렉토리로 복사한다.

  • gmake -f nwgnumakefile install

    \dist\Apache2 디렉토리에 실행파일, 문서, 추가 지원파일을 포함한 완전한 아파치 배포본을 만든다.

  • gmake -f nwgnumakefile installdev

    install과 비슷하지만, \lib과 \include 디렉토리를 만들고 헤더파일과 import 파일을 복사한다.

  • gmake -f nwgnumakefile clean

    DEBUG 정의 유무에 따라 \release나 \debug에 있는 오브젝트파일과 실행파일을 모두 지운다.

  • gmake -f nwgnumakefile clobber_all

    clean과 비슷하지만 디렉토리도 지운다.


HPUX에서 고성능 웹서버 실행하기 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Platform Specific Notes

HPUX에서 고성능 웹서버 실행하기

Date: Wed, 05 Nov 1997 16:59:34 -0800
From: Rick Jones <raj@cup.hp.com>
Reply-To: raj@cup.hp.com
Organization: Network Performance
Subject: HP-UX tuning tips

이 글은 성능향상 페이지에 추가할 HP-UX 성능향상 팁이다.

HP-UX 9.X는: 10.20으로 업그레이드하라
HP-UX 10.[00|01|10]은: 10.20으로 업그레이드하라

HP-UX 10.20은:

최근 ARPA Transport 패치 모음을 설치한다. 그러면 TCP 연결찾기 해쉬테이블 크기를 설정할 수 있다. 기본값은 256 개이고, 2의 거듭제곱값으로 지정해야 한다. adb로 커널의 *disc* 이미지를 수정하여 설정한다. 변수명은 tcp_hash_size이다. tcp_hash_size 변수값이 32비트이므로 disc 이미지를 수정할때 반드시 16비트 값을 기록하는 "w" 대신 32비트 값을 기록하는 "W"를 사용해야 한다.

어떤 값을 고를까? ftp://ftp.cup.hp.com/dist/networking/tools/connhist의 결과를 보고, 시스템에 존재하는 TCP 연결 총개수를 살펴봐라. 이 숫자를 해쉬테이블 크기로 나눈 값이 상당히 (10 이하) 작으면 좋다. HP의 SPECweb96 결과에서 일반적인 설정을 볼 수 있다. 결과는 http://www.specbench.org/에 있다. HP-UX 시스템이 초당 1000번 SPECweb96 연결을 하는 경우 TIME_WAIT가 60초라면 60,000개의 TCP "연결"을 추적한다는 뜻이다.

ftp://ftp.cup.hp.com/dist/networking/misc/listenq를 실행하여 시스템의 연결대기행렬 깊이를 알 수 있다.

PA-8000기반 시스템에서 아파치를 실행한다면, 아파치 실행파일이 큰 페이지크기를 사용하도록 "chatr"한다. 명령은 "chatr +pi L <실행파일>"이다. 실행파일을 실행하는 GID에 MLOCK 권한이 반드시 필요하다. MLOCK 부여에 대해서는 Setprivgrp(1m)를 참고하라. 수정후 Glance를 실행하여 서버의 메모리영역을 살펴보면 상당한 text 세그먼트가 잠겨있음을 확인할 수 있다.

다중프로세스 시스템에서 아파치를 실행한다면, 프로세스를 프로세스에 배정하는 mpctl()를 사용한 작은 프로그램을 작성해봐라. 단순한 pid % numcpu 알고리즘으로도 충분할 것이다. 이 부분은 앞으로 소스코드에 포함될 수 있다.

FIN_WAIT_2 연결의 개수가 걱정스럽다면, nettune을 사용하여 tcp_keepstart 값을 줄일 수 있다. 그러나 조심해야 한다 - 4분 보다 작게 설정하지 마라. tcp_hash_size를 잘 설정하였다면, FIN_WAIT_2 값이 커도 (심지어 기본값인 2시간도) 문제없다 - 보통 성능에 큰 영향을 주지 않는다.

앞으로 소스코드에 포함될 부분이 더 있지만, 여기서 줄인다. 관심이 있다면 메일을 주길 바란다.

그럼 이만,

rick jones

http://www.cup.hp.com/netperf/NetperfPage.html


아파치 EBCDIC 포팅 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Platform Specific Notes

아파치 EBCDIC 포팅

이 문서는 아파치 웹서버 2.0 버전에서 변경된 내용을 담고있지 않다. 아직도 유효한 정보가 있지만, 주의해서 사용하길 바란다.

아파치 EBCDIC 포팅 개요

아파치 웹서버는 1.3 버전때 처음으로 EBCDIC 문자집합을 기본 문자집합으로 사용하는 (비-ASCII) 메인플레임 컴퓨터로 포팅되었다.

(BS2000/OSD 운영체제를 사용하는 SIEMENS 계열 메인플레임을 말한다. 이 메인플레임 운영체제에는 현재 SVR4계열의 POSIX 하위시스템이 있다).

포팅은 처음에 다음과 같은 목적에서 시작되었다

  • 이 플레폼으로도 아파치 웹서버를 포팅할 수 있다는 가능성을 보이기위해서
  • (몇년 전에 포팅된) 오래된 CERN-3.0 서버를 대체할 "쓸만하고 유능한" 후계자를 찾기위해
  • 이 플레폼에서 아파치의 prefork 프로세스 방식이 CERN의 accept-fork-serve 방식 보다 5배 이상 성능이 좋음을 보이기위해서.

이 문서는 포팅시 여러 설계상 결정의 이유를 설명한다.

설계 목표

EBCDIC 포팅의 목적중 하나는 새로운 서버로 전환을 유도하고 쉽게 전환할 수 있도록 가능한 (EBCDIC) CERN 서버와 호환성을 유지하는 것이다. 그래서 HTML 문서가 (이전 CERN 서버가 인식하는 유일한 형식인) ASCII와 (POSIX 하위시스템의 기본 문서 형식. 그러므로 grep이나 sed 같은 POSIX 도구를 사용할 수 있는 현실적인 형식인) EBCDIC 중 어느 형식인지 설정할 수 있어야 한다. 현재 해결책은 아파치 서버가 중간에서 문서를 가로채서 문서의 형식을 파악하는 "가상 MIME 형식"이다 (아래 참고). 다음 버전에서는 변환해야할 모든 문서에 "ebcdic-handler"를 정의하는 방법으로 문제를 해결할 것이다.

기술적 해결책

아파치가 BUFF 자료형과 메써드를 사용하여 모든 입출력을 하므로 가장 쉬운 방법은 BUFF 처리 함수에 변환기능을 추가하는 것이다. 언제든지 변환할 수 있어야 하기때문에 BUFF 객체를 변환해야 하는지 알려주는 BUFF 표시를 추가했다. 이 표시는 HTTP 프로토콜의 여러 단계에서 변경될 수 있다:

  • 요청을 받기 전에 변환 (요청과 요청헤더가 항상 ASCII 형식이기 때문에)
  • 요청 내용을 받았을때 content type에 따라 변환/변환안함 (요청 내용이 ASCII 문자나 바이너리 파일인 경우 변환해야 하기때문에)
  • 응답헤더를 보내기 전에 변환 (응답헤더는 항상 ASCII 형식이기때문에)
  • 응답 내용을 보낼때 content type에 따라 변환/변환안함 (응답 내용이 문자 파일이거나 바이너리 파일이기때문에)

포팅에 대해서

  1. 소스의 변화는 두가지 #ifdef로 구분할 수 있다:

    #ifdef CHARSET_EBCDIC

    모든 EBCDIC기반 컴퓨터에 필요한 코드. 문자변환, 두 문자집합간의 연속된 문자값 차이, 어떤 HTTP 프로토콜 부분이 변환되야 하는지를 알려주는 표시 등.

    #ifdef _OSD_POSIX

    SIEMENS BS2000/OSD 메인플레임 플레폼에만 필요한 코드. BS2000/OSD 플레폼에만 필요한 헤더파일 차이와 소켓 구현 문제를 다룬다.

  2. 소켓 수준에서 ASCII와 EBCDIC간 변화는 (BS2000 POSIX에는 이 기능을 지원하는 소켓 옵션이 있다) HTTP 프로토콜 수준에서 전송되는 자료에 프로토콜관련 문자열과 프로토콜과 무관한 일반파일이 섞여있기때문에 의도적으로 사용하지 않았다. HTTP 프로토콜 문자열은 (GET 요청, Header: 줄, 기타 정보 등.) 항상 ASCII 형식이고, 파일전송 부분은 (즉, GIF 그림, CGI 출력 등.) 서버가 항상 "변환하지않고 그냥" 보내야 한다. 서버 코드는 "프로토콜 문자열"과 "일반 자료"를, 문자열에는 bgets()나 rvputs(), 바이너리 자료에는 bgets()나 rvputs() 함수를 사용하여 구별한다. 그러므로 무조건 모든 것을 변환하는 것은 적절하지 않다.

    (물론 문자파일의 경우 EBCDIC 문서를 항상 ASCII로 서비스하도록 준비해야 한다)

  3. 그래서 포팅에는 (컴파일러가 EBCDIC 문자열로 변환한) 서버 내부 문자열과 서버가 생성한 문서를 기본 프로토콜 수준에서 변환하는 기능이 있다. 서버 코드에 산재된 ASCII escape문자 \012와 \015는 예외다: 이들이 이미 ASCII \n과 \r의 바이너리 값이기때문에 ASCII로 두번 변환하면 안된다. 이 예외는 서버가 생성한 문자열에만 적용된다; 외부 EBCDIC 문서는 ASCII 줄바꿈문자를 포함하면 안된다.

  4. BUFF 관리함수를 사용하는 방법을 살펴본 후 나는 모든 puts/write/get/gets가 거치게되는 "ebcdic/ascii 변환 계층"을 추가하고, 동적으로 변환유무를 설정할 수 있는 변환 표시를 추가했다. 문서가 원본(파일이나 CGI 출력)에서 대상(요청한 클라이언트)으로 이동할때 항상 이 계층을 두번 지난다: 파일 -> 아파치, 아파치 -> 클라이언트.

    서버는 이제 EBCDIC 형식으로 된 CGI 스크립트 출력의 헤더줄을 읽고, 나머지 스크립트 출력이 ASCII임을 알아낼 수 있다 (WWW 방문자수를 세는 프로그램과 같은 경우: 문서 내용은 GIF 그림이다). 기본 EBCDIC 형식으로 모든 헤더를 처리한다; 그런 다음 서비스할 문서의 type에 따라 서버는 문서 내용이 이미 ASCII인지 혹은 EBCDIC에서 변환을 해야 하는지 결정한다.

  5. (MIME type이 text/plain, text/html 등) 내용이 일반 문자인 문서를 암묵적으로 ASCII로 변환하거나, (사용자에게 빠르게 서비스하기위해 미리 문서를 ASCII 형식으로 저장하였거나 NFS로 마운트한 디렉토리에 파일이 있는 경우) 변환없이 서비스할 수 있다.

    예:

    이름이 .ahtml로 끝나는 파일을 암묵적인 변환없이 ASCII text/html 문서로 (그리고 .ascii 확장자는 ASCII text/plain으로) 서비스하려면 다음 지시어를 사용한다:

    AddType text/x-ascii-html .ahtml
    AddType text/x-ascii-plain .ascii

    또, text/foo 식의 MIME type을 AddType "text/x-ascii-foo" 설정하여 "일반 ASCII"로 서비스할 수 있다.

  6. 내용이 일반 문자가 아닌 문서는 변환없이 항상 "바이너리"로 서비스한다. 예를 들어, GIF/ZIP/AU 파일형식에 가장 적합한 선택이다. 물론 사용자는 "rcp -b" 바이너리 옵션을 사용하여 파일을 메인플레임 호스트로 복사했어야 한다.

  7. 서버파싱 파일은 항상 컴퓨터가 사용하는 기본 형식으로 (즉, EBCDIC) 저장되었다고 가정하고, 처리후에 변환한다.

  8. CGI 출력의 경우 CGI 스크립트가 변환이 필요한지 결정한다: 적절한 Content-Type을 설정하여, 문자파일은 변환하고, GIF 출력은 변환없이 보낼 수 있다. 우리가 포팅한 wwwcount 프로그램이 후자의 경우다.

문서 저장에 대해서

바이너리 파일

서버는 Content-Type:이 text/로 시작하는 않는 파일을 바이너리 파일로 간주하여 어떤 변환도 하지 않는다. 바이너리 파일에는 GIF 그림, gzip으로 압축한 파일 등이 있다.

메인플레임 호스트와 유닉스 혹은 윈도우즈 PC간에 바이너리 파일을 전송할 때는 ftp "binary" (TYPE I) 명령어나 메인플레임 호스트에서 (유닉스 rcp는 -b 옵션을 지원하지 않는다) rcp -b 명령어를 반드시 사용하라.

문자 문서

기본적으로 서버는 문자파일이 (즉, Content-Type:이 text/로 시작하는 모든 파일) 호스트의 기본 문자집합인 EBCDIC으로 저장되었다고 가정한다.

Server Side Include 문서

SSI 문서는 현재 EBCDIC 형식으로만 저장해야 한다. 처리하기 전에 ASCII를 변환하지 않는다.

아파치 모듈의 상태

모듈 | 상태 | 비고
core | + |
mod_access | + |
mod_actions | + |
mod_alias | + |
mod_asis | + |
mod_auth | + |
mod_auth_anon | + |
mod_auth_dbm | ? | 자체 libdb.a를 사용하여
mod_autoindex | + |
mod_cern_meta | ? |
mod_cgi | + |
mod_digest | + |
mod_dir | + |
mod_so | - | 공유라이브러리가 없음
mod_env | + |
mod_example | - | (시험 단계)
mod_expires | + |
mod_headers | + |
mod_imap | + |
mod_include | + |
mod_info | + |
mod_log_agent | + |
mod_log_config | + |
mod_log_referer | + |
mod_mime | + |
mod_mime_magic | ? | 아직 포팅안됨
mod_negotiation | + |
mod_proxy | + |
mod_rewrite | + | 테스트안됨
mod_setenvif | + |
mod_speling | + |
mod_status | + |
mod_unique_id | + |
mod_userdir | + |
mod_usertrack | ? | 테스트안됨

제삼자가 만든 모듈의 상태

모듈 | 상태 | 비고
mod_jserv | - | JAVA는 포팅중이다.
mod_php3 | + | mod_php3는 LDAP, GD, FreeType 라이브러리와 함께 잘 동작한다.
mod_put | ? | 테스트안됨
mod_session | - | 테스트안됨


서버와 지원 프로그램 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

서버와 지원 프로그램

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

아파치 웹서버에 포함된 프로그램들이다.

목록

httpd
아파치 하이퍼텍스트 전송 프로토콜 서버
apachectl
아파치 웹서버 조절 인터페이스
ab
아파치 웹서버 성능검사 도구
apxs
아파치 확장 도구 (APache eXtenSion tool)
configure
소스 트리를 구성한다
dbmmanage
basic authentication에 사용할 DBM 형식의 사용자 인증파일을 만들고 수정한다
htdigest
digest authentication에 사용할 사용자 인증파일을 만들고 수정한다
htpasswd
basic authentication에 사용할 사용자 인증파일을 만들고 수정한다
logresolve
아파치 로그파일의 IP-주소를 호스트명으로 변환한다
rotatelogs
서버를 죽이지않고 아파치 로그를 순환한다
suexec
실행을 위해 사용자를 변경한다 (Switch User For Exec)
다른 프로그램들
manpage가 없는 지원 도구들.


httpd - 아파치 하이퍼텍스트 전송 프로토콜 서버 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

httpd - 아파치 하이퍼텍스트 전송 프로토콜 서버

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

httpd는 아파치 하이퍼텍스트 전송 프로토콜 (HTTP) 서버 프로그램이다. 자체(standalone) 데몬 프로세스로 실행하도록 설계되었다. 원한다면 요청을 처리하기위해 자식 프로세스와 쓰레드들을 만든다.

일반적으로 httpd를 직접 실행하기보다는 유닉스기반 시스템에서는 apachectl을 통해, 2000, XP에서는 서비스로, Windows 9x와 ME에서는 콜솔 프로그램으로 실행해야 한다.

참고

  • 아파치 시작
  • 아파치 중단
  • 설정파일
  • 플래폼별 문서
  • apachectl

개요

httpd [ -d serverroot ] [ -f config ] [ -C directive ] [ -c directive ] [ -D parameter ] [ -e level ] [ -E file ] [ -k start|restart|graceful|stop ] [ -R directory ] [ -h ] [ -l ] [ -L ] [ -S ] [ -t ] [ -v ] [ -V ] [ -X ]

Windows 시스템에서는 다음 아규먼트를 추가로 사용할 수 있다:

httpd [ -k install|config|uninstall ] [ -n name ] [ -w ]

옵션

-d serverroot
ServerRoot 지시어의 기본값을 serverroot로 설정한다. 설정파일에서 ServerRoot 지시어를 사용하여 이 값을 수정할 수 있다. 기본값은 /usr/local/apache2이다.
-f config
시작할때 config 파일에 있는 지시어를 사용한다. config가 /로 시작하지 않으면 ServerRoot에 상대경로이다. 기본값은 conf/httpd.conf이다.
-k start|restart|graceful|stop
httpd를 시작, 재시작, 중단한다. 더 자세한 정보는 아파치 중단하기를 참고하라.
-C directive
설정파일을 읽기전에 directive 지시어를 처리한다.
-c directive
설정파일을 읽기전에 directive 지시어를 처리한다.
-D parameter
서버 시작 혹은 재시작시 선택적으로 명령어를 처리하기위해 설정파일의 <IfDefine> 섹션에 사용할 parameter를 설정한다.
-e level
서버가 시작하는동안 LogLevel을 level로 설정한다. 이는 시작중 문제를 찾기위해 잠시 더 자세한 오류문을 얻을때 유용하다.
-E file
서버가 시작하는동안 file로 오류문을 보낸다.
-R directory
서버를 SHARED_CORE 규칙을 사용하여 컴파일한 경우 공유오브젝트파일 directory를 지정한다.
-h
사용할 수 있는 명령행 옵션들의 짧은 요약을 출력한다.
-l
서버에 같이 컴파일한 모듈 목록을 출력한다. LoadModule 지시어를 사용하여 동적으로 읽어들이는 모듈은 출력하지 않는다.
-L
지시어 목록을 지시어가 받는 아규먼트와 지시어 사용장소와 같이 출력한다.
-S
설정파일에서 읽어들인 설정을 보여준다 (현재는 가상호스트 설정만을 보여준다).
-t
설정파일의 문법검사만 한다. 프로그램은 문법을 검사한후 (문법이 올바른 경우) 0이나 (문법에 문제가 있는 경우) 0이 아닌 종료코드로 즉시 종료한다. -D DUMP_VHOSTS을 사용하면 가상호스트 설정을 자세히 출력한다.
-v
httpd의 버전을 출력하고 종료한다.
-V
httpd의 버전과 컴파일 파라미터를 출력하고 종료한다.
-X
디버그 상태로 웹서버를 실행한다. 오직 한 프로세스나 쓰레드로만 서비스하고, 서버는 콘솔에서 떨어지지 않는다.

다음 아규먼트는 Windows 플래폼에서만 사용할 수 있다:

-k install|config|uninstall
아파치를 Windows NT 서비스로 설치한다; 아파치 서비스의 시작 옵션을 수정한다; 아파치 서비스 설치를 지운다.
-n name
아파치 서비스의 name.
-w
오류가 발생하면 콘솔창을 열어서 오류문을 보여준다.


ab - 아파치 웹서버 성능검사 도구 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

ab - 아파치 웹서버 성능검사 도구

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

ab는 아파치 하이퍼텍스트 전송 프로토콜 (HTTP) 서버의 성능을 검사하는(benchmarking) 도구이다. 현재 아파치가 어떻게 동작하는지 알려준다. 특히 아파치가 현재 초당 몇개의 요청을 서비스하는지 알려준다.

참고

  • httpd

개요

ab
    [ -A auth-username:password ]
    [ -c concurrency ]
    [ -C cookie-name=value ]
    [ -d ]
    [ -e csv-file ]
    [ -g gnuplot-file ]
    [ -h ]
    [ -H custom-header ]
    [ -i ]
    [ -k ]
    [ -n requests ]
    [ -p POST-file ]
    [ -P proxy-auth-username:password ]
    [ -q ]
    [ -s ]
    [ -S ]
    [ -t timelimit ]
    [ -T content-type ]
    [ -v verbosity]
    [ -V ]
    [ -w ]
    [ -x <table>-attributes ]
    [ -X proxy[:port] ]
    [ -y <tr>-attributes ]
    [ -z <td>-attributes ]
    [http://]hostname[:port]/path

옵션

-A auth-username:password
서버에게 BASIC Authentication 정보를 제공한다. :으로 구분한 사용자명과 암호를 base64 인코딩하여 전송한다. 서버가 정보를 요구하는지 (예를 들어, 401 인증 필요를 보내는지) 관계없이 문자열을 전송한다.
-c concurrency
동시에 요청하는 요청수. 기본적으로 한번에 한 요청만을 보낸다.
-C cookie-name=value
요청에 Cookie: 헤더를 추가한다. 아규먼트는 보통 name=value와 같은 쌍이다. 이 옵션은 여러번 사용할 수 있다.
-d
"percentage served within XX [ms] table"을 출력하지 않는다. (호환성을 위해).
-e csv-file
요청을 처리하는데 걸린 (밀리초 단위) 시간들의 (1%에서 100%) 누적백분율을 쉼표로 구분한 형식(CSV)으로 출력한다. 결과를 이미 '정리'하였기때문에 'gnuplot' 파일보다 보통 더 유용하다.
-g gnuplot-file
측정한 모든 값을 'gnuplot' 혹은 TSV (Tab separate values, 탭으로 구분한 값) 파일에 기록한다. Gnuplot, IDL, Mathematica, Igor, 심지어 Excel 같은 프로그램에서도 이런 파일을 쉽게 읽을 수 있다. 파일의 첫번째 줄에 항목이름이 나온다.
-h
사용법을 출력한다.
-H custom-header
요청에 헤더를 추가한다. 아규먼트는 보통 콜론으로 구분한 쌍인 (예를 들어, "Accept-Encoding: zip/zop;8bit") 유효한 헤더줄이다.
-i
GET 대신 HEAD 요청을 한다.
-k
HTTP KeepAlive 기능을 사용한다. 예를 들어, 한 HTTP 세션에서 여러 요청을 한다. 기본적으로 KeepAlive를 사용하지 않는다.
-n requests
성능을 검사하기위해 보내는 요청수. 기본값으로 요청을 한번만 보내기때문에 일반적인 성능검사 결과를 얻을 수 없다.
-p POST-file
POST 자료 파일.
-P proxy-auth-username:password
프록시를 통해 BASIC Authentication 정보를 제공한다. :로 구분한 사용자명과 암호를 base64 인코딩하여 전송한다. 프록시가 정보를 요구하는지 (예를 들어, 401 인증 필요를 보내는지) 관계없이 문자열을 전송한다.
-q
150개 이상 요청을 보낼때 ab는 10% 혹은 매 100 요청당 표준오류에 진행상황을 출력한다. -q 옵션은 이 문구를 출력하지 않는다.
-s
기능을 추가하여 컴파일하였다면 (ab -h로 확인할 수 있다) http 프로토콜 대신 SSL을 사용한 https 프로토콜을 사용한다. 이 기능은 실험적이고 매우 기초적이다. 아마도 사용을 꺼려할 것이다.
-S
중간값과 표준편차를 출력하지 않고, 평균과 중간값의 차이가 표준편차보다 크더라도 경고/오류를 출력하지 않는다. 최소/평균/최대 값을 출력한다. (호환성을 위해).
-t timelimit
성능을 검사하는 최대 초단위 시간. 내부적으로 -n 50000을 가정한다. 정해진 시간동안 서버 성능을 검사할때 사용한다. 기본적으로 시간제한 없이 검사한다.
-T content-type
POST 자료의 Content-type 헤더.
-v verbosity
출력의 자세함 수준을 지정한다. 4 이상이면 헤더에 대한 정보를, 3 이상이면 (404, 202, 등) 응답코드를, 2 이상이면 경고(warning)와 정보(info)를 출력한다.
-V
버전을 출력하고 종료한다.
-w
결과를 HTML 표로 출력한다. 기본적으로 표를 흰 배경에 두 열로 작성한다.
-x <table>-attributes
<table>의 속성으로 사용할 문자열. 속성을 <table 여기에 > 추가한다.
-X proxy[:port]
프록시 서버를 사용하여 요청한다.
-y <tr>-attributes
<tr>의 속성으로 사용할 문자열.
-z <td>-attributes
<td>의 속성으로 사용할 문자열.

버그

정적으로 길이가 고정된 버퍼를 많이 사용한다. 명령행 아규먼트, 서버의 응답 헤더, 다른 외부 입력들을 같이 읽어들이면서 문제가 발생할 수 있다.

이 프로그램은 HTTP/1.x를 완전히 구현하지 않는다; 단지 '기대하는' 형식의 응답만을 받는다. strstr(3)을 매우 많이 사용기때문에 속도가 문제가 될 수 있다; 즉, 서버 성능보다는 ab 성능을 측정하게 될 수도 있다.


apachectl - 아파치 웹서버 조절 인터페이스 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

apachectl - 아파치 웹서버 조절 인터페이스

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

apachectl은 아파치 하이퍼텍스트 전송 프로토콜 (HTTP) 서버의 앞단이다. 이 프로그램은 관리자가 아파치 httpd 데몬을 조정하도록 돕는다.

apachectl 스크립트는 두가지 방법으로 실행한다. 첫번째 방법은 httpd을 부르는 간단한 스크립트 역할을 하여, 필요한 환경변수를 설정하고 받은 명령행 아규먼트를 가지고 httpd를 실행한다. 두번째 방법은 apachectl를 SysV init 스크립트로 사용하여, start, restart, stop 같은 한단어 아규먼트를 받아서 httpd에게 적절한 신호를 보낸다.

아파치를 일반적인 경로에 설치하지 않았다면, 적절한 httpd 경로로 apachectl 스크립트를 수정해야 한다. 또, httpd 명령행 아규먼트를 추가로 지정할 수 있다. 자세한 내용은 스크립트의 주석을 참고하라.

apachectl 스크립트는 성공시 종료코드 0을, 오류시 >0을 반환한다. 자세한 내용은 스크립트의 주석을 참고하라.

참고

  • 아파치 시작
  • 아파치 중단
  • 설정파일
  • 플래폼 문서
  • httpd

개요

간단한 실행 스크립트로 동작하면, apachectl은 httpd 실행파일의 모든 아규먼트를 받는다.

apachectl [ httpd-argument ]

SysV init 방식으로 동작하면, apachectl은 아래서 설명할 간단한 한단어 명령어를 받는다.

apachectl command

옵션

여기서는 SysV init-식 옵션만 설명한다. 다른 옵션은 httpd manpage에서 설명한다.

start
아파치 httpd 데몬을 시작한다. 이미 실행중이라면 오류를 낸다. apachectl -k start와 같다.
stop
아파치 httpd 데몬을 중단한다. apachectl -k stop과 같다.
restart
아파치 httpd 데몬을 재시작한다. 데몬이 실행중이 아니라면, 시작한다. 데몬이 재시작시 실패하지 않음을 확인하기위해 재시작 전에 자동으로 configtest 명령과 같이 설정파일을 검사한다. apachectl -k restart와 같다.
fullstatus
mod_status의 모든 상태 정보를 출력한다. 이 명령을 사용하기위해서는 서버가 mod_status를 사용하고, 시스템에 lynx 같은 문자기반 브라우저가 필요하다. 상태 정보에 접근하는 URL은 스크립트의 STATUSURL 변수를 수정하여 설정할 수 있다.
status
간단한 상태 정보를 출력한다. fullstatus 옵션과 비슷하지만, 현재 서비스중인 요청 목록을 출력하지 않는다.
graceful
아파치 httpd 데몬을 점잖게(gracefully) 재시작한다. 데몬이 실행중이 아니라면, 시작한다. 일반적인 재시작과 달리 현재 열려있는 연결을 끊지않는다. 또, 이전 로그파일을 즉시 닫지 않는다. 즉, 로그순환 스크립트에서 이 명령을 사용한다면, 이전 로그파일을 처리하기전에 로그파일을 닫혔음을 보장하기위해 상당히 기다려야 한다. 아파치가 재시작시 실패하지 않음을 확인하기위해 재시작 전에 자동으로 configtest 명령과 같이 설정파일을 검사한다. apachectl -k graceful과 같다.
configtest
설정파일의 문법을 검사한다. 설정파일을 읽고 Syntax Ok 혹은 특정 설정오류에 대한 자세한 정보를 알려준다. apachectl -t와 같다.

아래 옵션을 사용할 수 있지만, 앞으로 사라질 것이다.

startssl
apachectl -k start -DSSL과 같다. 우리는 직접 앞의 명령어를 사용하거나 항상 SSL을 사용하도록 httpd.conf에서 <IfDefine> 섹션을 제거하길 권한다.


apxs - APache eXtenSion 도구 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

apxs - APache eXtenSion 도구

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

apxs는 아파치 하이퍼텍스트 전송 프로토콜 (HTTP) 서버의 확장모듈을 컴파일하고 설치하는 도구이다. 이 도구는 여러 소스와 오브젝트파일을 가지고, mod_so의 LoadModule 지시어로 실행중에 아파치 서버로 읽어들일 수 있는 동적공유객체(DSO)를 만든다.

그래서 이런 확장방식을 사용하려면 플래폼이 DSO 기능을 지원하고 아파치 httpd 실행파일을 mod_so 모듈과 같이 컴파일해야 한다. apxs 도구는 이 조건이 만족하지않으면 실행하지 않는다. 직접 명령어를 실행하여 조건이 만족하는지 알아볼 수 있다

$ httpd -l

목록에 mod_so 모듈이 나와야 한다. 조건을 만족하면 apxs 도구로 DSO 모듈을 설치하여 아파치서버의 기능을 쉽게 확장할 수 있다:

$ apxs -i -a -c mod_foo.c
gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c
ld -Bshareable -o mod_foo.so mod_foo.o
cp mod_foo.so /path/to/apache/modules/mod_foo.so
chmod 755 /path/to/apache/modules/mod_foo.so
[activating module `foo' in /path/to/apache/etc/httpd.conf]
$ apachectl restart
/path/to/apache/sbin/apachectl restart: httpd not running, trying to start
[Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module
/path/to/apache/sbin/apachectl restart: httpd started
$ _

아규먼트 files에는 C 소스파일 (.c) 이나 오브젝트파일 (.o), 라이브러리모음 (.a)을 사용할 수 있다. apxs 도구는 확장자를 보고 자동으로 C 소스파일은 컴파일하고, 오브젝트와 모음파일은 링크에만 사용한다. 그러나 컴파일한 오브젝트를 사용하려면 동적으로 읽어들일 수 있는 공유객체로 사용하기위해 반드시 오브젝트를 위치독립코드(PIC, position independent code)로 컴파일해야 한다. GCC의 경우 -fpic을 사용하면 된다. 다른 C 컴파일러는 설명서를 참고하거나 apxs가 오브젝트파일을 컴파일할때 사용하는 옵션을 참고하라.

아파치의 DSO 지원에 대한 더 자세한 내용은 mod_so 문서를 참고하거나 src/modules/standard/mod_so.c 소스파일을 읽어봐라.

참고

  • apachectl
  • httpd

개요

apxs -g [ -S name=value ] -n modname

apxs -q [ -S name=value ] query ...

apxs -c
    [ -S name=value ]
    [ -o dsofile ]
    [ -I incdir ]
    [ -D name=value ]
    [ -L libdir ]
    [ -l libname ]
    [ -Wc,compiler-flags ]
    [ -Wl,linker-flags ]
    files ...

apxs -i
    [ -S name=value ]
    [ -n modname ]
    [ -a ]
    [ -A ]
    dso-file ...

apxs -e
    [ -S name=value ]
    [ -n modname ]
    [ -a ]
    [ -A ]
    dso-file ...

옵션

공통 옵션

-n modname
-i (install)과 -g (template generation) 옵션을 사용할때 직접 모듈명을 지정한다. 이 옵션을 사용하여 모듈명을 직접 지정한다. -g 옵션을 사용한다면 이 옵션을 반드시 사용해야하고, -i 옵션을 사용한다면 apxs 도구는 소스나 (마지막 시도로) 파일명을 가지고 이름을 추측한다.

질의 옵션

-q
apxs의 설정값을 알아낸다. query에는 다음을 사용할 수 있다: CC, CFLAGS, CFLAGS_SHLIB, INCLUDEDIR, LD_SHLIB, LDFLAGS_SHLIB, LIBEXECDIR, LIBS_SHLIB, SBINDIR, SYSCONFDIR, TARGET.

설정을 직접 알아낼때 사용한다.

INC=-I`apxs -q INCLUDEDIR`

예를 들어, 아파치 C 헤더파일을 직접 접근한다면 Makefile에서 위와 같이 사용한다.

설정 옵션

-S name=value
이 옵션은 위에서 설명한 apxs 설정을 변경한다.

견본(template) 생성 옵션

-g
하위디렉토리 name을 만들고 (-n 옵션 참고) 그곳에 파일 두개를 만든다: 한 파일은 mod_name.c라는 견본 모듈소스파일로, 자신의 모듈을 만들때 견본으로 사용하거나 apxs 기능을 시험해볼때 사용한다. 다른 파일은 이 모듈을 쉽게 컴파일하고 설치하기위한 Makefile이다.

DSO 컴파일 옵션

-c
컴파일을 지시한다. 먼저 files에서 C 소스파일들(.c)을 오브젝트파일(.o)로 컴파일하고, files의 나머지 오브젝트파일들(.o과 .a)과 링크하여 동적공유객체 dsofile을 만든다. -o 옵션을 사용하지않으면 files의 첫번째 파일명에서 이름을 추측하여 보통 mod_name.so를 사용한다.
-o dsofile
생성할 동적공유객체 파일명을 직접 지정한다. 이름을 지정하지않고 files 목록에서 이름을 추측하지 못하면 마지막으로 mod_unknown.so를 이름으로 사용한다.
-D name=value
이 옵션을 컴파일 명령어로 직접 전달한다. 컴파일때 자신의 define을 추가한다.
-I incdir
이 옵션을 컴파일 명령어로 직접 전달한다. 컴파일때 include를 찾을 디렉토리를 추가한다.
-L libdir
이 옵션을 링커 명령어로 직접 전달한다. 컴파일때 라이브러리를 찾을 디렉토리를 추가한다.
-l libname
이 옵션을 링커 명령어로 직접 전달한다. 컴파일때 사용할 라이브러리를 추가한다.
-Wc,compiler-flags
이 옵션은 추가 옵션 compiler-flags를 컴파일 명령어로 전달한다. 컴파일러 특유의 옵션을 추가할때 사용한다.
-Wl,linker-flags
이 옵션은 추가 옵션 linker-flags를 링커 명령어로 전달한다. 링커 특유의 옵션을 추가할때 사용한다.

DSO 설치과 설정 옵션

-i
설치를 지시한다. 여러 동적공유객체를 서버의 modules 디렉토리에 설치한다.
-a
아파치 httpd.conf 설정파일에 적절한 LoadModule 줄을 추가하거나 이미 있다면 활성화하여 모듈을 사용하도록 만든다.
-A
-a와 비슷하지만, LoadModule 지시어 앞에 우물정자(#)를 붙인다. 즉, 현재는 사용하지않지만 나중에 사용할 수 있도록 모듈을 준비한다.
-e
편집을 지시한다. -a 혹은 -A 옵션과 같이 사용할 수 있으며, -i 명령과 비슷하지만 모듈을 설치하지않고 아파치 httpd.conf 설정파일만 편집한다.

예제

아파치서버의 기능을 확장하는 mod_foo.c라는 아파치 모듈이 있다고 가정하자. 먼저 다음 명령어를 사용하여 C 소스를 아파치 서버가 읽어들일 공유객체로 컴파일한다:

$ apxs -c mod_foo.c
gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c
ld -Bshareable -o mod_foo.so mod_foo.o
$ _

그리고 이 공유객체를 읽어들이는 LoadModule 지시어를 아파치 설정에 추가한다. apxs는 자동으로 공유객체를 "modules" 디렉토리에 설치하고 httpd.conf 파일을 알맞게 수정하여 간단히 작업을 마친다. 다음 같이 실행한다:

$ apxs -i -a mod_foo.c
cp mod_foo.so /path/to/apache/modules/mod_foo.so
chmod 755 /path/to/apache/modules/mod_foo.so
[activating module `foo' in /path/to/apache/etc/httpd.conf]
$ _

그러면 다음과 같은 줄을

LoadModule foo_module modules/mod_foo.so

설정파일에 없다면 추가한다. 이 설정을 기본적으로 사용하지 않는다면 -A 옵션을 사용한다. 즉

$ apxs -i -A mod_foo.c

apxs를 쉽게 사용하려고 다음과 같이 아파치 모듈 견본과 Makefile을 만들 수 있다:

$ apxs -g -n foo
Creating [DIR] foo
Creating [FILE] foo/Makefile
Creating [FILE] foo/mod_foo.c
$ _

그런후 바로 견본 모듈을 공유객체로 컴파일하여 아파치 서버가 읽도록한다:

$ cd foo
$ make all reload
apxs -c mod_foo.c
gcc -fpic -DSHARED_MODULE -I/path/to/apache/include -c mod_foo.c
ld -Bshareable -o mod_foo.so mod_foo.o
apxs -i -a -n "foo" mod_foo.so
cp mod_foo.so /path/to/apache/modules/mod_foo.so
chmod 755 /path/to/apache/modules/mod_foo.so
[activating module `foo' in /path/to/apache/etc/httpd.conf]
apachectl restart
/path/to/apache/sbin/apachectl restart: httpd not running, trying to start
[Tue Mar 31 11:27:55 1998] [debug] mod_so.c(303): loaded module foo_module
/path/to/apache/sbin/apachectl restart: httpd started
$ _

심지어 아파치 소스 밖에서 apxs를 사용하여 PHP3와 같이 복잡한 모듈을 컴파일할 수 있다:

$ cd php3
$ ./configure --with-shared-apache=../apache-1.3
$ apxs -c -o libphp3.so mod_php3.c libmodphp3-so.a
gcc -fpic -DSHARED_MODULE -I/tmp/apache/include -c mod_php3.c
ld -Bshareable -o libphp3.so mod_php3.o libmodphp3-so.a
$ _

apxs는 자동으로 C 소스파일과 오브젝트파일을 구별한다. C 소스파일만 컴파일하고 나머지 오브젝트파일은 링크할때 사용한다.


configure - 소스 트리를 구성한다 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

configure - 소스 트리를 구성한다

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

configure 스크립트는 특정 플래폼에서 아파치 웹서버를 컴파일하고 설치하기위해 소스 트리를 구성한다. 여러 옵션을 사용하여 원하는 요구조건에 맞게 서버를 컴파일할 수 있다.

소스 배포본의 최상위 디렉토리에 있는 이 스크립트는 유닉스와 유닉스류 시스템에서만 사용한다. 다른 플래폼을 사용한다면 플래폼 문서를 참고하라.

참고

  • 컴파일과 설치

개요

configure 스크립트는 배포본의 최상위 디렉토리에서 실행해야 한다.

./configure [OPTION]... [VAR=VALUE]...

환경변수를 (예를 들어, CC, CFLAGS, ...) 지정하려면, VAR=VALUE와 같이 지시한다. 아래에서 유용한 환경변수들을 설명한다.

옵션

  • 구성 옵션
  • 설치 디렉토리
  • 시스템 종류
  • 기능 선택
  • 지원 프로그램을 위한 옵션

구성 옵션

이 옵션들은 configure 자체 행동에 영향을 준다.

-C
--config-cache
--cache-file=config.cache와 같다.
--cache-file=FILE
검사 결과를 FILE 파일에 캐싱한다. 기본값은 검사 결과를 기록하지 않는다.
-h
--help [short|recursive]
도움말을 출력하고 종료한다. short 아규먼트는 이 패키지 특유의 옵션만을 출력한다. recursive 아규먼트는 포함된 모든 패키지에 대한 짧은 도움말을 보여준다.
-n
--no-create
configure 스크립트를 정상적으로 실행하지만, 출력파일을 만들지 않는다. 이 옵션은 컴파일을 위한 makefile을 만들기 이전에 검사 결과를 확인해볼때 유용하다.
-q
--quiet
실행중에 checking ... 문구를 출력하지 않는다.
--srcdir=DIR
DIR 디렉토리를 소스파일 디렉토리로 지정한다. 기본값은 configure가 있는 디렉토리 혹은 상위디렉토리 ..이다.
--silent
--quiet와 같다.
-V
--version
저작권 정보를 출력하고 종료한다.

설치 디렉토리

이 옵션들은 설치 디렉토리를 지정한다. 설치 위치는 선택한 구조(layout)에 따라 다르다.

--prefix=PREFIX
아키텍쳐에 독립적인 파일을 PREFIX에 설치한다. 기본값은 /usr/local/apache2이다.
--exec-prefix=EPREFIX
아키텍쳐에 의존적인 파일을 EPREFIX에 설치한다. 기본값은 PREFIX 디렉토리이다.

기본적으로 make install은 /usr/local/apache2/bin, /usr/local/apache2/lib와 같은 위치에 모든 파일을 설치한다. --prefix=$HOME과 같이 --prefix 옵션을 사용하여 /usr/local/apache2 이외의 설치 상위디렉토리를 지정할 수 있다.

디렉토리 구조 지정

--enable-layout=LAYOUT
설치 위치를 LAYOUT 구조에 따르도록 소스코드와 컴파일 스크립트를 구성한다. 구조를 사용하면 파일 종류에 따라 설치 위치를 따로 지정할 수 있다. config.layout 파일에 여러 설정 예가 있고, 이를 참고하여 직접 설정을 만들 수도 있다. 파일에서 각 구조는 <Layout FOO>...</Layout>로 구분되며, 이 부분은 FOO라는 이름의 구조를 나타낸다. 구조의 기본값은 Apache이다.

설치 디렉토리의 자세한 조정

설치 디렉토리를 더 수정한다면 아래 옵션을 사용한다. 각 디렉토리의 기본값은 autoconf가 지정하며, 선택한 구조에 따라 다름을 주의하라.

--bindir=DIR
사용자 실행파일을 DIR에 설치한다. 사용자 실행파일에는 사이트 관리자에게 유용한 htpasswd와 dbmmanage 같은 지원 프로그램도 포함된다. DIR의 기본값은 EPREFIX/bin이다.
--datadir=DIR
아키텍쳐 독립적인 읽기전용 자료를 DIR에 설치한다. datadir의 기본값은 PREFIX/share이다. autoconf에 이 옵션이 있지만 현재 사용하지 않는다.
--includedir=DIR
C 헤더파일을 DIR에 설치한다. includedir의 기본값은 EPREFIX/include이다.
--infodir=DIR
info 문서를 DIR에 설치한다. infodir의 기본값은 PREFIX/info이다. 현재 이 옵션은 사용하지 않는다.
--libdir=DIR
오브젝트코드 라이브러리를 DIR에 설치한다. libdir의 기본값은 EPREFIX/lib이다.
--libexecdir=DIR
프로그램 실행파일을 (즉, 공유모듈) DIR에 설치한다. libexecdir의 기본값은 EPREFIX/libexec이다.
--localstatedir=DIR
변경되는 머쉰별 정보를 DIR에 설치한다. localstatedir의 기본값은 PREFIX/var이다. autoconf에 이 옵션이 있지만 현재 사용하지 않는다.
--mandir=DIR
man 문서를 DIR에 설치한다. mandir의 기본값은 EPREFIX/man이다.
--oldincludedir=DIR
gcc가 아닌 컴파일러를 위한 C 헤더파일을 DIR에 설치한다. oldincludedir의 기본값은 /usr/include이다. autoconf에 이 옵션이 있지만 현재 사용하지 않는다.
--sbindir=DIR
시스템 관리자용 실행파일을 DIR에 설치한다. 시스템 관리자용 실행파일이란 아파치 웹서버를 실행하는데 필요한 httpd, apachectl, suexec 등 서버 프로그램을 말한다. sbindir의 기본값은 EPREFIX/sbin이다.
--sharedstatedir=DIR
변경되는 아키텍쳐 독립적인 자료를 DIR에 설치한다. sharedstatedir의 기본값은 PREFIX/com이다. autoconf에 이 옵션이 있지만 현재 사용하지 않는다.
--sysconfdir=DIR
서버 설정파일 httpd.conf, mime.types와 같은 읽기전용 머쉰별 자료를 DIR에 설치한다. sysconfdir의 기본값은 PREFIX/etc이다.

시스템 종류

다른 시스템에서 실행할 아파치 웹서버를 교차컴파일하기(cross-compile)하기 위한 옵션들이다. 서버를 컴파일한 시스템에서 서버를 실행하는 일반적인 경우, 이 옵션을 사용하지 않는다.

--build=BUILD
도구를 컴파일하는 시스템의 종류를 지정한다. 기본값은 config.guess 스크립트의 결과이다.
--host=HOST
서버를 실행할 시스템의 종류를 지정한다. HOST의 기본값은 BUILD이다.
--target=TARGET
TARGET 시스템 종류를 위한 컴파일러를 만들때 사용한다. 기본값은 HOST이다. autoconf에 이 옵션이 있지만 아파치 웹서버와는 관련이 없다.

기능 선택

이 옵션은 웹서버의 세부 기능을 조절한다.

일반적인 문법

일반적으로 다음 문법을 사용하여 기능을 포함하고 뺀다:

--disable-FEATURE
FEATURE 기능을 뺀다. --enable-FEATURE=no와 같다.
--enable-FEATURE[=ARG]
FEATURE 기능을 포함한다. ARG의 기본값은 yes이다.
--enable-MODULE=shared
해당 모듈을 DSO 모듈로 컴파일한다.
--enable-MODULE=static
포함하는 모듈은 기본적으로 정적으로 링크된다. 이 옵션은 명시적으로 정적 링크를 강제한다.

주의

configure는 foo가 없는 경우 --enable-foo를 사용해도 이 사실을 알려주지 않으므로 주의해서 입력해야 한다.

기본적으로 포함하는 모듈

어떤 모듈은 기본적으로 컴파일되기때문에 사용하지 않는다면 명시적으로 빼줘야 한다. 다음 옵션은 특정 모듈을 컴파일 과정에서 제외한다.

--disable-actions
mod_actions가 제공하는 요청에 대한 행동 기능을 사용하지 않는다.
--disable-alias
mod_alias가 제공하는 요청을 파일시스템의 다른 부분으로 대응하는 기능을 사용하지 않는다.
--disable-asis
mod_asis가 제공하는 as-is 파일형을 지원하지 않는다.
--disable-auth
mod_auth가 제공하는 사용자별 접근제어 기능을 사용하지 않는다. 이 모듈은 사용자명과 암호를 일반 문자파일에 저장하는 HTTP Basic Authentication에서 사용한다.
--disable-autoindex
mod_autoindex가 제공하는 디렉토리 목록 기능을 사용하지 않는다.
--disable-access
mod_access가 제공하는 호스트별 접근제어 기능을 사용하지 않는다.
--disable-cgi
비쓰레드 MPM을 사용하는 경우 CGI 스크립트를 지원하는 mod_cgi를 기본적으로 포함한다. 이 옵션을 사용하면 CGI를 지원하지 않는다.
--disable-cgid
쓰레드 MPM인 worker나 perchild를 사용하는 경우 기본적으로 mod_cgid가 CGI 스크립트를 지원한다. 이 옵션을 사용하면 CGI를 지원하지 않는다.
--disable-charset-lite
mod_charset_lite가 제공하는 문자집합 변환 기능을 사용하지 않는다. 이 모듈은 EBCDIC 시스템에서만 기본적으로 포함한다.
--disable-dir
mod_dir이 제공하는 디렉토리 요청 처리 기능을 사용하지 않는다.
--disable-env
mod_env가 제공하는 환경변수 설정/해제 기능을 사용하지 않는다.
--disable-http
HTTP 프로토콜을 처리하지 않는다. http 모듈은 서버가 웹서버로 동작하는데 기본적인 모듈이다. 대신 다른 프로토콜 모듈을 사용할 경우에만 이 모듈이 유용하다. 자신이 무엇을 하는지 확실히 알지 못한다면 이 옵션을 빼지 마라
주의: 이 모듈은 항상 정적으로 링크된다.
--disable-imap
mod_imap이 제공하는 서버기반 imagemap 기능을 사용하지 않는다.
--disable-include
mod_include가 제공하는 Server Side Includes 기능을 사용하지 않는다.
--disable-log-config
mod_log_config가 제공하는 로그 설정을 사용하지 않는다. 이 모듈이 없으면 서버의 요청을 로그에 기록할 수 없다.
--disable-mime
mod_mime은 요청한 파일명의 확장자에 따라 파일의 행동과 내용(mime-type, 언어, 문자집합, 인코딩)을 결정한다. (이 모듈을 제거하여) 파일 확장자를 MIME과 연관하지 않는 것을 일반적으로 추천하지 않는다.
--disable-negotiation
mod_negotiation이 제공하는 내용협상 기능을 사용하지 않는다.
--disable-setenvif
mod_setenvif가 제공하는 헤더에 따라 환경변수를 설정하는 기능을 사용하지 않는다.
--disable-status
mod_status가 제공하는 프로세스/쓰레드 감시 기능을 사용하지 않는다.
--disable-userdir
mod_userdir이 제공하는 요청을 사용자별 디렉토리에 대응하는 기능을 사용하지 않는다.

기본적으로 포함하지 않는 모듈

기본적으로 컴파일되는 모듈도 있지만, 모듈을 사용하려면 직접 혹은 most나 all 키워드를 사용하여 명시적으로 포함해야 하는 모듈이 있다. 그래서 아래 옵션들을 사용한다.

--enable-auth-anon
mod_auth_anon이 제공하는 익명사용자 접근 기능을 사용한다.
--enable-auth-dbm
mod_auth_dbm은 사용자명과 암호를 DBM형식의 데이터베이스 파일에 저장하는 HTTP Basic Authentication에서 사용한다. 모듈을 사용하려면 이 옵션을 사용한다.
--enable-auth-digest
mod_auth_digest가 제공하는 RFC2617 Digest authentication을 사용한다. 이 모듈은 정보를 일반 문자파일에 저장한다.
--enable-auth-ldap
mod_auth_ldap이 제공하는 LDAP기반 인증 기능을 사용한다.
--enable-cache
mod_cache가 제공하는 동적으로 생성하는 파일의 캐싱 기능을 사용한다. 매우 부하가 많거나 프록시 서버를 캐싱하는 서버에게 이 실험적인 모듈이 유용할 수 있다. 최소한 한가지 저장관리모듈(storage management module)을 (예를 들어, mod_disk_cache나 mod_mem_cache) 같이 사용해야 한다.
--enable-cern-meta
mod_cern_meta가 제공하는 CERN 메타파일 지원 기능을 사용한다.
--enable-charset-lite
mod_charset_lite가 제공하는 문자집합 변환 기능을 사용한다. 이 모듈은 EBCDIC 시스템에서만 기본적으로 포함된다. 다른 시스템에서는 직접 포함시켜줘야 한다.
--enable-dav
mod_dav가 제공하는 WebDAV 프로토콜 처리 기능을 사용한다. 독립된 mod_dav_fs 모듈이 파일시스템 자원을 지원한다. 이 모듈은 --enable-dav를 사용하면 자동으로 포함한다.
주의: mod_dav는 http 프로토콜 모듈과 같이 사용해야 한다.
--enable-dav-fs
mod_dav_fs가 제공하는 DAV의 파일시스템 자원 지원 기능을 사용한다. 이 모듈은 mod_dav 모듈을 위한 제공자이기 때문에 --enable-dav도 사용해야 한다.
--enable-deflate
mod_deflate가 제공하는 압축전송 인코딩 기능을 사용한다.
--enable-disk-cache
mod_disk_cache가 제공하는 디스크 캐싱 기능을 사용한다.
--enable-expires
mod_expires가 제공하는 Expires 헤더 조절 기능을 사용한다.
--enable-ext-filter
mod_ext_filter가 제공하는 외부 필터 지원 기능을 사용한다.
--enable-file-cache
mod_file_cache가 제공하는 파일 캐싱 기능을 사용한다.
--enable-headers
mod_headers가 제공하는 HTTP 헤더 조절 기능을 사용한다.
--enable-info
mod_info가 제공하는 서버정보 기능을 사용한다.
--enable-ldap
mod_ldap이 제공하는 LDAP 캐싱과 연결풀 기능을 사용한다.
--enable-logio
mod_logio가 제공하는 로그에 헤더와 입출력 바이트수를 기록하는 기능을 사용한다.
--enable-mem-cache
mod_mem_cache가 제공하는 메모리 캐싱 기능을 사용한다.
--enable-mime-magic
mod_mime_magic이 제공하는 MIME type 자동 인식 기능을 사용한다.
--enable-isapi
mod_isapi가 제공하는 isapi 확장을 지원한다.
--enable-proxy
mod_proxy가 제공하는 프록시/게이트웨이 기능을 사용한다. CONNECT, FTP, HTTP에 대한 프록시 기능을 각각 mod_proxy_connect, mod_proxy_ftp, mod_proxy_http 모듈이 제공한다. --enable-proxy를 사용하면 이 세 모듈을 자동으로 포함한다.
--enable-proxy-connect
mod_proxy_connect가 제공하는 CONNECT 요청에 대한 프록시 지원 기능을 사용한다. 이 모듈은 mod_proxy 모듈의 확장이므로, --enable-proxy도 같이 사용해야 한다.
--enable-proxy-ftp
mod_proxy_ftp가 제공하는 FTP 요청에 대한 프록시 지원 기능을 사용한다. 이 모듈은 mod_proxy 모듈의 확장이므로, --enable-proxy도 같이 사용해야 한다.
--enable-proxy-http
mod_proxy_http가 제공하는 HTTP 요청에 대한 프록시 지원 기능을 사용한다. 이 모듈은 mod_proxy 모듈의 확장이므로, --enable-proxy도 같이 사용해야 한다.
--enable-rewrite
mod_rewrite가 제공하는 규칙기반 URL 조작 기능을 사용한다.
--enable-so
mod_so가 제공하는 DSO 기능을 사용한다. --enable-mods-shared 옵션을 사용하면 자동으로 이 모듈을 포함한다.
--enable-speling
mod_spelling이 제공하는 URL에서 일반적인 맞춤법 실수를 고치는 기능을 사용한다.
--enable-ssl
mod_ssl이 제공하는 SSL/TLS 기능을 사용한다.
--enable-unique-id
mod_unique_id가 제공하는 요청마다 유일한 식별자를 만드는 기능을 사용한다.
--enable-usertrack
mod_usertrack이 제공하는 사용자세션 추적 기능을 사용한다.
--enable-vhost-alias
mod_vhost_alias가 제공하는 대량 가상호스트 기능을 사용한다.

개발자를 위한 모듈

다음 모듈은 테스트용으로 개발자에게만 유용하며, 기본적으로 포함하지 않는다. 이 모듈을 사용하려면 다음 옵션을 사용한다. 이 모듈이 필요한지 확실치않다면 사용하지 마라.

--enable-bucketeer
mod_bucketeer가 제공하는 버킷(bucket) 조작 필터를 사용한다.
--enable-case-filter
mod_case_filter의 대문자변환 출력필터 견본을 사용한다.
--enable-case-filter-in
mod_case_filter_in의 대문자변환 입력필터 견본을 사용한다.
--enable-echo
mod_echo가 제공하는 ECHO 서버를 사용한다.
--enable-example
견본 예제모듈인 mod_example을 사용한다.
--enable-optional-fn-export
mod_optional_fn_export가 제공하는 선택적인 함수 엑스포트(exporter)의 예를 사용한다.
--enable-optional-fn-import
mod_optional_fn_import가 제공하는 선택적인 함수 임포트(importer)의 예를 사용한다.
--enable-optional-hook-export
mod_optional_hook_export가 제공하는 선택적인 훅(hook) 엑스포트의 예를 사용한다.
--enable-optional-hook-import
mod_optional_hook_import가 제공하는 선택적인 훅 임포트의 예를 사용한다.

MPM과 제삼자가 만든 모듈

다음 옵션을 사용하여 필요한 다중처리모듈과 제삼자가 만든 모듈을 추가한다:

--with-module=module-type:module-file

제삼자가 만든 모듈을 정적으로 링크할 모듈 목록에 추가한다. 아파치 웹서버 소스 트리의 modules/module-type에서 모듈의 소스파일 module-file을 찾기때문에 그곳에 소스파일이 있어야 한다. 그곳에 파일이 없다면 configure는 module-file이 절대파일경로라고 가정하고 소스파일을 module-type 하위디렉토리에 복사하려고 시도한다.

이 옵션은 소스파일이 한개인 작은 외부 모듈을 추가하는데 유용하다. 더 복잡한 모듈은 개발사가 제공한 문서를 참고해야 한다.

주의

정적으로 링크된 모듈이 아닌 DSO 모듈을 원한다면 apxs를 사용하라.
--with-mpm=MPM
서버의 동작방식을 선택한다. 정확히 한가지 다중처리모듈만을 선택해야 한다. 선택하지 않으면 사용하는 운영체제의 기본 MPM을 사용한다. 사용할 수 있는 MPM에는 beos, leader, mpmt_os2, perchild, prefork, threadpool, worker가 있다.

기타 옵션

--enable-maintainer-mode
디버깅 모드와 컴파일시 경고를 작동한다.
--enable-mods-shared=MODULE-LIST

동적공유모듈로 컴파일할 모듈 목록을 지정한다. 즉, 이 모듈들은 LoadModule 지시어를 사용하여 동적으로 읽어들여야 한다.

MODULE-LIST는 공백으로 구분한 모듈명들을 따옴표로 묶은 목록이다. 모듈명에서 앞에 mod_는 뺀다. 예를 들어:

--enable-mods-shared='headers rewrite dav'

또, 특별한 키워드 all과 most를 사용할 수 있다. 예를 들어,

--enable-mods-shared=most

는 대부분의 모듈을 DSO 모듈로 컴파일한다.

--enable-modules=MODULE-LIST
--enable-mods-shared와 비슷하지만, 이 옵션은 열거한 모듈들을 정적으로 링크한다. 즉, 이 모듈들은 httpd 실행하면 언제나 사용할 수 있다. LoadModule로 읽어들일 필요가 없다.
--enable-v4-mapped
IPv6 소켓이 IPv4 연결을 처리할 수 있도록 한다.
--with-port=PORT
httpd가 기다릴 포트를 지정한다. 이 포트번호는 설정파일 httpd.conf를 만들때 쓰인다. 기본값은 80이다.
--with-program-name
다른 실행파일명을 지정한다. 기본값은 httpd이다.

추가 패키지 선택

다음 옵션은 추가 패키지를 선택한다.

일반적인 문법

일반적으로 다음과 같은 문법을 사용하여 추가 패키지를 다룬다:

--with-PACKAGE[=ARG]
패키지 PACKAGE를 사용한다. ARG의 기본값은 yes이다.
--without-PACKAGE
패키지 PACKAGE를 사용하지 않는다. --with-PACKAGE=no와 같다. autoconf에 이 옵션이 있지만 아파치 웹서버와는 관계가 없다.

특정 패키지

--with-apr=DIR|FILE
httpd 소스 배포본에 포함된 Apache Portable Runtime (APR)은 자동으로 웹서버와 같이 컴파일된다. 만약 이미 설치된 APR을 대신 사용하고 싶다면 configure에게 apr-config 스크립트의 경로를 알려주어야 한다. APR가 설치된 절대경로, 파일명, 디렉토리명을 사용할 수 있다. 지정한 디렉토리나 그 디렉토리의 하위디렉토리 bin에 apr-config가 있어야 한다.
--with-apr-util=DIR|FILE
httpd 소스 배포본에 포함된 Apache Portable Runtime Utilities (APU)는 자동으로 웹서버와 같이 컴파일된다. 만약 이미 설치된 APU을 대신 사용하고 싶다면 configure에게 apu-config 스크립트의 경로를 알려주어야 한다. APU가 설치된 절대경로, 파일명, 디렉토리명을 사용할 수 있다. 지정한 디렉토리나 그 디렉토리의 하위디렉토리 bin에 apu-config가 있어야 한다.
--with-ssl=DIR
mod_ssl을 사용하는 경우 configure는 설치된 OpenSSL을 찾는다. 대신 이 옵션을 사용하여 SSL/TLS 도구의 디렉토리경로를 알려줄 수 있다.
--with-z=DIR
(mod_deflate를 사용하는 경우와 같이) 구성에 필요하다면 자동으로 configure는 설치된 zlib 라이브러리를 찾는다. 대신 이 옵션을 사용하여 압축 라이브러리의 디렉토리경로를 알려줄 수 있다.

mod_authn_dbm과 mod_rewrite의 DBM RewriteMap 같은 아파치 웹서버의 일부 기능은 정보를 빨리 찾기위해 간단한 키/값 데이터베이스를 사용한다. APU에 SDBM이 들어있어서 언제나 최소한 이 데이터베이스는 사용할 수 있다. 다른 종류의 데이터베이스를 사용하고 싶다면 아래 옵션을 사용한다:

--with-gdbm[=path]
path를 지정하지 않으면, configure는 일반적인 검색경로에서 설치된 GNU DBM 헤더파일과 라이브러리를 찾는다. 직접 path를 지정하면 configure는 path/lib과 path/include에서 필요한 파일을 찾는다. 마지막으로 path에 헤더파일 경로와 라이브러리 경로를 콜론을 사이에 두고 같이 적을 수 있다.
--with-ndbm[=path]
--with-gdbm과 같지만 설치된 New DBM을 찾는다.
--with-berkeley-db[=path]
--with-gdbm과 같지만 설치된 Berkeley DB를 찾는다.

주의

DBM 옵션은 APU가 제공하며 APU 구성스크립트로 직접 전달된다. 그래서 --with-apr-util을 사용하여 이미 설치된 APU를 사용한다면 DBM 옵션은 소용이 없다.

웹서버는 여러 DBM 구현을 같이 사용할 수 있다. 실행시 적절한 DBM 종류를 설정할 수 있다.

지원 프로그램을 위한 옵션

--enable-static-support
지원 프로그램을 정적으로 링크된 실행파일로 만든다. 즉, 필요한 라이브러리를 모두 포함하도록 실행파일을 컴파일한다. 이 옵션을 사용하지 않으면 기본값으로 지원 프로그램을 동적으로 링크한다.
--enable-suexec
웹서버가 실행하는 프로세스의 uid와 gid를 설정하는 suexec를 사용하려면 이 옵션을 사용한다. suid 실행파일의 보안상 위험을 모두 알지 못한다면 이 옵션을 사용하지 마라. suexec를 구성하는 옵션은 아래에서 설명한다.

다음 옵션을 사용하여 지원 프로그램별로 정적으로 링크된 실행파일을 만들 수 있다:

--enable-static-ab
ab를 정적으로 링크된 실행파일로 컴파일한다.
--enable-static-checkgid
checkgid를 정적으로 링크된 실행파일로 컴파일한다.
--enable-static-htdbm
htdbm을 정적으로 링크된 실행파일로 컴파일한다.
--enable-static-htdigest
htdigest를 정적으로 링크된 실행파일로 컴파일한다.
--enable-static-htpasswd
htpasswd를 정적으로 링크된 실행파일로 컴파일한다.
--enable-static-logresolve
logresolve를 정적으로 링크된 실행파일로 컴파일한다.
--enable-static-rotatelogs
rotatelogs를 정적으로 링크된 실행파일로 컴파일한다.

suexec 설정 옵션

아래 옵션은 suexec를 자세히 설정한다. 더 자세한 정보는 suEXEC 구성과 설치를 참고하라.

--with-suexec-bin
suexec 실행파일의 경로를 지정한다. 기본값은 --sbindir이다 (설치 디렉토리의 자세한 조정 참고).
--with-suexec-caller
suexec를 실행할 사용자를 지정한다. 이 사용자는 보통 httpd를 실행하는 사용자와 같아야 한다.
--with-suexec-docroot
suexec는 이 옵션으로 지정한 디렉토리 아래에 있는 실행파일만을 실행할 수 있다. 기본값은 --datadir/htdocs다.
--with-suexec-gidmin
suexec에서 지정가능한 최소 GID를 설정한다. 기본값은 100이다.
--with-suexec-logfile
suexec 로그파일명을 지정한다. 로그파일명의 기본값은 suexec_log이고, --logfiledir에 위치한다.
--with-suexec-safepath
suexec가 시작하는 프로세스의 PATH 환경변수값을 지정한다. 기본값은 /usr/local/bin:/usr/bin:/bin이다.
--with-suexec-userdir
사용자 디렉토리에서 suexec가 접근할 수 있는 (실행파일이 있는) 하위디렉토리를 지정한다. 이 설정은 suexec와 (mod_userdir이 제공하는) 사용자별 디렉토리를 같이 사용할때 필요하다. 기본값은 public_html이다.
--with-suexec-uidmin
suexec에서 지정가능한 최소 UID를 설정한다. 기본값은 100이다.
--with-suexec-umask
suexec가 실행하는 프로세스의 umask를 지정한다. 기본값은 사용하는 시스템의 기본 설정과 같다.

환경변수

configure의 선택을 무시하거나 관례와 다른 이름이나 위치에 있는 라이브러리와 프로그램을 찾도록 도와주는 유용한 환경변수들이 있다.

CC
컴파일에 사용할 C 컴파일러 명령어를 지정한다.
CFLAGS
컴파일때 사용하길 바라는 C 컴파일러 옵션을 지정한다.
CPP
사용할 C 선처리기 명령어를 지정한다.
CPPFLAGS
C/C++ 선처리기 옵션. 예를 들어, 헤더파일이 관례와 달리 includedir 디렉토리에 있다면 -Iincludedir을 사용한다.
LDFLAGS
링커 옵션. 예를 들어, 라이브러리가 관례와 달리 libdir 디렉토리에 있다면 -Llibdir을 사용한다.


dbmmanage - DBM 형식의 사용자인증 파일을 관리한다 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

dbmmanage - DBM 형식의 사용자인증 파일을 관리한다

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

dbmmanage는 HTTP basic authentication에 사용할 사용자명과 암호를 저장하는 DBM형식의 파일을 만들고 수정한다. 아파치 웹서버는 자원을 dbmmanage로 만든 파일에 기록한 사용자에게만 보여줄 수 있다. 사용자명이 DBM 파일에 기록되있을때만 이 프로그램을 사용할 수 있다. 일반파일을 데이터베이스로 사용하려면 htpasswd를 참고하라.

이 manpage는 명령행 옵션만을 설명한다. httpd에서 사용자인증을 설정하는 지시어에 대한 설명은 아파치 배포본에 포함되있고 http://httpd.apache.org/에서도 볼 수 있는 아파치 설명서를 참고하라.

참고

  • httpd
  • mod_auth_dbm

개요

dbmmanage [ encoding ] filename add|adduser|check|delete|update username [ encpasswd [ group[,group...] [ comment ] ] ]

dbmmanage filename view [ username ]

dbmmanage filename import

옵션

filename
DBM형식 파일의 파일명. 보통 .db, .pag, .dir 확장자를 뺀다.
username
작업할 사용자명. username에 콜론(:)을 사용할 수 없다.
encpasswd
update나 add 명령에 사용할 이미 암호화된 암호이다. 암호를 나중에 지정하고 싶은 경우 빼기기호(-)를 사용한다. 또, update 명령을 사용할때 마침표(.)를 사용하면 원래 암호를 그대로 둔다.
group
사용자가 속한 그룹. 그룹명에 콜론(:)을 사용할 수 없다. 사용자를 그룹에 추가하지는 않지만 설명란을 채우고 싶다면 빼기기호(-)를 사용한다. 또, update 명령을 사용할때 마침표(.)를 사용한다면 원래 그룹을 그대로 둔다.
comment
실제 이름, 메일 주소 등 사용자에 대한 설명을 적는 란이다. 서버는 이 항목을 무시한다.

인코딩

-d
crypt 암호화 (Win32나 Netware가 아니라면 기본값)
-m
MD5 암호화 (Win32과 Netware에서 기본값)
-s
SHA1 암호화
-p
암호를 그대로 기록 (추천하지 않음)

명령

add
암호화된 암호 encpasswd를 사용하여 filename에 username 항목을 추가한다.
adduser
암호를 물어보고 filename에 username 항목을 추가한다.
check
암호를 물어본후 filename에 username이 있고 암호가 일치하는지 검사한다.
delete
filename에서 username 항목을 삭제한다.
import
STDIN에서 username:password 항목을 (한줄에 하나씩) 읽어서 filename에 추가한다. 암호는 이미 암호화되있어야 한다.
update
adduser 명령과 비슷하지만, filename에 이미 username이 있는지 확인한다.
view
DBM 파일 내용을 출력한다. username을 지정하면 특정 항목만을 출력한다.

버그

여러 다른 DBM 파일형식들이 있고 당신의 시스템에 여러 형식에 대한 비슷한 라이브러리들이 있음을 주의해야 한다. 가장 대표적인 네가지가 SDBM, NDBM, GNU 프로젝트의 GDBM, Berkeley DB 2이다. 불행히도 이 라이브러리들은 모두 다른 파일형식을 사용한다. 그래서 filename이 사용하는 파일형식이 dbmmanage가 원하는 형식과 같은지 확인해야 한다. dbmmanage는 DBM 파일의 형식을 알아내지 못한다. 다른 형식을 사용하면 아무일도 하지 않거나, 다름 이름의 DBM 파일을 만들거나, 최악의 경우 파일을 기록하여 DBM 파일을 망칠 수 있다.

dbmmanage 프로그램 앞부분에 있는 @AnyDBM::ISA 배열이 DBM형식 선호순서이다. 우리는 Berkeley DB 2 파일형식을 선호하므로 dbmmanage가 시스템 라이브러리를 찾는 순서는 Berkeley DB 2, NDBM, GDBM, SDBM 순이다. dbmmanage는 제일 먼저 찾은 라이브러리를 사용하여 모든 DBM 파일 작업을 한다. 이 순서는 Perl의 간단한 dbmopen() 호출이 사용하는 순서나 Perl의 표준 @AnyDBM::ISA 순서와 조금 다르다. 그래서 다른 도구를 사용하여 DBM 파일을 관리한다면 이 순서를 따라야 한다. C와 같이 다른 언어로 작성한 프로그램을 사용하여 파일을 다루는 경우에도 마찬가지다.

대부분의 유닉스 시스템에서 file 프로그램으로 DBM 파일형식을 확인할 수 있다.


htdigest - digest authentication에 사용할 사용자파일을 관리한다 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

htdigest - digest authentication에 사용할 사용자파일을 관리한다

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

htdigest는 HTTP 사용자의 digest authentication에 사용할 사용자명, 영역, 암호를 저장하는 일반파일을 만들고 수정한다. 아파치 웹서버는 자원을 htdigest로 만든 파일에 기록한 사용자에게만 보여줄 수 있다.

이 manpage는 명령행 옵션만을 설명한다. httpd에서 digest authentication을 설정하는 지시어에 대한 설명은 아파치 배포본에 포함되있고 http://httpd.apache.org/에서도 볼 수 있는 아파치 설명서를 참고하라.

참고

  • httpd
  • mod_auth_digest

개요

htdigest [ -c ] passwdfile realm username

옵션

-c
passwdfile을 만든다. passwdfile이 이미 있다면 먼저 지우고 만든다.
passwdfile
사용자명, 영역, 암호를 저장할 파일명. -c를 같이 사용한 경우 파일이 없다면 만들고, 있다면 파일을 지우고 다시 만든다.
realm
사용자명이 속한 영역이름.
username
passwdfile에 만들거나 수정할 사용자명. 파일에 username이 없다면 항목을 추가한다. 있다면 암호를 수정한다.


htpasswd - basic authentication에 사용할 사용자파일을 관리한다 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

htpasswd - basic authentication에 사용할 사용자파일을 관리한다

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

htpasswd는 HTTP basic authentication에 사용할 사용자명과 암호를 저장하는 일반파일을 생성하고 수정한다. htpasswd가 파일을 쓰거나 읽을 수 없다면, 오류상태를 반환하고 아무것도 수정하지 않는다.

아파치 웹서버는 자원을 htpasswd로 만든 파일에 기록한 사용자에게만 보여줄 수 있다. 이 프로그램은 사용자명과 암호를 저장하는 일반 파일을 관리한다. 그러나 다른 자료저장 방식을 위해 암호 정보를 암호화하여 저장할 수 있다. DBM 데이터베이스를 사용하려면 dbmmanage를 참고하라.

htpasswd는 아파치 특유의 MD5 혹은 시스템의 crypt()를 사용하여 암호를 암호화한다. htpasswd가 관리하는 파일은 두 종류의 암호를 모두 저장할 수 있다. 즉, 같은 파일에 MD5로 암호화한 암호를 사용하는 사용자와 crypt()로 암호화한 암호를 사용하는 사용자 정보 모두 나올 수 있다.

이 manpage는 명령행 옵션만을 설명한다. httpd에서 사용자인증을 설정하는 지시어에 대한 설명은 아파치 배포본에 포함되있고 http://httpd.apache.org/에서도 볼 수 있는 아파치 설명서를 참고하라.

참고

  • httpd
  • 배포본에는 SHA1을 지원하는 스크립트도 있다.

개요

htpasswd [ -c ] [ -m ] [ -D ] passwdfile username

htpasswd -b [ -c ] [ -m | -d | -p | -s ] [ -D ] passwdfile username password

htpasswd -n [ -m | -d | -s | -p ] username

htpasswd -nb [ -m | -d | -s | -p ] username password

옵션

-b
배치(batch) 모드를 사용한다. 예를 들어, 암호를 물어보지않고 명령행에서 받는다. 명령행에 암호가 직접 드러나므로, 이 옵션은 매우 조심해서 사용해야 한다.
-c
passwdfile을 만든다. passwdfile이 이미 존재한다면, 덮어쓴다. 이 옵션을 -n 옵션과 같이 사용할 수 없다.
-n
파일을 수정하지않고 결과를 표준출력으로 출력한다. 아파치가 문서이외의 곳에 생성한 암호를 저장할때 유용하다. (항상 첫번째 아규먼트인) passwdfile 아규먼트가 없기때문에 명령행 문법이 다르다. -c 옵션과 같이 사용할 수 없다.
-m
MD5를 사용하여 암호를 암호화한다. Windows, Netware, TPF에서 기본값이다.
-d
crypt()를 사용하여 암호를 암호화한다. Windows, Netware, TPF를 제외한 모든 플래폼에서 기본값이다. 모든 플래폼의 htpasswd가 이 형식을 지원할 수는 있지만, Windows, Netware, TPF의 httpd 서버는 이 형식을 지원하지 않는다.
-s
암호를 SHA 암호화한다. LDAP 디렉토리교환형식(ldif)을 사용하여 Netscape 서버로 정보를 보내거나 거져올때 유용하다.
-p
암호를 그대로 사용한다. 모든 플래폼의 htpasswd가 지원하지만, Windows, Netware, TPF의 httpd 데몬만이 일반 암호를 받는다.
-D
사용자를 삭제한다. htpasswd 파일에 사용자명이 있다면 삭제한다.
passwdfile
사용자명과 암호를 저장하는 파일명. -c를 사용한 경우 파일이 없다면 새로 만들고, 있다면 덮어쓴다.
username
passwdfile에 만들거나 수정할 사용자명. username이 이 파일에 없다면 항목을 추가한다. 있다면 암호를 수정한다.
password
암호화하여 파일에 저장할 암호. 오직 -b 옵션과 같이 사용할 수 있다.

종료코드

htpasswd는 passwdfile에 사용자명과 암호를 성공적으로 추가하거나 수정한 경우 ("참") 종료코드 0을 반환한다. htpasswd는 파일에 접근할때 문제가 발생한 경우 1을, 명령행 형식이 잘못된 경우 2를, 입력한 암호와 확인차 다시 입력한 값이 일치하지 않은 경우 3을, 명령이 중단된 경우 4를, (사용자명, 파일명, 암호, 최종 계산결과) 값이 너무 긴 경우 5를, 사용자명에 허용하지않는 문자가 포함된 경우 제한 절 참고) 6를, 파일이 올바른 암호파일이 아닌 경우 7을 반환한다.

예제

htpasswd /usr/local/etc/apache/.htpasswd-users jsmith

사용자 jsmith의 암호를 추가하거나 수정한다. 사용자에게 암호를 물어본다. Windows 시스템에서 실행하면 암호를 아파치 특유의 MD5 알고리즘을 사용하여 암호화하고, 아니면 시스템의 crypt() 함수를 사용한다. 파일이 없다면 htpasswd는 아무 일도 하지않고 오류를 낸다.

htpasswd -c /home/doe/public_html/.htpasswd jane

새로 파일을 만들고 그 파일에 사용자 jane을 추가한다. 사용자에게 암호를 물어본다. 파일이 있지만 읽거나 쓸 수 없다면, htpasswd는 파일을 수정하지않고 문구를 출력한후 오류상태를 반환한다.

htpasswd -mb /usr/web/.htpasswd-all jones Pwd4Steve

명령행의 암호(Pwd4Steve)를 MD5 알고리즘으로 암호화하여 지정한 파일에 저장한다.

보안상 고려할 점

htpasswd 등이 관리하는 웹 암호파일이 웹서버의 URI 공간에 있으면 안된다. 즉, 브라우저가 이 파일을 볼 수 없어야 한다.

명령행에 암호화하지않은 암호를 사용하기때문에 -b 옵션을 추천하지 않는다.

제한

Windows와 MPE 플래폼은 htpasswd가 암호화하는 암호의 길이를 255 문자로 제한한다. 더 긴 암호는 255자에서 짤린다.

htpasswd가 사용하는 MD5 알고리즘은 아파치 소프트웨어 특유의 것이다. 이를 사용하여 암호화한 암호를 다른 웹서버에서 사용할 수 없다.

사용자명은 255 바이트로 제한되고 : 문자를 포함할 수 없다.


logresolve - 아파치 로그파일의 IP-주소를 호스트명으로 변환한다 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

logresolve - 아파치 로그파일의 IP-주소를 호스트명으로 변환한다

logresolve는 아파치 접근로그파일에 있는 IP-주소를 찾는 후처리 프로그램이다. 네임서버의 부하를 최소화하기위해 logresolve는 내부적으로 해쉬테이블 캐쉬를 사용한다. 즉, IP 주소가 로그파일에 처음 나올때만 찾는다.

표준입력으로 아파치 로그파일을 읽는다. 각 줄의 첫번째 항목이 IP 주소이고, 나머지 부분과 공백으로 구분되야 한다.

개요

logresolve [ -s filename ] [ -c ] < access_log > access_log.new

옵션

-s filename
통계를 기록할 파일명을 지정한다.
-c
logresolve가 몇가지 DNS 검사를 하도록 한다: IP 주소로 호스트명을 찾은후 그 호스트명으로 다시 IP 주소들을 찾아서 그중 하나가 원래 주소와 일치하는지 검사한다.


rotatelogs - 아파치 로그를 순환하기위해 파이프로 연결할 로그 프로그램 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

rotatelogs - 아파치 로그를 순환하기위해 파이프로 연결할 로그 프로그램

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

rotatelogs는 아파치의 파이프 로그파일 기능을 위한 간단한 프로그램이다. 예를 들어:

CustomLog "|bin/rotatelogs /var/logs/logfile 86400" common

그러면 /var/logs/logfile.nnnn 파일을 만든다. nnnn은 로그를 시작한 시스템시간이다 (이 시간은 항상 순환기간의 배수이다. 그래서 cron 스크립트로 처리하기 쉽다). 순환기간 (여기서는 24 시간) 마다 새로운 로그를 시작한다.

CustomLog "|bin/rotatelogs /var/logs/logfile 5M" common

이 설정은 로그파일 크기가 5 메가바이트가 될때마다 순환한다.

ErrorLog "|bin/rotatelogs /var/logs/errorlog.%Y-%m-%d-%H_%M_%S 5M"

이 설정은 오류로그 파일 크기가 5 메가바이트가 될때마다 errorlog.YYYY-mm-dd-HH_MM_SS와 같은 파일을 만들어서 오류로그 파일을 순환한다.

개요

rotatelogs [ -l ] logfile [ rotationtime [ offset ]] | [ filesizeM ]

옵션

-l (2.0.51 이후)
순환주기로 GMT 대신 지역시간을 사용한다. (BST나 DST와 같이) GMT 시간차가 변하는 환경에서 -l을 사용하면 예기치 않은 결과가 발생할 수 있다!
logfile
로그파일의 경로와 이름. logfile에 '%' 문자가 있다면 strftime(3)의 형식문자열과 같이 처리한다. '%' 문자가 없다면 뒤에 초단위 시간 .nnnnnnnnnn을 자동으로 붙인다. 두 형식 모두 현재 기간부터 시작시간을 계산한다.
rotationtime
로그파일을 순환할 초단위 시간.
offset
UTC에서 분단위 시간차이. 생략하면 0으로 가정하여 UTC를 사용한다. 예를 들어, UTC -5 시간대의 지역시간을 사용한다면 아규먼트로 -300을 지정한다.
filesizeM
시간이 아닌 크기를 지정할때 메가바이트단위 최대 파일크기 뒤에 M을 붙인다. rotationtime과 offset 대신 이 파라미터를 사용한다.

포팅가능성

다음 로그파일 형식문자열 표현은 모든 strftime(3) 구현이 지원해야 한다. 라이브러리 특유의 확장은 strftime(3) manpage를 참고하라.

%A | (지역화된) 완전한 요일 이름
%a | (지역화된) 3-문자 요일 이름
%B | (지역화된) 완전한 달 이름
%b | (지역화된) 3-문자 달 이름
%c | (지역화된) 날짜와 시간
%d | 2-자리 일
%H | 2-자리 시간 (24 시간 시계)
%I | 2-자리 시간 (12 시간 시계)
%j | 3-자리 날짜수
%M | 2-자리 분
%m | 2-자리 달
%p | (지역화된) 12 시간 시계의 am/pm
%S | 2-자리 초
%U | 2-자리 주일수 (주의 첫번재 날은 일요일)
%W | 2-자리 주일수 (주의 첫번재 날은 월요일)
%w | 1-자리 요일수 (주의 첫번째 날은 일요일)
%X | (지역화된) 시간
%x | (지역화된) 날짜
%Y | 4-자리 연도
%y | 2-자리 연도
%Z | 시간대 이름
%% | 문자그대로 `%'


suexec - 외부 프로그램을 실행하기 전에 사용자를 변경한다 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

suexec - 외부 프로그램을 실행하기 전에 사용자를 변경한다

아파치 웹서버는 CGI 프로그램을 실행하기 전에 다른 사용자로 전환하기위해 suexec를 사용한다. 이를 사용하려면 서버를 root 계정으로 실행해야 한다. 보통 웹 데몬을 root 계정으로 실행하지 않기때문에 suexec 실행파일에 setuid 비트를 설정하고 root가 소유주이어야 한다. root이외의 다른 사용자가 쓰기권한을 가지면 안된다.

suexec의 개념과 보안모델에 대한 정보는 suexec 문서를 (http://httpd.apache.org/docs-2.0/suexec.html) 참고하라.

개요

suexec -V

옵션

-V
root가 실행하면 suexec의 컴파일 옵션을 출력한다. 보안상 이유로 모든 설정옵션은 컴파일할 때만 지정할 수 있다.


Other Programs - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Programs

Other Programs

다음은 간단하여 manpage가 없는, 아파치 웹서버에 포함된 지원 프로그램들이다. 자동으로 이들을 설치하지 않는다. 구성과정후 support/ 디렉토리에서 이 프로그램들을 찾을 수 있다.

log_server_status

이 perl 스크립트는 cron 등에서 자주 실행하도록 설계되었다. 이 스크립트를 서버에 연결하여 상태 정보를 다운로드한다. 그런후 이 정보를 한줄로 정리하여 파일에 기록한다. 로그파일의 위치를 지정하려면 스크립트 앞부분의 변수를 수정한다.

split-logfile

이 perl 스크립트는 결합된 웹서버 접근로그파일의 내용을 여러 파일로 나눈다. 각 줄의 첫번째 항목이 ("%v"로 추가한) 가상호스트 정보이고, 로그파일명은 현재 디렉토리에 가상호스트명 + ".log"라고 가정한다.

결합된 로그파일을 표준입력으로 읽는다. 읽은 내용을 기존의 로그파일들에 추가한다.


Apache Miscellaneous Documentation - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

Apache Miscellaneous Documentation

Below is a list of additional documentation pages that apply to the Apache web server development project.

Warning

Some of the documents below have not been fully updated to take into account changes made in the 2.0 version of the Apache HTTP Server. Some of the information may still be relevant, but please use it with care.

How to use XSSI and Negotiation for custom ErrorDocuments

Describes a solution which uses XSSI and negotiation to custom-tailor the Apache ErrorDocuments to taste, adding the advantage of returning internationalized versions of the error messages depending on the client's language preferences.

File Descriptor use in Apache

Describes how Apache uses file descriptors and talks about various limits imposed on the number of descriptors available by various operating systems.

FIN_WAIT_2

A description of the causes of Apache processes going into the FIN_WAIT_2 state, and what you can do about it.

Known Client Problems

A list of problems in HTTP clients which can be mitigated by Apache.

Performance Notes - Apache Tuning

Notes about how to (run-time and compile-time) configure Apache for highest performance. Notes explaining why Apache does some things, and why it doesn't do other things (which make it slower/faster).

Security Tips

Some "do"s - and "don't"s - for keeping your Apache web site secure.

URL Rewriting Guide

This document supplements the mod_rewrite reference documentation. It describes how one can use Apache's mod_rewrite to solve typical URL-based problems webmasters are usually confronted with in practice.

Apache Tutorials

A list of external resources which help to accomplish common tasks with the Apache HTTP server.

Relevant Standards

This document acts as a reference page for most of the relevant standards that Apache follows.


International Customized Server Error Messages - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

International Customized Server Error Messages

Warning:

This document has not been fully updated to take into account changes made in the 2.0 version of the Apache HTTP Server. Some of the information may still be relevant, but please use it with care.

This document describes an easy way to provide your Apache HTTP Server with a set of customized error messages which take advantage of Content Negotiation and mod_include to return error messages generated by the server in the client's native language.

Introduction

By using SSI, all ErrorDocument messages can share a homogenous and consistent style and layout, and maintenance work (changing images, changing links) is kept to a minimum because all layout information can be kept in a single file.

Error documents can be shared across different servers, or even hosts, because all varying information is inserted at the time the error document is returned on behalf of a failed request.

Content Negotiation then selects the appropriate language version of a particular error message text, honoring the language preferences passed in the client's request. (Users usually select their favorite languages in the preferences options menu of today's browsers). When an error document in the client's primary language version is unavailable, the secondary languages are tried or a default (fallback) version is used.

You have full flexibility in designing your error documents to your personal taste (or your company's conventions). For demonstration purposes, we present a simple generic error document scheme. For this hypothetic server, we assume that all error messages...

  • possibly are served by different virtual hosts (different host name, different IP address, or different port) on the server machine,
  • show a predefined company logo in the right top of the message (selectable by virtual host),
  • print the error title first, followed by an explanatory text and (depending on the error context) help on how to resolve the error,
  • have some kind of standardized background image,
  • display an apache logo and a feedback email address at the bottom of the error message.

An example of a "document not found" message for a german client might look like this:

[Needs graphics capability to display]

All links in the document as well as links to the server's administrator mail address, and even the name and port of the serving virtual host are inserted in the error document at "run-time", i.e., when the error actually occurs.

Creating an ErrorDocument directory

For this concept to work as easily as possible, we must take advantage of as much server support as we can get:

  1. By defining the MultiViews Options, we enable the language selection of the most appropriate language alternative (content negotiation).
  2. By setting the LanguagePriority directive we define a set of default fallback languages in the situation where the client's browser did not express any preference at all.
  3. By enabling mod_include (and disallowing execution of cgi scripts for security reasons), we allow the server to include building blocks of the error message, and to substitute the value of certain environment variables into the generated document (dynamic HTML) or even to conditionally include or omit parts of the text.
  4. The AddHandler and AddType directives are useful for automatically SSI-expanding all files with a .shtml suffix to text/html.
  5. By using the Alias directive, we keep the error document directory outside of the document tree because it can be regarded more as a server part than part of the document tree.
  6. The <Directory> block restricts these "special" settings to the error document directory and avoids an impact on any of the settings for the regular document tree.
  7. For each of the error codes to be handled (see RFC2068 for an exact description of each error code, or look at src/main/http_protocol.c if you wish to see apache's standard messages), an ErrorDocument in the aliased /errordocs directory is defined. Note that we only define the basename of the document here because the MultiViews option will select the best candidate based on the language suffixes and the client's preferences. Any error situation with an error code not handled by a custom document will be dealt with by the server in the standard way (i.e., a plain error message in english).
  8. Finally, the AllowOverride directive tells apache that it is not necessary to look for a .htaccess file in the /errordocs directory: a minor speed optimization.

The resulting httpd.conf configuration would then look similar to this:

Note

Note that you can define your own error messages using this method for only part of the document tree, e.g., a /~user/ subtree. In this case, the configuration could as well be put into the .htaccess file at the root of the subtree, and the <Directory> and </Directory> directives -but not the contained directives- must be omitted.

LanguagePriority en fr de
Alias /errordocs /usr/local/apache/errordocs

<Directory /usr/local/apache/errordocs>
AllowOverride none
Options MultiViews IncludesNoExec FollowSymLinks
AddType text/html .shtml
<FilesMatch "\.shtml[.$]">
SetOutputFilter INCLUDES
</FilesMatch>
</Directory>

# "400 Bad Request",
ErrorDocument 400 /errordocs/400
# "401 Authorization Required",
ErrorDocument 401 /errordocs/401
# "403 Forbidden",
ErrorDocument 403 /errordocs/403
# "404 Not Found",
ErrorDocument 404 /errordocs/404
# "500 Internal Server Error",
ErrorDocument 500 /errordocs/500

The directory for the error messages (here: /usr/local/apache/errordocs/) must then be created with the appropriate permissions (readable and executable by the server uid or gid, only writable for the administrator).

Naming the Individual Error Document files

By defining the MultiViews option, the server was told to automatically scan the directory for matching variants (looking at language and content type suffixes) when a requested document was not found. In the configuration, we defined the names for the error documents to be just their error number (without any suffix).

The names of the individual error documents are now determined like this (I'm using 403 as an example, think of it as a placeholder for any of the configured error documents):

  • No file errordocs/403 should exist. Otherwise, it would be found and served (with the DefaultType, usually text/plain), all negotiation would be bypassed.
  • For each language for which we have an internationalized version (note that this need not be the same set of languages for each error code - you can get by with a single language version until you actually have translated versions), a document errordocs/403.shtml.lang is created and filled with the error text in that language (see below).
  • One fallback document called errordocs/403.shtml is created, usually by creating a symlink to the default language variant (see below).

The Common Header and Footer Files

By putting as much layout information in two special "include files", the error documents can be reduced to a bare minimum.

One of these layout files defines the HTML document header and a configurable list of paths to the icons to be shown in the resulting error document. These paths are exported as a set of SSI environment variables and are later evaluated by the "footer" special file. The title of the current error (which is put into the TITLE tag and an H1 header) is simply passed in from the main error document in a variable called title.

By changing this file, the layout of all generated error messages can be changed in a second. (By exploiting the features of SSI, you can easily define different layouts based on the current virtual host, or even based on the client's domain name).

The second layout file describes the footer to be displayed at the bottom of every error message. In this example, it shows an apache logo, the current server time, the server version string and adds a mail reference to the site's webmaster.

For simplicity, the header file is simply called head.shtml because it contains server-parsed content but no language specific information. The footer file exists once for each language translation, plus a symlink for the default language.

for English, French and German versions (default english)

foot.shtml.en,
foot.shtml.fr,
foot.shtml.de,
foot.shtml symlink to
foot.shtml.en

Both files are included into the error document by using the directives <!--#include virtual="head" --> and <!--#include virtual="foot" --> respectively: the rest of the magic occurs in mod_negotiation and in mod_include.

See the listings below to see an actual HTML implementation of the discussed example.

Creating ErrorDocuments in Different Languages

After all this preparation work, little remains to be said about the actual documents. They all share a simple common structure:

<!--#set var="title" value="error description title" -->
<!--#include virtual="head" -->
explanatory error text
<!--#include virtual="foot" -->

In the listings section, you can see an example of a [400 Bad Request] error document. Documents as simple as that certainly cause no problems to translate or expand.

The Fallback Language

Do we need a special handling for languages other than those we have translations for? We did set the LanguagePriority, didn't we?!

Well, the LanguagePriority directive is for the case where the client does not express any language priority at all. But what happens in the situation where the client wants one of the languages we do not have, and none of those we do have?

Without doing anything, the Apache server will usually return a [406 no acceptable variant] error, listing the choices from which the client may select. But we're in an error message already, and important error information might get lost when the client had to choose a language representation first.

So, in this situation it appears to be easier to define a fallback language (by copying or linking, e.g., the english version to a language-less version). Because the negotiation algorithm prefers "more specialized" variants over "more generic" variants, these generic alternatives will only be chosen when the normal negotiation did not succeed.

A simple shell script to do it (execute within the errordocs/ dir):

for f in *.shtml.en
do
ln -s $f `basename $f .en`
done

Customizing Proxy Error Messages

As of Apache-1.3, it is possible to use the ErrorDocument mechanism for proxy error messages as well (previous versions always returned fixed predefined error messages).

Most proxy errors return an error code of [500 Internal Server Error]. To find out whether a particular error document was invoked on behalf of a proxy error or because of some other server error, and what the reason for the failure was, you can check the contents of the new ERROR_NOTES CGI environment variable: if invoked for a proxy error, this variable will contain the actual proxy error message text in HTML form.

The following excerpt demonstrates how to exploit the ERROR_NOTES variable within an error document:

<!--#if expr="$REDIRECT_ERROR_NOTES = ''" -->

<p>
The server encountered an unexpected condition
which prevented it from fulfilling the request.
</p>

<p>
<a href="mailto:<!--#echo var="SERVER_ADMIN" -->"
SUBJECT="Error message [<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" --> for <!--#echo var="REQUEST_URI" -->">
Please forward this error screen to <!--#echo var="SERVER_NAME" -->'s
WebMaster</a>; it includes useful debugging information about
the Request which caused the error.

<pre><!--#printenv --></pre>
</p>

<!--#else -->
<!--#echo var="REDIRECT_ERROR_NOTES" -->
<!--#endif -->

HTML Listing of the Discussed Example

So, to summarize our example, here's the complete listing of the 400.shtml.en document. You will notice that it contains almost nothing but the error text (with conditional additions). Starting with this example, you will find it easy to add more error documents, or to translate the error documents to different languages.

<!--#set var="title" value="Bad Request"-->
<!--#include virtual="head" -->

<p>
Your browser sent a request that this server could not understand:
<blockquote>
<strong><!--#echo var="REQUEST_URI" --></strong>
 </blockquote>

The request could not be understood by the server due to malformed
syntax. The client should not repeat the request without
modifications.
</p>

<p>
<!--#if expr="$HTTP_REFERER != ''" -->
Please inform the owner of
<a href="<!--#echo var="HTTP_REFERER" -->">the referring page</a> about
the malformed link.

<!--#else -->
Please check your request for typing errors and retry.

<!--#endif -->
</p>

<!--#include virtual="foot" -->

Here is the complete head.shtml.en file (the funny line breaks avoid empty lines in the document after SSI processing). Note the configuration section at top. That's where you configure the images and logos as well as the apache documentation directory. Look how this file displays two different logos depending on the content of the virtual host name ($SERVER_NAME), and that an animated apache logo is shown if the browser appears to support it (the latter requires server configuration lines of the form

BrowserMatch "^Mozilla/[2-4]" anigif

for browser types which support animated GIFs).

<!--#if expr="$SERVER_NAME = /.*\.mycompany\.com/" -->
<!--#set var="IMG_CorpLogo" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/CorpLogo.gif" -->
<!--#set var="ALT_CorpLogo" value="Powered by Linux!" -->
<!--#else -->
<!--#set var="IMG_CorpLogo" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/PrivLogo.gif" -->
<!--#set var="ALT_CorpLogo" value="Powered by Linux!" -->
<!--#endif-->

<!--#set var="IMG_BgImage" value="http://$SERVER_NAME:$SERVER_PORT/errordocs/BgImage.gif" -->
<!--#set var="DOC_Apache" value="http://$SERVER_NAME:$SERVER_PORT/Apache/" -->

<!--#if expr="$anigif" -->
<!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_anim.gif" -->
<!--#else-->
<!--#set var="IMG_Apache" value="http://$SERVER_NAME:$SERVER_PORT/icons/apache_pb.gif" -->
 <!--#endif-->

<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
<html>
<head>
<title>
[<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" -->
</title>
</head>

<body bgcolor="white" background="<!--#echo var="IMG_BgImage" -->">
<h1 align="center">
[<!--#echo var="REDIRECT_STATUS" -->] <!--#echo var="title" -->
<img src="<!--#echo var="IMG_CorpLogo" -->"
  alt="<!--#echo var="ALT_CorpLogo" -->" align="right">
</h1>

<hr /> <!-- ======================================================== -->
<div>

and this is the foot.shtml.en file:

</div>
<hr />

<div align="right">
<small>Local Server time: <!--#echo var="DATE_LOCAL" --></small>
</div>

<div align="center">
<a href="<!--#echo var="DOC_Apache" -->">
<img src="<!--#echo var="IMG_Apache" -->" border="0" align="bottom"
  alt="Powered by <!--#echo var="SERVER_SOFTWARE" -->"></a>
<br />
<small><!--#set var="var" value="Powered by $SERVER_SOFTWARE --
File last modified on $LAST_MODIFIED" -->
<!--#echo var="var" --></small>
</div>

<p>If the indicated error looks like a misconfiguration, please inform
<a href="mailto:<!--#echo var="SERVER_ADMIN" -->"
subject="Feedback about Error message [<!--#echo var="REDIRECT_STATUS" -->]
<!--#echo var="title" -->, req=<!--#echo var="REQUEST_URI" -->">
<!--#echo var="SERVER_NAME" -->'s WebMaster</a>.
</p>
</body>
</html>

If you have tips to contribute, send mail to martin@apache.org


Connections in the FIN_WAIT_2 state and Apache - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

Connections in the FIN_WAIT_2 state and Apache

Warning:

This document has not been fully updated to take into account changes made in the 2.0 version of the Apache HTTP Server. Some of the information may still be relevant, but please use it with care.

Starting with the Apache 1.2 betas, people are reporting many more connections in the FIN_WAIT_2 state (as reported by netstat) than they saw using older versions. When the server closes a TCP connection, it sends a packet with the FIN bit set to the client, which then responds with a packet with the ACK bit set. The client then sends a packet with the FIN bit set to the server, which responds with an ACK and the connection is closed. The state that the connection is in during the period between when the server gets the ACK from the client and the server gets the FIN from the client is known as FIN_WAIT_2. See the TCP RFC for the technical details of the state transitions.

The FIN_WAIT_2 state is somewhat unusual in that there is no timeout defined in the standard for it. This means that on many operating systems, a connection in the FIN_WAIT_2 state will stay around until the system is rebooted. If the system does not have a timeout and too many FIN_WAIT_2 connections build up, it can fill up the space allocated for storing information about the connections and crash the kernel. The connections in FIN_WAIT_2 do not tie up an httpd process.

Why Does It Happen?

There are numerous reasons for it happening, some of them may not yet be fully clear. What is known follows.

Buggy Clients and Persistent Connections

Several clients have a bug which pops up when dealing with persistent connections (aka keepalives). When the connection is idle and the server closes the connection (based on the KeepAliveTimeout), the client is programmed so that the client does not send back a FIN and ACK to the server. This means that the connection stays in the FIN_WAIT_2 state until one of the following happens:

  • The client opens a new connection to the same or a different site, which causes it to fully close the older connection on that socket.
  • The user exits the client, which on some (most?) clients causes the OS to fully shutdown the connection.
  • The FIN_WAIT_2 times out, on servers that have a timeout for this state.

If you are lucky, this means that the buggy client will fully close the connection and release the resources on your server. However, there are some cases where the socket is never fully closed, such as a dialup client disconnecting from their provider before closing the client. In addition, a client might sit idle for days without making another connection, and thus may hold its end of the socket open for days even though it has no further use for it. This is a bug in the browser or in its operating system's TCP implementation.

The clients on which this problem has been verified to exist:

  • Mozilla/3.01 (X11; I; FreeBSD 2.1.5-RELEASE i386)
  • Mozilla/2.02 (X11; I; FreeBSD 2.1.5-RELEASE i386)
  • Mozilla/3.01Gold (X11; I; SunOS 5.5 sun4m)
  • MSIE 3.01 on the Macintosh
  • MSIE 3.01 on Windows 95

This does not appear to be a problem on:

  • Mozilla/3.01 (Win95; I)

It is expected that many other clients have the same problem. What a client should do is periodically check its open socket(s) to see if they have been closed by the server, and close their side of the connection if the server has closed. This check need only occur once every few seconds, and may even be detected by a OS signal on some systems (e.g., Win95 and NT clients have this capability, but they seem to be ignoring it).

Apache cannot avoid these FIN_WAIT_2 states unless it disables persistent connections for the buggy clients, just like we recommend doing for Navigator 2.x clients due to other bugs. However, non-persistent connections increase the total number of connections needed per client and slow retrieval of an image-laden web page. Since non-persistent connections have their own resource consumptions and a short waiting period after each closure, a busy server may need persistence in order to best serve its clients.

As far as we know, the client-caused FIN_WAIT_2 problem is present for all servers that support persistent connections, including Apache 1.1.x and 1.2.

A necessary bit of code introduced in 1.2

While the above bug is a problem, it is not the whole problem. Some users have observed no FIN_WAIT_2 problems with Apache 1.1.x, but with 1.2b enough connections build up in the FIN_WAIT_2 state to crash their server. The most likely source for additional FIN_WAIT_2 states is a function called lingering_close() which was added between 1.1 and 1.2. This function is necessary for the proper handling of persistent connections and any request which includes content in the message body (e.g., PUTs and POSTs). What it does is read any data sent by the client for a certain time after the server closes the connection. The exact reasons for doing this are somewhat complicated, but involve what happens if the client is making a request at the same time the server sends a response and closes the connection. Without lingering, the client might be forced to reset its TCP input buffer before it has a chance to read the server's response, and thus understand why the connection has closed. See the appendix for more details.

The code in lingering_close() appears to cause problems for a number of factors, including the change in traffic patterns that it causes. The code has been thoroughly reviewed and we are not aware of any bugs in it. It is possible that there is some problem in the BSD TCP stack, aside from the lack of a timeout for the FIN_WAIT_2 state, exposed by the lingering_close code that causes the observed problems.

What Can I Do About it?

There are several possible workarounds to the problem, some of which work better than others.

Add a timeout for FIN_WAIT_2

The obvious workaround is to simply have a timeout for the FIN_WAIT_2 state. This is not specified by the RFC, and could be claimed to be a violation of the RFC, but it is widely recognized as being necessary. The following systems are known to have a timeout:

  • FreeBSD versions starting at 2.0 or possibly earlier.
  • NetBSD version 1.2(?)
  • OpenBSD all versions(?)
  • BSD/OS 2.1, with the K210-027 patch installed.
  • Solaris as of around version 2.2. The timeout can be tuned by using ndd to modify tcp_fin_wait_2_flush_interval, but the default should be appropriate for most servers and improper tuning can have negative impacts.
  • Linux 2.0.x and earlier(?)
  • HP-UX 10.x defaults to terminating connections in the FIN_WAIT_2 state after the normal keepalive timeouts. This does not refer to the persistent connection or HTTP keepalive timeouts, but the SO_LINGER socket option which is enabled by Apache. This parameter can be adjusted by using nettune to modify parameters such as tcp_keepstart and tcp_keepstop. In later revisions, there is an explicit timer for connections in FIN_WAIT_2 that can be modified; contact HP support for details.
  • SGI IRIX can be patched to support a timeout. For IRIX 5.3, 6.2, and 6.3, use patches 1654, 1703 and 1778 respectively. If you have trouble locating these patches, please contact your SGI support channel for help.
  • NCR's MP RAS Unix 2.xx and 3.xx both have FIN_WAIT_2 timeouts. In 2.xx it is non-tunable at 600 seconds, while in 3.xx it defaults to 600 seconds and is calculated based on the tunable "max keep alive probes" (default of 8) multiplied by the "keep alive interval" (default 75 seconds).
  • Sequent's ptx/TCP/IP for DYNIX/ptx has had a FIN_WAIT_2 timeout since around release 4.1 in mid-1994.

The following systems are known to not have a timeout:

  • SunOS 4.x does not and almost certainly never will have one because it as at the very end of its development cycle for Sun. If you have kernel source should be easy to patch.

There is a patch available for adding a timeout to the FIN_WAIT_2 state; it was originally intended for BSD/OS, but should be adaptable to most systems using BSD networking code. You need kernel source code to be able to use it.

Compile without using lingering_close()

It is possible to compile Apache 1.2 without using the lingering_close() function. This will result in that section of code being similar to that which was in 1.1. If you do this, be aware that it can cause problems with PUTs, POSTs and persistent connections, especially if the client uses pipelining. That said, it is no worse than on 1.1, and we understand that keeping your server running is quite important.

To compile without the lingering_close() function, add -DNO_LINGCLOSE to the end of the EXTRA_CFLAGS line in your Configuration file, rerun Configure and rebuild the server.

Use SO_LINGER as an alternative to lingering_close()

On most systems, there is an option called SO_LINGER that can be set with setsockopt(2). It does something very similar to lingering_close(), except that it is broken on many systems so that it causes far more problems than lingering_close. On some systems, it could possibly work better so it may be worth a try if you have no other alternatives.

To try it, add -DUSE_SO_LINGER -DNO_LINGCLOSE to the end of the EXTRA_CFLAGS line in your Configuration file, rerun Configure and rebuild the server.

NOTE

Attempting to use SO_LINGER and lingering_close() at the same time is very likely to do very bad things, so don't.

Increase the amount of memory used for storing connection state

BSD based networking code:
BSD stores network data, such as connection states, in something called an mbuf. When you get so many connections that the kernel does not have enough mbufs to put them all in, your kernel will likely crash. You can reduce the effects of the problem by increasing the number of mbufs that are available; this will not prevent the problem, it will just make the server go longer before crashing.

The exact way to increase them may depend on your OS; look for some reference to the number of "mbufs" or "mbuf clusters". On many systems, this can be done by adding the line NMBCLUSTERS="n", where n is the number of mbuf clusters you want to your kernel config file and rebuilding your kernel.

Disable KeepAlive

If you are unable to do any of the above then you should, as a last resort, disable KeepAlive. Edit your httpd.conf and change "KeepAlive On" to "KeepAlive Off".

Appendix

Below is a message from Roy Fielding, one of the authors of HTTP/1.1.

Why the lingering close functionality is necessary with HTTP

The need for a server to linger on a socket after a close is noted a couple times in the HTTP specs, but not explained. This explanation is based on discussions between myself, Henrik Frystyk, Robert S. Thau, Dave Raggett, and John C. Mallery in the hallways of MIT while I was at W3C.

If a server closes the input side of the connection while the client is sending data (or is planning to send data), then the server's TCP stack will signal an RST (reset) back to the client. Upon receipt of the RST, the client will flush its own incoming TCP buffer back to the un-ACKed packet indicated by the RST packet argument. If the server has sent a message, usually an error response, to the client just before the close, and the client receives the RST packet before its application code has read the error message from its incoming TCP buffer and before the server has received the ACK sent by the client upon receipt of that buffer, then the RST will flush the error message before the client application has a chance to see it. The result is that the client is left thinking that the connection failed for no apparent reason.

There are two conditions under which this is likely to occur:

  1. sending POST or PUT data without proper authorization
  2. sending multiple requests before each response (pipelining) and one of the middle requests resulting in an error or other break-the-connection result.

The solution in all cases is to send the response, close only the write half of the connection (what shutdown is supposed to do), and continue reading on the socket until it is either closed by the client (signifying it has finally read the response) or a timeout occurs. That is what the kernel is supposed to do if SO_LINGER is set. Unfortunately, SO_LINGER has no effect on some systems; on some other systems, it does not have its own timeout and thus the TCP memory segments just pile-up until the next reboot (planned or not).

Please note that simply removing the linger code will not solve the problem -- it only moves it to a different and much harder one to detect.


Known Problems in Clients - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

Known Problems in Clients

Warning:

This document has not been fully updated to take into account changes made in the 2.0 version of the Apache HTTP Server. Some of the information may still be relevant, but please use it with care.

Over time the Apache Group has discovered or been notified of problems with various clients which we have had to work around, or explain. This document describes these problems and the workarounds available. It's not arranged in any particular order. Some familiarity with the standards is assumed, but not necessary.

For brevity, Navigator will refer to Netscape's Navigator product (which in later versions was renamed "Communicator" and various other names), and MSIE will refer to Microsoft's Internet Explorer product. All trademarks and copyrights belong to their respective companies. We welcome input from the various client authors to correct inconsistencies in this paper, or to provide us with exact version numbers where things are broken/fixed.

For reference, RFC1945 defines HTTP/1.0, and RFC2068 defines HTTP/1.1. Apache as of version 1.2 is an HTTP/1.1 server (with an optional HTTP/1.0 proxy).

Various of these workarounds are triggered by environment variables. The admin typically controls which are set, and for which clients, by using mod_browser. Unless otherwise noted all of these workarounds exist in versions 1.2 and later.

Trailing CRLF on POSTs

This is a legacy issue. The CERN webserver required POST data to have an extra CRLF following it. Thus many clients send an extra CRLF that is not included in the Content-Length of the request. Apache works around this problem by eating any empty lines which appear before a request.

Broken KeepAlive

Various clients have had broken implementations of keepalive (persistent connections). In particular the Windows versions of Navigator 2.0 get very confused when the server times out an idle connection. The workaround is present in the default config files:

BrowserMatch Mozilla/2 nokeepalive

Note that this matches some earlier versions of MSIE, which began the practice of calling themselves Mozilla in their user-agent strings just like Navigator.

MSIE 4.0b2, which claims to support HTTP/1.1, does not properly support keepalive when it is used on 301 or 302 (redirect) responses. Unfortunately Apache's nokeepalive code prior to 1.2.2 would not work with HTTP/1.1 clients. You must apply this patch to version 1.2.1. Then add this to your config:

BrowserMatch "MSIE 4\.0b2;" nokeepalive

Incorrect interpretation of HTTP/1.1 in response

To quote from section 3.1 of RFC1945:

HTTP uses a "<MAJOR>.<MINOR>" numbering scheme to indicate versions of the protocol. The protocol versioning policy is intended to allow the sender to indicate the format of a message and its capacity for understanding further HTTP communication, rather than the features obtained via that communication.

Since Apache is an HTTP/1.1 server, it indicates so as part of its response. Many client authors mistakenly treat this part of the response as an indication of the protocol that the response is in, and then refuse to accept the response.

The first major indication of this problem was with AOL's proxy servers. When Apache 1.2 went into beta it was the first wide-spread HTTP/1.1 server. After some discussion, AOL fixed their proxies. In anticipation of similar problems, the force-response-1.0 environment variable was added to Apache. When present Apache will indicate "HTTP/1.0" in response to an HTTP/1.0 client, but will not in any other way change the response.

The pre-1.1 Java Development Kit (JDK) that is used in many clients (including Navigator 3.x and MSIE 3.x) exhibits this problem. As do some of the early pre-releases of the 1.1 JDK. We think it is fixed in the 1.1 JDK release. In any event the workaround:

BrowserMatch Java/1.0 force-response-1.0
BrowserMatch JDK/1.0 force-response-1.0

RealPlayer 4.0 from Progressive Networks also exhibits this problem. However they have fixed it in version 4.01 of the player, but version 4.01 uses the same User-Agent as version 4.0. The workaround is still:

BrowserMatch "RealPlayer 4.0" force-response-1.0

Requests use HTTP/1.1 but responses must be in HTTP/1.0

MSIE 4.0b2 has this problem. Its Java VM makes requests in HTTP/1.1 format but the responses must be in HTTP/1.0 format (in particular, it does not understand chunked responses). The workaround is to fool Apache into believing the request came in HTTP/1.0 format.

BrowserMatch "MSIE 4\.0b2;" downgrade-1.0 force-response-1.0

This workaround is available in 1.2.2, and in a patch against 1.2.1.

Boundary problems with header parsing

All versions of Navigator from 2.0 through 4.0b2 (and possibly later) have a problem if the trailing CRLF of the response header starts at offset 256, 257 or 258 of the response. A BrowserMatch for this would match on nearly every hit, so the workaround is enabled automatically on all responses. The workaround implemented detects when this condition would occur in a response and adds extra padding to the header to push the trailing CRLF past offset 258 of the response.

Multipart responses and Quoted Boundary Strings

On multipart responses some clients will not accept quotes (") around the boundary string. The MIME standard recommends that such quotes be used. But the clients were probably written based on one of the examples in RFC2068, which does not include quotes. Apache does not include quotes on its boundary strings to workaround this problem.

Byterange Requests

A byterange request is used when the client wishes to retrieve a portion of an object, not necessarily the entire object. There was a very old draft which included these byteranges in the URL. Old clients such as Navigator 2.0b1 and MSIE 3.0 for the MAC exhibit this behaviour, and it will appear in the servers' access logs as (failed) attempts to retrieve a URL with a trailing ";xxx-yyy". Apache does not attempt to implement this at all.

A subsequent draft of this standard defines a header Request-Range, and a response type multipart/x-byteranges. The HTTP/1.1 standard includes this draft with a few fixes, and it defines the header Range and type multipart/byteranges.

Navigator (versions 2 and 3) sends both Range and Request-Range headers (with the same value), but does not accept a multipart/byteranges response. The response must be multipart/x-byteranges. As a workaround, if Apache receives a Request-Range header it considers it "higher priority" than a Range header and in response uses multipart/x-byteranges.

The Adobe Acrobat Reader plugin makes extensive use of byteranges and prior to version 3.01 supports only the multipart/x-byterange response. Unfortunately there is no clue that it is the plugin making the request. If the plugin is used with Navigator, the above workaround works fine. But if the plugin is used with MSIE 3 (on Windows) the workaround won't work because MSIE 3 doesn't give the Range-Request clue that Navigator does. To workaround this, Apache special cases "MSIE 3" in the User-Agent and serves multipart/x-byteranges. Note that the necessity for this with MSIE 3 is actually due to the Acrobat plugin, not due to the browser.

Netscape Communicator appears to not issue the non-standard Request-Range header. When an Acrobat plugin prior to version 3.01 is used with it, it will not properly understand byteranges. The user must upgrade their Acrobat reader to 3.01.

Set-Cookie header is unmergeable

The HTTP specifications say that it is legal to merge headers with duplicate names into one (separated by commas). Some browsers that support Cookies don't like merged headers and prefer that each Set-Cookie header is sent separately. When parsing the headers returned by a CGI, Apache will explicitly avoid merging any Set-Cookie headers.

Expires headers and GIF89A animations

Navigator versions 2 through 4 will erroneously re-request GIF89A animations on each loop of the animation if the first response included an Expires header. This happens regardless of how far in the future the expiry time is set. There is no workaround supplied with Apache, however there are hacks for 1.2 and for 1.3.

POST without Content-Length

In certain situations Navigator 3.01 through 3.03 appear to incorrectly issue a POST without the request body. There is no known workaround. It has been fixed in Navigator 3.04, Netscapes provides some information. There's also some information about the actual problem.

JDK 1.2 betas lose parts of responses.

The http client in the JDK1.2beta2 and beta3 will throw away the first part of the response body when both the headers and the first part of the body are sent in the same network packet AND keep-alive's are being used. If either condition is not met then it works fine.

See also Bug-ID's 4124329 and 4125538 at the java developer connection.

If you are seeing this bug yourself, you can add the following BrowserMatch directive to work around it:

BrowserMatch "Java1\.2beta[23]" nokeepalive

We don't advocate this though since bending over backwards for beta software is usually not a good idea; ideally it gets fixed, new betas or a final release comes out, and no one uses the broken old software anymore. In theory.

Content-Type change is not noticed after reload

Navigator (all versions?) will cache the content-type for an object "forever". Using reload or shift-reload will not cause Navigator to notice a content-type change. The only work-around is for the user to flush their caches (memory and disk). By way of an example, some folks may be using an old mime.types file which does not map .htm to text/html, in this case Apache will default to sending text/plain. If the user requests the page and it is served as text/plain. After the admin fixes the server, the user will have to flush their caches before the object will be shown with the correct text/html type.

MSIE Cookie problem with expiry date in the year 2000

MSIE versions 3.00 and 3.02 (without the Y2K patch) do not handle cookie expiry dates in the year 2000 properly. Years after 2000 and before 2000 work fine. This is fixed in IE4.01 service pack 1, and in the Y2K patch for IE3.02. Users should avoid using expiry dates in the year 2000.

Lynx incorrectly asking for transparent content negotiation

The Lynx browser versions 2.7 and 2.8 send a "negotiate: trans" header in their requests, which is an indication the browser supports transparent content negotiation (TCN). However the browser does not support TCN. As of version 1.3.4, Apache supports TCN, and this causes problems with these versions of Lynx. As a workaround future versions of Apache will ignore this header when sent by the Lynx client.

MSIE 4.0 mishandles Vary response header

MSIE 4.0 does not handle a Vary header properly. The Vary header is generated by mod_rewrite in apache 1.3. The result is an error from MSIE saying it cannot download the requested file. There are more details in PR#4118.

A workaround is to add the following to your server's configuration files:

BrowserMatch "MSIE 4\.0" force-no-vary

(This workaround is only available with releases after 1.3.6 of the Apache Web server.)


Descriptors and Apache - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

Descriptors and Apache

Warning:

This document has not been fully updated to take into account changes made in the 2.0 version of the Apache HTTP Server. Some of the information may still be relevant, but please use it with care.

A descriptor, also commonly called a file handle is an object that a program uses to read or write an open file, or open network socket, or a variety of other devices. It is represented by an integer, and you may be familiar with stdin, stdout, and stderr which are descriptors 0, 1, and 2 respectively. Apache needs a descriptor for each log file, plus one for each network socket that it listens on, plus a handful of others. Libraries that Apache uses may also require descriptors. Normal programs don't open up many descriptors at all, and so there are some latent problems that you may experience should you start running Apache with many descriptors (i.e., with many virtual hosts).

The operating system enforces a limit on the number of descriptors that a program can have open at a time. There are typically three limits involved here. One is a kernel limitation, depending on your operating system you will either be able to tune the number of descriptors available to higher numbers (this is frequently called FD_SETSIZE). Or you may be stuck with a (relatively) low amount. The second limit is called the hard resource limit, and it is sometimes set by root in an obscure operating system file, but frequently is the same as the kernel limit. The third limit is called the soft resource limit. The soft limit is always less than or equal to the hard limit. For example, the hard limit may be 1024, but the soft limit only 64. Any user can raise their soft limit up to the hard limit. Root can raise the hard limit up to the system maximum limit. The soft limit is the actual limit that is used when enforcing the maximum number of files a process can have open.

To summarize:

#open files <= soft limit <= hard limit <= kernel limit

You control the hard and soft limits using the limit (csh) or ulimit (sh) directives. See the respective man pages for more information. For example you can probably use ulimit -n unlimited to raise your soft limit up to the hard limit. You should include this command in a shell script which starts your webserver.

Unfortunately, it's not always this simple. As mentioned above, you will probably run into some system limitations that will need to be worked around somehow. Work was done in version 1.2.1 to improve the situation somewhat. Here is a partial list of systems and workarounds (assuming you are using 1.2.1 or later).

BSDI 2.0

Under BSDI 2.0 you can build Apache to support more descriptors by adding -DFD_SETSIZE=nnn to EXTRA_CFLAGS (where nnn is the number of descriptors you wish to support, keep it less than the hard limit). But it will run into trouble if more than approximately 240 Listen directives are used. This may be cured by rebuilding your kernel with a higher FD_SETSIZE.

FreeBSD 2.2, BSDI 2.1+

Similar to the BSDI 2.0 case, you should define FD_SETSIZE and rebuild. But the extra Listen limitation doesn't exist.

Linux

By default Linux has a kernel maximum of 256 open descriptors per process. There are several patches available for the 2.0.x series which raise this to 1024 and beyond, and you can find them in the "unofficial patches" section of the Linux Information HQ. None of these patches are perfect, and an entirely different approach is likely to be taken during the 2.1.x development. Applying these patches will raise the FD_SETSIZE used to compile all programs, and unless you rebuild all your libraries you should avoid running any other program with a soft descriptor limit above 256. As of this writing the patches available for increasing the number of descriptors do not take this into account. On a dedicated webserver you probably won't run into trouble.

Solaris through 2.5.1

Solaris has a kernel hard limit of 1024 (may be lower in earlier versions). But it has a limitation that files using the stdio library cannot have a descriptor above 255. Apache uses the stdio library for the ErrorLog directive. When you have more than approximately 110 virtual hosts (with an error log and an access log each) you will need to build Apache with -DHIGH_SLACK_LINE=256 added to EXTRA_CFLAGS. You will be limited to approximately 240 error logs if you do this.

AIX

AIX version 3.2?? appears to have a hard limit of 128 descriptors. End of story. Version 4.1.5 has a hard limit of 2000.

SCO OpenServer

Edit the /etc/conf/cf.d/stune file or use /etc/conf/cf.d/configure choice 7 (User and Group configuration) and modify the NOFILES kernel parameter to a suitably higher value. SCO recommends a number between 60 and 11000, the default is 110. Relink and reboot, and the new number of descriptors will be available.

Compaq Tru64 UNIX/Digital UNIX/OSF

  1. Raise open_max_soft and open_max_hard to 4096 in the proc subsystem. Do a man on sysconfig, sysconfigdb, and sysconfigtab.
  2. Raise max-vnodes to a large number which is greater than the number of apache processes * 4096 (Setting it to 250,000 should be good for most people). Do a man on sysconfig, sysconfigdb, and sysconfigtab.
  3. If you are using Tru64 5.0, 5.0A, or 5.1, define NO_SLACK to work around a bug in the OS. CFLAGS="-DNO_SLACK" ./configure

Others

If you have details on another operating system, please submit it through our Bug Report Page.

In addition to the problems described above there are problems with many libraries that Apache uses. The most common example is the bind DNS resolver library that is used by pretty much every unix, which fails if it ends up with a descriptor above 256. We suspect there are other libraries that similar limitations. So the code as of 1.2.1 takes a defensive stance and tries to save descriptors less than 16 for use while processing each request. This is called the low slack line.

Note that this shouldn't waste descriptors. If you really are pushing the limits and Apache can't get a descriptor above 16 when it wants it, it will settle for one below 16.

In extreme situations you may want to lower the low slack line, but you shouldn't ever need to. For example, lowering it can increase the limits 240 described above under Solaris and BSDI 2.0. But you'll play a delicate balancing game with the descriptors needed to serve a request. Should you want to play this game, the compile time parameter is LOW_SLACK_LINE and there's a tiny bit of documentation in the header file httpd.h.

Finally, if you suspect that all this slack stuff is causing you problems, you can disable it. Add -DNO_SLACK to EXTRA_CFLAGS and rebuild. But please report it to our Bug Report Page so that we can investigate.


관련 표준 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Miscellaneous Documentation

관련 표준

이 문서에는 간단한 설명과 함께 아파치 웹서버가 따르는 모든 관련 표준을 열거한다.

아래 정보에 더하여 다음 자료도 살펴봐야 한다:

  • http://purl.org/NET/http-errata - HTTP/1.1 규약 정오표
  • http://www.rfc-editor.org/errata.html - RFC 정오표
  • http://ftp.ics.uci.edu/pub/ietf/http/#RFC - HTTP 관련 RFC 목록

주의

이 문서는 아직 완전하지 않다.

HTTP 권고

어떤 모듈을 컴파일하고 사용하는지와 관계없이 기본적으로 웹서버인 아파치는 다음 IETF 권고(recommendation)를 따른다:

RFC 1945 (Informational)
하이퍼텍스트 전송 프로토콜 (Hypertext Transfer Protocol, HTTP)은 분산, 협동, 하이퍼매체 정보 시스템에 필요한 빠르고 가벼운 어플리케이션 수준(application-level) 프로토콜이다. 이 문서는 HTTP/1.0을 설명한다.
RFC 2616 (Standards Track)
하이퍼텍스트 전송 프로토콜 (Hypertext Transfer Protocol, HTTP)은 분산, 협동, 하이퍼매체 정보 시스템을 위한 어플리케이션 수준 프로토콜이다. 이 문서는 HTTP/1.1을 설명한다.
RFC 2396 (Standards Track)
표준 자원 식별자 (Uniform Resource Identifier, URI)는 추상적 혹은 물리적 자원을 식별하기위한 짧은 문자열이다.

HTML 권고

하이퍼텍스트 마크업 언어 (Hypertext Markup Language, HTML)와 관련하여 아파치는 다음 IETF 권고와 W3C 권고를 따른다:

RFC 2854 (Informational)
이 문서는 HTML 개발과정을 요약하고, 관련 W3C 권고를 기반으로 "text/html" MIME type을 정의한다.
HTML 4.01 규약 (Errata)
이 규약은 월드와이드웹의 출판언어인 하이퍼텍스트 마크업 언어 (Hypertext Markup Language, HTML)를 정의한다. 이 규약은 HTML 4의 하위버전인 HTML 4.01을 정의한다.
HTML 3.2 참고 규약
하이퍼텍스트 마크업 언어 (Hypertext Markup Language, HTML)는 플래폼과 무관한 하이퍼텍스트 문서를 위한 간단한 마크업 언어이다. HTML 문서는 SGML 문서이기도 하다.
XHTML 1.1 - 모듈기반 XHTML (정오표)
이 권고는 Modularization of XHTML에서 정의한 모듈 플레임워크와 모듈들을 기반으로 새로운 XHTML document type을 정의한다.
XHTML 1.0 확장 하이퍼텍스트 마크업 언어 (Extensible HyperText Markup Language) (Second Edition) (정오표)
이 문서는 HTML 4를 XML 1.0으로 재구성한 XHTML 1.0의 두번째 버전과 HTML 4에 해당하는 세가지 DTD를 정의한다.

인증

인증방법에 대해 아파치는 다음 IETF 권고를 따른다:

RFC 2617 (Draft standard)
Basic Access Authentication 규약을 포함한 "HTTP/1.0".

언어/국가 코드

아래 링크에 ISO와 다른 언어/국가 코드 정보가 있다:

ISO 639-2
ISO 639는 언어의 이름을 나타내는 두가지 언어 코드를 제공한다. 하나는 (639-1) 두 글자 코드이고 다른 하나는 (이 문서) 세 글자 코드이다.
ISO 3166-1
이 문서는 ISO 3166-1과 ISO 3166-1-alpha-2 코드에 따라 알파벳 순서로 (영어로 짧은 공식이름) 국가명을 열거한다.
BCP 47 (Best Current Practice), RFC 3066
이 문서는 정보 객체에 사용한 언어를 알리기위해 사용할 언어 태그와 언어 태그에 사용할 값을 등록하는 방법, 언어 태그를 찾는 방식을 설명한다.
RFC 3282 (Standards Track)
이 문서는 MIME 내용 부분과 웹 문서와 같은 RFC 822식 헤더가 있는 정보의 언어를 알리기위한 "Content-language:" 헤더와, 선호하는 언어를 나타내는 "Accept-Language:" 헤더를 정의한다.


모듈을 설명하기위해 사용한 용어들 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

모듈을 설명하기위해 사용한 용어들

이 문서는 아파치 모듈을 설명하기위해 사용한 용어를 설명한다.

설명

모듈 목적에 대한 간단한 설명.

상태

모듈이 아파치 웹서버와 얼마나 밀접히 연관되있는지 나타낸다. 즉, 특정 모듈과 모듈의 기능을 사용하기위해서 서버를 다시 컴파일해야 할 경우가 있다. 이 속성의 값은:

MPM
상태가 "MPM"인 모듈은 다중처리 모듈이다. 다른 종류의 모듈과 달리 아파치는 오직 한 MPM만을 사용한다. 이런 종류의 모듈은 기본적인 요청 처리와 분배를 담당한다.
Base
상태가 "Base"인 모듈은 기본적으로 서버와 같이 컴파일되므로, 설정에서 모듈을 제거하지 않는 한 보통 사용할 수 있다.
Extension
상태가 "Extension"인 모듈은 보통 서버와 같이 컴파일되지 않는다. 모듈과 모듈의 기능을 사용하려면 서버 컴파일 구성파일을 변경하고 아파치를 다시 컴파일해야 한다.
Experimental
"Experimental" 상태는 모듈이 아파치 배포본에 포함되있지만, 사용하려면 위험을 감수해야 한다. 모듈에 대한 문서가 있지만, 모듈을 지원한다는 말은 아니다.
External
"External" 상태는 기본 아파치 배포본에 포함되지 않은 모듈("제삼자가 만든 모듈")이다. 우리는 이런 모듈에 책임이 없고 지원하지도 않는다.

소스파일

간단하게 말해서 모듈 소스코드가 있는 소스파일명이다. <IfModule> 지시어에서 사용하는 이름이기도 하다.

모듈명

모듈을 지칭하는 문자열로, 모듈을 동적으로 읽어들이는 LoadModule 지시어에서 사용한다. 정확히 말하면 소스파일에서 module 형의 외부변수 이름이다.

지원

모듈이 원래 아파치 버전 2 배포본에 포함되지 않았다면, 모듈을 처음 소개한 버전을 알려준다. 또, 모듈이 특정 플래폼용이라면 상세히 설명한다.


지시어를 설명하는데 사용한 용어들 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

지시어를 설명하는데 사용한 용어들

이 문서는 아파치 설정 지시어를 설명하는데 사용한 용어들을 설명한다.

참고

  • 설정파일

설명 (Description)

지시어의 목적에 대한 간단한 설명.

문법 (Syntax)

설정파일에서 사용할 지시어의 형식을 알려준다. 이 문법은 지시어마다 매우 다르며, 지시어를 정의할 때마다 자세히 설명한다. 일반적으로 지시어 이름 뒤에 공백으로 구분한 아규먼트들이 나온다. 아규먼트가 공백을 포함한다면 아규먼트를 쌍따옴표로 묶어야 한다. 선택적인 아규먼트는 중괄호로 묶는다. 아규먼트가 여러 값중 하나일 경우 값들을 수직막대 "|"로 구분한다. 문자그대로 사용할 부분은 기본 문자체로 쓰고, 대체할 아규먼트는 강조한다. 아규먼트 개수가 정해지지않은 지시어는 마지막 아규먼트가 반복됨을 나타내는 "..."으로 끝난다.

지시어는 매우 다양한 종류의 아규먼트를 받는다. 이중 자주 사용하는 것은 아래와 같다.

URL
http://www.example.com/path/to/file.html과 같이 스킴(scheme), 호스트명, 선택적인 경로명을 포함한 완전한 Uniform Resource Locator
URL-path
/path/to/file.html과 같이 url에서 스킴과 호스트명 뒤에 나오는 부분. url-path는 파일시스템에서 본 시점이 아닌 웹에서 본 시점에서의 자료를 나타낸다.
file-path
/usr/local/apache/htdocs/path/to/file.html과 같이 root 디렉토리로 시작하는 파일시스템상의 파일 경로. 따로 언급하지않으면, 슬래쉬로 시작하지않은 file-path는 ServerRoot에 상대경로로 취급한다.
directory-path
/usr/local/apache/htdocs/path/to/와 같이 root 디렉토리로 시작하는 파일시스템상의 디렉토리 경로.
filename
file.html과 같이 경로 정보가 없는 파일명.
regex
Perl 형식의 정규표현식(regular expression). 지시어는 regex로 무엇인가를 검색한다.
extension
일반적으로 filename에서 마지막 마침표 뒤에 나오는 부분이다. 그러나 아파치는 여러 확장자를 인식할 수 있기때문에, filename에 마침표가 여러개 포함된 경우 마침표로 구분된 모든 부분을 확장자(extension)로 처리한다. 예를 들어, 파일명 file.html.en은 .html과 .en이라는 두가지 확장자를 가진다. 아파치 지시어에서 extension에 지정한 값 앞에 마침표가 있어도 되고 없어도 된다. 또, extension은 대소문자를 가리지않는다.
MIME-type
text/html과 같이 슬래쉬로 major format type과 minor format type를 구분하여 파일의 형식을 설명하는 방식.
env-variable
아파치 설정에서 정의한 환경변수 이름. 운영체제의 환경변수와 다름을 주의하라. 자세한 내용은 환경변수 문서를 참고하라.

기본값 (Default)

지시어에 기본값이 있다면 (예를 들어, 설정에서 지시어를 생략한 경우 아파치 웹서버는 이 값을 사용한다.) 이 항목에 나온다. 기본값이 없다면 이 항목은 "None"이어야 한다. 기본값이 서버에 포함된 기본 httpd.conf의 지시어 값과 다를 수 있음을 주의하라.

사용장소 (Context)

서버의 설정파일중 어느곳에서 지시어를 사용할 수 있는지 알려준다. 다음 값들을 쉼표로 구분한 목록이다:

주서버설정 (server config)
지시어를 서버 설정파일에서 (예를 들어, httpd.conf) 사용할 수 있으나, <VirtualHost>나 <Directory>에서 사용할 수 없음을 뜻한다. 이 지시어는 .htaccess 파일에서도 사용할 수 없다.
가상호스트 (virtual host)
지시어를 서버 설정파일의 <VirtualHost> 안에서 사용할 수 있음을 뜻한다.
디렉토리 (directory)
지시어가 어떻게 Directory, Location, Files 섹션이 동작하나에 설명한 제약을 따르며, 서버 설정파일의 <Directory>, <Location>, <Files>에서 사용할 수 있음을 뜻한다.
.htaccess
지시어를 디렉토리별 .htaccess 파일에서 사용할 수 있음을 뜻한다. 이 지시어는 현재 사용하는 overrides 값에 따라 무시될 수 있다.

지시어는 지정된 장소에서만 사용할 수 있다. 다른 곳에서 사용하면 설정오류가 발생하고 서버는 부분에 대한 요청을 올바로 처리하지 못하거나 작동이, 예를 들어 시작조차도, 안될 수 있다.

지시어를 사용할 수 있는 장소는 열거한 장소를 모두 불린(boolean) OR한 결과이다. 즉, "server config, .htaccess"에서 가능하다는 지시어는 httpd.conf 파일과 .htaccess 파일에서는 사용할 수 있지만, <Directory>나 <VirtualHost>에서는 사용할 수 없다.

Override 옵션 (Override)

이 지시어를 .htaccess 파일에서 사용하려면 어떤 override 옵션을 사용해야 하는지를 나타낸다. 지시어의 사용장소가 지시어를 .htaccess 파일에서 사용할 수 없다고 한다면 어떤 사용장소도 나오지 않는다.

Overrides는 AllowOverride 지시어로 지시하고, (디렉토리 등의) 특정 범위와 하위 범위에서 다른 AllowOverride 지시어로 다른 값을 설정하지않았다면 하위 범위에도 그대로 적용된다. 지시어 설명에 사용가능한 override 이름들이 나온다.

상태 (Status)

지시어가 아파치 웹서버에 얼마나 긴밀히 묶여있는지를 나타낸다. 즉, 그 지시어나 기능을 사용하기위해 서버를 모듈과 같이 다시 컴파일할 필요가 있을 수도 있다. 가능한 값은 다음과 같다:

Core
지시어가 "Core" 상태를 가지면, 지시어가 아파치 웹서버 핵심부분에 속하고 항상 사용가능함을 뜻한다.
MPM
"MPM" 상태인 지시어는 다중처리 모듈을 제공한다. 이런 지시어는 지시어 설명에서 모듈에 열거된 MPM중 하나를 사용할때만 가능하다.
Base
기본적으로 서버와 같이 컴파일되므로 직접 구성에서 모듈을 제거하지 않았다면 일반적으로 사용가능한 표준 아파치 모듈이 제공하는 지시어는 "Base" 상태이다.
Extension
아파치 서버 배포본에는 포함되있지만 보통 서버와 같이 컴파일되지않는 모듈이 제공하는 지시어는 "Extension" 상태이다. 이런 지시어를 사용하려면 서버 컴파일 구성파일을 수정하고 아파치를 다시 컴파일해야 한다.
Experimental
"Experimental"은 지시어가 아파치 배포본에 포함되있지만, 사용은 자신의 책임임을 나타낸다. 지시어는 문서화되있지만, 실제와 다를 수 있다. 지시어를 제공하는 모듈은 기본적으로 아파치와 같이 컴파일될 수도 안될 수도 있다. 지시어와 모듈을 설명하는 문서 앞에서 사용할 수 있는지 살펴봐라.

모듈 (Module)

단순히 지시어를 정의한 소스 모듈명을 열거한다.

지원 (Compatibility)

지시어가 원래 아파치 버전 2 배포본의 일부가 아니였다면, 지시어를 추가하기 시작한 버전이 여기 나온다. 또, 어떤 플래폼에서만 사용가능한 지시어도 여기 나온다.


core - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Core Features

Description: | Core Apache HTTP Server features that are always available
Status: | Core

AcceptPathInfo Directive

Description: | Resources accept trailing pathname information
Syntax: | AcceptPathInfo On|Off|Default
Default: | AcceptPathInfo Default
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core
Compatibility: | Available in Apache 2.0.30 and later

This directive controls whether requests that contain trailing pathname information that follows an actual filename (or non-existent file in an existing directory) will be accepted or rejected. The trailing pathname information can be made available to scripts in the PATH_INFO environment variable.

For example, assume the location /test/ points to a directory that contains only the single file here.html. Then requests for /test/here.html/more and /test/nothere.html/more both collect /more as PATH_INFO.

The three possible arguments for the AcceptPathInfo directive are:

Off
A request will only be accepted if it maps to a literal path that exists. Therefore a request with trailing pathname information after the true filename such as /test/here.html/more in the above example will return a 404 NOT FOUND error.
On
A request will be accepted if a leading path component maps to a file that exists. The above example /test/here.html/more will be accepted if /test/here.html maps to a valid file.
Default
The treatment of requests with trailing pathname information is determined by the handler responsible for the request. The core handler for normal files defaults to rejecting PATH_INFO requests. Handlers that serve scripts, such as cgi-script and isapi-isa, generally accept PATH_INFO by default.

The primary purpose of the AcceptPathInfo directive is to allow you to override the handler's choice of accepting or rejecting PATH_INFO. This override is required, for example, when you use a filter, such as INCLUDES, to generate content based on PATH_INFO. The core handler would usually reject the request, so you can use the following configuration to enable such a script:

<Files "mypaths.shtml">
Options +Includes
SetOutputFilter INCLUDES
AcceptPathInfo On
 </Files>

AccessFileName Directive

Description: | Name of the distributed configuration file
Syntax: | AccessFileName filename [filename] ...
Default: | AccessFileName .htaccess
Context: | server config, virtual host
Status: | Core
Module: | core

While processing a request the server looks for the first existing configuration file from this list of names in every directory of the path to the document, if distributed configuration files are enabled for that directory. For example:

AccessFileName .acl

before returning the document /usr/local/web/index.html, the server will read /.acl, /usr/.acl, /usr/local/.acl and /usr/local/web/.acl for directives, unless they have been disabled with

<Directory />
AllowOverride None
 </Directory>

See also

  • AllowOverride
  • Configuration Files
  • .htaccess Files

AddDefaultCharset Directive

Description: | Default charset parameter to be added when a response content-type is text/plain or text/html
Syntax: | AddDefaultCharset On|Off|charset
Default: | AddDefaultCharset Off
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core

This directive specifies a default value for the media type charset parameter (the name of a character encoding) to be added to a response if and only if the response's content-type is either text/plain or text/html. This should override any charset specified in the body of the response via a META element, though the exact behavior is often dependent on the user's client configuration. A setting of AddDefaultCharset Off disables this functionality. AddDefaultCharset On enables a default charset of iso-8859-1. Any other value is assumed to be the charset to be used, which should be one of the IANA registered charset values for use in MIME media types. For example:

AddDefaultCharset utf-8

AddDefaultCharset should only be used when all of the text resources to which it applies are known to be in that character encoding and it is too inconvenient to label their charset individually. One such example is to add the charset parameter to resources containing generated content, such as legacy CGI scripts, that might be vulnerable to cross-site scripting attacks due to user-provided data being included in the output. Note, however, that a better solution is to just fix (or delete) those scripts, since setting a default charset does not protect users that have enabled the "auto-detect character encoding" feature on their browser.

See also

  • AddCharset

AddOutputFilterByType Directive

Description: | assigns an output filter to a particular MIME-type
Syntax: | AddOutputFilterByType filter[;filter...] MIME-type [MIME-type] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core
Compatibility: | Available in Apache 2.0.33 and later

This directive activates a particular output filter for a request depending on the response MIME-type.

The following example uses the DEFLATE filter, which is provided by mod_deflate. It will compress all output (either static or dynamic) which is labeled as text/html or text/plain before it is sent to the client.

AddOutputFilterByType DEFLATE text/html text/plain

If you want the content to be processed by more than one filter, their names have to be separated by semicolons. It's also possible to use one AddOutputFilterByType directive for each of these filters.

The configuration below causes all script output labeled as text/html to be processed at first by the INCLUDES filter and then by the DEFLATE filter.

<Location /cgi-bin/>
Options Includes
AddOutputFilterByType INCLUDES;DEFLATE text/html
 </Location>

Note

Enabling filters with AddOutputFilterByType may fail partially or completely in some cases. For example, no filters are applied if the MIME-type could not be determined and falls back to the DefaultType setting, even if the DefaultType is the same.

However, if you want to make sure, that the filters will be applied, assign the content type to a resource explicitly, for example with AddType or ForceType. Setting the content type within a (non-nph) CGI script is also safe.

The by-type output filters are never applied on proxy requests.

See also

  • AddOutputFilter
  • SetOutputFilter
  • filters

AllowEncodedSlashes Directive

Description: | Determines whether encoded path separators in URLs are allowed to be passed through
Syntax: | AllowEncodedSlashes On|Off
Default: | AllowEncodedSlashes Off
Context: | server config, virtual host
Status: | Core
Module: | core
Compatibility: | Available in Apache 2.0.46 and later

The AllowEncodedSlashes directive allows URLs which contain encoded path separators (%2F for / and additionally %5C for \ on according systems) to be used. Normally such URLs are refused with a 404 (Not found) error.

Turning AllowEncodedSlashes On is mostly useful when used in conjunction with PATH_INFO.

Note

Allowing encoded slashes does not imply decoding. Occurrences of %2F or %5C (only on according systems) will be left as such in the otherwise decoded URL string.

See also

  • AcceptPathInfo

AllowOverride Directive

Description: | Types of directives that are allowed in .htaccess files
Syntax: | AllowOverride All|None|directive-type [directive-type] ...
Default: | AllowOverride All
Context: | directory
Status: | Core
Module: | core

When the server finds an .htaccess file (as specified by AccessFileName) it needs to know which directives declared in that file can override earlier configuration directives.

Only available in <Directory> sections

AllowOverride is valid only in <Directory> sections specified without regular expressions, not in <Location>, <DirectoryMatch> or <Files> sections.

When this directive is set to None, then .htaccess files are completely ignored. In this case, the server will not even attempt to read .htaccess files in the filesystem.

When this directive is set to All, then any directive which has the .htaccess Context is allowed in .htaccess files.

The directive-type can be one of the following groupings of directives.

AuthConfig
Allow use of the authorization directives (AuthDBMGroupFile, AuthDBMUserFile, AuthGroupFile, AuthName, AuthType, AuthUserFile, Require, etc.).
FileInfo
Allow use of the directives controlling document types (DefaultType, ErrorDocument, ForceType, LanguagePriority, SetHandler, SetInputFilter, SetOutputFilter, and mod_mime Add* and Remove* directives, etc.).
Indexes
Allow use of the directives controlling directory indexing (AddDescription, AddIcon, AddIconByEncoding, AddIconByType, DefaultIcon, DirectoryIndex, FancyIndexing, HeaderName, IndexIgnore, IndexOptions, ReadmeName, etc.).
Limit
Allow use of the directives controlling host access (Allow, Deny and Order).
Options
Allow use of the directives controlling specific directory features (Options and XBitHack).

Example:

AllowOverride AuthConfig Indexes

In the example above all directives that are neither in the group AuthConfig nor Indexes cause an internal server error.

See also

  • AccessFileName
  • Configuration Files
  • .htaccess Files

AuthName Directive

Description: | Authorization realm for use in HTTP authentication
Syntax: | AuthName auth-domain
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Core
Module: | core

This directive sets the name of the authorization realm for a directory. This realm is given to the client so that the user knows which username and password to send. AuthName takes a single argument; if the realm name contains spaces, it must be enclosed in quotation marks. It must be accompanied by AuthType and Require directives, and directives such as AuthUserFile and AuthGroupFile to work.

For example:

AuthName "Top Secret"

The string provided for the AuthName is what will appear in the password dialog provided by most browsers.

See also

  • Authentication, Authorization, and Access Control

AuthType Directive

Description: | Type of user authentication
Syntax: | AuthType Basic|Digest
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Core
Module: | core

This directive selects the type of user authentication for a directory. Only Basic and Digest are currently implemented. It must be accompanied by AuthName and Require directives, and directives such as AuthUserFile and AuthGroupFile to work.

See also

  • Authentication, Authorization, and Access Control

CGIMapExtension Directive

Description: | Technique for locating the interpreter for CGI scripts
Syntax: | CGIMapExtension cgi-path .extension
Context: | directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core
Compatibility: | NetWare only

This directive is used to control how Apache finds the interpreter used to run CGI scripts. For example, setting CGIMapExtension sys:\foo.nlm .foo will cause all CGI script files with a .foo extension to be passed to the FOO interpreter.

ContentDigest Directive

Description: | Enables the generation of Content-MD5 HTTP Response headers
Syntax: | ContentDigest On|Off
Default: | ContentDigest Off
Context: | server config, virtual host, directory, .htaccess
Override: | Options
Status: | Core
Module: | core

This directive enables the generation of Content-MD5 headers as defined in RFC1864 respectively RFC2068.

MD5 is an algorithm for computing a "message digest" (sometimes called "fingerprint") of arbitrary-length data, with a high degree of confidence that any alterations in the data will be reflected in alterations in the message digest.

The Content-MD5 header provides an end-to-end message integrity check (MIC) of the entity-body. A proxy or client may check this header for detecting accidental modification of the entity-body in transit. Example header:

Content-MD5: AuLb7Dp1rqtRtxz2m9kRpA==

Note that this can cause performance problems on your server since the message digest is computed on every request (the values are not cached).

Content-MD5 is only sent for documents served by the core, and not by any module. For example, SSI documents, output from CGI scripts, and byte range responses do not have this header.

DefaultType Directive

Description: | MIME content-type that will be sent if the server cannot determine a type in any other way
Syntax: | DefaultType MIME-type
Default: | DefaultType text/plain
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core

There will be times when the server is asked to provide a document whose type cannot be determined by its MIME types mappings.

The server must inform the client of the content-type of the document, so in the event of an unknown type it uses the DefaultType. For example:

DefaultType image/gif

would be appropriate for a directory which contained many GIF images with filenames missing the .gif extension.

Note that unlike ForceType, this directive only provides the default mime-type. All other mime-type definitions, including filename extensions, that might identify the media type will override this default.

<Directory> Directive

Description: | Enclose a group of directives that apply only to the named file-system directory and sub-directories
Syntax: | <Directory directory-path> ... </Directory>
Context: | server config, virtual host
Status: | Core
Module: | core

<Directory> and </Directory> are used to enclose a group of directives that will apply only to the named directory and sub-directories of that directory. Any directive that is allowed in a directory context may be used. Directory-path is either the full path to a directory, or a wild-card string using Unix shell-style matching. In a wild-card string, ? matches any single character, and * matches any sequences of characters. You may also use [] character ranges. None of the wildcards match a `/' character, so <Directory /*/public_html> will not match /home/user/public_html, but <Directory /home/*/public_html> will match. Example:

<Directory /usr/local/httpd/htdocs>
Options Indexes FollowSymLinks
 </Directory>

Be careful with the directory-path arguments: They have to literally match the filesystem path which Apache uses to access the files. Directives applied to a particular <Directory> will not apply to files accessed from that same directory via a different path, such as via different symbolic links.

Extended regular expressions can also be used, with the addition of the ~ character. For example:

<Directory ~ "^/www/.*/[0-9]{3}">

would match directories in /www/ that consisted of three numbers.

If multiple (non-regular expression) <Directory> sections match the directory (or one of its parents) containing a document, then the directives are applied in the order of shortest match first, interspersed with the directives from the .htaccess files. For example, with

<Directory />
AllowOverride None
 </Directory>

<Directory /home/>
AllowOverride FileInfo
 </Directory>

for access to the document /home/web/dir/doc.html the steps are:

  • Apply directive AllowOverride None (disabling .htaccess files).
  • Apply directive AllowOverride FileInfo (for directory /home).
  • Apply any FileInfo directives in /home/.htaccess, /home/web/.htaccess and /home/web/dir/.htaccess in that order.

Regular expressions are not considered until after all of the normal sections have been applied. Then all of the regular expressions are tested in the order they appeared in the configuration file. For example, with

<Directory ~ abc$>
# ... directives here ...
 </Directory>

the regular expression section won't be considered until after all normal <Directory>s and .htaccess files have been applied. Then the regular expression will match on /home/abc/public_html/abc and the corresponding <Directory> will be applied.

Note that the default Apache access for <Directory /> is Allow from All. This means that Apache will serve any file mapped from an URL. It is recommended that you change this with a block such as

<Directory />
Order Deny,Allow
Deny from All
 </Directory>

and then override this for directories you want accessible. See the Security Tips page for more details.

The directory sections occur in the httpd.conf file. <Directory> directives cannot nest, and cannot appear in a <Limit> or <LimitExcept> section.

See also

  • How <Directory>, <Location> and <Files> sections work for an explanation of how these different sections are combined when a request is received

<DirectoryMatch> Directive

Description: | Enclose directives that apply to file-system directories matching a regular expression and their subdirectories
Syntax: | <DirectoryMatch regex> ... </DirectoryMatch>
Context: | server config, virtual host
Status: | Core
Module: | core

<DirectoryMatch> and </DirectoryMatch> are used to enclose a group of directives which will apply only to the named directory and sub-directories of that directory, the same as <Directory>. However, it takes as an argument a regular expression. For example:

<DirectoryMatch "^/www/(.+/)?[0-9]{3}">

would match directories in /www/ that consisted of three numbers.

See also

  • <Directory> for a description of how regular expressions are mixed in with normal <Directory>s
  • How <Directory>, <Location> and <Files> sections work for an explanation of how these different sections are combined when a request is received

DocumentRoot Directive

Description: | Directory that forms the main document tree visible from the web
Syntax: | DocumentRoot directory-path
Default: | DocumentRoot /usr/local/apache/htdocs
Context: | server config, virtual host
Status: | Core
Module: | core

This directive sets the directory from which httpd will serve files. Unless matched by a directive like Alias, the server appends the path from the requested URL to the document root to make the path to the document. Example:

DocumentRoot /usr/web

then an access to http://www.my.host.com/index.html refers to /usr/web/index.html.

The DocumentRoot should be specified without a trailing slash.

See also

  • Mapping URLs to Filesystem Location

EnableMMAP Directive

Description: | Use memory-mapping to read files during delivery
Syntax: | EnableMMAP On|Off
Default: | EnableMMAP On
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core

This directive controls whether the httpd may use memory-mapping if it needs to read the contents of a file during delivery. By default, when the handling of a request requires access to the data within a file -- for example, when delivering a server-parsed file using mod_include -- Apache memory-maps the file if the OS supports it.

This memory-mapping sometimes yields a performance improvement. But in some environments, it is better to disable the memory-mapping to prevent operational problems:

  • On some multiprocessor systems, memory-mapping can reduce the performance of the httpd.
  • With an NFS-mounted DocumentRoot, the httpd may crash due to a segmentation fault if a file is deleted or truncated while the httpd has it memory-mapped.

For server configurations that are vulnerable to these problems, you should disable memory-mapping of delivered files by specifying:

EnableMMAP Off

For NFS mounted files, this feature may be disabled explicitly for the offending files by specifying:

<Directory "/path-to-nfs-files"> EnableMMAP Off </Directory>

EnableSendfile Directive

Description: | Use the kernel sendfile support to deliver files to the client
Syntax: | EnableSendfile On|Off
Default: | EnableSendfile On
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core
Compatibility: | Available in version 2.0.44 and later

This directive controls whether httpd may use the sendfile support from the kernel to transmit file contents to the client. By default, when the handling of a request requires no access to the data within a file -- for example, when delivering a static file -- Apache uses sendfile to deliver the file contents without ever reading the file if the OS supports it.

This sendfile mechanism avoids separate read and send operations, and buffer allocations. But on some platforms or within some filesystems, it is better to disable this feature to avoid operational problems:

  • Some platforms may have broken sendfile support that the build system did not detect, especially if the binaries were built on another box and moved to such a machine with broken sendfile support.
  • On Linux the use of sendfile triggers TCP-checksum offloading bugs on certain networking cards when using IPv6.
  • With a network-mounted DocumentRoot (e.g., NFS or SMB), the kernel may be unable to serve the network file through its own cache.

For server configurations that are vulnerable to these problems, you should disable this feature by specifying:

EnableSendfile Off

For NFS or SMB mounted files, this feature may be disabled explicitly for the offending files by specifying:

<Directory "/path-to-nfs-files"> EnableSendfile Off </Directory>

ErrorDocument Directive

Description: | What the server will return to the client in case of an error
Syntax: | ErrorDocument error-code document
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core
Compatibility: | Quoting syntax for text messages is different in Apache 2.0

In the event of a problem or error, Apache can be configured to do one of four things,

  1. output a simple hardcoded error message
  2. output a customized message
  3. redirect to a local URL-path to handle the problem/error
  4. redirect to an external URL to handle the problem/error

The first option is the default, while options 2-4 are configured using the ErrorDocument directive, which is followed by the HTTP response code and a URL or a message. Apache will sometimes offer additional information regarding the problem/error.

URLs can begin with a slash (/) for local web-paths (relative to the DocumentRoot), or be a full URL which the client can resolve. Alternatively, a message can be provided to be displayed by the browser. Examples:

ErrorDocument 500 http://foo.example.com/cgi-bin/tester
ErrorDocument 404 /cgi-bin/bad_urls.pl
ErrorDocument 401 /subscription_info.html
ErrorDocument 403 "Sorry can't allow you access today"

Additionally, the special value default can be used to specify Apache's simple hardcoded message. While not required under normal circumstances, default will restore Apache's simple hardcoded message for configurations that would otherwise inherit an existing ErrorDocument.

ErrorDocument 404 /cgi-bin/bad_urls.pl

<Directory /web/docs>
ErrorDocument 404 default
 </Directory>

Note that when you specify an ErrorDocument that points to a remote URL (ie. anything with a method such as http in front of it), Apache will send a redirect to the client to tell it where to find the document, even if the document ends up being on the same server. This has several implications, the most important being that the client will not receive the original error status code, but instead will receive a redirect status code. This in turn can confuse web robots and other clients which try to determine if a URL is valid using the status code. In addition, if you use a remote URL in an ErrorDocument 401, the client will not know to prompt the user for a password since it will not receive the 401 status code. Therefore, if you use an ErrorDocument 401 directive then it must refer to a local document.

Microsoft Internet Explorer (MSIE) will by default ignore server-generated error messages when they are "too small" and substitute its own "friendly" error messages. The size threshold varies depending on the type of error, but in general, if you make your error document greater than 512 bytes, then MSIE will show the server-generated error rather than masking it. More information is available in Microsoft Knowledge Base article Q294807.

Although most error messages can be overriden, there are certain circumstances where the internal messages are used regardless of the setting of ErrorDocument. In particular, if a malformed request is detected, normal request processing will be immediately halted and the internal error message returned. This is necessary to guard against security problems caused by bad requests.

Prior to version 2.0, messages were indicated by prefixing them with a single unmatched double quote character.

See also

  • documentation of customizable responses

ErrorLog Directive

Description: | Location where the server will log errors
Syntax: | ErrorLog file-path|syslog[:facility]
Default: | ErrorLog logs/error_log (Unix) ErrorLog logs/error.log (Windows and OS/2)
Context: | server config, virtual host
Status: | Core
Module: | core

The ErrorLog directive sets the name of the file to which the server will log any errors it encounters. If the file-path is not absolute then it is assumed to be relative to the ServerRoot.

Example

ErrorLog /var/log/httpd/error_log

If the file-path begins with a pipe (|) then it is assumed to be a command to spawn to handle the error log.

Example

ErrorLog "|/usr/local/bin/httpd_errors"

Using syslog instead of a filename enables logging via syslogd(8) if the system supports it. The default is to use syslog facility local7, but you can override this by using the syslog:facility syntax where facility can be one of the names usually documented in syslog(1).

Example

ErrorLog syslog:user

SECURITY: See the security tips document for details on why your security could be compromised if the directory where log files are stored is writable by anyone other than the user that starts the server.

Note

When entering a file path on non-Unix platforms, care should be taken to make sure that only forward slashed are used even though the platform may allow the use of back slashes. In general it is a good idea to always use forward slashes throughout the configuration files.

See also

  • LogLevel
  • Apache Log Files

FileETag Directive

Description: | File attributes used to create the ETag HTTP response header
Syntax: | FileETag component ...
Default: | FileETag INode MTime Size
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core

The FileETag directive configures the file attributes that are used to create the ETag (entity tag) response header field when the document is based on a file. (The ETag value is used in cache management to save network bandwidth.) In Apache 1.3.22 and earlier, the ETag value was always formed from the file's inode, size, and last-modified time (mtime). The FileETag directive allows you to choose which of these -- if any -- should be used. The recognized keywords are:

INode
The file's i-node number will be included in the calculation
MTime
The date and time the file was last modified will be included
Size
The number of bytes in the file will be included
All
All available fields will be used. This is equivalent to:

FileETag INode MTime Size

None
If a document is file-based, no ETag field will be included in the response

The INode, MTime, and Size keywords may be prefixed with either + or -, which allow changes to be made to the default setting inherited from a broader scope. Any keyword appearing without such a prefix immediately and completely cancels the inherited setting.

If a directory's configuration includes FileETag INode MTime Size, and a subdirectory's includes FileETag -INode, the setting for that subdirectory (which will be inherited by any sub-subdirectories that don't override it) will be equivalent to FileETag MTime Size.

<Files> Directive

Description: | Contains directives that apply to matched filenames
Syntax: | <Files filename> ... </Files>
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

The <Files> directive limits the scope of the enclosed directives by filename. It is comparable to the <Directory> and <Location> directives. It should be matched with a </Files> directive. The directives given within this section will be applied to any object with a basename (last component of filename) matching the specified filename. <Files> sections are processed in the order they appear in the configuration file, after the <Directory> sections and .htaccess files are read, but before <Location> sections. Note that <Files> can be nested inside <Directory> sections to restrict the portion of the filesystem they apply to.

The filename argument should include a filename, or a wild-card string, where ? matches any single character, and * matches any sequences of characters. Extended regular expressions can also be used, with the addition of the ~ character. For example:

<Files ~ "\.(gif|jpe?g|png)$">

would match most common Internet graphics formats. <FilesMatch> is preferred, however.

Note that unlike <Directory> and <Location> sections, <Files> sections can be used inside .htaccess files. This allows users to control access to their own files, at a file-by-file level.

See also

  • How <Directory>, <Location> and <Files> sections work for an explanation of how these different sections are combined when a request is received

<FilesMatch> Directive

Description: | Contains directives that apply to regular-expression matched filenames
Syntax: | <FilesMatch regex> ... </FilesMatch>
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

The <FilesMatch> directive limits the scope of the enclosed directives by filename, just as the <Files> directive does. However, it accepts a regular expression. For example:

<FilesMatch "\.(gif|jpe?g|png)$">

would match most common Internet graphics formats.

See also

  • How <Directory>, <Location> and <Files> sections work for an explanation of how these different sections are combined when a request is received

ForceType Directive

Description: | Forces all matching files to be served with the specified MIME content-type
Syntax: | ForceType MIME-type|None
Context: | directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core
Compatibility: | Moved to the core in Apache 2.0

When placed into an .htaccess file or a <Directory>, or <Location> or <Files> section, this directive forces all matching files to be served with the content type identification given by MIME-type. For example, if you had a directory full of GIF files, but did not want to label them all with .gif, you might want to use:

ForceType image/gif

Note that unlike DefaultType, this directive overrides all mime-type associations, including filename extensions, that might identify the media type.

You can override any ForceType setting by using the value of None:

# force all files to be image/gif:
<Location /images>
ForceType image/gif
 </Location>

# but normal mime-type associations here:
<Location /images/mixed>
ForceType None
 </Location>

HostnameLookups Directive

Description: | Enables DNS lookups on client IP addresses
Syntax: | HostnameLookups On|Off|Double
Default: | HostnameLookups Off
Context: | server config, virtual host, directory
Status: | Core
Module: | core

This directive enables DNS lookups so that host names can be logged (and passed to CGIs/SSIs in REMOTE_HOST). The value Double refers to doing double-reverse DNS lookup. That is, after a reverse lookup is performed, a forward lookup is then performed on that result. At least one of the IP addresses in the forward lookup must match the original address. (In "tcpwrappers" terminology this is called PARANOID.)

Regardless of the setting, when mod_access is used for controlling access by hostname, a double reverse lookup will be performed. This is necessary for security. Note that the result of this double-reverse isn't generally available unless you set HostnameLookups Double. For example, if only HostnameLookups On and a request is made to an object that is protected by hostname restrictions, regardless of whether the double-reverse fails or not, CGIs will still be passed the single-reverse result in REMOTE_HOST.

The default is Off in order to save the network traffic for those sites that don't truly need the reverse lookups done. It is also better for the end users because they don't have to suffer the extra latency that a lookup entails. Heavily loaded sites should leave this directive Off, since DNS lookups can take considerable amounts of time. The utility logresolve, compiled by default to the bin subdirectory of your installation directory, can be used to look up host names from logged IP addresses offline.

IdentityCheck Directive

Description: | Enables logging of the RFC1413 identity of the remote user
Syntax: | IdentityCheck On|Off
Default: | IdentityCheck Off
Context: | server config, virtual host, directory
Status: | Core
Module: | core

This directive enables RFC1413-compliant logging of the remote user name for each connection, where the client machine runs identd or something similar. This information is logged in the access log.

The information should not be trusted in any way except for rudimentary usage tracking.

Note that this can cause serious latency problems accessing your server since every request requires one of these lookups to be performed. When firewalls are involved each lookup might possibly fail and add 30 seconds of latency to each hit. So in general this is not very useful on public servers accessible from the Internet.

<IfDefine> Directive

Description: | Encloses directives that will be processed only if a test is true at startup
Syntax: | <IfDefine [!]parameter-name> ... </IfDefine>
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

The <IfDefine test>...</IfDefine> section is used to mark directives that are conditional. The directives within an <IfDefine> section are only processed if the test is true. If test is false, everything between the start and end markers is ignored.

The test in the <IfDefine> section directive can be one of two forms:

  • parameter-name
  • !parameter-name

In the former case, the directives between the start and end markers are only processed if the parameter named parameter-name is defined. The second format reverses the test, and only processes the directives if parameter-name is not defined.

The parameter-name argument is a define as given on the httpd command line via -Dparameter- , at the time the server was started.

<IfDefine> sections are nest-able, which can be used to implement simple multiple-parameter tests. Example:

httpd -DReverseProxy ...

# httpd.conf
<IfDefine ReverseProxy>
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/libproxy.so
 </IfDefine>

<IfModule> Directive

Description: | Encloses directives that are processed conditional on the presence or absence of a specific module
Syntax: | <IfModule [!]module-name> ... </IfModule>
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

The <IfModule test>...</IfModule> section is used to mark directives that are conditional on the presence of a specific module. The directives within an <IfModule> section are only processed if the test is true. If test is false, everything between the start and end markers is ignored.

The test in the <IfModule> section directive can be one of two forms:

  • module name
  • !module name

In the former case, the directives between the start and end markers are only processed if the module named module name is included in Apache -- either compiled in or dynamically loaded using LoadModule. The second format reverses the test, and only processes the directives if module name is not included.

The module name argument is the file name of the module, at the time it was compiled. For example, mod_rewrite.c. If a module consists of several source files, use the name of the file containing the string STANDARD20_MODULE_STUFF.

<IfModule> sections are nest-able, which can be used to implement simple multiple-module tests.

This section should only be used if you need to have one configuration file that works whether or not a specific module is available. In normal operation, directives need not be placed in <IfModule> sections.

Include Directive

Description: | Includes other configuration files from within the server configuration files
Syntax: | Include file-path|directory-path
Context: | server config, virtual host, directory
Status: | Core
Module: | core
Compatibility: | Wildcard matching available in 2.0.41 and later

This directive allows inclusion of other configuration files from within the server configuration files.

Shell-style (fnmatch()) wildcard characters can be used to include several files at once, in alphabetical order. In addition, if Include points to a directory, rather than a file, Apache will read all files in that directory and any subdirectory. But including entire directories is not recommended, because it is easy to accidentally leave temporary files in a directory that can cause httpd to fail.

The file path specified may be an absolute path, or may be relative to the ServerRoot directory.

Examples:

Include /usr/local/apache2/conf/ssl.conf
Include /usr/local/apache2/conf/vhosts/*.conf

Or, providing paths relative to your ServerRoot directory:

Include conf/ssl.conf
Include conf/vhosts/*.conf

Running apachectl configtest will give you a list of the files that are being processed during the configuration check:

root@host# apachectl configtest
Processing config file: /usr/local/apache2/conf/ssl.conf
Processing config file: /usr/local/apache2/conf/vhosts/vhost1.conf
Processing config file: /usr/local/apache2/conf/vhosts/vhost2.conf
Syntax OK

See also

  • apachectl

KeepAlive Directive

Description: | Enables HTTP persistent connections
Syntax: | KeepAlive On|Off
Default: | KeepAlive On
Context: | server config, virtual host
Status: | Core
Module: | core

The Keep-Alive extension to HTTP/1.0 and the persistent connection feature of HTTP/1.1 provide long-lived HTTP sessions which allow multiple requests to be sent over the same TCP connection. In some cases this has been shown to result in an almost 50% speedup in latency times for HTML documents with many images. To enable Keep-Alive connections, set KeepAlive On.

For HTTP/1.0 clients, Keep-Alive connections will only be used if they are specifically requested by a client. In addition, a Keep-Alive connection with an HTTP/1.0 client can only be used when the length of the content is known in advance. This implies that dynamic content such as CGI output, SSI pages, and server-generated directory listings will generally not use Keep-Alive connections to HTTP/1.0 clients. For HTTP/1.1 clients, persistent connections are the default unless otherwise specified. If the client requests it, chunked encoding will be used in order to send content of unknown length over persistent connections.

See also

  • MaxKeepAliveRequests

KeepAliveTimeout Directive

Description: | Amount of time the server will wait for subsequent requests on a persistent connection
Syntax: | KeepAliveTimeout seconds
Default: | KeepAliveTimeout 15
Context: | server config, virtual host
Status: | Core
Module: | core

The number of seconds Apache will wait for a subsequent request before closing the connection. Once a request has been received, the timeout value specified by the Timeout directive applies.

Setting KeepAliveTimeout to a high value may cause performance problems in heavily loaded servers. The higher the timeout, the more server processes will be kept occupied waiting on connections with idle clients.

<Limit> Directive

Description: | Restrict enclosed access controls to only certain HTTP methods
Syntax: | <Limit method [method] ... > ... </Limit>
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

Access controls are normally effective for all access methods, and this is the usual desired behavior. In the general case, access control directives should not be placed within a <Limit> section.

The purpose of the <Limit> directive is to restrict the effect of the access controls to the nominated HTTP methods. For all other methods, the access restrictions that are enclosed in the <Limit> bracket will have no effect. The following example applies the access control only to the methods POST, PUT, and DELETE, leaving all other methods unprotected:

<Limit POST PUT DELETE>
Require valid-user
 </Limit>

The method names listed can be one or more of: GET, POST, PUT, DELETE, CONNECT, OPTIONS, PATCH, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, and UNLOCK. The method name is case-sensitive. If GET is used it will also restrict HEAD requests. The TRACE method cannot be limited.

A <LimitExcept> section should always be used in preference to a <Limit> section when restricting access, since a <LimitExcept> section provides protection against arbitrary methods.

<LimitExcept> Directive

Description: | Restrict access controls to all HTTP methods except the named ones
Syntax: | <LimitExcept method [method] ... > ... </LimitExcept>
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

<LimitExcept> and </LimitExcept> are used to enclose a group of access control directives which will then apply to any HTTP access method not listed in the arguments; i.e., it is the opposite of a <Limit> section and can be used to control both standard and nonstandard/unrecognized methods. See the documentation for <Limit> for more details.

For example:

<LimitExcept POST GET>
Require valid-user
 </LimitExcept>

LimitInternalRecursion Directive

Description: | Determine maximum number of internal redirects and nested subrequests
Syntax: | LimitInternalRecursion number [number]
Default: | LimitInternalRecursion 10
Context: | server config, virtual host
Status: | Core
Module: | core
Compatibility: | Available in Apache 2.0.47 and later

An internal redirect happens, for example, when using the Action directive, which internally redirects the original request to a CGI script. A subrequest is Apache's mechanism to find out what would happen for some URI if it were requested. For example, mod_dir uses subrequests to look for the files listed in the DirectoryIndex directive.

LimitInternalRecursion prevents the server from crashing when entering an infinite loop of internal redirects or subrequests. Such loops are usually caused by misconfigurations.

The directive stores two different limits, which are evaluated on per-request basis. The first number is the maximum number of internal redirects, that may follow each other. The second number determines, how deep subrequests may be nested. If you specify only one number, it will be assigned to both limits.

Example

LimitInternalRecursion 5

LimitRequestBody Directive

Description: | Restricts the total size of the HTTP request body sent from the client
Syntax: | LimitRequestBody bytes
Default: | LimitRequestBody 0
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

This directive specifies the number of bytes from 0 (meaning unlimited) to 2147483647 (2GB) that are allowed in a request body.

The LimitRequestBody directive allows the user to set a limit on the allowed size of an HTTP request message body within the context in which the directive is given (server, per-directory, per-file or per-location). If the client request exceeds that limit, the server will return an error response instead of servicing the request. The size of a normal request message body will vary greatly depending on the nature of the resource and the methods allowed on that resource. CGI scripts typically use the message body for retrieving form information. Implementations of the PUT method will require a value at least as large as any representation that the server wishes to accept for that resource.

This directive gives the server administrator greater control over abnormal client request behavior, which may be useful for avoiding some forms of denial-of-service attacks.

If, for example, you are permitting file upload to a particular location, and wish to limit the size of the uploaded file to 100K, you might use the following directive:

LimitRequestBody 102400

LimitRequestFields Directive

Description: | Limits the number of HTTP request header fields that will be accepted from the client
Syntax: | LimitRequestFields number
Default: | LimitRequestFields 100
Context: | server config
Status: | Core
Module: | core

Number is an integer from 0 (meaning unlimited) to 32767. The default value is defined by the compile-time constant DEFAULT_LIMIT_REQUEST_FIELDS (100 as distributed).

The LimitRequestFields directive allows the server administrator to modify the limit on the number of request header fields allowed in an HTTP request. A server needs this value to be larger than the number of fields that a normal client request might include. The number of request header fields used by a client rarely exceeds 20, but this may vary among different client implementations, often depending upon the extent to which a user has configured their browser to support detailed content negotiation. Optional HTTP extensions are often expressed using request header fields.

This directive gives the server administrator greater control over abnormal client request behavior, which may be useful for avoiding some forms of denial-of-service attacks. The value should be increased if normal clients see an error response from the server that indicates too many fields were sent in the request.

For example:

LimitRequestFields 50

LimitRequestFieldSize Directive

Description: | Limits the size of the HTTP request header allowed from the client
Syntax: | LimitRequestFieldsize bytes
Default: | LimitRequestFieldsize 8190
Context: | server config
Status: | Core
Module: | core

This directive specifies the number of bytes that will be allowed in an HTTP request header.

The LimitRequestFieldSize directive allows the server administrator to reduce or increase the limit on the allowed size of an HTTP request header field. A server needs this value to be large enough to hold any one header field from a normal client request. The size of a normal request header field will vary greatly among different client implementations, often depending upon the extent to which a user has configured their browser to support detailed content negotiation. SPNEGO authentication headers can be up to 12392 bytes.

This directive gives the server administrator greater control over abnormal client request behavior, which may be useful for avoiding some forms of denial-of-service attacks.

For example:

LimitRequestFieldSize 4094

Under normal conditions, the value should not be changed from the default.
Apache 2.0.53 or higher is required for increasing the limit above the compiled-in value of DEFAULT_LIMIT_REQUEST_FIELDSIZE (8190 as distributed).

LimitRequestLine Directive

Description: | Limit the size of the HTTP request line that will be accepted from the client
Syntax: | LimitRequestLine bytes
Default: | LimitRequestLine 8190
Context: | server config
Status: | Core
Module: | core

This directive sets the number of bytes from 0 to the value of the compile-time constant DEFAULT_LIMIT_REQUEST_LINE (8190 as distributed) that will be allowed on the HTTP request-line.

The LimitRequestLine directive allows the server administrator to reduce the limit on the allowed size of a client's HTTP request-line below the normal input buffer size compiled with the server. Since the request-line consists of the HTTP method, URI, and protocol version, the LimitRequestLine directive places a restriction on the length of a request-URI allowed for a request on the server. A server needs this value to be large enough to hold any of its resource names, including any information that might be passed in the query part of a GET request.

This directive gives the server administrator greater control over abnormal client request behavior, which may be useful for avoiding some forms of denial-of-service attacks.

For example:

LimitRequestLine 4094

Under normal conditions, the value should not be changed from the default.

LimitXMLRequestBody Directive

Description: | Limits the size of an XML-based request body
Syntax: | LimitXMLRequestBody bytes
Default: | LimitXMLRequestBody 1000000
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

Limit (in bytes) on maximum size of an XML-based request body. A value of 0 will disable any checking.

Example:

LimitXMLRequestBody 0

<Location> Directive

Description: | Applies the enclosed directives only to matching URLs
Syntax: | <Location URL-path|URL> ... </Location>
Context: | server config, virtual host
Status: | Core
Module: | core

The <Location> directive limits the scope of the enclosed directives by URL. It is similar to the <Directory> directive, and starts a subsection which is terminated with a </Location> directive. <Location> sections are processed in the order they appear in the configuration file, after the <Directory> sections and .htaccess files are read, and after the <Files> sections.

<Location> sections operate completely outside the filesystem. This has several consequences. Most importantly, <Location> directives should not be used to control access to filesystem locations. Since several different URLs may map to the same filesystem location, such access controls may by circumvented.

When to use <Location>

Use <Location> to apply directives to content that lives outside the filesystem. For content that lives in the filesystem, use <Directory> and <Files>. An exception is <Location />, which is an easy way to apply a configuration to the entire server.

For all origin (non-proxy) requests, the URL to be matched is a URL-path of the form /path/. No scheme, hostname, port, or query string may be included. For proxy requests, the URL to be matched is of the form scheme://servername/path, and you must include the prefix.

The URL may use wildcards. In a wild-card string, ? matches any single character, and * matches any sequences of characters.

Extended regular expressions can also be used, with the addition of the ~ character. For example:

<Location ~ "/(extra|special)/data">

would match URLs that contained the substring /extra/data or /special/data. The directive <LocationMatch> behaves identical to the regex version of <Location>.

The <Location> functionality is especially useful when combined with the SetHandler directive. For example, to enable status requests, but allow them only from browsers at foo.com, you might use:

<Location /status>
SetHandler server-status
Order Deny,Allow
Deny from all
Allow from .foo.com
 </Location>

Note about / (slash)

The slash character has special meaning depending on where in a URL it appears. People may be used to its behavior in the filesystem where multiple adjacent slashes are frequently collapsed to a single slash (i.e., /home///foo is the same as /home/foo). In URL-space this is not necessarily true. The <LocationMatch> directive and the regex version of <Location> require you to explicitly specify multiple slashes if that is your intention.

For example, <LocationMatch ^/abc> would match the request URL /abc but not the request URL //abc. The (non-regex) <Location> directive behaves similarly when used for proxy requests. But when (non-regex) <Location> is used for non-proxy requests it will implicitly match multiple slashes with a single slash. For example, if you specify <Location /abc/def> and the request is to /abc//def then it will match.

See also

  • How <Directory>, <Location> and <Files> sections work for an explanation of how these different sections are combined when a request is received

<LocationMatch> Directive

Description: | Applies the enclosed directives only to regular-expression matching URLs
Syntax: | <LocationMatch regex> ... </LocationMatch>
Context: | server config, virtual host
Status: | Core
Module: | core

The <LocationMatch> directive limits the scope of the enclosed directives by URL, in an identical manner to <Location>. However, it takes a regular expression as an argument instead of a simple string. For example:

<LocationMatch "/(extra|special)/data">

would match URLs that contained the substring /extra/data or /special/data.

See also

  • How <Directory>, <Location> and <Files> sections work for an explanation of how these different sections are combined when a request is received

LogLevel Directive

Description: | Controls the verbosity of the ErrorLog
Syntax: | LogLevel level
Default: | LogLevel warn
Context: | server config, virtual host
Status: | Core
Module: | core

LogLevel adjusts the verbosity of the messages recorded in the error logs (see ErrorLog directive). The following levels are available, in order of decreasing significance:

Level | Description | Example
emerg | Emergencies - system is unusable. | "Child cannot open lock file. Exiting"
alert | Action must be taken immediately. | "getpwuid: couldn't determine user name from uid"
crit | Critical Conditions. | "socket: Failed to get a socket, exiting child"
error | Error conditions. | "Premature end of script headers"
warn | Warning conditions. | "child process 1234 did not exit, sending another SIGHUP"
notice | Normal but significant condition. | "httpd: caught SIGBUS, attempting to dump core in ..."
info | Informational. | "Server seems busy, (you may need to increase StartServers, or Min/MaxSpareServers)..."
debug | Debug-level messages | "Opening config file ..."

When a particular level is specified, messages from all other levels of higher significance will be reported as well. E.g., when LogLevel info is specified, then messages with log levels of notice and warn will also be posted.

Using a level of at least crit is recommended.

For example:

LogLevel notice

Note

When logging to a regular file messages of the level notice cannot be suppressed and thus are always logged. However, this doesn't apply when logging is done using syslog.

MaxKeepAliveRequests Directive

Description: | Number of requests allowed on a persistent connection
Syntax: | MaxKeepAliveRequests number
Default: | MaxKeepAliveRequests 100
Context: | server config, virtual host
Status: | Core
Module: | core

The MaxKeepAliveRequests directive limits the number of requests allowed per connection when KeepAlive is on. If it is set to 0, unlimited requests will be allowed. We recommend that this setting be kept to a high value for maximum server performance.

For example:

MaxKeepAliveRequests 500

NameVirtualHost Directive

Description: | Designates an IP address for name-virtual hosting
Syntax: | NameVirtualHost addr[:port]
Context: | server config
Status: | Core
Module: | core

The NameVirtualHost directive is a required directive if you want to configure name-based virtual hosts.

Although addr can be hostname it is recommended that you always use an IP address, e.g.

NameVirtualHost 111.22.33.44

With the NameVirtualHost directive you specify the IP address on which the server will receive requests for the name-based virtual hosts. This will usually be the address to which your name-based virtual host names resolve. In cases where a firewall or other proxy receives the requests and forwards them on a different IP address to the server, you must specify the IP address of the physical interface on the machine which will be servicing the requests. If you have multiple name-based hosts on multiple addresses, repeat the directive for each address.

Note

Note, that the "main server" and any _default_ servers will never be served for a request to a NameVirtualHost IP address (unless for some reason you specify NameVirtualHost but then don't define any VirtualHosts for that address).

Optionally you can specify a port number on which the name-based virtual hosts should be used, e.g.

NameVirtualHost 111.22.33.44:8080

IPv6 addresses must be enclosed in square brackets, as shown in the following example:

NameVirtualHost [fe80::a00:20ff:fea7:ccea]:8080

To receive requests on all interfaces, you can use an argument of *

NameVirtualHost *

Argument to <VirtualHost> directive

Note that the argument to the <VirtualHost> directive must exactly match the argument to the NameVirtualHost directive.

NameVirtualHost 1.2.3.4
<VirtualHost 1.2.3.4>
# ...
</VirtualHost>

See also

  • Virtual Hosts documentation

Options Directive

Description: | Configures what features are available in a particular directory
Syntax: | Options [+|-]option [[+|-]option] ...
Default: | Options All
Context: | server config, virtual host, directory, .htaccess
Override: | Options
Status: | Core
Module: | core

The Options directive controls which server features are available in a particular directory.

option can be set to None, in which case none of the extra features are enabled, or one or more of the following:

All
All options except for MultiViews. This is the default setting.
ExecCGI
Execution of CGI scripts using mod_cgi is permitted.
FollowSymLinks
The server will follow symbolic links in this directory.

Even though the server follows the symlink it does not change the pathname used to match against <Directory> sections.

Note also, that this option gets ignored if set inside a <Location> section.

Includes
Server-side includes provided by mod_include are permitted.
IncludesNOEXEC
Server-side includes are permitted, but the #exec cmd and #exec cgi are disabled. It is still possible to #include virtual CGI scripts from ScriptAliased directories.
Indexes
If a URL which maps to a directory is requested, and there is no DirectoryIndex (e.g., index.html) in that directory, then mod_autoindex will return a formatted listing of the directory.
MultiViews
Content negotiated "MultiViews" are allowed using mod_negotiation.
SymLinksIfOwnerMatch
The server will only follow symbolic links for which the target file or directory is owned by the same user id as the link.

Note

This option gets ignored if set inside a <Location> section.

Normally, if multiple Options could apply to a directory, then the most specific one is used and others are ignored; the options are not merged. (See how sections are merged.) However if all the options on the Options directive are preceded by a + or - symbol, the options are merged. Any options preceded by a + are added to the options currently in force, and any options preceded by a - are removed from the options currently in force.

For example, without any + and - symbols:

<Directory /web/docs>
Options Indexes FollowSymLinks
 </Directory>

<Directory /web/docs/spec>
Options Includes
 </Directory>

then only Includes will be set for the /web/docs/spec directory. However if the second Options directive uses the + and - symbols:

<Directory /web/docs>
Options Indexes FollowSymLinks
 </Directory>

<Directory /web/docs/spec>
Options +Includes -Indexes
 </Directory>

then the options FollowSymLinks and Includes are set for the /web/docs/spec directory.

Note

Using -IncludesNOEXEC or -Includes disables server-side includes completely regardless of the previous setting.

The default in the absence of any other settings is All.

Require Directive

Description: | Selects which authenticated users can access a resource
Syntax: | Require entity-name [entity-name] ...
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Core
Module: | core

This directive selects which authenticated users can access a resource. The allowed syntaxes are:

Require user userid [userid] ...
Only the named users can access the resource.
Require group group-name [group-name] ...
Only users in the named groups can access the resource.
Require valid-user
All valid users can access the resource.

Require must be accompanied by AuthName and AuthType directives, and directives such as AuthUserFile and AuthGroupFile (to define users and groups) in order to work correctly. Example:

AuthType Basic
AuthName "Restricted Resource"
AuthUserFile /web/users
AuthGroupFile /web/groups
Require group admin

Access controls which are applied in this way are effective for all methods. This is what is normally desired. If you wish to apply access controls only to specific methods, while leaving other methods unprotected, then place the Require statement into a <Limit> section.

See also

  • Satisfy
  • mod_access

RLimitCPU Directive

Description: | Limits the CPU consumption of processes launched by Apache children
Syntax: | RLimitCPU seconds|max [seconds|max]
Default: | Unset; uses operating system defaults
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

Takes 1 or 2 parameters. The first parameter sets the soft resource limit for all processes and the second parameter sets the maximum resource limit. Either parameter can be a number, or max to indicate to the server that the limit should be set to the maximum allowed by the operating system configuration. Raising the maximum resource limit requires that the server is running as root, or in the initial startup phase.

This applies to processes forked off from Apache children servicing requests, not the Apache children themselves. This includes CGI scripts and SSI exec commands, but not any processes forked off from the Apache parent such as piped logs.

CPU resource limits are expressed in seconds per process.

See also

  • RLimitMEM
  • RLimitNPROC

RLimitMEM Directive

Description: | Limits the memory consumption of processes launched by Apache children
Syntax: | RLimitMEM bytes|max [bytes|max]
Default: | Unset; uses operating system defaults
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

Takes 1 or 2 parameters. The first parameter sets the soft resource limit for all processes and the second parameter sets the maximum resource limit. Either parameter can be a number, or max to indicate to the server that the limit should be set to the maximum allowed by the operating system configuration. Raising the maximum resource limit requires that the server is running as root, or in the initial startup phase.

This applies to processes forked off from Apache children servicing requests, not the Apache children themselves. This includes CGI scripts and SSI exec commands, but not any processes forked off from the Apache parent such as piped logs.

Memory resource limits are expressed in bytes per process.

See also

  • RLimitCPU
  • RLimitNPROC

RLimitNPROC Directive

Description: | Limits the number of processes that can be launched by processes launched by Apache children
Syntax: | RLimitNPROC number|max [number|max]
Default: | Unset; uses operating system defaults
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

Takes 1 or 2 parameters. The first parameter sets the soft resource limit for all processes and the second parameter sets the maximum resource limit. Either parameter can be a number, or max to indicate to the server that the limit should be set to the maximum allowed by the operating system configuration. Raising the maximum resource limit requires that the server is running as root, or in the initial startup phase.

This applies to processes forked off from Apache children servicing requests, not the Apache children themselves. This includes CGI scripts and SSI exec commands, but not any processes forked off from the Apache parent such as piped logs.

Process limits control the number of processes per user.

Note

If CGI processes are not running under user ids other than the web server user id, this directive will limit the number of processes that the server itself can create. Evidence of this situation will be indicated by cannot fork messages in the error_log.

See also

  • RLimitMEM
  • RLimitCPU

Satisfy Directive

Description: | Interaction between host-level access control and user authentication
Syntax: | Satisfy Any|All
Default: | Satisfy All
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Core
Module: | core
Compatibility: | Influenced by <Limit> and <LimitExcept> in version 2.0.51 and later

Access policy if both Allow and Require used. The parameter can be either All or Any. This directive is only useful if access to a particular area is being restricted by both username/password and client host address. In this case the default behavior (All) is to require that the client passes the address access restriction and enters a valid username and password. With the Any option the client will be granted access if they either pass the host restriction or enter a valid username and password. This can be used to password restrict an area, but to let clients from particular addresses in without prompting for a password.

For example, if you wanted to let people on your network have unrestricted access to a portion of your website, but require that people outside of your network provide a password, you could use a configuration similar to the following:

Require valid-user
Allow from 192.168.1
Satisfy Any

Since version 2.0.51 Satisfy directives can be restricted to particular methods by <Limit> and <LimitExcept> sections.

See also

  • Allow
  • Require

ScriptInterpreterSource Directive

Description: | Technique for locating the interpreter for CGI scripts
Syntax: | ScriptInterpreterSource Registry|Registry-Strict|Script
Default: | ScriptInterpreterSource Script
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core
Compatibility: | Win32 only; option Registry-Strict is available in Apache 2.0 and later

This directive is used to control how Apache finds the interpreter used to run CGI scripts. The default setting is Script. This causes Apache to use the interpreter pointed to by the shebang line (first line, starting with #!) in the script. On Win32 systems this line usually looks like:

#!C:/Perl/bin/perl.exe

or, if perl is in the PATH, simply:

#!perl

Setting ScriptInterpreterSource Registry will cause the Windows Registry tree HKEY_CLASSES_ROOT to be searched using the script file extension (e.g., .pl) as a search key. The command defined by the registry subkey Shell\ExecCGI\Command or, if it does not exist, by the subkey Shell\Open\Command is used to open the script file. If the registry keys cannot be found, Apache falls back to the behavior of the Script option.

Security

Be careful when using ScriptInterpreterSource Registry with ScriptAlias'ed directories, because Apache will try to execute every file within this directory. The Registry setting may cause undesired program calls on files which are typically not executed. For example, the default open command on .htm files on most Windows systems will execute Microsoft Internet Explorer, so any HTTP request for an .htm file existing within the script directory would start the browser in the background on the server. This is a good way to crash your system within a minute or so.

The option Registry-Strict which is new in Apache 2.0 does the same thing as Registry but uses only the subkey Shell\ExecCGI\Command. The ExecCGI key is not a common one. It must be configured manually in the windows registry and hence prevents accidental program calls on your system.

ServerAdmin Directive

Description: | Email address that the server includes in error messages sent to the client
Syntax: | ServerAdmin email-address
Context: | server config, virtual host
Status: | Core
Module: | core

The ServerAdmin sets the e-mail address that the server includes in any error messages it returns to the client.

It may be worth setting up a dedicated address for this, e.g.

ServerAdmin www-admin@foo.example.com

as users do not always mention that they are talking about the server!

ServerAlias Directive

Description: | Alternate names for a host used when matching requests to name-virtual hosts
Syntax: | ServerAlias hostname [hostname] ...
Context: | virtual host
Status: | Core
Module: | core

The ServerAlias directive sets the alternate names for a host, for use with name-based virtual hosts.

<VirtualHost *>
ServerName server.domain.com
ServerAlias server server2.domain.com server2
# ...
</VirtualHost>

See also

  • Apache Virtual Host documentation

ServerName Directive

Description: | Hostname and port that the server uses to identify itself
Syntax: | ServerName fully-qualified-domain-name[:port]
Context: | server config, virtual host
Status: | Core
Module: | core
Compatibility: | In version 2.0, this directive supersedes the functionality of the Port directive from version 1.3.

The ServerName directive sets the hostname and port that the server uses to identify itself. This is used when creating redirection URLs. For example, if the name of the machine hosting the web server is simple.example.com, but the machine also has the DNS alias www.example.com and you wish the web server to be so identified, the following directive should be used:

ServerName www.example.com:80

If no ServerName is specified, then the server attempts to deduce the hostname by performing a reverse lookup on the IP address. If no port is specified in the ServerName, then the server will use the port from the incoming request. For optimal reliability and predictability, you should specify an explicit hostname and port using the ServerName directive.

If you are using name-based virtual hosts, the ServerName inside a <VirtualHost> section specifies what hostname must appear in the request's Host: header to match this virtual host.

See the description of the UseCanonicalName directive for settings which determine whether self-referential URL's (e.g., by the mod_dir module) will refer to the specified port, or to the port number given in the client's request.

See also

  • Issues Regarding DNS and Apache
  • Apache virtual host documentation
  • UseCanonicalName
  • NameVirtualHost
  • ServerAlias

ServerPath Directive

Description: | Legacy URL pathname for a name-based virtual host that is accessed by an incompatible browser
Syntax: | ServerPath URL-path
Context: | virtual host
Status: | Core
Module: | core

The ServerPath directive sets the legacy URL pathname for a host, for use with name-based virtual hosts.

See also

  • Apache Virtual Host documentation

ServerRoot Directive

Description: | Base directory for the server installation
Syntax: | ServerRoot directory-path
Default: | ServerRoot /usr/local/apache
Context: | server config
Status: | Core
Module: | core

The ServerRoot directive sets the directory in which the server lives. Typically it will contain the subdirectories conf/ and logs/. Relative paths in other configuration directives (such as Include or LoadModule, for example) are taken as relative to this directory.

Example

ServerRoot /home/httpd

See also

  • the -d option to httpd
  • the security tips for information on how to properly set permissions on the ServerRoot

ServerSignature Directive

Description: | Configures the footer on server-generated documents
Syntax: | ServerSignature On|Off|EMail
Default: | ServerSignature Off
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Core
Module: | core

The ServerSignature directive allows the configuration of a trailing footer line under server-generated documents (error messages, mod_proxy ftp directory listings, mod_info output, ...). The reason why you would want to enable such a footer line is that in a chain of proxies, the user often has no possibility to tell which of the chained servers actually produced a returned error message.

The Off setting, which is the default, suppresses the footer line (and is therefore compatible with the behavior of Apache-1.2 and below). The On setting simply adds a line with the server version number and ServerName of the serving virtual host, and the EMail setting additionally creates a "mailto:" reference to the ServerAdmin of the referenced document.

After version 2.0.44, the details of the server version number presented are controlled by the ServerTokens directive.

See also

  • ServerTokens

ServerTokens Directive

Description: | Configures the Server HTTP response header
Syntax: | ServerTokens Major|Minor|Min[imal]|Prod[uctOnly]|OS|Full
Default: | ServerTokens Full
Context: | server config
Status: | Core
Module: | core

This directive controls whether Server response header field which is sent back to clients includes a description of the generic OS-type of the server as well as information about compiled-in modules.

ServerTokens Prod[uctOnly]
Server sends (e.g.): Server: Apache
ServerTokens Major
Server sends (e.g.): Server: Apache/2
ServerTokens Minor
Server sends (e.g.): Server: Apache/2.0
ServerTokens Min[imal]
Server sends (e.g.): Server: Apache/2.0.41
ServerTokens OS
Server sends (e.g.): Server: Apache/2.0.41 (Unix)
ServerTokens Full (or not specified)
Server sends (e.g.): Server: Apache/2.0.41 (Unix) PHP/4.2.2 MyMod/1.2

This setting applies to the entire server, and cannot be enabled or disabled on a virtualhost-by-virtualhost basis.

After version 2.0.44, this directive also controls the information presented by the ServerSignature directive.

See also

  • ServerSignature

SetHandler Directive

Description: | Forces all matching files to be processed by a handler
Syntax: | SetHandler handler-name|None
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core
Compatibility: | Moved into the core in Apache 2.0

When placed into an .htaccess file or a <Directory> or <Location> section, this directive forces all matching files to be parsed through the handler given by handler-name. For example, if you had a directory you wanted to be parsed entirely as imagemap rule files, regardless of extension, you might put the following into an .htaccess file in that directory:

SetHandler imap-file

Another example: if you wanted to have the server display a status report whenever a URL of http://servername/status was called, you might put the following into httpd.conf:

<Location /status>
SetHandler server-status
 </Location>

You can override an earlier defined SetHandler directive by using the value None.

See also

  • AddHandler

SetInputFilter Directive

Description: | Sets the filters that will process client requests and POST input
Syntax: | SetInputFilter filter[;filter...]
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core

The SetInputFilter directive sets the filter or filters which will process client requests and POST input when they are received by the server. This is in addition to any filters defined elsewhere, including the AddInputFilter directive.

If more than one filter is specified, they must be separated by semicolons in the order in which they should process the content.

See also

  • Filters documentation

SetOutputFilter Directive

Description: | Sets the filters that will process responses from the server
Syntax: | SetOutputFilter filter[;filter...]
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Core
Module: | core

The SetOutputFilter directive sets the filters which will process responses from the server before they are sent to the client. This is in addition to any filters defined elsewhere, including the AddOutputFilter directive.

For example, the following configuration will process all files in the /www/data/ directory for server-side includes.

<Directory /www/data/>
SetOutputFilter INCLUDES
 </Directory>

If more than one filter is specified, they must be separated by semicolons in the order in which they should process the content.

See also

  • Filters documentation

TimeOut Directive

Description: | Amount of time the server will wait for certain events before failing a request
Syntax: | TimeOut seconds
Default: | TimeOut 300
Context: | server config
Status: | Core
Module: | core

The TimeOut directive currently defines the amount of time Apache will wait for three things:

  1. The total amount of time it takes to receive a GET request.
  2. The amount of time between receipt of TCP packets on a POST or PUT request.
  3. The amount of time between ACKs on transmissions of TCP packets in responses.

We plan on making these separately configurable at some point down the road. The timer used to default to 1200 before 1.2, but has been lowered to 300 which is still far more than necessary in most situations. It is not set any lower by default because there may still be odd places in the code where the timer is not reset when a packet is sent.

TraceEnable Directive

Description: | Determines the behaviour on TRACE requests
Syntax: | TraceEnable [on|off|extended]
Default: | TraceEnable on
Context: | server config
Status: | Core
Module: | core
Compatibility: | Available in Apache 1.3.34, 2.0.55 and later

This directive overrides the behavior of TRACE for both the core server and mod_proxy. The default TraceEnable on permits TRACE requests per RFC 2616, which disallows any request body to accompany the request. TraceEnable off causes the core server and mod_proxy to return a 405 (Method not allowed) error to the client.

Finally, for testing and diagnostic purposes only, request bodies may be allowed using the non-compliant TraceEnable extended directive. The core (as an origin server) will restrict the request body to 64k (plus 8k for chunk headers if Transfer-Encoding: chunked is used). The core will reflect the full headers and all chunk headers with the response body. As a proxy server, the request body is not restricted to 64k.

UseCanonicalName Directive

Description: | Configures how the server determines its own name and port
Syntax: | UseCanonicalName On|Off|DNS
Default: | UseCanonicalName On
Context: | server config, virtual host, directory
Status: | Core
Module: | core

In many situations Apache must construct a self-referential URL -- that is, a URL that refers back to the same server. With UseCanonicalName On Apache will use the hostname and port specified in the ServerName directive to construct the canonical name for the server. This name is used in all self-referential URLs, and for the values of SERVER_NAME and SERVER_PORT in CGIs.

With UseCanonicalName Off Apache will form self-referential URLs using the hostname and port supplied by the client if any are supplied (otherwise it will use the canonical name, as defined above). These values are the same that are used to implement name based virtual hosts, and are available with the same clients. The CGI variables SERVER_NAME and SERVER_PORT will be constructed from the client supplied values as well.

An example where this may be useful is on an intranet server where you have users connecting to the machine using short names such as www. You'll notice that if the users type a shortname, and a URL which is a directory, such as http://www/splat, without the trailing slash then Apache will redirect them to http://www.domain.com/splat/. If you have authentication enabled, this will cause the user to have to authenticate twice (once for www and once again for www.domain.com -- see the FAQ on this subject for more information). But if UseCanonicalName is set Off, then Apache will redirect to http://www/splat/.

There is a third option, UseCanonicalName DNS, which is intended for use with mass IP-based virtual hosting to support ancient clients that do not provide a Host: header. With this option Apache does a reverse DNS lookup on the server IP address that the client connected to in order to work out self-referential URLs.

Warning

If CGIs make assumptions about the values of SERVER_NAME they may be broken by this option. The client is essentially free to give whatever value they want as a hostname. But if the CGI is only using SERVER_NAME to construct self-referential URLs then it should be just fine.

See also

  • ServerName
  • Listen

<VirtualHost> Directive

Description: | Contains directives that apply only to a specific hostname or IP address
Syntax: | <VirtualHost addr[:port] [addr[:port]] ...> ... </VirtualHost>
Context: | server config
Status: | Core
Module: | core

<VirtualHost> and </VirtualHost> are used to enclose a group of directives that will apply only to a particular virtual host. Any directive that is allowed in a virtual host context may be used. When the server receives a request for a document on a particular virtual host, it uses the configuration directives enclosed in the <VirtualHost> section. Addr can be:

  • The IP address of the virtual host;
  • A fully qualified domain name for the IP address of the virtual host;
  • The character *, which is used only in combination with NameVirtualHost * to match all IP addresses; or
  • The string _default_, which is used only with IP virtual hosting to catch unmatched IP addresses.

Example

<VirtualHost 10.1.2.3>
ServerAdmin webmaster@host.foo.com
DocumentRoot /www/docs/host.foo.com
ServerName host.foo.com
ErrorLog logs/host.foo.com-error_log
TransferLog logs/host.foo.com-access_log
 </VirtualHost>

IPv6 addresses must be specified in square brackets because the optional port number could not be determined otherwise. An IPv6 example is shown below:

<VirtualHost [fe80::a00:20ff:fea7:ccea]>
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>

Each Virtual Host must correspond to a different IP address, different port number or a different host name for the server, in the former case the server machine must be configured to accept IP packets for multiple addresses. (If the machine does not have multiple network interfaces, then this can be accomplished with the ifconfig alias command -- if your OS supports it).

Note

The use of <VirtualHost> does not affect what addresses Apache listens on. You may need to ensure that Apache is listening on the correct addresses using Listen.

When using IP-based virtual hosting, the special name _default_ can be specified in which case this virtual host will match any IP address that is not explicitly listed in another virtual host. In the absence of any _default_ virtual host the "main" server config, consisting of all those definitions outside any VirtualHost section, is used when no IP-match occurs. (But note that any IP address that matches a NameVirtualHost directive will use neither the "main" server config nor the _default_ virtual host. See the name-based virtual hosting documentation for further details.)

You can specify a :port to change the port that is matched. If unspecified then it defaults to the same port as the most recent Listen statement of the main server. You may also specify :* to match all ports on that address. (This is recommended when used with _default_.)

Security

See the security tips document for details on why your security could be compromised if the directory where log files are stored is writable by anyone other than the user that starts the server.

See also

  • Apache Virtual Host documentation
  • Issues Regarding DNS and Apache
  • Setting which addresses and ports Apache uses
  • How <Directory>, <Location> and <Files> sections work for an explanation of how these different sections are combined when a request is received


mpm_common - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache MPM Common Directives

Description: | A collection of directives that are implemented by more than one multi-processing module (MPM)
Status: | MPM

AcceptMutex Directive

Description: | Method that Apache uses to serialize multiple children accepting requests on network sockets
Syntax: | AcceptMutex Default|method
Default: | AcceptMutex Default
Context: | server config
Status: | MPM
Module: | leader, perchild, prefork, threadpool, worker

The AcceptMutex directives sets the method that Apache uses to serialize multiple children accepting requests on network sockets. Prior to Apache 2.0, the method was selectable only at compile time. The optimal method to use is highly architecture and platform dependent. For further details, see the performance tuning documentation.

If this directive is set to Default, then the compile-time selected default will be used. Other possible methods are listed below. Note that not all methods are available on all platforms. If a method is specified which is not available, a message will be written to the error log listing the available methods.

flock
uses the flock(2) system call to lock the file defined by the LockFile directive.
fcntl
uses the fcntl(2) system call to lock the file defined by the LockFile directive.
posixsem
uses POSIX compatible semaphores to implement the mutex.
pthread
uses POSIX mutexes as implemented by the POSIX Threads (PThreads) specification.
sysvsem
uses SySV-style semaphores to implement the mutex.

If you want to find out the compile time chosen default for your system, you may set your LogLevel to debug. Then the default AcceptMutex will be written into the ErrorLog.

BS2000Account Directive

Description: | Define the non-privileged account on BS2000 machines
Syntax: | BS2000Account account
Context: | server config
Status: | MPM
Module: | perchild, prefork
Compatibility: | Only available for BS2000 machines

The BS2000Account directive is available for BS2000 hosts only. It must be used to define the account number for the non-privileged apache server user (which was configured using the User directive). This is required by the BS2000 POSIX subsystem (to change the underlying BS2000 task environment by performing a sub-LOGON) to prevent CGI scripts from accessing resources of the privileged account which started the server, usually SYSROOT.

Note

Only one BS2000Account directive can be used.

See also

  • Apache EBCDIC port

CoreDumpDirectory Directive

Description: | Directory where Apache attempts to switch before dumping core
Syntax: | CoreDumpDirectory directory
Default: | See usage for the default setting
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_winnt, perchild, prefork, threadpool, worker

This controls the directory to which Apache attempts to switch before dumping core. The default is in the ServerRoot directory, however since this should not be writable by the user the server runs as, core dumps won't normally get written. If you want a core dump for debugging, you can use this directive to place it in a different location.

Core Dumps on Linux

If Apache starts as root and switches to another user, the Linux kernel disables core dumps even if the directory is writable for the process. Apache (2.0.46 and later) reenables core dumps on Linux 2.4 and beyond, but only if you explicitly configure a CoreDumpDirectory.

EnableExceptionHook Directive

Description: | Enables a hook that runs exception handlers after a crash
Syntax: | EnableExceptionHook On|Off
Default: | EnableExceptionHook Off
Context: | server config
Status: | MPM
Module: | leader, perchild, prefork, threadpool, worker
Compatibility: | Available in version 2.0.49 and later

For safety reasons this directive is only available if the server was configured with the --enable-exception-hook option. It enables a hook that allows external modules to plug in and do something after a child crashed.

There are already two modules, mod_whatkilledus and mod_backtrace that make use of this hook. Please have a look at Jeff Trawick's EnableExceptionHook site for more information about these.

Group Directive

Description: | Group under which the server will answer requests
Syntax: | Group unix-group
Default: | Group #-1
Context: | server config
Status: | MPM
Module: | beos, leader, mpmt_os2, perchild, prefork, threadpool, worker
Compatibility: | Only valid in global server config since Apache 2.0

The Group directive sets the group under which the server will answer requests. In order to use this directive, the server must be run initially as root. If you start the server as a non-root user, it will fail to change to the specified group, and will instead continue to run as the group of the original user. Unix-group is one of:

A group name
Refers to the given group by name.
# followed by a group number.
Refers to a group by its number.

Example

Group www-group

It is recommended that you set up a new group specifically for running the server. Some admins use user nobody, but this is not always possible or desirable.

Security

Don't set Group (or User) to root unless you know exactly what you are doing, and what the dangers are.

Special note: Use of this directive in <VirtualHost> is no longer supported. To configure your server for suexec use SuexecUserGroup.

Note

Although the Group directive is present in the beos and mpmt_os2 MPMs, it is actually a no-op there and only exists for compatibility reasons.

Listen Directive

Description: | IP addresses and ports that the server listens to
Syntax: | Listen [IP-address:]portnumber
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_netware, mpm_winnt, mpmt_os2, perchild, prefork, threadpool, worker
Compatibility: | Required directive since Apache 2.0

The Listen directive instructs Apache to listen to only specific IP addresses or ports; by default it responds to requests on all IP interfaces. Listen is now a required directive. If it is not in the config file, the server will fail to start. This is a change from previous versions of Apache.

The Listen directive tells the server to accept incoming requests on the specified port or address-and-port combination. If only a port number is specified, the server listens to the given port on all interfaces. If an IP address is given as well as a port, the server will listen on the given port and interface.

Multiple Listen directives may be used to specify a number of addresses and ports to listen to. The server will respond to requests from any of the listed addresses and ports.

For example, to make the server accept connections on both port 80 and port 8000, use:

Listen 80
Listen 8000

To make the server accept connections on two specified interfaces and port numbers, use

Listen 192.170.2.1:80
Listen 192.170.2.5:8000

IPv6 addresses must be surrounded in square brackets, as in the following example:

Listen [fe80::a00:20ff:fea7:ccea]:80

Error condition

Multiple Listen directives for the same ip address and port will result in an Address already in use error message.

See also

  • DNS Issues
  • Setting which addresses and ports Apache uses

ListenBackLog Directive

Description: | Maximum length of the queue of pending connections
Syntax: | ListenBacklog backlog
Default: | ListenBacklog 511
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_netware, mpm_winnt, mpmt_os2, perchild, prefork, threadpool, worker

The maximum length of the queue of pending connections. Generally no tuning is needed or desired, however on some systems it is desirable to increase this when under a TCP SYN flood attack. See the backlog parameter to the listen(2) system call.

This will often be limited to a smaller number by the operating system. This varies from OS to OS. Also note that many OSes do not use exactly what is specified as the backlog, but use a number based on (but normally larger than) what is set.

LockFile Directive

Description: | Location of the accept serialization lock file
Syntax: | LockFile filename
Default: | LockFile logs/accept.lock
Context: | server config
Status: | MPM
Module: | leader, perchild, prefork, threadpool, worker

The LockFile directive sets the path to the lockfile used when Apache is used with an AcceptMutex value of either fcntl or flock. This directive should normally be left at its default value. The main reason for changing it is if the logs directory is NFS mounted, since the lockfile must be stored on a local disk. The PID of the main server process is automatically appended to the filename.

Security

It is best to avoid putting this file in a world writable directory such as /var/tmp because someone could create a denial of service attack and prevent the server from starting by creating a lockfile with the same name as the one the server will try to create.

See also

  • AcceptMutex

MaxClients Directive

Description: | Maximum number of child processes that will be created to serve requests
Syntax: | MaxClients number
Default: | See usage for details
Context: | server config
Status: | MPM
Module: | beos, leader, prefork, threadpool, worker

The MaxClients directive sets the limit on the number of simultaneous requests that will be served. Any connection attempts over the MaxClients limit will normally be queued, up to a number based on the ListenBacklog directive. Once a child process is freed at the end of a different request, the connection will then be serviced.

For non-threaded servers (i.e., prefork), MaxClients translates into the maximum number of child processes that will be launched to serve requests. The default value is 256; to increase it, you must also raise ServerLimit.

For threaded and hybrid servers (e.g. beos or worker) MaxClients restricts the total number of threads that will be available to serve clients. The default value for beos is 50. For hybrid MPMs the default value is 16 (ServerLimit) multiplied by the value of 25 (ThreadsPerChild). Therefore, to increase MaxClients to a value that requires more than 16 processes, you must also raise ServerLimit.

MaxMemFree Directive

Description: | Maximum amount of memory that the main allocator is allowed to hold without calling free()
Syntax: | MaxMemFree KBytes
Default: | MaxMemFree 0
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_netware, prefork, threadpool, worker, mpm_winnt

The MaxMemFree directive sets the maximum number of free Kbytes that the main allocator is allowed to hold without calling free(). When not set, or when set to zero, the threshold will be set to unlimited.

MaxRequestsPerChild Directive

Description: | Limit on the number of requests that an individual child server will handle during its life
Syntax: | MaxRequestsPerChild number
Default: | MaxRequestsPerChild 10000
Context: | server config
Status: | MPM
Module: | leader, mpm_netware, mpm_winnt, mpmt_os2, perchild, prefork, threadpool, worker

The MaxRequestsPerChild directive sets the limit on the number of requests that an individual child server process will handle. After MaxRequestsPerChild requests, the child process will die. If MaxRequestsPerChild is 0, then the process will never expire.

Different default values

The default value for mpm_netware and mpm_winnt is 0.

Setting MaxRequestsPerChild to a non-zero limit has two beneficial effects:

  • it limits the amount of memory that process can consume by (accidental) memory leakage;
  • by giving processes a finite lifetime, it helps reduce the number of processes when the server load reduces.

Note

For KeepAlive requests, only the first request is counted towards this limit. In effect, it changes the behavior to limit the number of connections per child.

MaxSpareThreads Directive

Description: | Maximum number of idle threads
Syntax: | MaxSpareThreads number
Default: | See usage for details
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_netware, mpmt_os2, perchild, threadpool, worker

Maximum number of idle threads. Different MPMs deal with this directive differently.

For perchild the default is MaxSpareThreads 10. This MPM monitors the number of idle threads on a per-child basis. If there are too many idle threads in that child, the server will begin to kill threads within that child.

For worker, leader and threadpool the default is MaxSpareThreads 250. These MPMs deal with idle threads on a server-wide basis. If there are too many idle threads in the server then child processes are killed until the number of idle threads is less than this number.

For mpm_netware the default is MaxSpareThreads 100. Since this MPM runs a single-process, the spare thread count is also server-wide.

beos and mpmt_os2 work similar to mpm_netware. The default for beos is MaxSpareThreads 50. For mpmt_os2 the default value is 10.

Restrictions

The range of the MaxSpareThreads value is restricted. Apache will correct the given value automatically according to the following rules:

  • perchild requires MaxSpareThreads to be less or equal than ThreadLimit.
  • mpm_netware wants the value to be greater than MinSpareThreads.
  • For leader, threadpool and worker the value must be greater or equal than the sum of MinSpareThreads and ThreadsPerChild.

See also

  • MinSpareThreads
  • StartServers

MinSpareThreads Directive

Description: | Minimum number of idle threads available to handle request spikes
Syntax: | MinSpareThreads number
Default: | See usage for details
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_netware, mpmt_os2, perchild, threadpool, worker

Minimum number of idle threads to handle request spikes. Different MPMs deal with this directive differently.

perchild uses a default of MinSpareThreads 5 and monitors the number of idle threads on a per-child basis. If there aren't enough idle threads in that child, the server will begin to create new threads within that child. Thus, if you set NumServers to 10 and a MinSpareThreads value of 5, you'll have at least 50 idle threads on your system.

worker, leader and threadpool use a default of MinSpareThreads 75 and deal with idle threads on a server-wide basis. If there aren't enough idle threads in the server then child processes are created until the number of idle threads is greater than number.

mpm_netware uses a default of MinSpareThreads 10 and, since it is a single-process MPM, tracks this on a server-wide bases.

beos and mpmt_os2 work similar to mpm_netware. The default for beos is MinSpareThreads 1. For mpmt_os2 the default value is 5.

See also

  • MaxSpareThreads
  • StartServers

PidFile Directive

Description: | File where the server records the process ID of the daemon
Syntax: | PidFile filename
Default: | PidFile logs/httpd.pid
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_winnt, mpmt_os2, perchild, prefork, threadpool, worker

The PidFile directive sets the file to which the server records the process id of the daemon. If the filename is not absolute then it is assumed to be relative to the ServerRoot.

Example

PidFile /var/run/apache.pid

It is often useful to be able to send the server a signal, so that it closes and then re-opens its ErrorLog and TransferLog, and re-reads its configuration files. This is done by sending a SIGHUP (kill -1) signal to the process id listed in the PidFile.

The PidFile is subject to the same warnings about log file placement and security.

Note

As of Apache 2 it is recommended to use only the apachectl script for (re-)starting or stopping the server.

ScoreBoardFile Directive

Description: | Location of the file used to store coordination data for the child processes
Syntax: | ScoreBoardFile file-path
Default: | ScoreBoardFile logs/apache_status
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_winnt, perchild, prefork, threadpool, worker

Apache uses a scoreboard to communicate between its parent and child processes. Some architectures require a file to facilitate this communication. If the file is left unspecified, Apache first attempts to create the scoreboard entirely in memory (using anonymous shared memory) and, failing that, will attempt to create the file on disk (using file-based shared memory). Specifying this directive causes Apache to always create the file on the disk.

Example

ScoreBoardFile /var/run/apache_status

File-based shared memory is useful for third-party applications that require direct access to the scoreboard.

If you use a ScoreBoardFile then you may see improved speed by placing it on a RAM disk. But be careful that you heed the same warnings about log file placement and security.

See also

  • Stopping and Restarting Apache

SendBufferSize Directive

Description: | TCP buffer size
Syntax: | SendBufferSize bytes
Default: | SendBufferSize 0
Context: | server config
Status: | MPM
Module: | beos, leader, mpm_netware, mpm_winnt, mpmt_os2, perchild, prefork, threadpool, worker

The server will set the TCP buffer size to the number of bytes specified. Very useful to increase past standard OS defaults on high speed high latency (i.e., 100ms or so, such as transcontinental fast pipes).

If set to the value of 0, the server will use the OS deault.

ServerLimit Directive

Description: | Upper limit on configurable number of processes
Syntax: | ServerLimit number
Default: | See usage for details
Context: | server config
Status: | MPM
Module: | leader, perchild, prefork, threadpool, worker

For the prefork MPM, this directive sets the maximum configured value for MaxClients for the lifetime of the Apache process. For the worker MPM, this directive in combination with ThreadLimit sets the maximum configured value for MaxClients for the lifetime of the Apache process. Any attempts to change this directive during a restart will be ignored, but MaxClients can be modified during a restart.

Special care must be taken when using this directive. If ServerLimit is set to a value much higher than necessary, extra, unused shared memory will be allocated. If both ServerLimit and MaxClients are set to values higher than the system can handle, Apache may not start or the system may become unstable.

With the prefork MPM, use this directive only if you need to set MaxClients higher than 256 (default). Do not set the value of this directive any higher than what you might want to set MaxClients to.

With worker, leader and threadpool use this directive only if your MaxClients and ThreadsPerChild settings require more than 16 server processes (default). Do not set the value of this directive any higher than the number of server processes required by what you may want for MaxClients and ThreadsPerChild.

With the perchild MPM, use this directive only if you need to set NumServers higher than 8 (default).

Note

There is a hard limit of ServerLimit 20000 compiled into the server. This is intended to avoid nasty effects caused by typos.

See also

  • Stopping and Restarting Apache

StartServers Directive

Description: | Number of child server processes created at startup
Syntax: | StartServers number
Default: | See usage for details
Context: | server config
Status: | MPM
Module: | leader, mpmt_os2, prefork, threadpool, worker

The StartServers directive sets the number of child server processes created on startup. As the number of processes is dynamically controlled depending on the load, there is usually little reason to adjust this parameter.

The default value differs from MPM to MPM. For leader, threadpool and worker the default is StartServers 3. For prefork defaults to 5 and for mpmt_os2 to 2.

StartThreads Directive

Description: | Number of threads created on startup
Syntax: | StartThreads number
Default: | See usage for details
Context: | server config
Status: | MPM
Module: | beos, mpm_netware, perchild

Number of threads created on startup. As the number of threads is dynamically controlled depending on the load, there is usually little reason to adjust this parameter.

For perchild the default is StartThreads 5 and this directive tracks the number of threads per process at startup.

For mpm_netware the default is StartThreads 50 and, since there is only a single process, this is the total number of threads created at startup to serve requests.

For beos the default is StartThreads 10. It also reflects the total number of threads created at startup to serve requests.

ThreadLimit Directive

Description: | Sets the upper limit on the configurable number of threads per child process
Syntax: | ThreadLimit number
Default: | See usage for details
Context: | server config
Status: | MPM
Module: | leader, mpm_winnt, perchild, threadpool, worker
Compatibility: | Available for mpm_winnt in Apache 2.0.41 and later

This directive sets the maximum configured value for ThreadsPerChild for the lifetime of the Apache process. Any attempts to change this directive during a restart will be ignored, but ThreadsPerChild can be modified during a restart up to the value of this directive.

Special care must be taken when using this directive. If ThreadLimit is set to a value much higher than ThreadsPerChild, extra unused shared memory will be allocated. If both ThreadLimit and ThreadsPerChild are set to values higher than the system can handle, Apache may not start or the system may become unstable. Do not set the value of this directive any higher than your greatest predicted setting of ThreadsPerChild for the current run of Apache.

The default value for ThreadLimit is 1920 when used with mpm_winnt and 64 when used with the others.

Note

There is a hard limit of ThreadLimit 20000 (or ThreadLimit 15000 with mpm_winnt) compiled into the server. This is intended to avoid nasty effects caused by typos.

ThreadsPerChild Directive

Description: | Number of threads created by each child process
Syntax: | ThreadsPerChild number
Default: | See usage for details
Context: | server config
Status: | MPM
Module: | leader, mpm_winnt, threadpool, worker

This directive sets the number of threads created by each child process. The child creates these threads at startup and never creates more. If using an MPM like mpm_winnt, where there is only one child process, this number should be high enough to handle the entire load of the server. If using an MPM like worker, where there are multiple child processes, the total number of threads should be high enough to handle the common load on the server.

The default value for ThreadsPerChild is 64 when used with mpm_winnt and 25 when used with the others.

User Directive

Description: | The userid under which the server will answer requests
Syntax: | User unix-userid
Default: | User #-1
Context: | server config
Status: | MPM
Module: | leader, perchild, prefork, threadpool, worker
Compatibility: | Only valid in global server config since Apache 2.0

The User directive sets the user ID as which the server will answer requests. In order to use this directive, the server must be run initially as root. If you start the server as a non-root user, it will fail to change to the lesser privileged user, and will instead continue to run as that original user. If you do start the server as root, then it is normal for the parent process to remain running as root. Unix-userid is one of:

A username
Refers to the given user by name.
# followed by a user number.
Refers to a user by its number.

The user should have no privileges that result in it being able to access files that are not intended to be visible to the outside world, and similarly, the user should not be able to execute code that is not meant for HTTP requests. It is recommended that you set up a new user and group specifically for running the server. Some admins use user nobody, but this is not always desirable, since the nobody user can have other uses on the system.

Security

Don't set User (or Group) to root unless you know exactly what you are doing, and what the dangers are.

With the perchild MPM, which is intended to server virtual hosts run under different user IDs, the User directive defines the user ID for the main server and the fallback for <VirtualHost> sections without an AssignUserID directive.

Special note: Use of this directive in <VirtualHost> is no longer supported. To configure your server for suexec use SuexecUserGroup.

Note

Although the User directive is present in the beos and mpmt_os2 MPMs, it is actually a no-op there and only exists for compatibility reasons.


beos - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 MPM beos

설명: | BeOS에 최적화된 다중처리 모듈.
상태: | MPM
모듈명: | mpm_beos_module
소스파일: | beos.c

요약

이 다중처리 모듈(MPM)은 BeOS에서 기본적으로 사용한다. 한 조절 프로세스가 요청을 처리할 쓰레드들을 만든다.

참고

  • 아파치가 사용할 주소와 포트 지정

MaxRequestsPerThread 지시어

설명: | 한 쓰레드가 실행하는 동안 처리할 요청개수 한계
문법: | MaxRequestsPerThread number
기본값: | MaxRequestsPerThread 0
사용장소: | 주서버설정
상태: | MPM
모듈: | beos

MaxRequestsPerThread 지시어는 한 서버 쓰레드가 처리할 요청개수를 제한한다. MaxRequestsPerThread개 요청을 처리한후 쓰레드는 죽는다. MaxRequestsPerThread가 0이면 절대로 쓰레드를 죽이지 않는다.

MaxRequestsPerThread를 0이 아닌 값으로 설정하면 두가지 장점이 있다:

  • (우연히 발생한) 메모리 유출(memory leakage)때문에 쓰레드가 낭비할 메모리량을 제한한다;
  • 쓰레드의 수명을 제한하여 서버 부하가 감소할때 쓰레드 수를 줄인다.

주의:

KeepAlive 요청의 경우 오직 첫번째 요청만을 센다. 그래서 이 지시어는 쓰레드당 연결 개수를 제한하게 된다.


leader - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 MPM leader

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.
설명: | 표준 worker MPM의 실험적인 변형
상태: | MPM
모듈명: | mpm_leader_module
소스파일: | leader.c

요약

주의

이 MPM은 실험적인 상태로, 기대한대로 동작하지않을 수 있다.

이 모듈은 표준 worker MPM의 실험적인 변형이다. 이 모듈은 쓰레드간의 협동을 위해 Leader/Followers 디자인패턴을 사용한다. 더 자세한 정보는 http://deuce.doc.wustl.edu/doc/pspdfs/lf.pdf를 참고하라.

leader MPM을 사용하려면, httpd를 컴파일할때 configure 스크립트 아규먼트에 --with-mpm=leader를 사용한다.

이 MPM은 쓰레드 동기를 위해 APR의 atomic compare-and-swap 명령을 사용한다. x86용으로 컴파일하지만 386을 지원할 필요가 없거나, SPARC용으로 컴파일하지만 UltraSPARC 칩 이전에서 실행하지 않는다면, configure 스크립트 아규먼트에 --enable-nonportable-atomics=yes를 사용하라. 그러면 APR이 오래된 CPU에는 없는 더 효율적인 명령어를 사용하여 atomic 명령을 구현한다.


mpm_netware - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache MPM netware

Description: | Multi-Processing Module implementing an exclusively threaded web server optimized for Novell NetWare
Status: | MPM
Module Identifier: | mpm_netware_module
Source File: | mpm_netware.c

Summary

This Multi-Processing Module (MPM) implements an exclusively threaded web server that has been optimized for Novell NetWare.

The main thread is responsible for launching child worker threads which listen for connections and serve them when they arrive. Apache always tries to maintain several spare or idle worker threads, which stand ready to serve incoming requests. In this way, clients do not need to wait for a new child threads to be spawned before their requests can be served.

The StartThreads, MinSpareThreads, MaxSpareThreads, and MaxThreads regulate how the main thread creates worker threads to serve requests. In general, Apache is very self-regulating, so most sites do not need to adjust these directives from their default values. Sites with limited memory may need to decrease MaxThreads to keep the server from thrashing (spawning and terminating idle threads). More information about tuning process creation is provided in the performance hints documentation.

MaxRequestsPerChild controls how frequently the server recycles processes by killing old ones and launching new ones. On the NetWare OS it is highly recommended that this directive remain set to 0. This allows worker threads to continue servicing requests indefinitely.

See also

  • Setting which addresses and ports Apache uses

MaxThreads Directive

Description: | Set the maximum number of worker threads
Syntax: | MaxThreads number
Default: | MaxThreads 2048
Context: | server config
Status: | MPM
Module: | mpm_netware

The MaxThreads directive sets the desired maximum number worker threads allowable. The default value is also the compiled in hard limit. Therefore it can only be lowered, for example:

MaxThreads 512

ThreadStackSize Directive

Description: | Determine the stack size for each thread
Syntax: | ThreadStackSize number
Default: | ThreadStackSize 65536
Context: | server config
Status: | MPM
Module: | mpm_netware

This directive tells the server what stack size to use for each of the running threads. If you ever get a stack overflow you will need to bump this number to a higher setting.


mpmt_os2 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache MPM os2

Description: | Hybrid multi-process, multi-threaded MPM for OS/2
Status: | MPM
Module Identifier: | mpm_mpmt_os2_module
Source File: | mpmt_os2.c

Summary

The Server consists of a main, parent process and a small, static number of child processes.

The parent process's job is to manage the child processes. This involves spawning children as required to ensure there are always StartServers processes accepting connections.

Each child process consists of a a pool of worker threads and a main thread that accepts connections and passes them to the workers via a work queue. The worker thread pool is dynamic, managed by a maintenance thread so that the number of idle threads is kept between MinSpareThreads and MaxSpareThreads.

See also

  • Setting which addresses and ports Apache uses


perchild - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache MPM perchild

Description: | Multi-Processing Module allowing for daemon processes serving requests to be assigned a variety of different userids
Status: | MPM
Module Identifier: | mpm_perchild_module
Source File: | perchild.c

Summary

This module is not functional. Development of this module is not complete and is not currently active. Do not use perchild unless you are a programmer willing to help fix it.

This Multi-Processing Module (MPM) implements a hybrid multi-process, multi-threaded web server. A fixed number of processes create threads to handle requests. Fluctuations in load are handled by increasing or decreasing the number of threads in each process.

See also

  • Setting which addresses and ports Apache uses

How it works

A single control process launches the number of child processes indicated by the NumServers directive at server startup. Each child process creates threads as specified in the StartThreads directive. The individual threads then listen for connections and serve them when they arrive.

Apache always tries to maintain a pool of spare or idle server threads, which stand ready to serve incoming requests. In this way, clients do not need to wait for new threads to be created. For each child process, Apache assesses the number of idle threads and creates or destroys threads to keep this number within the boundaries specified by MinSpareThreads and MaxSpareThreads. Since this process is very self-regulating, it is rarely necessary to modify these directives from their default values. The maximum number of clients that may be served simultaneously is determined by multiplying the number of server processes that will be created (NumServers) by the maximum number of threads created in each process (MaxThreadsPerChild).

While the parent process is usually started as root under Unix in order to bind to port 80, the child processes and threads are launched by Apache as a less-privileged user. The User and Group directives are used to set the privileges of the Apache child processes. The child processes must be able to read all the content that will be served, but should have as few privileges beyond that as possible. In addition, unless suexec is used, these directives also set the privileges which will be inherited by CGI scripts.

MaxRequestsPerChild controls how frequently the server recycles processes by killing old ones and launching new ones.

Working with different user-IDs

The perchild MPM adds the extra ability to specify that particular processes should serve requests under different user-IDs. These user-IDs can then be associated with specific virtual hosts. You have to use one ChildPerUserID directive for every user/group combination you want to be run. Then you can tie particular virtual hosts to that user and group IDs.

The following example runs 7 child processes. Two of them are run under user1/group1. The next four are run under user2/group2 and the remaining process uses the User and Group of the main server:

Global config

NumServers 7
ChildPerUserID user1 group1 2
ChildPerUserID user2 group2 4

Using unbalanced numbers of processes as above is useful, if the particular virtual hosts produce different load. The assignment to the virtual hosts is easily done as in the example below. In conclusion with the example above the following assumes, that server2 has to serve about twice of the hits of server1.

Example

NameVirtualHost *

<VirtualHost *>
ServerName fallbackhost
# no assignment; use fallback
 </VirtualHost>

<VirtualHost *>
ServerName server1
AssignUserID user1 group1
 </VirtualHost>

<VirtualHost *>
ServerName server2
AssignUserID user2 group2
 </VirtualHost>

AssignUserID Directive

Description: | Tie a virtual host to a user and group ID
Syntax: | AssignUserID user-id group-id
Context: | virtual host
Status: | MPM
Module: | perchild

Tie a virtual host to a specific user/group combination. Requests addressed to the virtual host where this directive appears will be served by a process running with the specified user and group ID.

The user and group ID has to be assigned to a number of children in the global server config using the ChildPerUserID directive. See the section above for a configuration example.

ChildPerUserID Directive

Description: | Specify user ID and group ID for a number of child processes
Syntax: | ChildPerUserID user-id group-id num-children
Context: | server config
Status: | MPM
Module: | perchild

Specify a user ID and group ID for a number of child processes. The third argument, num-children, is the number of child processes to start with the specified user and group. It does not represent a specific child number. In order to use this directive, the server must be run initially as root. If you start the server as a non-root user, it will fail to change to the lesser privileged user.

If the total number of child processes, found by totaling all of the third arguments to all ChildPerUserID directives in the config file, is less than NumServers, then all remaining children will inherit the User and Group settings from the main server. See the section above for a configuration example.

Security

Don't set user-id (or group-id) to root unless you know exactly what you are doing, and what the dangers are.

MaxThreadsPerChild Directive

Description: | Maximum number of threads per child process
Syntax: | MaxThreadsPerChild number
Default: | MaxThreadsPerChild 64
Context: | server config
Status: | MPM
Module: | perchild

This directive sets the maximum number of threads that will be created in each child process. To increase this value beyond its default, it is necessary to change the value of the ThreadLimit directive and stop and re-start the server.

NumServers Directive

Description: | Total number of children alive at the same time
Syntax: | NumServers number
Default: | NumServers 2
Context: | server config
Status: | MPM
Module: | perchild

The NumServers directive determines the number of children alive at the same time. This number should be large enough to handle the requests for the entire site. To increase this value beyond the value of 8, it is necessary to change the value of the ServerLimit directive and stop and re-start the server. See the section above for a configuration example.


prefork - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache MPM prefork

Description: | Implements a non-threaded, pre-forking web server
Status: | MPM
Module Identifier: | mpm_prefork_module
Source File: | prefork.c

Summary

This Multi-Processing Module (MPM) implements a non-threaded, pre-forking web server that handles requests in a manner similar to Apache 1.3. It is appropriate for sites that need to avoid threading for compatibility with non-thread-safe libraries. It is also the best MPM for isolating each request, so that a problem with a single request will not affect any other.

This MPM is very self-regulating, so it is rarely necessary to adjust its configuration directives. Most important is that MaxClients be big enough to handle as many simultaneous requests as you expect to receive, but small enough to assure that there is enough physical RAM for all processes.

See also

  • Setting which addresses and ports Apache uses

How it Works

A single control process is responsible for launching child processes which listen for connections and serve them when they arrive. Apache always tries to maintain several spare or idle server processes, which stand ready to serve incoming requests. In this way, clients do not need to wait for a new child processes to be forked before their requests can be served.

The StartServers, MinSpareServers, MaxSpareServers, and MaxClients regulate how the parent process creates children to serve requests. In general, Apache is very self-regulating, so most sites do not need to adjust these directives from their default values. Sites which need to serve more than 256 simultaneous requests may need to increase MaxClients, while sites with limited memory may need to decrease MaxClients to keep the server from thrashing (swapping memory to disk and back). More information about tuning process creation is provided in the performance hints documentation.

While the parent process is usually started as root under Unix in order to bind to port 80, the child processes are launched by Apache as a less-privileged user. The User and Group directives are used to set the privileges of the Apache child processes. The child processes must be able to read all the content that will be served, but should have as few privileges beyond that as possible.

MaxRequestsPerChild controls how frequently the server recycles processes by killing old ones and launching new ones.

MaxSpareServers Directive

Description: | Maximum number of idle child server processes
Syntax: | MaxSpareServers number
Default: | MaxSpareServers 10
Context: | server config
Status: | MPM
Module: | prefork

The MaxSpareServers directive sets the desired maximum number of idle child server processes. An idle process is one which is not handling a request. If there are more than MaxSpareServers idle, then the parent process will kill off the excess processes.

Tuning of this parameter should only be necessary on very busy sites. Setting this parameter to a large number is almost always a bad idea. If you are trying to set the value lower than MinSpareServers, Apache will automatically adjust it to MinSpareServers + 1.

See also

  • MinSpareServers
  • StartServers

MinSpareServers Directive

Description: | Minimum number of idle child server processes
Syntax: | MinSpareServers number
Default: | MinSpareServers 5
Context: | server config
Status: | MPM
Module: | prefork

The MinSpareServers directive sets the desired minimum number of idle child server processes. An idle process is one which is not handling a request. If there are fewer than MinSpareServers idle, then the parent process creates new children at a maximum rate of 1 per second.

Tuning of this parameter should only be necessary on very busy sites. Setting this parameter to a large number is almost always a bad idea.

See also

  • MaxSpareServers
  • StartServers


threadpool - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache MPM threadpool

Description: | Yet another experimental variant of the standard worker MPM
Status: | MPM
Module Identifier: | mpm_threadpool_module
Source File: | threadpool.c

Summary

Warning

This MPM is a developer playground and highly experimental, so it may or may not work as expected.

This is an experimental variant of the standard worker MPM. Rather than queuing connections like the worker MPM, the threadpool MPM queues idle worker threads and hands each accepted connection to the next available worker.

The threadpool MPM can't match the performance of the worker MPM in benchmark testing. As of 2.0.39, some of the key load-throtting concepts from the threadpool MPM have been incorporated into the worker MPM. The threadpool code is useful primarily as a research platform. For general-purpose use and for any production environments, use worker instead.


mpm_winnt - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache MPM winnt

Description: | This Multi-Processing Module is optimized for Windows NT.
Status: | MPM
Module Identifier: | mpm_winnt_module
Source File: | mpm_winnt.c

Summary

This Multi-Processing Module (MPM) is the default for the Windows NT operating systems. It uses a single control process which launches a single child process which in turn creates threads to handle requests

Win32DisableAcceptEx Directive

Description: | Use accept() rather than AcceptEx() to accept network connections
Syntax: | Win32DisableAcceptEx
Default: | AcceptEx() is enabled by default. Use this directive to disable use of AcceptEx()
Context: | server config
Status: | MPM
Module: | mpm_winnt
Compatibility: | Available in Version 2.0.49 and later

AcceptEx() is a Microsoft WinSock v2 API that provides some performance improvements over the use of the BSD style accept() API in certain circumstances. Some popular Windows products, typically virus scanning or virtual private network packages, have bugs that interfere with the proper operation of AcceptEx(). If you encounter an error condition like:

[error] (730038)An operation was attempted on something that is not a socket.: winnt_accept: AcceptEx failed. Attempting to recover.

you should use this directive to disable the use of AcceptEx().


worker - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache MPM worker

Description: | Multi-Processing Module implementing a hybrid multi-threaded multi-process web server
Status: | MPM
Module Identifier: | mpm_worker_module
Source File: | worker.c

Summary

This Multi-Processing Module (MPM) implements a hybrid multi-process multi-threaded server. By using threads to serve requests, it is able to serve a large number of requests with less system resources than a process-based server. Yet it retains much of the stability of a process-based server by keeping multiple processes available, each with many threads.

The most important directives used to control this MPM are ThreadsPerChild, which controls the number of threads deployed by each child process and MaxClients, which controls the maximum total number of threads that may be launched.

See also

  • Setting which addresses and ports Apache uses

How it Works

A single control process (the parent) is responsible for launching child processes. Each child process creates a fixed number of server threads as specified in the ThreadsPerChild directive, as well as a listener thread which listens for connections and passes them to a server thread for processing when they arrive.

Apache always tries to maintain a pool of spare or idle server threads, which stand ready to serve incoming requests. In this way, clients do not need to wait for a new threads or processes to be created before their requests can be served. The number of processes that will initially launched is set by the StartServers directive. Then during operation, Apache assesses the total number of idle threads in all processes, and forks or kills processes to keep this number within the boundaries specified by MinSpareThreads and MaxSpareThreads. Since this process is very self-regulating, it is rarely necessary to modify these directives from their default values. The maximum number of clients that may be served simultaneously (i.e., the maximum total number of threads in all processes) is determined by the MaxClients directive. The maximum number of active child processes is determined by the MaxClients directive divided by the ThreadsPerChild directive.

Two directives set hard limits on the number of active child processes and the number of server threads in a child process, and can only be changed by fully stopping the server and then starting it again. ServerLimit is a hard limit on the number of active child processes, and must be greater than or equal to the MaxClients directive divided by the ThreadsPerChild directive. ThreadLimit is a hard limit of the number of server threads, and must be greater than or equal to the ThreadsPerChild directive. If non-default values are specified for these directives, they should appear before other worker directives.

In addition to a the set of active child processes, there may be additional child processes which are terminating but where at least one server thread is still handling an existing client connection. Up to MaxClients terminating processes may be present, though the actual number can be expected to be much smaller. This behavior can be avoided by disabling the termination of individual child processes, which is achieved by the following:

  • set the value of MaxRequestsPerChild to zero
  • set the value of MaxSpareThreads to the same value as MaxClients

A typical configuration of the process-thread controls in the worker MPM could look as follows:

ServerLimit 16
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25

While the parent process is usually started as root under Unix in order to bind to port 80, the child processes and threads are launched by Apache as a less-privileged user. The User and Group directives are used to set the privileges of the Apache child processes. The child processes must be able to read all the content that will be served, but should have as few privileges beyond that as possible. In addition, unless suexec is used, these directives also set the privileges which will be inherited by CGI scripts.

MaxRequestsPerChild controls how frequently the server recycles processes by killing old ones and launching new ones.


mod_access - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_access

Description: | Provides access control based on client hostname, IP address, or other characteristics of the client request.
Status: | Base
Module Identifier: | access_module
Source File: | mod_access.c
Compatibility: | Available only in versions prior to 2.1

Summary

The directives provided by mod_access are used in <Directory>, <Files>, and <Location> sections as well as .htaccess files to control access to particular parts of the server. Access can be controlled based on the client hostname, IP address, or other characteristics of the client request, as captured in environment variables. The Allow and Deny directives are used to specify which clients are or are not allowed access to the server, while the Order directive sets the default access state, and configures how the Allow and Deny directives interact with each other.

Both host-based access restrictions and password-based authentication may be implemented simultaneously. In that case, the Satisfy directive is used to determine how the two sets of restrictions interact.

In general, access restriction directives apply to all access methods (GET, PUT, POST, etc). This is the desired behavior in most cases. However, it is possible to restrict some methods, while leaving other methods unrestricted, by enclosing the directives in a <Limit> section.

See also

  • Satisfy
  • Require

Allow Directive

Description: | Controls which hosts can access an area of the server
Syntax: | Allow from all|host|env=env-variable [host|env=env-variable] ...
Context: | directory, .htaccess
Override: | Limit
Status: | Base
Module: | mod_access

The Allow directive affects which hosts can access an area of the server. Access can be controlled by hostname, IP Address, IP Address range, or by other characteristics of the client request captured in environment variables.

The first argument to this directive is always from. The subsequent arguments can take three different forms. If Allow from all is specified, then all hosts are allowed access, subject to the configuration of the Deny and Order directives as discussed below. To allow only particular hosts or groups of hosts to access the server, the host can be specified in any of the following formats:

A (partial) domain-name

Example:

Allow from apache.org
Allow from .net example.edu

Hosts whose names match, or end in, this string are allowed access. Only complete components are matched, so the above example will match foo.apache.org but it will not match fooapache.org. This configuration will cause Apache to perform a double reverse DNS lookup on the client IP address, regardless of the setting of the HostnameLookups directive. It will do a reverse DNS lookup on the IP address to find the associated hostname, and then do a forward lookup on the hostname to assure that it matches the original IP address. Only if the forward and reverse DNS are consistent and the hostname matches will access be allowed.

A full IP address

Example:

Allow from 10.1.2.3
Allow from 192.168.1.104 192.168.1.205

An IP address of a host allowed access

A partial IP address

Example:

Allow from 10.1
Allow from 10 172.20 192.168.2

The first 1 to 3 bytes of an IP address, for subnet restriction.

A network/netmask pair

Example:

Allow from 10.1.0.0/255.255.0.0

A network a.b.c.d, and a netmask w.x.y.z. For more fine-grained subnet restriction.

A network/nnn CIDR specification

Example:

Allow from 10.1.0.0/16

Similar to the previous case, except the netmask consists of nnn high-order 1 bits.

Note that the last three examples above match exactly the same set of hosts.

IPv6 addresses and IPv6 subnets can be specified as shown below:

Allow from fe80::a00:20ff:fea7:ccea
Allow from fe80::a00:20ff:fea7:ccea/10

The third format of the arguments to the Allow directive allows access to the server to be controlled based on the existence of an environment variable. When Allow from env=env-variable is specified, then the request is allowed access if the environment variable env-variable exists. The server provides the ability to set environment variables in a flexible way based on characteristics of the client request using the directives provided by mod_setenvif. Therefore, this directive can be used to allow access based on such factors as the clients User-Agent (browser type), Referer, or other HTTP request header fields.

Example:

SetEnvIf User-Agent ^KnockKnock/2\.0 let_me_in
<Directory /docroot>
Order Deny,Allow
Deny from all
Allow from env=let_me_in
 </Directory>

In this case, browsers with a user-agent string beginning with KnockKnock/2.0 will be allowed access, and all others will be denied.

Deny Directive

Description: | Controls which hosts are denied access to the server
Syntax: | Deny from all|host|env=env-variable [host|env=env-variable] ...
Context: | directory, .htaccess
Override: | Limit
Status: | Base
Module: | mod_access

This directive allows access to the server to be restricted based on hostname, IP address, or environment variables. The arguments for the Deny directive are identical to the arguments for the Allow directive.

Order Directive

Description: | Controls the default access state and the order in which Allow and Deny are evaluated.
Syntax: | Order ordering
Default: | Order Deny,Allow
Context: | directory, .htaccess
Override: | Limit
Status: | Base
Module: | mod_access

The Order directive controls the default access state and the order in which Allow and Deny directives are evaluated. Ordering is one of

Deny,Allow
The Deny directives are evaluated before the Allow directives. Access is allowed by default. Any client which does not match a Deny directive or does match an Allow directive will be allowed access to the server.
Allow,Deny
The Allow directives are evaluated before the Deny directives. Access is denied by default. Any client which does not match an Allow directive or does match a Deny directive will be denied access to the server.
Mutual-failure
Only those hosts which appear on the Allow list and do not appear on the Deny list are granted access. This ordering has the same effect as Order Allow,Deny and is deprecated in favor of that configuration.

Keywords may only be separated by a comma; no whitespace is allowed between them. Note that in all cases every Allow and Deny statement is evaluated.

In the following example, all hosts in the apache.org domain are allowed access; all other hosts are denied access.

Order Deny,Allow
Deny from all
Allow from apache.org

In the next example, all hosts in the apache.org domain are allowed access, except for the hosts which are in the foo.apache.org subdomain, who are denied access. All hosts not in the apache.org domain are denied access because the default state is to deny access to the server.

Order Allow,Deny
Allow from apache.org
Deny from foo.apache.org

On the other hand, if the Order in the last example is changed to Deny,Allow, all hosts will be allowed access. This happens because, regardless of the actual ordering of the directives in the configuration file, the Allow from apache.org will be evaluated last and will override the Deny from foo.apache.org. All hosts not in the apache.org domain will also be allowed access because the default state will change to allow.

The presence of an Order directive can affect access to a part of the server even in the absence of accompanying Allow and Deny directives because of its effect on the default access state. For example,

<Directory /www>
Order Allow,Deny
 </Directory>

will deny all access to the /www directory because the default access state will be set to deny.

The Order directive controls the order of access directive processing only within each phase of the server's configuration processing. This implies, for example, that an Allow or Deny directive occurring in a <Location> section will always be evaluated after an Allow or Deny directive occurring in a <Directory> section or .htaccess file, regardless of the setting of the Order directive. For details on the merging of configuration sections, see the documentation on How Directory, Location and Files sections work.


mod_actions - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_actions

설명: | 이 모듈은 미디어종류나 요청메서드에 따라 CGI 스크립트를 실행한다.
상태: | Base
모듈명: | actions_module
소스파일: | mod_actions.c

요약

이 모듈에는 두가지 지시어가 있다. Action 지시어는 요청하는 파일의 종류에 따라 CGI 스크립트를 실행한다. Script 지시어는 요청이 특정 메서드를 사용할 경우 CGI 스크립트를 실행한다. 그래서 파일을 처리하는 스크립트를 매우 쉽게 실행할 수 있다.

참고

  • mod_cgi
  • CGI로 페이지 내용
  • 아파치에서 핸들러 사용

Action 지시어

설명: | 특정 핸들러나 content-type에 대해 CGI 스크립트를 사용한다
문법: | Action action-type cgi-script
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_actions

이 지시어는 요청이 action-type이면 cgi-script를 실행하는 행동을 서버에 추가한다. cgi-script는 ScriptAlias나 AddHandler를 사용하여 CGI 스크립트로 지정한 리소스의 URL경로이다. action-type에는 핸들러나 MIME content type을 사용할 수 있다. 이 지시어는 PATH_INFO와 PATH_TRANSLATED CGI 표준 환경변수로 요청한 문서의 URL과 파일경로를 전달한다.

예제

# 특정 종류의 파일 요청:
Action image/gif /cgi-bin/images.cgi

# 특정한 확장자를 가진 파일
AddHandler my-file-type .xyz
Action my-file-type /cgi-bin/program.cgi

첫번째 예에서 MIME content type이 image/gif인 파일을 요청하면 지정한 cgi 스크립트 /cgi-bin/images.cgi가 대신 처리한다.

두번째 예에서 확장자가 .xyz인 파일을 요청하면 지정한 cgi 스크립트 /cgi-bin/program.cgi가 대신 처리한다.

참고

  • AddHandler

Script 지시어

설명: | 특정 요청메서드에 대해 CGI 스크립트를 사용한다.
문법: | Script method cgi-script
사용장소: | 주서버설정, 가상호스트, directory
상태: | Base
모듈: | mod_actions

이 지시어는 파일을 method 메서드를 사용하여 요청하면 cgi-script를 실행하는 행동을 서버에 추가한다. cgi-script는 ScriptAlias나 AddHandler를 사용하여 CGI 스크립트로 지정한 리소스의 URL경로이다. 이 지시어는 PATH_INFO와 PATH_TRANSLATED CGI 표준 환경변수로 요청한 문서의 URL과 파일경로를 전달한다.

어떤 메서드 이름이라도 사용할 수 있다. 메서드 이름은 대소문자를 구별한다. 그래서 Script PUT과 Script put은 완전히 다르다.

Script 명령어는 기본적인 행동만을 처리함을 주의하라. CGI 스크립트가 불리거나, 요청한 메서드를 알아서 처리할 수 있는 리소스의 경우 그대로 처리한다. GET 메서드의 Script는 질의아규먼트가 있을때만 (예, foo.html?hi) 사용함을 주의하라. 질의아규먼트가 없다면 정상적으로 요청을 처리한다.

예제

# <ISINDEX>식 검색을 위해
Script GET /cgi-bin/search

# CGI PUT 핸들러
Script PUT /~bob/put.cgi


mod_alias - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_alias

설명: | 파일시스템의 다른 부분들을 문서 계층구조에 포함하고, URL 리다이렉션을 제공한다
상태: | Base
모듈명: | alias_module
소스파일: | mod_alias.c

요약

이 모듈이 제공하는 지시어들을 사용하여 서버가 요청을 받을때 URL을 수정하거나 조작할 수 있다. Alias와 ScriptAlias 지시어는 URL을 파일시스템 경로로 대응한다. 그래서 DocumentRoot 아래에 없는 내용을 웹으로 서비스할 수 있다. 또, ScriptAlias 지시어는 지정한 디렉토리에 CGI 스크립트밖에 없다고 알린다.

Redirect 지시어는 클라이언트에게 다른 URL로 새로운 요청을 하도록 지시한다. 자원을 새로운 장소로 옮긴 경우 자주 사용한다.

mod_alias는 간단한 URL 조작을 위해 설계되었다. 질의문자열 조작과 같은 복잡한 작업은 mod_rewrite가 제공하는 기능을 이용하라.

참고

  • mod_rewrite
  • URL을 파일시스템에 대응

처리 순서

서로 다른 사용장소에서 Alias와 Redirect를 사용하면 다른 지시어와 같이 표준 결합 방법에 따라 처리한다. 그러나 같은 사용장소에 (예를 들어, 같은 <VirtualHost> 섹션에) Alias와 Redirect를 사용하면 아래 순서대로 처리한다.

먼저 모든 Redirect를 처리한 후 Alias를 처리한다. 그래서 Redirect나 RedirectMatch에 해당하는 요청은 절대로 Alias하지 않는다. 그리고 Alias와 Redirect는 설정파일에서 첫번째로 나오는 것을 사용한다.

그래서 여러 지시어가 동일한 하위경로에 해당하는 경우 모든 지시어를 적용하기위해서는 가장 상세한 경로를 먼저 사용해야 한다. 예를 들어, 다음 설정은 의도한대로 동작한다:

Alias /foo/bar /baz
Alias /foo /gaq

그러나 위의 두 지시어 순서를 바꾸면 /foo/bar Alias 이전에 /foo Alias를 적용하므로 항상 두번째 지시어를 무시한다.

Alias 지시어

설명: | URL을 특정 파일시스템 장소로 대응한다
문법: | Alias URL-path file-path|directory-path
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_alias

Alias 지시어를 사용하면 파일시스템에서 DocumentRoot 밖에 있는 문서도 서비스할 수 있다. url-path로 시작하는 (%로 인코딩된) URL을 directory-path로 시작하는 파일에 대응한다.

예제:

Alias /image /ftp/pub/image

http://myserver/image/foo.gif를 요청하면 서버는 /ftp/pub/image/foo.gif 파일을 넘겨준다.

url-path 끝에 /를 포함하면, URL 끝에 /를 사용해야만 영향이 있음을 주의하라. 즉, Alias /icons/ /usr/local/apache/icons/ 설정은 url /icons와 관계가 없다.

대응의 대상을 포함하는 여러 <Directory> 섹션이 필요할지도 모른다. 이 지시어는 <Directory> 섹션을 검사하기 전에 처리하므로, 대응의 대상만 섹션의 영향을 받는다. (그러나 <Location> 섹션은 이 지시어를 처리하기 전에 한번만 검사하므로 지정한 URL 이하 전체에 영향을 준다.)

특히 DocumentRoot 밖에 있는 디렉토리로 Alias를 만들었다면, 직접 대상 디렉토리의 접근을 허용해줘야 한다.

예제:

Alias /image /ftp/pub/image
<Directory /ftp/pub/image>
Order allow,deny
Allow from all
 </Directory>

AliasMatch 지시어

설명: | 정규표현식을 사용하여 URL을 파일시스템 장소로 대응한다
문법: | AliasMatch regex file-path|directory-path
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_alias

이 지시어는 Alias와 같지만, 간단히 URL의 앞부분만 비교하는 대신 표준 정규표현식을 사용한다. 지정한 정규표현식을 URL 경로와 비교하여 맞다면, 서버는 괄호로 묶은 부분을 대체하여 파일명으로 사용한다. 예를 들어, 다음과 같이 /icons 디렉토리를 사용할 수 있다:

AliasMatch ^/icons(.*) /usr/local/apache/icons$1

Redirect 지시어

설명: | 클라이언트가 다른 URL에 접속하도록 요청하는 외부 리다이렉션을 보낸다
문법: | Redirect [status] URL-path URL
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_alias

Redirect 지시어는 이전 URL을 새로운 URL로 대응한다. 클라이언트에게 새로운 URL을 보내고, 클라이언트는 새로운 주소로 다시 한번 접속한다. (%로 인코딩된) URL-path로 시작하는 요청을 받으면 (%로 인코딩된) URL로 시작하는 새로운 URL로 리다이렉션 오류를 보낸다.

예제:

Redirect /service http://foo2.bar.com/service

클라이언트가 http://myserver/service/foo.txt를 요청하면 대신 http://foo2.bar.com/service/foo.txt에 접근하라는 응답을 받는다.

주의

Redirect 지시어는 설정파일에서 나오는 순서와 관계없이 Alias와 ScriptAlias 지시어보다 우선순위가 높다. 또, .htaccess 파일이나 <Directory> 섹션에서 사용하더라도 URL-path에는 상대경로가 아니라 반드시 완전한 URL을 사용해야 한다.

status 아규먼트를 지정하지않으면, "임시 (temporary)" (HTTP 상태 302) 리다이렉션을 보낸다. 즉, 클라이언트에게 자원을 임시로 옮겼다고 알린다. status 아규먼트를 사용하여 다른 HTTP 상태코드를 반환할 수 있다:

permanent
자원을 완전히 옮겼음을 뜻하는 영구 리다이렉션 상태를 (301) 반환한다.
temp
임시 리다이렉션 상태를 (302) 반환한다. 기본값이다.
seeother
자원이 교체되었음을 뜻하는 "참조 (See Other)" 상태를 (303) 반환한다.
gone
자원이 영구히 삭제되었음을 뜻하는 "소멸 (Gone)" 상태를 (410) 반환한다. 이 상태를 사용하면 URL 아규먼트를 사용할 수 없다.

status에 숫자 상태코드를 사용하여 다른 상태코드도 반환할 수 있다. 상태가 300과 399 사이라면 URL 아규먼트를 사용해야 하고, 아니라면 생략해야 한다. 단, 아파치 코드에 상태가 정의되있어야 한다 (http_protocol.c의 send_error_response 함수 참고).

예제:

Redirect permanent /one http://example.com/two
Redirect 303 /three http://example.com/other

RedirectMatch 지시어

설명: | 현재 URL이 정규표현식에 해당하면 외부 리다이렉션을 보낸다
문법: | RedirectMatch [status] regex URL
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_alias

이 지시어는 Redirect와 같지만, 간단히 URL의 앞부분만 비교하는 대신 표준 정규표현식을 사용한다. 지정한 정규표현식을 URL 경로와 비교하여 맞다면, 서버는 괄호로 묶은 부분을 대체하여 파일명으로 사용한다. 예를 들어, 다음은 모든 GIF 파일 요청에 대해 다른 서버의 비슷한 이름을 가진 JPEG 파일로 리다이렉션을 보낸다:

RedirectMatch (.*)\.gif$ http://www.anotherserver.com$1.jpg

RedirectPermanent 지시어

설명: | 클라이언트가 다른 URL에 접속하도록 요청하는 외부 영구 리다이렉션을 보낸다
문법: | RedirectPermanent URL-path URL
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_alias

이 지시어는 클라이언트에게 리다이렉션이 영구적임을 (상태 301) 알린다. Redirect permanent와 정확히 같다.

RedirectTemp 지시어

설명: | 클라이언트가 다른 URL에 접속하도록 요청하는 외부 임시 리다이렉션을 보낸다
문법: | RedirectTemp URL-path URL
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_alias

이 지시어는 클라이언트에게 리다이렉션이 임시적임을 (상태 302) 알린다. Redirect temp와 정확히 같다.

ScriptAlias 지시어

설명: | URL을 특정 파일시스템 장소로 대응하고 대상이 CGI 스크립트라고 알린다
문법: | ScriptAlias URL-path file-path|directory-path
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_alias

ScriptAlias 지시어는 Alias 지시어와 비슷하지만, 추가로 대상 디렉토리에 mod_cgi의 cgi-script 핸들러가 처리할 CGI 스크립트가 있다고 알린다. URL-path로 시작하는 (%로 인코딩된) URL을 파일시스템의 절대경로인 두번째 아규먼트로 시작하는 스크립트에 대응한다.

예제:

ScriptAlias /cgi-bin/ /web/cgi-bin/

http://myserver/cgi-bin/foo를 요청하면 서버는 /web/cgi-bin/foo 스크립트를 실행한다.

ScriptAliasMatch 지시어

설명: | 정규표현식을 사용하여 URL을 특정 파일시스템 장소로 대응하고 대상이 CGI 스크립트라고 알린다
문법: | ScriptAliasMatch regex file-path|directory-path
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_alias

이 지시어는 ScriptAlias와 같지만, 간단히 URL의 앞부분만 비교하는 대신 표준 정규표현식을 사용한다. 지정한 정규표현식을 URL 경로와 비교하여 맞다면, 서버는 괄호로 묶은 부분을 대체하여 파일명으로 사용한다. 예를 들어, 다음과 같이 표준적인 /cgi-bin을 사용할 수 있다:

ScriptAliasMatch ^/cgi-bin(.*) /usr/local/apache/cgi-bin$1


mod_asis - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_asis

설명: | HTTP 헤더를 포함한 파일을 보낸다
상태: | Base
모듈명: | asis_module
소스파일: | mod_asis.c

요약

이 모듈은 아파치가 일반적인 HTTP 헤더의 대부분을 추가하지않고 문서를 보내도록 만드는 send-as-is 핸들러를 제공한다.

그래서 서버는 cgi 스크립트나 nph 스크립트를 사용하지않고도 리다이렉션과 다른 특별한 HTTP 응답 등 어떤 자료도 보낼 수 있다.

과거에 이 모듈은 mime type이 httpd/send-as-is인 파일도 처리했다.

참고

  • mod_headers
  • mod_cern_meta
  • 아파치에서 핸들러 사용

사용법

서버 설정파일에서 파일과 send-as-is 핸들러를 예를 들어 다음과 같이 연결한다.

AddHandler send-as-is asis

아파치는 .asis 확장자를 가진 파일의 내용을 거의 수정하지않고 클라이언트에게 보낸다. 클라이언트는 HTTP 헤더가 필요하므로 빼먹지마라. Status: 헤더도 필요하다. 이 헤더의 내용은 세자리 숫자인 HTTP 응답코드와 그 뒤의 문구이다.

다음은 내용 그대로 클라이언트에게 파일이 리다이력션되었다고 알리는 파일의 예이다.

Status: 301 Now where did I leave that URL
Location: http://xyz.abc.com/foo/bar.html
Content-type: text/html

<html>
<head>
<title>Lame excuses'R'us</title>
</head>
<body>
<h1>Fred's exceptionally wonderful page has moved to
<a href="http://xyz.abc.com/foo/bar.html">Joe's</a> site.
</h1>
</body>
</html>

주의:

서버는 자료를 클라이언트에게 보낼때 항상 Date:와 Server: 헤더를 추가하므로, 파일에 이 헤더가 있으면 안된다. 서버는 Last-Modified 헤더를 추가하지 않는다. 그래서 아마도 이 헤더는 포함해야 한다.


mod_auth - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_auth

Description: | User authentication using text files
Status: | Base
Module Identifier: | auth_module
Source File: | mod_auth.c
Compatibility: | Available only in versions prior to 2.1

Summary

This module allows the use of HTTP Basic Authentication to restrict access by looking up users in plain text password and group files. Similar functionality and greater scalability is provided by mod_auth_dbm. HTTP Digest Authentication is provided by mod_auth_digest.

See also

  • Require
  • Satisfy
  • AuthName
  • AuthType

AuthAuthoritative Directive

Description: | Sets whether authorization and authentication are passed to lower level modules
Syntax: | AuthAuthoritative On|Off
Default: | AuthAuthoritative On
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Base
Module: | mod_auth

Setting the AuthAuthoritative directive explicitly to Off allows for both authentication and authorization to be passed on to lower level modules (as defined in the modules.c files) if there is no userID or rule matching the supplied userID. If there is a userID and/or rule specified; the usual password and access checks will be applied and a failure will give an "Authentication Required" reply.

So if a userID appears in the database of more than one module; or if a valid Require directive applies to more than one module; then the first module will verify the credentials; and no access is passed on; regardless of the AuthAuthoritative setting.

A common use for this is in conjunction with one of the database modules; such as mod_auth_dbm, mod_auth_msql, and mod_auth_anon. These modules supply the bulk of the user credential checking; but a few (administrator) related accesses fall through to a lower level with a well protected AuthUserFile.

By default control is not passed on and an unknown userID or rule will result in an "Authentication Required" reply. Not setting it thus keeps the system secure and forces an NCSA compliant behaviour.

Security

Do consider the implications of allowing a user to allow fall-through in his .htaccess file; and verify that this is really what you want; Generally it is easier to just secure a single .htpasswd file, than it is to secure a database such as mSQL. Make sure that the AuthUserFile and the AuthGroupFile are stored outside the document tree of the web-server; do not put them in the directory that they protect. Otherwise, clients will be able to download the AuthUserFile and the AuthGroupFile.

AuthGroupFile Directive

Description: | Sets the name of a text file containing the list of user groups for authentication
Syntax: | AuthGroupFile file-path
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Base
Module: | mod_auth

The AuthGroupFile directive sets the name of a textual file containing the list of user groups for user authentication. File-path is the path to the group file. If it is not absolute, it is treated as relative to the ServerRoot.

Each line of the group file contains a groupname followed by a colon, followed by the member usernames separated by spaces.

Example:

mygroup: bob joe anne

Note that searching large text files is very inefficient; AuthDBMGroupFile provides a much better performance.

Security

Make sure that the AuthGroupFile is stored outside the document tree of the web-server; do not put it in the directory that it protects. Otherwise, clients may be able to download the AuthGroupFile.

AuthUserFile Directive

Description: | Sets the name of a text file containing the list of users and passwords for authentication
Syntax: | AuthUserFile file-path
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Base
Module: | mod_auth

The AuthUserFile directive sets the name of a textual file containing the list of users and passwords for user authentication. File-path is the path to the user file. If it is not absolute (i.e., if it doesn't begin with a slash), it is treated as relative to the ServerRoot.

Each line of the user file contains a username followed by a colon, followed by the encrypted password. If the same user ID is defined multiple times, mod_auth will use the first occurrence to verify the password.

The utility htpasswd which is installed as part of the binary distribution, or which can be found in src/support, is used to maintain this password file. See the man page for more details. In short:

Create a password file Filename with username as the initial ID. It will prompt for the password:

htpasswd -c Filename username

Add or modify username2 in the password file Filename:

htpasswd Filename username2

Note that searching large text files is very inefficient; AuthDBMUserFile should be used instead.

Security

Make sure that the AuthUserFile is stored outside the document tree of the web-server. Do not put it in the directory that it protects. Otherwise, clients may be able to download the AuthUserFile.


mod_auth_anon - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_auth_anon

Description: | Allows "anonymous" user access to authenticated areas
Status: | Extension
Module Identifier: | auth_anon_module
Source File: | mod_auth_anon.c
Compatibility: | Available only in versions prior to 2.1

Summary

This module does access control in a manner similar to anonymous-ftp sites; i.e. have a 'magic' user id 'anonymous' and the email address as a password. These email addresses can be logged.

Combined with other (database) access control methods, this allows for effective user tracking and customization according to a user profile while still keeping the site open for 'unregistered' users. One advantage of using Auth-based user tracking is that, unlike magic-cookies and funny URL pre/postfixes, it is completely browser independent and it allows users to share URLs.

Example

The example below (when combined with the Auth directives of a htpasswd-file based (or GDM, mSQL etc.) base access control system allows users in as 'guests' with the following properties:

  • It insists that the user enters a userID. (Anonymous_NoUserID)
  • It insists that the user enters a password. (Anonymous_MustGiveEmail)
  • The password entered must be a valid email address, ie. contain at least one '@' and a '.'. (Anonymous_VerifyEmail)
  • The userID must be one of anonymous guest www test welcome and comparison is not case sensitive. (Anonymous)
  • And the Email addresses entered in the passwd field are logged to the error log file. (Anonymous_LogEmail)

Excerpt of httpd.conf:

Anonymous_NoUserID off
Anonymous_MustGiveEmail on
Anonymous_VerifyEmail on
Anonymous_LogEmail on
Anonymous anonymous guest www test welcome

AuthName "Use 'anonymous' & Email address for guest entry"
AuthType basic

# An AuthUserFile/AuthDBUserFile/AuthDBMUserFile
# directive must be specified, or use
# Anonymous_Authoritative for public access.
# In the .htaccess for the public directory, add:
<Files *>
Order Deny,Allow
Allow from all

Require valid-user
 </Files>

Anonymous Directive

Description: | Specifies userIDs that are allowed access without password verification
Syntax: | Anonymous user [user] ...
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_anon

A list of one or more 'magic' userIDs which are allowed access without password verification. The userIDs are space separated. It is possible to use the ' and " quotes to allow a space in a userID as well as the \ escape character.

Please note that the comparison is case-IN-sensitive.
I strongly suggest that the magic username 'anonymous' is always one of the allowed userIDs.

Example:

Anonymous anonymous "Not Registered" "I don't know"

This would allow the user to enter without password verification by using the userIDs "anonymous", "AnonyMous", "Not Registered" and "I Don't Know".

Anonymous_Authoritative Directive

Description: | Configures if authorization will fall-through to other methods
Syntax: | Anonymous_Authoritative On|Off
Default: | Anonymous_Authoritative Off
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_anon

When set On, there is no fall-through to other authentication methods. So if a userID does not match the values specified in the Anonymous directive, access is denied.

Be sure you know what you are doing when you decide to switch it on. And remember that the order in which the Authentication modules are queried is defined in the modules.c files at compile time.

Anonymous_LogEmail Directive

Description: | Sets whether the password entered will be logged in the error log
Syntax: | Anonymous_LogEmail On|Off
Default: | Anonymous_LogEmail On
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_anon

When set On, the default, the 'password' entered (which hopefully contains a sensible email address) is logged in the error log.

Anonymous_MustGiveEmail Directive

Description: | Specifies whether blank passwords are allowed
Syntax: | Anonymous_MustGiveEmail On|Off
Default: | Anonymous_MustGiveEmail On
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_anon

Specifies whether the user must specify an email address as the password. This prohibits blank passwords.

Anonymous_NoUserID Directive

Description: | Sets whether the userID field may be empty
Syntax: | Anonymous_NoUserID On|Off
Default: | Anonymous_NoUserID Off
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_anon

When set On, users can leave the userID (and perhaps the password field) empty. This can be very convenient for MS-Explorer users who can just hit return or click directly on the OK button; which seems a natural reaction.

Anonymous_VerifyEmail Directive

Description: | Sets whether to check the password field for a correctly formatted email address
Syntax: | Anonymous_VerifyEmail On|Off
Default: | Anonymous_VerifyEmail Off
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_anon

When set On the 'password' entered is checked for at least one '@' and a '.' to encourage users to enter valid email addresses (see the above Anonymous_LogEmail).


mod_auth_dbm - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_auth_dbm

Description: | Provides for user authentication using DBM files
Status: | Extension
Module Identifier: | auth_dbm_module
Source File: | mod_auth_dbm.c
Compatibility: | Available only in versions prior to 2.1

Summary

This module provides for HTTP Basic Authentication, where the usernames and passwords are stored in DBM type database files. It is an alternative to the plain text password files provided by mod_auth.

See also

  • AuthName
  • AuthType
  • Require
  • Satisfy

AuthDBMAuthoritative Directive

Description: | Sets whether authentication and authorization will be passed on to lower level modules
Syntax: | AuthDBMAuthoritative On|Off
Default: | AuthDBMAuthoritative On
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_dbm

Setting the AuthDBMAuthoritative directive explicitly to Off allows for both authentication and authorization to be passed on to lower level modules (as defined in the modules.c files) if there is no userID or rule matching the supplied userID. If there is a userID and/or rule specified; the usual password and access checks will be applied and a failure will give an "Authentication Required" reply.

So if a userID appears in the database of more than one module; or if a valid Require directive applies to more than one module; then the first module will verify the credentials; and no access is passed on; regardless of the AuthDBMAuthoritative setting.

A common use for this is in conjunction with one of the basic auth modules; such as mod_auth. Whereas this DBM module supplies the bulk of the user credential checking; a few (administrator) related accesses fall through to a lower level with a well protected .htpasswd file.

By default, control is not passed on and an unknown userID or rule will result in an "Authentication Required" reply. Not setting it thus keeps the system secure and forces an NCSA compliant behaviour.

Security:

Do consider the implications of allowing a user to allow fall-through in his .htaccess file; and verify that this is really what you want; Generally it is easier to just secure a single .htpasswd file, than it is to secure a database which might have more access interfaces.

AuthDBMGroupFile Directive

Description: | Sets the name of the database file containing the list of user groups for authentication
Syntax: | AuthDBMGroupFile file-path
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_dbm

The AuthDBMGroupFile directive sets the name of a DBM file containing the list of user groups for user authentication. File-path is the absolute path to the group file.

The group file is keyed on the username. The value for a user is a comma-separated list of the groups to which the users belongs. There must be no whitespace within the value, and it must never contain any colons.

Security: make sure that the AuthDBMGroupFile is stored outside the document tree of the web-server; do not put it in the directory that it protects. Otherwise, clients will be able to download the AuthDBMGroupFile unless otherwise protected.

Combining Group and Password DBM files: In some cases it is easier to manage a single database which contains both the password and group details for each user. This simplifies any support programs that need to be written: they now only have to deal with writing to and locking a single DBM file. This can be accomplished by first setting the group and password files to point to the same DBM:

AuthDBMGroupFile /www/userbase
AuthDBMUserFile /www/userbase

The key for the single DBM is the username. The value consists of

Unix Crypt-ed Password:List of Groups[:(ignored)]

The password section contains the encrypted password as before. This is followed by a colon and the comma separated list of groups. Other data may optionally be left in the DBM file after another colon; it is ignored by the authentication module. This is what www.telescope.org uses for its combined password and group database.

AuthDBMType Directive

Description: | Sets the type of database file that is used to store passwords
Syntax: | AuthDBMType default|SDBM|GDBM|NDBM|DB
Default: | AuthDBMType default
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_dbm
Compatibility: | Available in version 2.0.30 and later.

Sets the type of database file that is used to store the passwords. The default database type is determined at compile time. The availability of other types of database files also depends on compile-time settings.

It is crucial that whatever program you use to create your password files is configured to use the same type of database.

AuthDBMUserFile Directive

Description: | Sets thename of a database file containing the list of users and passwords for authentication
Syntax: | AuthDBMUserFile file-path
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_auth_dbm

The AuthDBMUserFile directive sets the name of a DBM file containing the list of users and passwords for user authentication. File-path is the absolute path to the user file.

The user file is keyed on the username. The value for a user is the encrypted password, optionally followed by a colon and arbitrary data. The colon and the data following it will be ignored by the server.

Security:

Make sure that the AuthDBMUserFile is stored outside the document tree of the web-server; do not put it in the directory that it protects. Otherwise, clients will be able to download the AuthDBMUserFile.

Important compatibility note: The implementation of "dbmopen" in the apache modules reads the string length of the hashed values from the DBM data structures, rather than relying upon the string being NULL-appended. Some applications, such as the Netscape web server, rely upon the string being NULL-appended, so if you are having trouble using DBM files interchangeably between applications this may be a part of the problem.

A perl script called dbmmanage is included with Apache. This program can be used to create and update DBM format password files for use with this module.


mod_auth_digest - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_auth_digest

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.
설명: | MD5 Digest Authentication을 사용한 사용자인증.
상태: | Experimental
모듈명: | auth_digest_module
소스파일: | mod_auth_digest.c

요약

이 모듈은 HTTP Digest Authentication을 구현한다. 그러나 많은 테스트를 거치지 않은 실험적인 모듈이다.

참고

  • AuthName
  • AuthType
  • Require
  • Satisfy

Digest Authentication 사용하기

MD5 Digest authentication은 매우 쉽게 사용할 수 있다. 모든 AuthGroupFile을 AuthDigestGroupFile로 변경하고, AuthType Basic과 AuthUserFile 대신 AuthType Digest와 AuthDigestFile을 사용하여 간단히 인증을 설정할 수 있다. 그리고 최소한 보호하려는 영역의 기본 URI을 AuthDigestDomain 지시어에 사용한다.

htdigest 도구를 사용하여 사용자 (문자)파일을 만들 수 있다.

예제:

<Location /private/>
AuthType Digest
AuthName "private area"
AuthDigestDomain /private/ http://mirror.my.dom/private2/
AuthDigestFile /web/auth/.digest_pw
Require valid-user
 </Location>

주의

Digest authentication은 Basic authentication보다 더 안전한 암호시스템을 제공하지만, 브라우저가 지원해야 한다. 2002년 11월 현재 digest authentication을 지원하는 브라우저에는 Opera, (질의문자열과 함께 사용하면 안되지만 - 해결방법은 아래 "MS Internet Explorer 문제 해결하기"를 참고) MS Internet Explorer, Amaya, Mozilla, 버전 7 이후의 Netscape 등이 있다. digest authentication이 basic authentication 만큼 널리 구현되지 않았기때문에 주의해서 사용해야 한다.

MS Internet Explorer 문제 해결하기

현재 Internet Explorer는 Digest authentication 사용시 질의문자열이 있는 GET 요청을 RFC와 다르게 처리하는 문제가 있다. 몇가지 방법으로 이 문제를 해결할 수 있다.

첫번째는 프로그램에 자료를 넘겨주기위해 GET 대신 POST 요청을 사용하는 방법이다. 이 방법이 가능하다면 가장 간단한 해결책이다.

또, 아파치 2.0.51부터 AuthDigestEnableQueryStringHack 환경변수를 제공하여 문제를 해결한다. 요청에 AuthDigestEnableQueryStringHack을 설정하면 아파치는 MSIE 버그를 피해갈 조치를 취하고 요청 URI를 digest 비교에서 제외한다. 이 방법은 다음과 같이 사용한다.

MSIE에서 Digest Authentication 사용하기:

BrowserMatch "MSIE" AuthDigestEnableQueryStringHack=On

선택적인 환경변수 설정에 대한 자세한 내용은 BrowserMatch 지시어를 참고하라.

AuthDigestAlgorithm 지시어

설명: | digest authentication에서 challenge와 response hash를 계산하는 알고리즘을 선택한다
문법: | AuthDigestAlgorithm MD5|MD5-sess
기본값: | AuthDigestAlgorithm MD5
사용장소: | directory, .htaccess
Override 옵션: | AuthConfig
상태: | Experimental
모듈: | mod_auth_digest

AuthDigestAlgorithm 지시어는 challenge와 response hash를 계산하는 알고리즘을 선택한다.

MD5-sess는 아직 완전히 구현되지 않았다.

AuthDigestDomain 지시어

설명: | digest authentication에서 같은 보호영역에 속하는 URI들
문법: | AuthDigestDomain URI [URI] ...
사용장소: | directory, .htaccess
Override 옵션: | AuthConfig
상태: | Experimental
모듈: | mod_auth_digest

AuthDigestDomain 지시어는 같은 보호영역에 있는 (예를 들어 같은 영역과 사용자명/암호 정보를 사용하는) URI들을 지정한다. 지정한 URI는 접두사로 사용한다. 즉, 클라이언트는 URI "아래" 모두를 같은 사용자명/암호로 보호한다고 가정한다. URI는 (즉, 스킴(scheme), 호스트, 포트 등을 포함하는) 절대 URL이거나 상대 URI이다.

이 지시어는 항상 지정해야 하며, 최소한 영역들의 기본 URI(들)를 포함해야 한다. 생략하면 클라이언트는 이 서버로 보내는 모든 요청에 Authorization 헤더를 포함한다. 그러면 요청의 크기가 커지며, AuthDigestNcCheck를 사용한다면 성능에 나쁜 영향을 줄 수 있다.

다른 서버의 URI를 지정하면, (이를 이해하는) 클라이언트는 여러 서버마다 매번 사용자에게 묻지않고 같은 사용자명/암호를 사용할 수 있다.

AuthDigestFile 지시어

설명: | digest authentication에 사용할 사용자명과 인코딩된 암호 목록을 저장한 문서파일 위치
문법: | AuthDigestFile file-path
사용장소: | directory, .htaccess
Override 옵션: | AuthConfig
상태: | Experimental
모듈: | mod_auth_digest

AuthDigestFile 지시어는 digest authentication에 사용할 사용자명과 인코딩된 암호를 저장하는 문서파일명을 지정한다. File-path는 사용자정보 파일의 절대경로이다.

이 파일 내용은 특별한 형식이 있다. 아파치 배포본의 support/ 하위디렉토리에 있는 htdigest 도구를 사용하여 이런 형식의 파일을 만들 수 있다.

AuthDigestGroupFile 지시어

설명: | digest authentication에 사용할 그룹 목록을 저장한 문서파일명
문법: | AuthDigestGroupFile file-path
사용장소: | directory, .htaccess
Override 옵션: | AuthConfig
상태: | Experimental
모듈: | mod_auth_digest

AuthDigestGroupFile 지시어는 그룹과 그룹의 구성원들(사용자명) 목록을 저장하는 문서파일명을 지정한다. File-path는 그룹정보 파일의 절대경로이다.

그룹파일은 그룹명 뒤에 콜론, 그뒤에 그룹에 속한 사용자명들을 공백으로 구분하여 한 줄로 기록한다. 예를 들어 다음과 같다.

mygroup: bob joe anne

큰 문자파일을 검색하는 것이 매우 비효율적임을 명심하라.

보안:

AuthGroupFile을 웹서버 문서들 밖에 저장해야 한다. 그룹파일이 보호하는 디렉토리 안에 그룹파일을 두지 마라. 그렇지 않으면 클라이언트가 AuthGroupFile을 다운받을 수도 있다.

AuthDigestNcCheck 지시어

설명: | 서버가 보내는 nonce-count를 검사할지 여부
문법: | AuthDigestNcCheck On|Off
기본값: | AuthDigestNcCheck Off
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_auth_digest
아직 구현되지 않았다.

AuthDigestNonceFormat 지시어

설명: | nonce를 만드는 방법을 결정한다
문법: | AuthDigestNonceFormat format
사용장소: | directory, .htaccess
Override 옵션: | AuthConfig
상태: | Experimental
모듈: | mod_auth_digest
아직 구현되지 않았다.

AuthDigestNonceLifetime 지시어

설명: | 서버 nonce가 유효한 기간
문법: | AuthDigestNonceLifetime seconds
기본값: | AuthDigestNonceLifetime 300
사용장소: | directory, .htaccess
Override 옵션: | AuthConfig
상태: | Experimental
모듈: | mod_auth_digest

AuthDigestNonceLifetime 지시어는 서버 nonce가 유효한 기간을 조절한다. 클라이언트가 만기된 nonce를 가지고 서버에 접근하면 서버는 stale=true와 함께 401을 반환한다. seconds가 0보다 크면 nonce가 유효한 기간을 지정한다. 아마도 10 초보다 작게 설정하면 안된다. seconds가 0보다 작으면 nonce는 영원히 만기되지 않는다.

AuthDigestQop 지시어

설명: | digest authentication가 사용할 보호수준(quality-of-protection)을 지정한다.
문법: | AuthDigestQop none|auth|auth-int [auth|auth-int]
기본값: | AuthDigestQop auth
사용장소: | directory, .htaccess
Override 옵션: | AuthConfig
상태: | Experimental
모듈: | mod_auth_digest

AuthDigestQop 지시어는 보호수준(quality-of-protection)을 지정한다. auth는 (사용자명/암호) 인증만 하고, auth-int는 인증과 완결성 검사를 (MD5 해쉬도 계산하여 검사한다) 한다. none은 (완결성 검사를 하지않는) 오래된 RFC-2069 digest 알고리즘을 사용한다. auth와 auth-int를 모두 지정할 수 있다. 이 경우 브라우저는 어떤 것을 사용할지 선택한다. 브라우저가 어던 이유에서건 challenge를 좋아하지 않는다면 none을 사용해야 한다.

auth-int는 아직 구현되지 않았다.

AuthDigestShmemSize 지시어

설명: | 클라이언트를 추적하기위해 할당하는 공유메모리량
문법: | AuthDigestShmemSize size
기본값: | AuthDigestShmemSize 1000
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_auth_digest

AuthDigestShmemSize 지시어는 클라이언트를 추적하기위해 서버가 시작할때 할당하는 공유메모리량을 정의한다. 공유메모리는 최소한 하나의 클라이언트를 추적하기위해 필요한 공간보다 작을 수 없음을 주의하라. 이 값은 시스템에 따라 다르다. 정확한 값을 알려면 AuthDigestShmemSize를 0으로 설정하고 서버를 시작한후 오류문을 참고하라.

size는 보통 바이트 단위이지만, 뒤에 K나 M을 사용하여 KBytes나 MBytes를 나타낼 수 있다. 예를 들어, 다음 지시어들은 모두 같다:

AuthDigestShmemSize 1048576
AuthDigestShmemSize 1024K
AuthDigestShmemSize 1M


mod_auth_ldap - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_auth_ldap

Description: | Allows an LDAP directory to be used to store the database for HTTP Basic authentication.
Status: | Experimental
Module Identifier: | auth_ldap_module
Source File: | mod_auth_ldap.c
Compatibility: | Available in version 2.0.41 and later

Summary

mod_auth_ldap supports the following features:

  • Known to support the OpenLDAP SDK (both 1.x and 2.x), Novell LDAP SDK and the iPlanet (Netscape) SDK.
  • Complex authorization policies can be implemented by representing the policy with LDAP filters.
  • Support for Microsoft FrontPage allows FrontPage users to control access to their webs, while retaining LDAP for user authentication.
  • Uses extensive caching of LDAP operations via mod_ldap.
  • Support for LDAP over SSL (requires the Netscape SDK) or TLS (requires the OpenLDAP 2.x SDK or Novell LDAP SDK).

See also

  • mod_ldap

Contents

  • Operation
    • The Authentication Phase
    • The Authorization Phase
  • The require Directives
    • require valid-user
    • require user
    • require group
    • require dn
    • require ldap-attribute
  • Examples
  • Using TLS
  • Using SSL
  • Using Microsoft FrontPage with mod_auth_ldap
    • How It Works
    • Caveats

Operation

There are two phases in granting access to a user. The first phase is authentication, in which mod_auth_ldap verifies that the user's credentials are valid. This also called the search/bind phase. The second phase is authorization, in which mod_auth_ldap determines if the authenticated user is allowed access to the resource in question. This is also known as the compare phase.

The Authentication Phase

During the authentication phase, mod_auth_ldap searches for an entry in the directory that matches the username that the HTTP client passes. If a single unique match is found, then mod_auth_ldap attempts to bind to the directory server using the DN of the entry plus the password provided by the HTTP client. Because it does a search, then a bind, it is often referred to as the search/bind phase. Here are the steps taken during the search/bind phase.

  1. Generate a search filter by combining the attribute and filter provided in the AuthLDAPURL directive with the username passed by the HTTP client.
  2. Search the directory using the generated filter. If the search does not return exactly one entry, deny or decline access.
  3. Fetch the distinguished name of the entry retrieved from the search and attempt to bind to the LDAP server using the DN and the password passed by the HTTP client. If the bind is unsuccessful, deny or decline access.

The following directives are used during the search/bind phase

AuthLDAPURL | Specifies the LDAP server, the base DN, the attribute to use in the search, as well as the extra search filter to use.
AuthLDAPBindDN | An optional DN to bind with during the search phase.
AuthLDAPBindPassword | An optional password to bind with during the search phase.

The Authorization Phase

During the authorization phase, mod_auth_ldap attempts to determine if the user is authorized to access the resource. Many of these checks require mod_auth_ldap to do a compare operation on the LDAP server. This is why this phase is often referred to as the compare phase. mod_auth_ldap accepts the following Require directives to determine if the credentials are acceptable:

  • Grant access if there is a require valid-user directive.
  • Grant access if there is a require user directive, and the username in the directive matches the username passed by the client.
  • Grant access if there is a require dn directive, and the DN in the directive matches the DN fetched from the LDAP directory.
  • Grant access if there is a require group directive, and the DN fetched from the LDAP directory (or the username passed by the client) occurs in the LDAP group.
  • Grant access if there is a require ldap-attribute directive, and the attribute fetched from the LDAP directory matches the given value.
  • otherwise, deny or decline access

mod_auth_ldap uses the following directives during the compare phase:

AuthLDAPURL | The attribute specified in the URL is used in compare operations for the require user operation.
AuthLDAPCompareDNOnServer | Determines the behavior of the require dn directive.
AuthLDAPGroupAttribute | Determines the attribute to use for comparisons in the require group directive.
AuthLDAPGroupAttributeIsDN | Specifies whether to use the user DN or the username when doing comparisons for the require group directive.

The require Directives

Apache's Require directives are used during the authorization phase to ensure that a user is allowed to access a resource.

require valid-user

If this directive exists, mod_auth_ldap grants access to any user that has successfully authenticated during the search/bind phase.

require user

The require user directive specifies what usernames can access the resource. Once mod_auth_ldap has retrieved a unique DN from the directory, it does an LDAP compare operation using the username specified in the require user to see if that username is part of the just-fetched LDAP entry. Multiple users can be granted access by putting multiple usernames on the line, separated with spaces. If a username has a space in it, then it must be surrounded with double quotes. Multiple users can also be granted access by using multiple require user directives, with one user per line. For example, with a AuthLDAPURL of ldap://ldap/o=Airius?cn (i.e., cn is used for searches), the following require directives could be used to restrict access:

require user "Barbara Jenson"
require user "Fred User"
require user "Joe Manager"

Because of the way that mod_auth_ldap handles this directive, Barbara Jenson could sign on as Barbara Jenson, Babs Jenson or any other cn that she has in her LDAP entry. Only the single require user line is needed to support all values of the attribute in the user's entry.

If the uid attribute was used instead of the cn attribute in the URL above, the above three lines could be condensed to

require user bjenson fuser jmanager

require group

This directive specifies an LDAP group whose members are allowed access. It takes the distinguished name of the LDAP group. Note: Do not surround the group name with quotes. For example, assume that the following entry existed in the LDAP directory:

dn: cn=Administrators, o=Airius
objectClass: groupOfUniqueNames
uniqueMember: cn=Barbara Jenson, o=Airius
uniqueMember: cn=Fred User, o=Airius

The following directive would grant access to both Fred and Barbara:

require group cn=Administrators, o=Airius

Behavior of this directive is modified by the AuthLDAPGroupAttribute and AuthLDAPGroupAttributeIsDN directives.

require dn

The require dn directive allows the administrator to grant access based on distinguished names. It specifies a DN that must match for access to be granted. If the distinguished name that was retrieved from the directory server matches the distinguished name in the require dn, then authorization is granted. Note: do not surround the distinguished name with quotes.

The following directive would grant access to a specific DN:

require dn cn=Barbara Jenson, o=Airius

Behavior of this directive is modified by the AuthLDAPCompareDNOnServer directive.

require ldap-attribute

The require ldap-attribute directive allows the administrator to grant access based on attributes of the authenticated user in the LDAP directory. If the attribute in the directory matches the value given in the configuration, access is granted.

The following directive would grant access to anyone with the attribute employeeType = active

require ldap-attribute employeeType=active

Multiple attribute/value pairs can be specified on the same line separated by spaces or they can be specified in multiple require ldap-attribute directives. The effect of listing multiple attribute/values pairs is an OR operation. Access will be granted if any of the listed attribute values match the value of a corresponding attribute in the user object. If the value of the attribute contains a space, only the value must be within double quotes.

The following directive would grant access to anyone with the city attribute equal to "San Jose" or status equal to "Active"

require ldap-attribute city="San Jose" status=active

Examples

  • Grant access to anyone who exists in the LDAP directory, using their UID for searches.

    AuthLDAPURL ldap://ldap1.airius.com:389/ou=People, o=Airius?uid?sub?(objectClass=*)
    require valid-user

  • The next example is the same as above; but with the fields that have useful defaults omitted. Also, note the use of a redundant LDAP server.

    AuthLDAPURL ldap://ldap1.airius.com ldap2.airius.com/ou=People, o=Airius
    require valid-user

  • The next example is similar to the previous one, but is uses the common name instead of the UID. Note that this could be problematical if multiple people in the directory share the same cn, because a search on cn must return exactly one entry. That's why this approach is not recommended: it's a better idea to choose an attribute that is guaranteed unique in your directory, such as uid.

    AuthLDAPURL ldap://ldap.airius.com/ou=People, o=Airius?cn
    require valid-user

  • Grant access to anybody in the Administrators group. The users must authenticate using their UID.

    AuthLDAPURL ldap://ldap.airius.com/o=Airius?uid
    require group cn=Administrators, o=Airius

  • The next example assumes that everyone at Airius who carries an alphanumeric pager will have an LDAP attribute of qpagePagerID. The example will grant access only to people (authenticated via their UID) who have alphanumeric pagers:

    AuthLDAPURL ldap://ldap.airius.com/o=Airius?uid??(qpagePagerID=*)
    require valid-user

  • The next example demonstrates the power of using filters to accomplish complicated administrative requirements. Without filters, it would have been necessary to create a new LDAP group and ensure that the group's members remain synchronized with the pager users. This becomes trivial with filters. The goal is to grant access to anyone who has a filter, plus grant access to Joe Manager, who doesn't have a pager, but does need to access the same resource:

    AuthLDAPURL ldap://ldap.airius.com/o=Airius?uid??(|(qpagePagerID=*)(uid=jmanager))
    require valid-user

    This last may look confusing at first, so it helps to evaluate what the search filter will look like based on who connects, as shown below. The text in blue is the part that is filled in using the attribute specified in the URL. The text in red is the part that is filled in using the filter specified in the URL. The text in green is filled in using the information that is retrieved from the HTTP client. If Fred User connects as fuser, the filter would look like

    (&(|(qpagePagerID=*)(uid=jmanager))(uid=fuser))

    The above search will only succeed if fuser has a pager. When Joe Manager connects as jmanager, the filter looks like

    (&(|(qpagePagerID=*)(uid=jmanager))(uid=jmanager))

    The above search will succeed whether jmanager has a pager or not.

Using TLS

To use TLS, see the mod_ldap directives LDAPTrustedCA and LDAPTrustedCAType.

Using SSL

To use SSL, see the mod_ldap directives LDAPTrustedCA and LDAPTrustedCAType.

To specify a secure LDAP server, use ldaps:// in the AuthLDAPURL directive, instead of ldap://.

Using Microsoft FrontPage with mod_auth_ldap

Normally, FrontPage uses FrontPage-web-specific user/group files (i.e., the mod_auth module) to handle all authentication. Unfortunately, it is not possible to just change to LDAP authentication by adding the proper directives, because it will break the Permissions forms in the FrontPage client, which attempt to modify the standard text-based authorization files.

Once a FrontPage web has been created, adding LDAP authentication to it is a matter of adding the following directives to every .htaccess file that gets created in the web

AuthLDAPURL            "the url"
AuthLDAPAuthoritative  off
AuthLDAPFrontPageHack  on

AuthLDAPAuthoritative must be off to allow mod_auth_ldap to decline group authentication so that Apache will fall back to file authentication for checking group membership. This allows the FrontPage-managed group file to be used.

How It Works

FrontPage restricts access to a web by adding the require valid-user directive to the .htaccess files. If AuthLDAPFrontPageHack is not on, the require valid-user directive will succeed for any user who is valid as far as LDAP is concerned. This means that anybody who has an entry in the LDAP directory is considered a valid user, whereas FrontPage considers only those people in the local user file to be valid. The purpose of the hack is to force Apache to consult the local user file (which is managed by FrontPage) - instead of LDAP - when handling the require valid-user directive.

Once directives have been added as specified above, FrontPage users will be able to perform all management operations from the FrontPage client.

Caveats

  • When choosing the LDAP URL, the attribute to use for authentication should be something that will also be valid for putting into a mod_auth user file. The user ID is ideal for this.
  • When adding users via FrontPage, FrontPage administrators should choose usernames that already exist in the LDAP directory (for obvious reasons). Also, the password that the administrator enters into the form is ignored, since Apache will actually be authenticating against the password in the LDAP database, and not against the password in the local user file. This could cause confusion for web administrators.
  • Apache must be compiled with mod_auth in order to use FrontPage support. This is because Apache will still use the mod_auth group file for determine the extent of a user's access to the FrontPage web.
  • The directives must be put in the .htaccess files. Attempting to put them inside <Location> or <Directory> directives won't work. This is because mod_auth_ldap has to be able to grab the AuthUserFile directive that is found in FrontPage .htaccess files so that it knows where to look for the valid user list. If the mod_auth_ldap directives aren't in the same .htaccess file as the FrontPage directives, then the hack won't work, because mod_auth_ldap will never get a chance to process the .htaccess file, and won't be able to find the FrontPage-managed user file.

AuthLDAPAuthoritative Directive

Description: | Prevent other authentication modules from authenticating the user if this one fails
Syntax: | AuthLDAPAuthoritative on|off
Default: | AuthLDAPAuthoritative on
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

Set to off if this module should let other authentication modules attempt to authenticate the user, should authentication with this module fail. Control is only passed on to lower modules if there is no DN or rule that matches the supplied user name (as passed by the client).

AuthLDAPBindDN Directive

Description: | Optional DN to use in binding to the LDAP server
Syntax: | AuthLDAPBindDN distinguished-name
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

An optional DN used to bind to the server when searching for entries. If not provided, mod_auth_ldap will use an anonymous bind.

AuthLDAPBindPassword Directive

Description: | Password used in conjuction with the bind DN
Syntax: | AuthLDAPBindPassword password
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

A bind password to use in conjunction with the bind DN. Note that the bind password is probably sensitive data, and should be properly protected. You should only use the AuthLDAPBindDN and AuthLDAPBindPassword if you absolutely need them to search the directory.

AuthLDAPCharsetConfig Directive

Description: | Language to charset conversion configuration file
Syntax: | AuthLDAPCharsetConfig file-path
Context: | server config
Status: | Experimental
Module: | mod_auth_ldap

The AuthLDAPCharsetConfig directive sets the location of the language to charset conversion configuration file. File-path is relative to the ServerRoot. This file specifies the list of language extensions to character sets. Most administrators use the provided charset.conv file, which associates common language extensions to character sets.

The file contains lines in the following format:

Language-Extension charset [Language-String] ...

The case of the extension does not matter. Blank lines, and lines beginning with a hash character (#) are ignored.

AuthLDAPCompareDNOnServer Directive

Description: | Use the LDAP server to compare the DNs
Syntax: | AuthLDAPCompareDNOnServer on|off
Default: | AuthLDAPCompareDNOnServer on
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

When set, mod_auth_ldap will use the LDAP server to compare the DNs. This is the only foolproof way to compare DNs. mod_auth_ldap will search the directory for the DN specified with the require dn directive, then, retrieve the DN and compare it with the DN retrieved from the user entry. If this directive is not set, mod_auth_ldap simply does a string comparison. It is possible to get false negatives with this approach, but it is much faster. Note the mod_ldap cache can speed up DN comparison in most situations.

AuthLDAPDereferenceAliases Directive

Description: | When will the module de-reference aliases
Syntax: | AuthLDAPDereferenceAliases never|searching|finding|always
Default: | AuthLDAPDereferenceAliases Always
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

This directive specifies when mod_auth_ldap will de-reference aliases during LDAP operations. The default is always.

AuthLDAPEnabled Directive

Description: | Turn on or off LDAP authentication
Syntax: | AuthLDAPEnabled on|off
Default: | AuthLDAPEnabled on
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

Set to off to disable mod_auth_ldap in certain directories. This is useful if you have mod_auth_ldap enabled at or near the top of your tree, but want to disable it completely in certain locations.

AuthLDAPFrontPageHack Directive

Description: | Allow LDAP authentication to work with MS FrontPage
Syntax: | AuthLDAPFrontPageHack on|off
Default: | AuthLDAPFrontPageHack off
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

See the section on using Microsoft FrontPage with mod_auth_ldap.

AuthLDAPGroupAttribute Directive

Description: | LDAP attributes used to check for group membership
Syntax: | AuthLDAPGroupAttribute attribute
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

This directive specifies which LDAP attributes are used to check for group membership. Multiple attributes can be used by specifying this directive multiple times. If not specified, then mod_auth_ldap uses the member and uniquemember attributes.

AuthLDAPGroupAttributeIsDN Directive

Description: | Use the DN of the client username when checking for group membership
Syntax: | AuthLDAPGroupAttributeIsDN on|off
Default: | AuthLDAPGroupAttributeIsDN on
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

When set on, this directive says to use the distinguished name of the client username when checking for group membership. Otherwise, the username will be used. For example, assume that the client sent the username bjenson, which corresponds to the LDAP DN cn=Babs Jenson, o=Airius. If this directive is set, mod_auth_ldap will check if the group has cn=Babs Jenson, o=Airius as a member. If this directive is not set, then mod_auth_ldap will check if the group has bjenson as a member.

AuthLDAPRemoteUserIsDN Directive

Description: | Use the DN of the client username to set the REMOTE_USER environment variable
Syntax: | AuthLDAPRemoteUserIsDN on|off
Default: | AuthLDAPRemoteUserIsDN off
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

If this directive is set to on, the value of the REMOTE_USER environment variable will be set to the full distinguished name of the authenticated user, rather than just the username that was passed by the client. It is turned off by default.

AuthLDAPUrl Directive

Description: | URL specifying the LDAP search parameters
Syntax: | AuthLDAPUrl url
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Experimental
Module: | mod_auth_ldap

An RFC 2255 URL which specifies the LDAP search parameters to use. The syntax of the URL is

ldap://host:port/basedn?attribute?scope?filter

ldap
For regular ldap, use the string ldap. For secure LDAP, use ldaps instead. Secure LDAP is only available if Apache was linked to an LDAP library with SSL support.
host:port

The name/port of the ldap server (defaults to localhost:389 for ldap, and localhost:636 for ldaps). To specify multiple, redundant LDAP servers, just list all servers, separated by spaces. mod_auth_ldap will try connecting to each server in turn, until it makes a successful connection.

Once a connection has been made to a server, that connection remains active for the life of the httpd process, or until the LDAP server goes down.

If the LDAP server goes down and breaks an existing connection, mod_auth_ldap will attempt to re-connect, starting with the primary server, and trying each redundant server in turn. Note that this is different than a true round-robin search.

basedn
The DN of the branch of the directory where all searches should start from. At the very least, this must be the top of your directory tree, but could also specify a subtree in the directory.
attribute
The attribute to search for. Although RFC 2255 allows a comma-separated list of attributes, only the first attribute will be used, no matter how many are provided. If no attributes are provided, the default is to use uid. It's a good idea to choose an attribute that will be unique across all entries in the subtree you will be using.
scope
The scope of the search. Can be either one or sub. Note that a scope of base is also supported by RFC 2255, but is not supported by this module. If the scope is not provided, or if base scope is specified, the default is to use a scope of sub.
filter
A valid LDAP search filter. If not provided, defaults to (objectClass=*), which will search for all objects in the tree. Filters are limited to approximately 8000 characters (the definition of MAX_STRING_LEN in the Apache source code). This should be than sufficient for any application.

When doing searches, the attribute, filter and username passed by the HTTP client are combined to create a search filter that looks like (&(filter)(attribute=username)).

For example, consider an URL of ldap://ldap.airius.com/o=Airius?cn?sub?(posixid=*). When a client attempts to connect using a username of Babs Jenson, the resulting search filter will be (&(posixid=*)(cn=Babs Jenson)).

See above for examples of AuthLDAPURL URLs.


mod_autoindex - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_autoindex

설명: | 자동으로 유닉스의 ls 명령어나 Win32의 dir 쉘명령어와 유사한 디렉토리 목록을 만든다
상태: | Base
모듈명: | autoindex_module
소스파일: | mod_autoindex.c

요약

디렉토리 목록은 얻는 방법은 두가지다:

  • 보통 index.html이란 이름으로 사용자가 작성한 파일. 이 파일의 이름은 DirectoryIndex 지시어로 지정한다. 이 작업은 mod_dir이 한다.
  • 아니면 서버가 목록을 만든다. 이 목록의 형식을 지정하는 지시어들이 있다. AddIcon, AddIconByEncoding, AddIconByType은 여러 파일종류마다 보여줄 아이콘들을 지정한다. 각 파일에 대응하는 첫번째 아이콘을 보인다. 이 작업을 mod_autoindex가 한다.

이 두 기능은 서로 별개로, 원한다면 자동 목록 생성을 완전히 제외할 (혹은 대체할) 수 있다.

자동 목록 생성은 Options +Indexes로 가능하다. 자세한 내용은 Options 지시어를 참고하라.

IndexOptions 지시어에 FancyIndexing 옵션을 주면, 열 이름을 출력할 순서를 바꾸는 링크로 만든다. 이름 링크를 선택하면 그 열의 값 순서로 목록을 다시 만든다. 같은 이름을 반복해서 선택하면 오름차순과 내림차순 사이를 오간다. IndexOptions 지시어의 SuppressColumnSorting 옵션은 이런 열 이름 링크를 만들지 않는다.

"Size(크기)" 순으로 볼때 출력되는 값 순서가 아니라 실제 파일크기 순서임을 주의하라. 즉, 1010 바이트 파일과 1011 바이트 파일은 둘다 "1K"로 보이더라도 항상 1010 바이트 파일이 앞에 나온다.

Autoindex 요청 아규먼트

아파치 2.0.23는 열순서에 대한 요청 아규먼트를 정리하고, 새로운 옵션들을 추가했다. 출력을 클라이언트가 조절할 수 없도록 만드는 IndexOptions IgnoreClient 옵션이 추가되었다.

열순서 이름은 아래 나온 순서 요청 옵션을 더한 자기참조 링크다. 아래 옵션은 디렉토리 자원에 대한 어떤 요청에도 사용할 수 있다.

  • C=N은 파일명 순이다
  • C=M은 최근 수정일 순, 그리고 파일명 순이다
  • C=S는 크기 순, 그리고 파일명 순이다
  • C=D는 설명 순, 그리고 파일명 순이다
  • O=A는 오름차순으로 목록을 정렬한다
  • O=D는 내림차순으로 목록을 정렬한다
  • F=0은 (FancyIndexed가 아닌) 간단한 목록 형식이다
  • F=1은 FancyIndexed 목록 형식이다
  • F=2는 HTMLTable FancyIndexed 목록 형식이다
  • V=0은 버전 순으로 정렬하지 않는다
  • V=1은 버전 순으로 정렬한다
  • P=pattern은 주어진 pattern에 해당하는 파일만을 목록으로 만든다

'P'attern 아규먼트는 일반적인 IndexIgnore 지시어를 처리한 후에 검사하기때문에, 목록은 다른 autoindex 조건을 따름을 주의하라. mod_autoindex의 요청 아규먼트를 읽어들일때 알 수 없는 옵션을 발견하면 더 이상 읽지않는다. 요청 아규먼트는 위의 표에 따라 만들어야 한다.

header.html 파일에 사용할 수 있는 아래 간단한 예제는 이 옵션들을 설명한다. submit 버턴의 알 수 없는 "X" 아규먼트는 mod_autoindex가 X=Go 전까지 모든 아규먼트를 읽어들임을 확인하기위해 마지막에 사용했다.

<form action="" method="get">
Show me a <select name="F">
<option value="0"> Plain list</option>
<option value="1" selected="selected"> Fancy list</option>
<option value="2"> Table list</option>
 </select>
Sorted by <select name="C">
<option value="N" selected="selected"> Name</option>
<option value="M"> Date Modified</option>
<option value="S"> Size</option>
<option value="D"> Description</option>
 </select>
<select name="O">
<option value="A" selected="selected"> Ascending</option>
<option value="D"> Descending</option>
 </select>
<select name="V">
<option value="0" selected="selected"> in Normal order</option>
<option value="1"> in Version order</option>
 </select>
Matching <input type="text" name="P" value="*" />
<input type="submit" name="X" value="Go" />
 </form>

AddAlt 지시어

설명: | 파일명으로 선택한 아이콘대신 사용할 파일 설명글
문법: | AddAlt string file [file] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

AddAlt는 FancyIndexing에서 파일에 대한 아이콘대신 보일 글을 지정한다. File에는 설명할 파일의 파일 확장자, 파일명 일부, 와일드카드 표현, 전체 파일명을 사용할 수 있다. String에 공백이 들어간다면 따옴표(" 혹은 ')로 묶어야 한다. 클라이언트가 이미지를 볼 수 없거나, 이미지를 읽지않거나, 아이콘을 못 얻은 경우 이 추가 글이 보이게 된다.

예제

AddAlt "PDF file" *.pdf
AddAlt Compressed *.gz *.zip *.Z

AddAltByEncoding 지시어

설명: | MIME-encoding으로 선택한 아이콘대신 사용할 파일 설명글
문법: | AddAltByEncoding string MIME-encoding [MIME-encoding] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

AddAltByEncoding은 FancyIndexing에서 파일에 대한 아이콘대신 보일 글을 지정한다. MIME-encoding은 x-compress와 같은 유효한 content-encoding이다. String에 공백이 들어간다면 따옴표(" 혹은 ')로 묶어야 한다. 클라이언트가 이미지를 볼 수 없거나, 이미지를 읽지않거나, 아이콘을 못 얻은 경우 이 추가 글이 보이게 된다.

예제

AddAltByEncoding gzip x-gzip

AddAltByType 지시어

설명: | MIME content-type으로 선택한 아이콘대신 사용할 파일 설명글
문법: | AddAltByType string MIME-type [MIME-type] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

AddAltByType은 FancyIndexing에서 파일에 대한 아이콘대신 보일 글을 지정한다. MIME-type은 text/html과 같은 유효한 content-type이다. String에 공백이 들어간다면 따옴표(" 혹은 ')로 묶어야 한다. 클라이언트가 이미지를 볼 수 없거나, 이미지를 읽지않거나, 아이콘을 못 얻은 경우 이 추가 글이 보이게 된다.

예제

AddAltByType 'plain text' text/plain

AddDescription 지시어

설명: | 파일에 대한 설명
문법: | AddDescription string file [file] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

이 지시어는 FancyIndexing에서 파일에 대한 설명을 지정한다. File에는 설명할 파일의 파일 확장자, 파일명 일부, 와일드카드 표현, 전체 파일명을 사용할 수 있다. String은 따옴표(")로 묶어야 한다.

예제

AddDescription "The planet Mars" /web/pics/mars.gif

전형적인 기본 설명 필드폭은 23 바이트다. IndexOptions SuppressIcon 옵션을 사용하면 기본폭에 6 바이트를 더 추가하고, IndexOptions SuppressSize 옵션은 7 바이트를, IndexOptions SuppressLastModified 옵션은 19 바이트를 더 추가한다. 그러므로 가장 넓은 설명폭은 55 바이트다.

이 필드의 폭를 바꾸거나 설명의 길이를 무한대로 만드려면 DescriptionWidth IndexOptions 키워드를 참고하라.

조심

AddDescription으로 지정한 설명글에 태그나 character entity(역주; &lt;, &amp; 등을 지칭)같은 HTML을 사용할 수 있다. 그러나 폭때문에 태그가 있는 부분이 짤리게되면 (예를 들어 굵은체 부분 끝이 짤리면) 나머지 디렉토리 목록에 영향을 줄 수 있다.

AddIcon 지시어

설명: | 이름으로 선택한 파일에 사용할 아이콘
문법: | AddIcon icon name [name] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

이 지시어는 FancyIndexing에서 name으로 끝나는 파일 옆에 보여줄 아이콘을 지정한다. Icon은 아이콘의 (%-escaped) 상대 URL 혹은 (alttext,url) 형식이다. 여기서 alttext는 그림을 보여줄 수 없는 브라우저가 아이콘대신 사용할 문구이다.

Name에는 디렉토리를 나타내는 ^^DIRECTORY^^, (목록 형식을 올바로 맞추기위해) 빈줄을 나타내는 ^^BLANKICON^^, 파일 확장자, 와일드카드 표현, 파일명 일부 혹은 전체를 사용할 수 있다.

예제

AddIcon (IMG,/icons/image.xbm) .gif .jpg .xbm
AddIcon /icons/dir.xbm ^^DIRECTORY^^
AddIcon /icons/backup.xbm *~

가능하면 AddIcon보다는 AddIconByType을 사용해야 한다.

AddIconByEncoding 지시어

설명: | MIME content-encoding으로 선택한 파일에 사용할 아이콘
문법: | AddIconByEncoding icon MIME-encoding [MIME-encoding] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

이 지시어는 FancyIndexing에서 파일 옆에 보여줄 아이콘을 지정한다. Icon은 아이콘의 (%-escaped) 상대 URL 혹은 (alttext,url) 형식이다. 여기서 alttext는 그림을 보여줄 수 없는 브라우저가 아이콘대신 사용할 문구이다.

MIME-encoding는 content-encoding에 해당하는 와일드카드 표현이다.

예제

AddIconByEncoding /icons/compress.xbm x-compress

AddIconByType 지시어

설명: | MIME content-type으로 선택한 파일에 사용할 아이콘
문법: | AddIconByType icon MIME-type [MIME-type] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

이 지시어는 FancyIndexing에서 MIME-type의 파일 옆에 보여줄 아이콘을 지정한다. Icon은 아이콘의 (%-escaped) 상대 URL 혹은 (alttext,url) 형식이다. 여기서 alttext는 그림을 보여줄 수 없는 브라우저가 아이콘대신 사용할 문구이다.

MIME-type은 mime type에 해당하는 와일드카드 표현이다.

예제

AddIconByType (IMG,/icons/image.xbm) image/*

DefaultIcon 지시어

설명: | 특정 아이콘을 설정하지않은 파일에 사용할 아이콘
문법: | DefaultIcon url-path
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

DefaultIcon 지시어는 FancyIndexing에서 특정 아이콘을 설정하지않은 파일 옆에 나올 아이콘이다. Icon은 아이콘의 (%-escaped) 상대 URL이다.

예제

DefaultIcon /icon/unknown.xbm

HeaderName 지시어

설명: | 파일목록 위에 삽입할 파일의 이름
문법: | HeaderName filename
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

HeaderName 지시어는 파일목록 앞에 삽입할 파일의 이름을 지정한다. Filename은 삽입할 파일명이다.

예제

HeaderName HEADER.html

현재 HeaderName과 ReadmeName 둘 모두 Filename을 접근하려는 디렉토리의 상대 URI 경로로 받아들인다. Filename이 슬래쉬로 시작하면 DocumentRoot에 상대적인 경로로 받아들인다.

예제

HeaderName /include/HEADER.html

Filename에는 major content type이 text/*인 (예를 들어, text/html, text/plain, 등) 문서를 사용해야 한다. 즉, 스크립트의 (출력이 아닌) 실제 파일 type을 다음과 같이 text/html로 지정한다면 filename으로 CGI 스크립트를 지정할 수도 있다:

AddType text/html .cgi

Options MultiViews을 사용하면 내용협상을 한다. filename이 (CGI 스크립트가 아닌) 고정된 text/html 문서이고 options Includes나 IncludesNOEXEC 중 하나를 사용한다면 파일을 server-side includes로 처리한다. (mod_include 문서 참고)

HeaderName으로 지정한 파일에 (<html>, <head>, 등) HTML 문서 시작부분이 포함되있다면 IndexOptions +SuppressHTMLPreamble을 사용하여 이 부분을 추가하지않는 것이 좋다.

IndexIgnore 지시어

설명: | 디렉토리 목록에서 숨길 파일목록을 추가한다
문법: | IndexIgnore file [file] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

IndexIgnore 지시어는 디렉토리 목록에서 감출 파일목록을 추가한다. File에는 감출 (쉘에서 사용하는) 화일드카드 표현이나 전체 파일명을 사용할 수 있다. 여러 IndexIgnore 지시어를 사용하면 기존의 감출 파일목록을 대체하지않고 목록에 지정한 파일들을 추가한다. 기본적으로 목록은 .을 (현재 디렉토리) 포함한다.

IndexIgnore README .htaccess *.bak *~

IndexOptions 지시어

설명: | 디렉토리 목록의 여러 설정들
문법: | IndexOptions [+|-]option [[+|-]option] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

IndexOptions 지시어는 디렉토리 목록을 설정한다. Option은 다음 중 하나이다

DescriptionWidth=[n | *] (아파치 2.0.23 이후)
DescriptionWidth 키워드를 사용하여 문자단위로 설명열의 폭을 지정할 수 있다.
-DescriptionWidth를 지정하면 (혹은 아무것도 지정하지않으면) mod_autoindex가 최적의 폭을 계산한다.
DescriptionWidth=n은 열의 폭을 n 바이트로 고정한다.
DescriptionWidth=*은 열의 폭을 가장 긴 설명글을 담을 수 있는만큼 늘린다.
설정이 짤릴 수 있는 문제는 AddDescription 절을 참고하라.
FancyIndexing
디렉토리의 fancy 목록을 만든다.
FoldersFirst (아파치 2.0.23 이후)
이 옵션을 사용하면 하위디렉토리 목록이 항상 먼저 나오고, 디렉토리에 있는 일반 파일이 뒤에 나온다. 기본적으로 목록은 파일과 하위디렉토리로 나뉘고, 따로 각각의 순서를 정리하여 하위디렉토리들을 먼저 보인다. 예를 들어, 이름 역순으로 정렬하고 FoldersFirst를 사용한다면 하위디렉토리 Zed가 하위디렉토리 Beta 앞에 나오고, 하위디렉토리 Beta는 일반 파일 Gamma와 Alpha 앞에 나온다. 이 옵션은 FancyIndexing을 함께 사용할때만 효과가 있다.
HTMLTable (실험적, 아파치 2.0.23 이후)
이 실험적인 FancyIndexing 옵션은 간단한 HTML 표로 fancy 디렉토리 목록을 만든다. 이 옵션은 오래된 브라우저를 혼란스럽게 할 수 있음을 주의하라. 이 옵션은 WinNT나 다른 utf-8 사용 플래폼에서 파일명이나 설명문의 읽기 순서(왼쪽에서 오른쪽 혹은 오른쪽에서 왼쪽으로)가 다를때 특별히 유용하다.
IconsAreLinks
fancy 목록에서 파일명 링크에 아이콘을 포함한다.
IconHeight[=pixels]
이 옵션을 IconWidth와 같이 사용하면 서버는 파일 아이콘의 img 태그에 height와 width 속성을 포함한다. 그러면 브라우저는 모든 이미지를 받지않은 상황에서도 페이지 구성을 미리 계산할 수 있다. 옵션에 값을 주지않으면 아파치가 제공하는 아이콘의 표준 높이를 사용한다.
IconWidth[=pixels]
이 옵션을 IconHeight와 같이 사용하면 서버는 파일 아이콘의 img 태그에 height와 width 속성을 포함한다. 그러면 브라우저는 모든 이미지를 박지않은 상황에서도 페이지 구성을 미리 계산할 수 있다. 옵션에 값을 주지않으면 아파치가 제공하는 아이콘의 표준 폭을 사용한다.
IgnoreCase
이 옵션을 사용하면 대소문자 구별하지않고 이름을 정렬한다. 예를 들어, 이름으로 오름차순이고 IgnoreCase를 사용하면 파일 Zeta는 파일 alfa 뒤에 나온다 (주의: 파일 GAMMA는 항상 파일 gamma 앞에 나온다).
IgnoreClient
이 옵션을 사용하면 mod_autoindex는 순서를 포함하여 클라이언트가 보내는 모든 질의변수를 무시한다. (SuppressColumnSorting을 가정한다.)
NameWidth=[n | *]
NameWidth 키워드는 바이트단위로 파일명 열의 폭을 지정한다.
-NameWidth을 지정하면 (혹은 아무것도 지정하지않으면) mod_autoindex가 최적의 폭을 계산한다.
NameWidth=n는 열의 폭을 n 바이트로 고정한다.
NameWidth=*은 열의 폭을 필요한만큼 늘린다.
ScanHTMLTitles
fancy 목록에서 HTML 문서의 title을 뽑는다. 파일에 AddDescription로 지정한 설명이 없다면 웹서버는 문서의 title 요소값을 읽어들인다. 이 작업은 CPU와 디스크를 많이 사용한다.
SuppressColumnSorting
이 옵션을 사용하면 아파치는 FancyIndexed 디렉토리 목록에서 열 이름을 순서를 바꾸는 링크로 만들지 않는다. 보통은 열 이름을 링크로 만들어서, 열 이름을 선택하면 그 열에 있는 값순서로 디렉토리 목록을 만든다. 아파치 2.0.23 이전에는 순서 아규먼트도 읽지 않았다. 아파치 2.0.23에서는 IndexOptions IgnoreClient를 사용하여 순서 아규먼트를 읽지 않는다.
SuppressDescription
fancy 목록에서 파일 설명을 포함하지 않는다. 기본적으로 어떤 파일 설명도 정의되있지않고, 이 옵션을 사용하면 23 문자 공간을 다른 용도로 사용한다. 파일 설명을 지정하는 방법은 AddDescription을 참고하라. 설명열의 크기를 지정하는 DescriptionWidth 옵션도 참고하라.
SuppressHTMLPreamble
디렉토리에 HeaderName 지시어로 지정한 파일이 있는 경우 모듈은 보통 표준 HTML 시작부분 (<html>, <head>, et cetera) 뒤에 파일 내용을 첨가한다. 그러나 SuppressHTMLPreamble 옵션을 사용하면 처음부터 header 파일 내용을 포함한다. 이 경우 header 파일에는 적절한 HTML 명령이 있어야 한다. header 파일이 없다면 일반적인 시작부분이 만들어진다.
SuppressIcon (아파치 2.0.23 이후)
fancy 목록에서 아이콘을 뺀다. SuppressIcon과 SuppressRules를 같이 사용하면, (FancyIndexed 목록이 사용한) pre 안에 img와 hr 요소 사용을 금지한 마지막 표준인 HTML 3.2에 알맞은 출력이 된다.
SuppressLastModified
fancy 목록에서 마지막 수정일을 표시하지 않는다.
SuppressRules (아파치 2.0.23 이후)
디렉토리 목록에서 수평줄을 (hr 요소) 사용하지 않는다. SuppressIcon과 SuppressRules를 같이 사용하면, (FancyIndexed 목록이 사용한) pre 안에 img와 hr 요소 사용을 금지한 마지막 표준인 HTML 3.2에 알맞은 출력이 된다.
SuppressSize
fancy 목록에서 파일크기를 표시하지 않는다.
TrackModified (아파치 2.0.23 이후)
디렉토리 목록의 HTTP 헤더에 Last-Modified와 ETag 값을 포함한다. 이 옵션은 운영체제와 파일시스템에서 적절한 stat() 결과를 얻을 수 있을때만 유효하다. 유닉스 시스템과 OS2의 JFS, Win32의 NTFS에서는 가능하다. 예를 들어, OS2와 Win32의 FAT은 불가능하다. 이 기능을 사용하면 클라이언트나 프록시는 HEAD 요청을 사용하여 파일목록의 변화를 추적할 수 있다. 어떤 운영체제는 새로운 파일과 삭제한 파일을 올바로 추적하지만, 디렉토리에 있는 파일의 크기나 날짜 변화를 추적하지 못함을 주의하라. 모든 유닉스 플래폼에서 기존 파일의 크기나 날짜 변화시 Last-Modified 헤더가 바뀌지않는다. 이런 변화가 중요하다면 이 옵션을 사용하지 마라.
VersionSort (아파치 2.0a3 이후)
VersionSort 키워드는 버전 번호를 포함한 파일명을 자연스럽게 정렬한다. 문자 부분은 정상적인 순서를 정렬하지만, 파일과 설명에 있는 숫자 부분은 숫자값으로 비교한다.

예제:

foo-1.7
foo-1.7.2
foo-1.7.12
foo-1.8.2
foo-1.8.2a
foo-1.12

수가 0으로 시작하면, 그 수를 분수로 취급한다:

foo-1.001
foo-1.002
foo-1.030
foo-1.04

XHTML (아파치 2.0.49 이후)
XHTML 키워드를 사용하면 mod_autoindex는 HTML 3.2 대신 XHTML 1.0 코드를 생성한다.
점진적인 IndexOptions

아파치 1.3.3에서 IndexOptions 지시어 처리방식이 크게 변화되었다. 특별히:

  • 이제 한 디렉토리에 대한 여러 IndexOptions 지시어들을 서로 결합한다. 다음의 결과는:

    <Directory /foo> IndexOptions HTMLTable
    IndexOptions SuppressColumnsorting     </Directory>

    다음과 같다

    IndexOptions HTMLTable SuppressColumnsorting

  • (예를 들어, 키워드 앞에 +나 -를 붙이는) 점진적인 문법이 추가되었다.

키워드 앞에 '+'나 '-'가 붙을때마다 해당 키워드가 현재 (상위 디렉토리에서 상속되었을) IndexOptions 설정에 반영된다. 그러나 앞에 아무것도 없는 키워드를 만나면 아직까지 상속되거나 점진적으로 변경된 설정을 모두 지운다. 다음 예제를 살펴보자:

IndexOptions +ScanHTMLTitles -IconsAreLinks FancyIndexing
IndexOptions +SuppressSize

앞에 아무것도 없는 FancyIndexing이 이전의 점진적인 설정을 지워버렸지만 설정이 다시 추가되여 결과는 IndexOptions FancyIndexing +SuppressSize와 같다.

특정 디렉토리에 대해 무조건적인 IndexOptions를 설정하려면 키워드 앞에 +나 -를 사용하지말고 상속된 설정을 지운다.

IndexOrderDefault 지시어

설명: | 디렉토리 목록의 기본 순서를 설정한다
문법: | IndexOrderDefault Ascending|Descending Name|Date|Size|Description
기본값: | IndexOrderDefault Ascending Name
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

IndexOrderDefault 지시어는 FancyIndexing 목록 옵션과 함께 사용한다. 기본적으로 fancyindexed 디렉토리 목록은 파일명 오름차순이다. IndexOrderDefault는 이 초기 순서를 변경할 수 있다.

IndexOrderDefault는 두 아규먼트를 받는다. 첫번째는 순서의 방향을 지시하는 Ascending (오른차순) 이나 Descending (내림차순) 중 하나다. 두번째 아규먼트는 일차 순서를 나타내는 키워드 Name, Date, Size, Description 중 하나다. 이차 순서는 항상 파일명 오름차순이다.

이 지시어와 SuppressColumnSorting 목록 옵션을 같이 사용하면 특정 순서로만 디렉토리 목록을 만든다. 이 경우 클라이언트는 다른 순서로 디렉토리 목록을 요청하지 못한다.

ReadmeName 지시어

설명: | 파일목록 마지막에 삽입할 파일의 이름
문법: | ReadmeName filename
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_autoindex

ReadmeName 지시어는 파일목록 끝에 삽입할 파일의 이름을 지정한다. Filename은 포함할 파일명이고, 목록을 만들려는 위치의 상대경로로 받아들인다. Filename이 슬래쉬로 시작하면 DocumentRoot에 상대경로로 받아들인다.

예제

ReadmeName FOOTER.html

예제 2

ReadmeName /include/FOOTER.html

이 동작을 자세히 설명한 HeaderName도 참고하라.


mod_cache - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_cache

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.
설명: | Content cache keyed to URIs.
상태: | Experimental
모듈명: | cache_module
소스파일: | mod_cache.c

요약

이 모듈은 실험적인 상태이다. 문서는 아직 작업중이다...

mod_cache는 같은 컴퓨터에 있는 내용이나 프록시된 내용을 캐쉬할 수 있는 RFC 2616 호환 HTTP 내용캐쉬를 구현한다. mod_cache를 사용하려면 저장관리모듈(storage management module)이 필요하다. 기본 아파치 배포본에는 두가지 저장관리모듈이 있다:

mod_disk_cache
는 디스크기반 저장관리자를 구현한다.
mod_mem_cache
는 메모리기반 저장관리자를 구현한다. mod_mem_cache는 파일기술자를 캐쉬하거나 힙(heap) 공간에 객체를 캐쉬하는 두가지 방식중 한가지 방법으로 동작하도록 설정할 수 있다. mod_mem_cache는 자신이 생성한 내용을 캐쉬하거나, (역프록시(reverse proxy)로 알려진) ProxyPass를 사용하여 mod_proxy를 위해 뒷단 서버내용을 캐쉬할 수 있다.

내용을 URI를 토대로 만든 키로 캐쉬에 저장하고 가져온다. 접근보호가 된 내용은 캐쉬하지않는다.

관련된 모듈과 지시어

관련된 모듈 관련된 지시어
  • mod_disk_cache
  • mod_mem_cache
  • CacheRoot
  • CacheSize
  • CacheGcInterval
  • CacheDirLevels
  • CacheDirLength
  • CacheExpiryCheck
  • CacheMinFileSize
  • CacheMaxFileSize
  • CacheTimeMargin
  • CacheGcDaily
  • CacheGcUnused
  • CacheGcClean
  • CacheGcMemUsage
  • MCacheSize
  • MCacheMaxObjectCount
  • MCacheMinObjectSize
  • MCacheMaxObjectSize
  • MCacheRemovalAlgorithm
  • MCacheMaxStreamingBuffer

설정예

Sample httpd.conf

#
# 예제 캐쉬 설정
#
LoadModule cache_module modules/mod_cache.so

<IfModule mod_cache.c>
#LoadModule disk_cache_module modules/mod_disk_cache.so
<IfModule mod_disk_cache.c>
CacheRoot c:/cacheroot
CacheSize 256
CacheEnable disk /
CacheDirLevels 5
CacheDirLength 3
 </IfModule>

LoadModule mem_cache_module modules/mod_mem_cache.so
<IfModule mod_mem_cache.c>
CacheEnable mem /
MCacheSize 4096
MCacheMaxObjectCount 100
MCacheMinObjectSize 1
MCacheMaxObjectSize 2048
 </IfModule>
 </IfModule>

CacheDefaultExpire 지시어

설명: | 만기시간을 지정하지않은 문서를 캐쉬할 기본 기간.
문법: | CacheDefaultExpire seconds
기본값: | CacheDefaultExpire 3600 (one hour)
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_cache

CacheDefaultExpire 지시어는 문서의 만기시간과 최근수정시간이 없는 경우 문서를 캐쉬할 초단위 기본 시간을 지정한다. CacheMaxExpire로 지정한 값이 이 설정을 무시하지 않는다.

CacheDefaultExpire 86400

CacheDisable 지시어

설명: | 특정 URL을 캐쉬하지 않는다
문법: | CacheDisable url-string
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_cache

CacheDisable 지시어를 사용하면 mod_cache가 url-string 이하의 url들을 캐쉬하지 않는다.

예제

CacheDisable /local_files

CacheEnable 지시어

설명: | 지정한 저장관리자를 사용하여 지정한 URL을 캐쉬한다
문법: | CacheEnable cache_type url-string
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_cache

CacheEnable 지시어를 사용하면 mod_cache가 url-string 이하 url들을 캐쉬한다. 캐쉬 저장관리자는 cache_type 아규먼트로 지정한다. cache_type mem은 mod_mem_cache가 구현하는 메모리기반 저장관리자를 사용한다. cache_type disk는 mod_disk_cache가 구현하는 디스크기반 저장관리자를 사용한다. cache_type fd는 mod_mem_cache가 구현하는 파일기술자 캐쉬를 사용한다.

(아래 예와 같이) URL 공간이 다른 CacheEnable 지시어와 겹치면 실제로 한 저장관리자가 요청을 처리할때까지 두 저장관리자를 모두 실행한다. 설정파일에서 CacheEnable 지시어의 순서대로 저장관리자가 실행된다.

CacheEnable mem /manual
CacheEnable fd /images
CacheEnable disk /

CacheForceCompletion 지시어

설명: | 요청이 취소되더라도 서버가 파일을 계속 캐쉬하기위해 필요한 문서의 서비스률.
문법: | CacheForceCompletion Percentage
기본값: | CacheForceCompletion 60
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_cache

보통 응답을 캐쉬하고 클라이언트로 보내는 도중에 요청이 취소되면 응답 처리를 중단되고 캐쉬 항목을 지운다. CacheForceCompletion 지시어는 요청이 취소되더라도 문서를 계속 캐쉬할 정도를 지정한다.

정도는 백분율로 나타내며 1과 100 사이의 값이다. 0 값을 지정하면 기본값을 사용한다. 100은 내용을 모두 서비스한 문서만을 캐쉬한다. 60과 90 사이의 값을 추천한다.

CacheForceCompletion 80

주의:

이 기능은 현재 구현되지 않았다.

CacheIgnoreCacheControl 지시어

설명: | 클라이언트가 캐쉬하지않는 내용을 요청함을 무시한다.
문법: | CacheIgnoreCacheControl On|Off
기본값: | CacheIgnoreCacheControl Off
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_cache

보통 no-cache나 no-store 헤더값을 가진 문서는 캐쉬에 저장하지않는다. CacheIgnoreCacheControl 지시어는 이런 행동을 변경한다. CacheIgnoreCacheControl On을 사용하면 서버는 문서에 no-cache나 no-store 헤더값이 있어도 문서를 캐쉬한다. 인증이 필요한 문서는 절대로 캐쉬하지 않는다.

CacheIgnoreCacheControl On

CacheIgnoreNoLastMod 지시어

설명: | 응답에 Last Modified 헤더가 없다는 사실을 무시한다.
문법: | CacheIgnoreNoLastMod On|Off
기본값: | CacheIgnoreNoLastMod Off
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_cache

보통 최근수정일이 없는 문서는 캐쉬하지 않는다. 어떤 경우 최근수정일을 (예를 들어 mod_include 처리중에) 빼거나 처음부터 없었을 수가 있다. CacheIgnoreNoLastMod 지시어는 최근수정일이 없는 문서도 반드시 캐쉬하도록 만든다. 문서에 최근수정일과 만기시간이 없는 경우 CacheDefaultExpire 지시어로 지정한 값을 만기시간으로 사용한다.

CacheIgnoreNoLastMod On

CacheLastModifiedFactor 지시어

설명: | LastModified 시간으로 만기시간을 계산하는데 사용하는 계수.
문법: | CacheLastModifiedFactor float
기본값: | CacheLastModifiedFactor 0.1
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_cache

문서에 만기시간은 없지만 최근수정일이 있는 경우 최근수정일 이후 지난 시간으로 만기시간을 계산한다. CacheLastModifiedFactor 지시어는 만기시간을 계산하는 다음 공식에서 사용할 factor를 지정한다: expiry-period = time-since-last-modified-date * factor expiry-date = current-date + expiry-period 예를 들어, 문서가 10 시간 전에 마지막으로 수정되었고 factor가 0.1이라면 만기기간은 10*01 = 1 시간이 된다. 현재 시간이 3:00pm이라면 만기시간은 3:00pm + 1시간 = 4:00pm이다. 만기기간이 CacheMaxExpire 보다 길다면 CacheMaxExpire를 사용한다.

CacheLastModifiedFactor 0.5

CacheMaxExpire 지시어

설명: | 문서를 캐쉬하는 초단위 최대시간
문법: | CacheMaxExpire seconds
기본값: | CacheMaxExpire 86400 (하루)
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_cache

CacheMaxExpire 지시어는 실제 서버를 검사하지않고 캐쉬가능한 HTTP 문서를 유지할 수 있는 초단위 최대시간을 지정한다. 즉, 문서는 최대한 이 설정값만큼 오래되었다. 문서가 만기시간을 지정하여도 이 최대값을 지킨다.

CacheMaxExpire 604800


mod_cern_meta - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_cern_meta

설명: | CERN 웹서버 메타파일 지원
상태: | Extension
모듈명: | cern_meta_module
소스파일: | mod_cern_meta.c

요약

CERN 웹서버 메타파일을 흉내낸다. 메타파일은 접근하는 파일에 대해 일반적인 헤더외에 추가로 출력할 HTTP 헤더를 담고있다. 아파치 .asis 파일과 비슷하고, Expires: 헤더를 수정하거나 다른 신기한 일들을 할 수 있다. 메타 정보를 다루는 방법은 다양하지만, 이미 이 모듈을 사용하는 많은 CERN 사용자들을 위해 이 방법을 선택했다.

더 자세한 정보는 CERN metafile semantics를 참고하라.

참고

  • mod_headers
  • mod_asis

MetaDir 지시어

설명: | CERN 메타정보를 찾을 디렉토리 이름
문법: | MetaDir directory
기본값: | MetaDir .web
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Extension
모듈: | mod_cern_meta

아파치가 메타정보 파일을 찾을 디렉토리명을 지정한다. 디렉토리는 보통 접근할 파일이 있는 디렉토리의 '감춰진' 하위디렉토리다. "."으로 지정하면 같은 디렉토리에서 파일을 찾는다:

MetaDir .

아니면 파일이 있는 하위디렉토리를 지정한다:

MetaDir .meta

MetaFiles 지시어

설명: | CERN 메타파일을 처리한다
문법: | MetaFiles on|off
기본값: | MetaFiles off
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Extension
모듈: | mod_cern_meta

디렉토리별로 메타파일 처리여부를 결정한다.

MetaSuffix 지시어

설명: | CERN 메타정보를 저장하는 파일의 접미사
문법: | MetaSuffix suffix
기본값: | MetaSuffix .meta
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Extension
모듈: | mod_cern_meta

메타정보를 저장하는 파일의 접미사를 지정한다. 예를 들어, 두 지시어의 기본값을 사용할 경우 DOCUMENT_ROOT/somedir/index.html을 요청하면 DOCUMENT_ROOT/somedir/.web/index.html.meta의 내용을 참고하여 MIME 헤더 정보를 추가한다.

예제:

MetaSuffix .meta


mod_cgi - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_cgi

설명: | CGI 스크립트 실행
상태: | Base
모듈명: | cgi_module
소스파일: | mod_cgi.c

요약

서버는 mime type이 application/x-httpd-cgi이거나 (아파치 1.1 이후) 핸들러가 cgi-script인 모든 파일을 CGI 스크립트로 인식하여, 실행하고, 그 결과를 클라이언트에게 보낸다. 파일이 AddType 지시어로 지정한 확장자를 가지거나, ScriptAlias 디렉토리 안에 있으면 CGI로 처리된다.

서버는 CGI 스크립트를 부를때 DOCUMENT_ROOT라는 환경변수를 추가한다. 이 변수는 DocumentRoot 설정값을 가진다.

아파치에서 CGI 스크립트를 사용하는 방법에 대한 소개는 CGI로 동적 페이지 생성 투토리얼을 참고하라.

유닉스에서 다중쓰레드 MPM을 사용한다면 이 모듈대신 mod_cgid 모듈을 사용해야 한다. 사용자 입장에서 이 두 모듈은 기본적으로 동일하다.

참고

  • AcceptPathInfo
  • Options
  • ScriptAlias
  • AddHandler
  • 다른 사용자 ID로 CGI 프로그램 실행하기
  • CGI 표준

CGI 환경변수

서버는 다음과 같은 방법으로 CGI 표준이 설명하는 CGI 환경변수를 설정한다:

PATH_INFO
이 변수는 AcceptPathInfo 지시어를 직접 off로 지정한 경우에만 설정한다. AcceptPathInfo가 없는 경우 서버는 기본적으로 경로 정보가 있는 요청에 대해 404 NOT FOUND 오류를 내지만, mod_cgi는 경로 정보를 (URI에서 스크립트 파일명 뒤에 나오는 /more/path/info) 받는다. AcceptPathInfo 지시어를 생략하면 mod_cgi 요청에 대해서 AcceptPathInfo를 On으로 설정한 것과 같다.
REMOTE_HOST
이 변수는 HostnameLookups가 on이고 (기본값은 off), 접속한 호스트 주소를 역DNS 검색하여 실제 호스트명을 찾은 경우에만 설정한다.
REMOTE_IDENT
이 변수는 IdentityCheck가 on이고, 접속한 호스트가 ident 프로토콜을 지원하는 경우에만 설정한다. 쉽게 이 값을 속일 수 있기때문에 이 변수의 내용을 믿으면 안되고, 클라이언트와 서버 사이에 프록시가 있다면 변수 내용이 완전히 무의미함을 주의하라.
REMOTE_USER
CGI 스크립트가 인증을 거쳐야하는 경우에만 설정한다.

CGI 디버깅

어디에서 잘못 실행되는지 스크립트의 출력을 (표준출력과 표준오류) 볼 수 없기때문에 CGI 스크립트는 전통적으로 디버깅하기 어려웠다. 아파치 1.2 이후에 추가된 지시어를 사용하면 발생한 오류를 자세히 로그에 남길 수 있다.

CGI 로그파일 형식

CGI 오류로그는 정상적으로 실행하지 못한 CGI를 기록한다. 오류가 발생한 CGI 스크립트는 로그에 여러 줄의 정보를 남긴다. 첫번째 두 줄은 항상 아래와 같은 형식이다:

%% [시간] 요청줄
%% HTTP-상태 CGI-스크립트-파일명

CGI 스크립트를 실행할 수 없는 오류인 경우 로그파일에 추가로 두 줄을 더 기록한다:

%%error
오류문

스크립트가 (보통 스크립트의 버그때문에) 잘못된 헤더 정보를 반환하는 경우, 다음 내용을 로그에 기록한다:

%request
받은 모든 HTTP 헤더
(있다면) POST나 PUT 내용
%response
CGI 스크립트 출력의 모든 헤더
%stdout
CGI 표준출력
%stderr
CGI 표준오류

(스크립트가 표준출력이나 표준오류에 아무 내용도 출력하지 않았다면 %stdout과 %stderr 부분은 생략될 수 있다).

ScriptLog 지시어

설명: | CGI 스크립트 오류로그파일의 위치
문법: | ScriptLog file-path
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_cgi, mod_cgid

ScriptLog 지시어는 CGI 스크립트 오류로그파일을 지정한다. ScriptLog를 사용하지않으면 오류로그를 만들지 않는다. 사용하면 아규먼트로 지정한 파일에 CGI 오류를 기록한다. 상대경로를 지정하면 ServerRoot에 상대경로로 받아들인다.

예제

ScriptLog logs/cgi_log

자식 프로세스를 실행하는 사용자, 즉 User 지시어로 지정한 사용자 권한으로 로그를 연다. 그래서 그 사용자가 스크립트 로그가 있는 디렉토리에 쓰기권한이 있던지, 직접 미리 파일을 만들어서 그 사용자에게 쓰기권한을 줘야 한다. 스크립트 로그를 주 로그 디렉토리에 둔다면 자식 프로세스를 실행하는 사용자에게 쓰기권한을 주기위해 디렉토리 권한을 변경하지 마라.

스크립트 로그는 CGI 스크립트를 작성할때 디버깅을 위한 용도이지 서버를 실행하는 동안 계속 사용하기위함이 아님을 주의하라. 속도와 효율성면에서 최적화가 안되있고, 설계한 목적이외의 방법으로 사용하면 보안상 문제가 될 수 있다.

ScriptLogBuffer 지시어

설명: | 스크립트 로그에 기록할 PUT 혹은 POST 요청의 최대량
문법: | ScriptLogBuffer bytes
기본값: | ScriptLogBuffer 1024
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_cgi, mod_cgid

큰 내용을 받아서 로그파일이 너무 빨리 커지는 현상을 막기위해 파일에 기록할 PUT 혹은 POST 내용의 크기를 제한한다. 기본적으로 1024 바이트까지 로그에 기록하지만, 이 지시어를 사용하여 수정할 수 있다.

ScriptLogLength 지시어

설명: | CGI 스크립트 로그파일의 크기 제한
문법: | ScriptLogLength bytes
기본값: | ScriptLogLength 10385760
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_cgi, mod_cgid

ScriptLogLength는 CGI 스크립트 로그파일의 크기를 제한한다. CGI 오류가 발생할때마다 (모든 요청 헤더, 모든 스크립트 출력 등) 많은 정보가 로그에 기록되기때문에 파일이 매우 커질 수 있다. 파일이 무한히 커지는 문제를 막기위해 이 지시어를 사용하여 CGI 로그파일의 최대 파일크기를 설정한다. 파일의 크기가 설정한 값을 넘으면 더 이상 정보를 기록하지않는다.


mod_cgid - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_cgid

설명: | 외부 CGI 데몬을 사용하여 CGI 스크립트를 실행
상태: | Base
모듈명: | cgid_module
소스파일: | mod_cgid.c
지원: | 유닉스에서 쓰레드를 사용하는 MPMs 전용

요약

아래에서 설명하는 추가된 ScriptSock 지시어를 제외하고 mod_cgid는 mod_cgi와 비슷하게 동작한다. 아파치와 CGI에 대한 자세한 설명은 mod_cgi를 참고하라.

어떤 유닉스 운영체제의 경우 다중쓰레드 서버에서 프로세스를 포크(fork)하면 새로운 프로세스가 부모 프로세스의 모든 쓰레드를 복제해야 하므로 부담이 된다. CGI 실행마다 이런 부담을 주지 않기위해 mod_cgid는 CGI 스크립트를 실행하는 자식 프로세스를 포크하는 외부 데몬을 만든다. 주서버는 이 데몬과 유닉스소켓(unix domain socket)을 사용하여 통신한다.

컴파일할때 다중쓰레드 MPM을 선택하면 기본적으로 mod_cgi 대신 이 모듈을 사용한다. 사용자 입장에서 이 모듈의 설정과 동작은 mod_cgi와 동일하다. 유일한 차이점은 cgi 데몬과 통신을 위해 사용할 소켓의 이름을 설정하는 ScriptSock 지시어가 추가된 점이다.

참고

  • mod_cgi
  • 다른 사용자 ID로 CGI 프로그램 실행하기

ScriptSock 지시어

설명: | cgi 데몬과 통신을 위해 사용할 소켓의 이름
문법: | ScriptSock file-path
기본값: | ScriptSock logs/cgisock
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_cgid

이 지시어는 CGI 데몬과 통신을 위해 사용할 소켓의 이름을 지정한다. 아파치를 시작한 사용자 (보통 root) 권한으로 소켓을 연다. CGI 스크립트와 통신의 보안을 위해 다른 사용자가 소켓이 있는 디렉토리에 쓰기권한을 가지지않는 것이 중요하다.

예제

ScriptSock /var/run/cgid.sock


mod_charset_lite - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_charset_lite

설명: | 문자집합 변환을 지정
상태: | Experimental
모듈명: | charset_lite_module
소스파일: | mod_charset_lite.c

요약

이 모듈은 실험적인 모듈이고, 주의있게 사용해야 한다. 원하는 동작을 하는지 mod_charset_lite 설정을 시험해봐라.

mod_charset_lite를 사용하여 문서 원본의 문자집합과 문서를 클라이언트로 보내기 전에 변환할 문자집합을 지정할 수 있다. mod_charset_lite는 직접 자료를 변환하지않고 대신 아파치에게 변환하라고 요청한다. mod_charset_lite는 EBCDIC과 ASCII 환경에서 사용할 수 있다. EBCDIC 환경에서 아파치는 보통 아파치 프로세스의 코드페이지에서 ISO-8859-1 문자집합으로 문서를 변환한다. mod_charset_lite를 사용하여 다른 변환을 지시할 수 있다. ASCII 환경에서 아파치는 기본적으로 변환을 하지 않기때문에, 어떤 변환을 위해서는 mod_charset_lite가 필요하다.

이 모듈은 러시아판 아파치의 mod_charset이 제공하는 설정의 일부를 제공한다.

일반적인 문제점

잘못된 문자집합 이름

mod_charset_lite를 사용하는 시스템의 ARP 번역기능이 CharsetSourceEnc와 CharsetDefault의 파라미터인 문자집합 이름을 처리할 수 있어야 한다. 문자집합 이름은 표준화되지 않았고, http 헤더에 사용하는 값과 항상 같지는 않다. 현재 APR은 iconv(3)만을 사용하기때문에, 다음과 같이 iconv(1) 프로그램을 사용하여 특정 문자집합 이름을 사용할 수 있는지 쉽게 알 수 있다:

iconv -f charsetsourceenc-value -t charsetdefault-value

내용과 변환규칙의 문자집합이 서로 다름

변환규칙이 상황에 맞지않으면 다음과 같은 여러 방식으로 변환이 실패할 수 있다:

  • 변환기능이 실패 반환코드를 반환하고 연결이 끊어질 수 있다.
  • 입력버퍼를 변환하지 못할때 출력버퍼에 대신 특별한 문자를 (예, 물음표) 적을 수 있다.

CharsetDefault 지시어

설명: | 변환할 문자집합
문법: | CharsetDefault charset
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Experimental
모듈: | mod_charset_lite

CharsetDefault 지시어는 지시어를 사용한 위치에 있는 원본을 변환할 문자집합을 지정한다.

charset 아규먼트에는 APR이 지원하는 문자집합 이름을 사용해야 한다. 일반적으로 iconv가 지원하는 문자집합을 의미한다.

예제

<Directory /export/home/trawick/apacheinst/htdocs/convert>
CharsetSourceEnc UTF-16BE
CharsetDefault ISO-8859-1
 </Directory>

CharsetOptions 지시어

설명: | 문자집합 변환 기능을 설정
문법: | CharsetOptions option [option] ...
기본값: | CharsetOptions DebugLevel=0 NoImplicitAdd
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Experimental
모듈: | mod_charset_lite

CharsetOptions 지시어는 mod_charset_lite의 기능을 설정한다. Option에는 아래 항목들을 사용할 수 있다

DebugLevel=n
DebugLevel 키워드는 mod_charset_lite가 기록하는 디버그문구의 수준을 설정한다. 기본적으로 어떤 것도 기록하지 않는다. 이는 DebugLevel=0과 같다. 높은 숫자를 사용할수록 더 많은 디버그문구를 기록하게되어 서버 성능이 떨어진다. 숫자값의 실제 의미는 mod_charset_lite.c 앞부분의 DBGLVL_ 상수 정의를 참고하라.
ImplicitAdd | NoImplicitAdd
ImplicitAdd 키워드는 내용을 변환할 문자집합을 지정하면 자동으로 mod_charset_lite를 필터에 추가한다. AddOutputFilter 지시어로 필터순서를 직접 지정한다면, NoImplicitAdd를 사용하여 mod_charset_lite가 자동으로 필터에 추가되지않도록 해야 한다.

CharsetSourceEnc 지시어

설명: | 파일 원본의 문자집합
문법: | CharsetSourceEnc charset
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Experimental
모듈: | mod_charset_lite

CharsetSourceEnc 지시어는 지시어를 사용한 위치에 있는 파일들 원본의 문자집합을 지정한다.

charset 아규먼트에는 APR이 지원하는 문자집합 이름을 사용해야 한다. 일반적으로 iconv가 지원하는 문자집합을 의미한다.

예제

<Directory /export/home/trawick/apacheinst/htdocs/convert>
CharsetSourceEnc UTF-16BE
CharsetDefault ISO-8859-1
 </Directory>

Solaris 8의 iconv가 이 예제의 문자집합을 지원한다.


mod_dav - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_dav

설명: | Distributed Authoring and Versioning (WebDAV) 기능
상태: | Extension
모듈명: | dav_module
소스파일: | mod_dav.c

요약

이 모듈은 아파치에 WebDAV ('Web-based Distributed Authoring and Versioning') class 1과 class 2 기능을 추가한다. WebDAV는 원격 웹서버의 자원과 콜렉션(collection)을 (역주; 콜렉션은 파일시스템의 디렉토리와 같은 개념이다) 만들고, 옮기고, 복사하고, 지울 수 있도록 HTTP 프로토콜을 확장한 것이다.

참고

  • DavLockDB
  • LimitXMLRequestBody
  • WebDAV 정보

WebDAV 사용하기

mod_dav를 사용하려면 httpd.conf 파일에 아래과 같이 추가한다:

Dav On

그러면 mod_dav_fs 모듈이 구현하는 DAV 파일시스템 제공자(provider)를 사용한다. 그러므로 이 모듈도 서버에 같이 컴파일되있거나 LoadModule 지시어로 실행중에 읽어들여야 한다.

또, DAV 잠금(lock) 데이터베이스의 위치를 httpd.conf 파일의 전역 부분에 DavLockDB 지시어를 사용하여 지정해야 한다:

DavLockDB /usr/local/apache2/var/DavLock

아파치를 실행하는 User와 Group은 잠금 데이터베이스가 있는 디렉토리에 쓰기 권한을 가져야 한다.

DAV를 사용하는 위치에 접근을 제한하기위해 <Location> 지시어 안에 <Limit> 지시어를 사용할 수 있다. DAV 클라이언트가 한번의 요청에 보낼 수 있는 최대 바이트수를 제한하려면 LimitXMLRequestBody 지시어를 사용한다. "일반적인" LimitRequestBody 지시어는 DAV 요청과 관계없다.

전체 예제

DavLockDB /usr/local/apache2/var/DavLock

<Location /foo>
Dav On

AuthType Basic
AuthName DAV
AuthUserFile user.passwd

<LimitExcept GET OPTIONS>
require user admin
 </LimitExcept>
 </Location>

mod_dav는 Greg Stein이 만든 Apache 1.3용 mod_dav를 기반으로 만들었다. 모듈에 대한 더 자세한 정보는 그 사이트를 참고하라.

보안 문제

DAV를 사용하면 원격 클라이언트가 서버의 파일을 조작할 수 있기때문에, mod_dav를 사용하기 전에 서버가 안전한지 특별히 관심을 가져야 한다.

서버에서 DAV가 가능한 위치는 인증으로 보호해야 한다. HTTP Basic Authentication는 추천하지 않는다. 최소한 mod_auth_digest 모듈이 제공하는 HTTP Digest Authentication을 사용해야 한다. 거의 모든 WebDAV 클라이언트는 이 인증 방식을 지원한다. 아니면 SSL 연결에서 Basic Authentication을 사용할 수도 있다.

mod_dav가 파일을 조작하려면, 아파치를 실행하는 User와 Group은 해당 디렉토리와 파일에 쓰기 권한을 가져야 한다. 또, 새로 생성한 파일은 User와 Group이 소유하게 된다. 그래서 아무나 이 계정에 접근할 수 없도록 하라. DAV 저장소는 아파치만 접근할 수 있다고 가정한다. 아파치를 통하지않고 (예를 들어 FTP나 파일시스템 도구를 사용하여) 파일을 수정함을 허용하면 안된다.

mod_dav는 여러 서비스거부 공격의 대상이 될 수 있다. LimitXMLRequestBody 지시어를 사용하여 큰 DAV 요청을 읽을때 메모리량을 제한할 수 있다. DavDepthInfinity 지시어를 사용하여 많은 메모리를 소모하기위한 매우 큰 저장소의 PROPFIND 요청을 막을 수 있다. 단순히 클라이언트가 여러 큰 파일들로 디스크공간을 채우는 서비스거부 공격도 가능하다. 아파치에서 이를 막을 직접적인 방법은 없다. 그러므로 신뢰하지않는 사용자에게 DAV 접근을 허용하지 않도록하라.

복잡한 설정

일반적인 질문중 하나는 (PHP 스크립트, CGI 스크립트 등) 동적파일 작업을 위해 mod_dav를 사용하는 방법이다. 이는 GET 요청이 파일 내용을 다운로드하지 않고 항상 스크립트를 실행하므로 어렵다. 해결방법중 하나는 내용에 두개의 URL을 대응하는 것이다. 한 URL은 스크립트를 실행하고, 다른 URL로는 파일을 다운로드하여 DAV로 작업할 수 있다.

Alias /phparea /home/gstein/php_files
Alias /php-source /home/gstein/php_files
<Location /php-source> DAV On
ForceType text/plain
 </Location>

이 설정에서 http://example.com/phparea는 PHP 스크립트의 결과를 보여주고, http://example.com/php-source로는 DAV 클라이언트에서 스크립트를 수정할 수 있다.

Dav 지시어

설명: | WebDAV HTTP 메써드를 시작한다
문법: | Dav On|Off|provider-name
기본값: | Dav Off
사용장소: | directory
상태: | Extension
모듈: | mod_dav

지정한 위치에서 WebDAV HTTP 메써드를 사용하려면 Dav 지시어를 사용한다:

<Location /foo>
Dav On
 </Location>

On 값은 실제로 mod_dav_fs 모듈이 제공하는 기본 제공자인 filesystem의 별칭이다. 어떤 위치에서 DAV를 시작하면 하위공간에서 DAV를 사용안하도록 설정할 수 없음을 주의하라. 완전한 설정예는 위의 절을 참고하라.

서버를 안전하게 구성할때까지 WebDAV을 사용하지 마라. 그렇지 않으면 누구라도 서버를 통해 파일을 분배할 수 있게 된다.

DavDepthInfinity 지시어

설명: | PROPFIND의 Depth: Infinity 요청을 허가한다
문법: | DavDepthInfinity on|off
기본값: | DavDepthInfinity off
사용장소: | 주서버설정, 가상호스트, directory
상태: | Extension
모듈: | mod_dav

DavDepthInfinity 지시어를 사용하면 'Depth: Infinity' 헤더를 가진 PROPFIND 요청을 허가한다. 이런 요청을 사용하여 서비스거부 공격이 가능하기 때문에 기본적으로 허용하지 않는다.

DavMinTimeout 지시어

설명: | 서버가 DAV 자원에 대해 유지할 잠금의 최소시간
문법: | DavMinTimeout seconds
기본값: | DavMinTimeout 0
사용장소: | 주서버설정, 가상호스트, directory
상태: | Extension
모듈: | mod_dav

클라이언트가 DAV 자원에 잠금(lock)을 요청할때 서버가 알아서 잠금을 제거할 수 있는 시간을 같이 알려줄 수 있다. 이 값은 단지 요청일뿐이며, 서버는 클라이언트가 요청한 값을 무시하고 클라이언트에게 임의의 시간을 알려줄 수 있다.

DavMinTimeout 지시어는 클라이언트에게 보낼 최소 잠금 시간을 (초단위) 지정한다. Microsoft Web Folders는 기본값으로 120 초를 사용한다. DavMinTimeout에 (600 초와 같이) 더 높은 값을 사용하면 클라이언트가 네트웍 지연때문에 잠금을 잃게되는 경우를 줄일 수 있다.

예제

<Location /MSWord>
DavMinTimeout 600
 </Location>


mod_dav_fs - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_dav_fs

설명: | mod_dav을 위한 파일시스템 제공자
상태: | Extension
모듈명: | dav_fs_module
소스파일: | mod_dav_fs.c

요약

이 모듈은 mod_dav 서비스에 필요하다. mod_dav를 지원하는 모듈로 서버의 파일시스템에 있는 자원을 접근할 수 있도록 한다. 이 제공자(provider)의 정식명칭은 filesystem이다. Dav 지시어를 지정하여 mod_dav 뒷단 제공자를 사용한다:

예제

Dav filesystem

filesystem이 mod_dav의 기본 제공자이므로 대신 On을 사용할 수 있다.

참고

  • mod_dav

DavLockDB 지시어

설명: | DAV 잠금 데이터베이스 위치
문법: | DavLockDB file-path
사용장소: | 주서버설정, 가상호스트
상태: | Extension
모듈: | mod_dav_fs

DavLockDB 지시어는 잠금 데이터베이스의 전체 경로를 확장자를 제외하고 지정한다. 절대경로가 아니면 ServerRoot에 상대경로로 처리한다. mod_dav_fs는 잠금을 SDBM 데이터베이스에 기록한다.

예제

DavLockDB var/DavLock

아파치를 실행하는 User와 Group은 잠금 데이터베이스가 있는 디렉토리에 쓰기 권한을 가져야 한다. 보안상 이유로 기존 디렉토리의 권한을 바꾸기보다는 잠금 데이터베이스용 디렉토리를 만들어야 한다. 위의 경우 아파치는 ServerRoot 아래 var/ 디렉토리에 서버가 선택한 확장명을 가진 DavLock 파일을 만든다.


mod_deflate - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_deflate

설명: | 내용을 클라이언트로 보내기 전에 압축한다
상태: | Extension
모듈명: | deflate_module
소스파일: | mod_deflate.c

요약

mod_deflate 모듈은 서버의 출력을 네트웍으로 클라이언트에 보내기 전에 압축하는 DEFLATE 출력필터를 제공한다.

참고

  • 필터

권장하는 설정

급한 사람을 위한 견본 설정이다.

일부 type만 압축

AddOutputFilterByType DEFLATE text/html text/plain text/xml

아래 설정은 요약하였지만 그래도 복잡하다. 설정을 완전히 이해한 후 사용하라.

이미지를 제외한 모든 것을 압축

<Location />
# 필터를 추가한다
SetOutputFilter DEFLATE

# Netscape 4.x에 문제가 있다...
BrowserMatch ^Mozilla/4 gzip-only-text/html

# Netscape 4.06-4.08에 더 문제가 있다
BrowserMatch ^Mozilla/4\.0[678] no-gzip

# MSIE은 Netscape라고 자신을 알리지만, 문제가 없다
# BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# 주의: 아파치 2.0.48까지 mod_setenvif의 버그때문에
# 위의 정규표현식은 동작하지 않는다. 원하는 효과를
# 얻기위해 다음과 같이 수정하여 사용한다:
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

# 이미지를 압축하지 않는다
SetEnvIfNoCase Request_URI \
\.(?:gif|jpe?g|png)$ no-gzip dont-vary
# 프록시가 잘못된 내용을 전달하지않도록 한다
Header append Vary User-Agent env=!dont-vary
 </Location>

압축하기

출력 압축

DEFLATE 필터가 압축을 한다. 다음 지시어는 지시어가 있는 위치의 문서를 압축한다:

SetOutputFilter DEFLATE

모든 내용을 압축하면 처리하지 못하는 브라우저가 있기때문에 html 파일만을 압축하기위해 (아래 참고) gzip-only-text/html을 1로 설정할지도 모른다. 이를 1이 아닌 값으로 설정하면 무시한다.

보통 특별한 MIME type만 압축하려면 AddOutputFilterByType 지시어를 사용한다. 다음 설정은 html 파일만을 압축한다:

<Directory "/your-server-root/manual">
AddOutputFilterByType DEFLATE text/html
 </Directory>

압축한 파일을 처리하지 못하는 브라우저에게는 압축하지않고 보내길위해 BrowserMatch 지시어에 no-gzip을 설정한다. 최적의 결과를 얻기위해 no-gzip과 gzip-only-text/html을 같이 사용할 수 있다. 이 경우 전자가 후자를 무시한다. 위 절의 설정 예제 일부를 살펴보자:

BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

먼저 User-Agent 문자열을 보고 Netscape Navigator 버전 4.x인지 검사한다. 이 버전은 text/html이 아닌 type의 압축을 처리하지 못한다. 버전 4.06, 4.07, 4.08은 html 파일 압축을 처리하는대도 문제가 있다. 그래서 우리는 이 경우 deflate 필터를 완전히 사용하지않는다.

세번째 BrowserMatch 지시어는 Microsoft Internet Explorer가 자신을 "Mozilla/4"로 알리지만 압축된 요청을 처리할 수 있기때문에 user agent 추측을 수정한다. User-Agent 헤더에서 "MSIE" (\b는 "단어 경계"를 뜻한다) 문자열을 발견하면 앞에서 설정한 제약을 푼다.

주의

DEFLATE 필터는 항상 PHP나 SSI와 같은 RESOURCE 필터 뒤에 들어간다. 또, 내부 하위요청(subrequest)에 영향을 주지 않는다.

입력 압축풀기

mod_deflate 모듈은 gzip으로 압축된 요청 내용을 푸는 필터도 제공한다. 이 기능을 사용하려면 다음과 같이 SetInputFilter나 AddInputFilter를 사용하여 입력필터순서에 DEFLATE 필터를 추가한다.

<Location /dav-area>
SetInputFilter DEFLATE
 </Location>

요청에 Content-Encoding: gzip 헤더가 있다면 자동으로 압축된 내용을 푼다. gzip 요청을 할 수 있는 브라우저는 드물다. 그러나 어떤 WebDAV 클라이언트와 같은 특별한 프로그램은 요청 압축을 지원한다.

Content-Length에 대한 주의

요청 내용을 직접 살펴본다면, Content-Length 헤더를 믿지마라! Content-Length 헤더는 클라이언트가 보낸 내용의 길이이지, 압축을 푼 결과의 바이트수가 아니다.

프록시 서버 다루기

mod_deflate 모듈은 프록시가 자신이 캐쉬한 응답을 적절한 Accept-Encoding 요청 헤더를 보낸 클라이언트에게만 보내도록 Vary: Accept-Encoding HTTP 응답 헤더를 추가한다. 그래서 압축된 내용을 이해할 수 없는 클라이언트에 압축된 내용을 보내지않도록 한다.

예를 들어, User-Agent 헤더 등에 따라 특별히 필터 적용을 취소한다면, 프록시에게 이러한 제한을 알려주기위해 직접 Vary 헤더에 추가해야 한다. 예를 들어, 설정이 User-Agent에 따라 DEFLATE 필터를 추가한다면 다음을 사용한다:

Header append Vary User-Agent

요청 헤더외의 다른 정보에 (예를 들어, HTTP 버전) 따라 압축 여부가 결정된다면, Vary 헤더값을 *로 설정해야 한다. 그러면 표준을 따르는 프록시는 캐쉬를 하지 않게 된다.

예제

Header set Vary *

DeflateBufferSize 지시어

설명: | zlib이 한번에 압축할 크기
문법: | DeflateBufferSize value
기본값: | DeflateBufferSize 8096
사용장소: | 주서버설정, 가상호스트
상태: | Extension
모듈: | mod_deflate

DeflateBufferSize 지시어는 zlib이 한번에 압축할 바이트수를 지정한다.

DeflateCompressionLevel 지시어

설명: | 출력을 어느정도 압축하는가
문법: | DeflateCompressionLevel value
기본값: | Zlib's default
사용장소: | 주서버설정, 가상호스트
상태: | Extension
모듈: | mod_deflate
지원: | 아파치 2.0.45 부터

DeflateCompressionLevel 지시어는 사용할 압축수준을 선택한다. 값이 클수록 압축률이 증가하지만, CPU를 더 많이 사용한다.

(가장 덜 압축) 1과 (가장 많이 압축) 9 사이의 값을 지정한다.

DeflateFilterNote 지시어

설명: | 압축률을 로그에 기록한다
문법: | DeflateFilterNote [type] notename
사용장소: | 주서버설정, 가상호스트
상태: | Extension
모듈: | mod_deflate
지원: | type은 아파치 2.0.45 부터

DeflateFilterNote 지시어는 요청의 압축률을 로그에 기록하는 기호를 지정한다. 기호 이름은 지시어로 지정한 값이다. 통계를 위해 접근 로그에서 기호를 사용할 수 있다.

예제

DeflateFilterNote ratio

LogFormat '"%r" %b (%{ratio}n) "%{User-agent}i"' deflate
CustomLog logs/deflate_log deflate

로그에서 더 정확한 값을 추출하려면 type 아규먼트로 기록할 자료를 선택한다. type는 다음중 하나이다:

Input
필터 입력스트림의 바이트수를 저장한다.
Output
필터 출력스트림의 바이트수를 저장한다..
Ratio
압축률을 (output/input * 100) 저장한다. type 아규먼트를 생략하면 사용하는 기본값이다.

그래서 이렇게 로그에 기록할 수 있다:

정밀한 로그

DeflateFilterNote Input instream
DeflateFilterNote Output outstream
DeflateFilterNote Ratio ratio

LogFormat '"%r" %{outstream}n/%{instream}n (%{ratio}n%%)' deflate
CustomLog logs/deflate_log deflate

참고

  • mod_log_config

DeflateMemLevel 지시어

설명: | zlib이 압축할때 사용하는 메모리량
문법: | DeflateMemLevel value
기본값: | DeflateMemLevel 9
사용장소: | 주서버설정, 가상호스트
상태: | Extension
모듈: | mod_deflate

DeflateMemLevel 지시어는 zlib이 압축할때 얼마만큼 메모리를 사용할지 결정한다. (1과 9 사이의 값)

DeflateWindowSize 지시어

설명: | Zlib 압축 window size
문법: | DeflateWindowSize value
기본값: | DeflateWindowSize 15
사용장소: | 주서버설정, 가상호스트
상태: | Extension
모듈: | mod_deflate

DeflateWindowSize 지시어는 zlib 압축 window size를 (1과 15 사이의 값) 지정한다. 일반적으로 window size가 클수록 압축률이 증가한다.


mod_dir - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_dir

설명: | "마지막 슬래쉬" 리다이렉션을 제공하고 디렉토리 index 파일을 서비스한다
상태: | Base
모듈명: | dir_module
소스파일: | mod_dir.c

요약

디렉토리의 index는 다음 둘중 한가지 방법으로 제공된다:

  • 사용자가 작성한 보통 index.html이라는 파일. DirectoryIndex 지시어는 이 파일의 이름을 지정한다. mod_dir가 이 지시어를 제공한다.
  • 아니라면 서버가 만든 목록. mod_autoindex가 이 기능을 제공한다.

두 기능은 서로 별개로 원한다면 자동 index 생성을 완전히 없앨 (혹은 교체할) 수 있다.

dirname이 디렉토리라면 서버는 URL http://servername/foo/dirname 요청을 받으면 "마지막 슬래쉬" 리다이렉션을 보낸다. 디렉토리에는 마지막 슬래쉬가 필요하다. 그래서 mod_dir은 http://servername/foo/dirname/로 리다이렉션을 보낸다.

DirectoryIndex 지시어

설명: | 클라이언트가 디렉토리를 요청할때 찾아볼 자원 목록
문법: | DirectoryIndex local-url [local-url] ...
기본값: | DirectoryIndex index.html
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_dir

DirectoryIndex 지시어는 클라이언트가 디렉토리명 끝에 /를 붙여서 디렉토리의 index를 요청할때 찾아볼 자원 목록을 지정한다. Local-url은 요청한 디렉토리에 상대적인 문서의 (%로 인코딩된) URL이다. 보통은 디렉토리에 있는 파일명이다. 여러 URL을 지정할 수 있고, 이 경우 서버는 첫번째로 찾은 파일을 보낸다. 자원을 찾을 수 없고 Indexes 옵션을 설정하였다면 서버는 직접 디렉토리 목록을 만든다.

예제

DirectoryIndex index.html

이 경우 http://myserver/docs/를 요청할때 http://myserver/docs/index.html이 있으면 이를 보내고, 없다면 디렉토리 목록을 보낸다.

문서가 반드시 디렉토리에 상대적일 필요는 없다.

DirectoryIndex index.html index.txt /cgi-bin/index.pl

이 경우 디렉토리에 index.html이나 index.txt가 없으면 CGI 스크립트 /cgi-bin/index.pl을 실행한다.

DirectorySlash 지시어

설명: | 마지막 슬래쉬 리다이렉션을 키고 끈다
문법: | DirectorySlash On|Off
기본값: | DirectorySlash On
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_dir
지원: | 아파치 2.0.51 이후부터

DirectorySlash 지시어는 mod_dir가 디렉토리를 가리키는 URL을 수정할지 여부를 결정한다.

사용자가 마지막 슬래쉬없이 디렉토리에 해당하는 자원을 요청하면, mod_dir는 보통 다음과 같은 이유로 사용자를 마지막 슬래쉬를 붙인 동일한 자원으로 리다이렉션한다.

  • 사용자는 결국 자원의 정규 URL을 요청하게 된다
  • mod_autoindex가 올바로 동작한다. 이 기능이 없다면 이 모듈은 링크에 잘못된 경로를 쓰게 된다.
  • DirectoryIndex는 마지막 슬래쉬가 있는 디렉토리 요청만을 처리한다.
  • html 페이지에 있는 상대적인 URL 참조가 올바로 동작한다.

그런데 이 기능을 원하지 않거나 위에 든 이유가 당신에게 알맞지 않다면 다음과 같이 리다이렉션을 하지 않을 수 있다.

# 아래 보안 경고 참고!
<Location /some/path>
DirectorySlash Off
SetHandler some-handler
 </Location>

보안 경고

마지막 슬래쉬 리다이렉션을 끄면 정보가 유출될 수 있다. (Options +Indexes) mod_autoindex를 사용하고 DirectoryIndex를 (index.html 같은) 유효한 자원으로 설정하였지만 해당 URL에 다른 특별한 핸들러가 없는 상황을 상상해보라. 이 경우 마지막 슬래쉬가 있는 요청은 index.html 파일을 보여준다. 그러나 마지막 슬래쉬가 없는 요청은 디렉토리 내용을 보여준다.


mod_disk_cache - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_disk_cache

설명: | Content cache storage manager keyed to URIs
상태: | Experimental
모듈명: | disk_cache_module
소스파일: | mod_disk_cache.c

요약

이 모듈은 실험적인 상태이다. 문서는 아직 작업중이다...

mod_disk_cache는 디스크기반 저장관리자를 구현한다. 이 모듈은 기본적으로 mod_proxy와 같이 사용한다.

내용을 URI를 토대로 만든 키로 캐쉬에 저장하고 가져온다. 접근보호가 된 내용은 캐쉬하지않는다.

주의:

mod_disk_cache는 mod_cache가 필요하다.

CacheDirLength 지시어

설명: | 하위디렉토리명의 문자개수
문법: | CacheDirLength length
기본값: | CacheDirLength 2
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

CacheDirLength 지시어는 캐쉬 계층구조에서 각 하위디렉토리명의 문자수를 지정한다.

CacheDirLevels와 CacheDirLength를 곱하여 20 보다 크면 안된다.

CacheDirLength 4

CacheDirLevels 지시어

설명: | 캐쉬의 하위디렉토리 깊이.
문법: | CacheDirLevels levels
기본값: | CacheDirLevels 3
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

CacheDirLevels 지시어는 캐쉬의 하위디렉토리 깊이를 지정한다. 캐쉬된 자료를 CacheRoot 디렉토리 아래 이 깊이까지 저장한다.

CacheDirLevels와 CacheDirLength를 곱하여 20 보다 크면 안된다.

CacheDirLevels 5

CacheExpiryCheck 지시어

설명: | 캐쉬에서 파일을 찾을때 만기시간을 고려할지 여부
문법: | CacheExpiryCheck On|Off
기본값: | CacheExpiryCheck On
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

함수가 구현되면 더 자세한 내용이 여기 나온다.

CacheExpiryCheck Off

CacheExpiryCheck 지시어는 현재 구현되지 않았다.

CacheGcClean 지시어

설명: | URL에 해당하는 변하지않은 캐쉬파일을 유지할 시간
문법: | CacheGcClean hours url-string
기본값: | CacheGcClean ?
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

함수가 구현되면 더 자세한 내용이 여기 나온다.

CacheGcClean 12 /daily_scripts

CacheGcClean 지시어는 현재 구현되지 않았다.

CacheGcDaily 지시어

설명: | 매일 가비지컬랙터를 실행할 반복 시간 (24시 시계)
문법: | CacheGcDaily time
기본값: | CacheGcDaily ?
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

함수가 구현되면 더 자세한 내용이 여기 나온다.

CacheGcDaily 23:59

CacheGcDaily 지시어는 현재 구현되지 않았다.

CacheGcInterval 지시어

설명: | 가비지컬랙터를 실행하는 간격.
문법: | CacheGcInterval hours
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

CacheGcInterval 지시어는 카비지컬랙터가 디스크공간을 비우는 시간 간격을 시간단위로 지정한다.

함수가 구현되면 더 자세한 내용이 여기 나온다.

CacheGcInterval 24

CacheGcInterval 지시어는 현재 구현되지 않았다.

CacheGcMemUsage 지시어

설명: | 가비지컬랙터가 사용할 최대 메모리량 (kilobyte 단위)
문법: | CacheGcMemUsage KBytes
기본값: | CacheGcMemUsage ?
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

함수가 구현되면 더 자세한 내용이 여기 나온다.

CacheGcMemUsage 16

CacheGcMemUsage 지시어는 현재 구현되지 않았다.

CacheGcUnused 지시어

설명: | URL에 해당하는 참조되지않은 캐쉬파일을 유지할 기간.
문법: | CacheGcUnused hours url-string
기본값: | CacheGcUnused ?
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

함수가 구현되면 더 자세한 내용이 여기 나온다.

CacheGcUnused 12 /local_images

CacheGcUnused 지시어는 현재 구현되지 않았다.

CacheMaxFileSize 지시어

설명: | 캐쉬에 저장할 문서의 최대크기 (바이트 단위)
문법: | CacheMaxFileSize bytes
기본값: | CacheMaxFileSize 1000000
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

CacheMaxFileSize 지시어는 캐쉬에 저장할 문서의 최대크기를 바이트 단위로 지정한다.

CacheMaxFileSize 64000

CacheMinFileSize 지시어

설명: | 캐쉬에 저장할 문서의 최소크기 (바이트 단위)
문법: | CacheMinFileSize bytes
기본값: | CacheMinFileSize 1
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

CacheMinFileSize 지시어는 캐쉬에 저장할 문서의 최소크기를 바이트 단위로 지정한다.

CacheMinFileSize 64

CacheRoot 지시어

설명: | 캐쉬 파일을 저장할 디렉토리 root
문법: | CacheRoot directory
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

CacheRoot 지시어는 디스크에서 캐쉬 파일을 저장할 디렉토리를 지정한다. mod_disk_cache 모듈을 아파치 서버와 같이 컴파일하였거나 읽어들인 경우 반드시 이 지시어를 정의해야 한다. CacheRoot에 값이 없으면 설정파일을 처리하지 않는다. CacheDirLevels와 CacheDirLength 지시어는 이 지시어로 지정한 root 디렉토리의 하위디렉토리 구조를 지시한다.

CacheRoot c:/cacheroot

CacheSize 지시어

설명: | 캐쉬로 사용할 최대 디스크공간 (KByte 단위)
문법: | CacheSize KBytes
기본값: | CacheSize 1000000
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

CacheSize 지시어는 캐쉬로 사용할 디스크공간 크기를 KByte (1024 바이트) 단위로 지정한다. 이 지시어는 캐쉬 크기를 제한하지 않는다. 가비지컬랙터가 캐쉬 사용량이 설정한 값보다 작게될때까지 파일을 지운다. 항상 사용가능한 디스크공간 보다 작은 값을 사용하라.

CacheSize 5000000

CacheTimeMargin 지시어

설명: | 문서를 캐쉬할 최소시간 한계
문법: | CacheTimeMargin ?
기본값: | CacheTimeMargin ?
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_disk_cache

함수가 구현되면 더 자세한 내용이 여기 나온다.

CacheTimeMargin X

CacheTimeMargin 지시어는 현재 구현되지 않았다.


mod_dumpio - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_dumpio

Description: | Dumps all I/O to error log as desired.
Status: | Experimental
Module Identifier: | dumpio_module
Source File: | mod_dumpio.c

Summary

mod_dumpio allows for the logging of all input received by Apache and/or all output sent by Apache to be logged (dumped) to the error.log file.

The data logging is done right after SSL decoding (for input) and right before SSL encoding (for output). As can be expected, this can produce extreme volumes of data, and should only be used when debugging problems.

Enabling dumpio Support

To enable the module, it should be compiled and loaded in to your running Apache configuration. Logging can then be enabled or disabled via the below directives.

DumpIOInput Directive

Description: | Dump all input data to the error log
Syntax: | DumpIOInput On|Off
Default: | DumpIOInput Off
Context: | server config
Status: | Experimental
Module: | mod_dumpio
Compatibility: | DumpIOInput is only available in Apache 2.0.53 and later.

Enable dumping of all input.

Example

DumpIOInput On

DumpIOOutput Directive

Description: | Dump all output data to the error log
Syntax: | DumpIOOutput On|Off
Default: | DumpIOOutput Off
Context: | server config
Status: | Experimental
Module: | mod_dumpio
Compatibility: | DumpIOOutput is only available in Apache 2.0.53 and later.

Enable dumping of all output.

Example

DumpIOOutput On


mod_echo - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_echo

설명: | 프로토콜 모듈을 설명하기위한 간단한 echo 서버
상태: | Experimental
모듈명: | echo_module
소스파일: | mod_echo.c
지원: | Apache 2.0 이후부터

요약

이 모듈은 프로토콜 모듈의 개념을 설명하기위한 예제이다. 이 모듈은 간단한 echo 서버를 구현한다. 이 서버로 telnet하여 무언가를 입력하면, 서버는 입력한 내용이 그대로 반환한다.

ProtocolEcho 지시어

설명: | echo 서버를 키고 끈다
문법: | ProtocolEcho On|Off
사용장소: | 주서버설정, 가상호스트
상태: | Experimental
모듈: | mod_echo
지원: | ProtocolEcho는 2.0 이후에만 있다.

ProtocolEcho 지시어는 echo 서버를 키고 끈다.

예제

ProtocolEcho On


mod_env - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_env

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.
설명: | CGI 스크립트나 SSI 페이지에 전달할 환경변수를 수정한다
상태: | Base
모듈명: | env_module
소스파일: | mod_env.c

요약

이 모듈은 CGI 스크립트나 SSI 페이지에 전달할 환경변수를 조절한다. 웹서버를 시작한 쉘에서 환경변수를 가져올 수 있다. 아니면 설정과정중에 환경변수를 설정하고 제거할 수 있다.

참고

  • 환경변수

PassEnv 지시어

설명: | 쉘에서 환경변수를 가져온다
문법: | PassEnv env-variable [env-variable] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_env

웹서버를 실행한 쉘의 특정 환경변수를 CGI 스크립트나 SSI 페이지로 전달한다.

예제

PassEnv LD_LIBRARY_PATH

SetEnv 지시어

설명: | 환경변수를 설정한다
문법: | SetEnv env-variable value
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_env

CGI 스크립트나 SSI 페이지에 전달할 환경변수를 설정한다.

예제

SetEnv SPECIAL_PATH /foo/bin

UnsetEnv 지시어

설명: | 환경변수를 제거한다
문법: | UnsetEnv env-variable [env-variable] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_env

CGI 스크립트나 SSI 페이지에 환경변수를 전달하지 않는다.

예제

UnsetEnv LD_LIBRARY_PATH


mod_example - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_example

설명: | 아파치 모듈 API를 설명한다
상태: | Experimental
모듈명: | example_module
소스파일: | mod_example.c

요약

이 문서는 아파치 웹서버 2.0 버전에서 변경된 내용을 담고 있지 않다. 아직도 유효한 정보가 있지만, 주의해서 사용하길 바란다.

아파치 배포본 src/modules/example 디렉토리에 있는 파일들은 아파치 API를 사용하여 모듈을 작성하려는 사람들을 돕기위한 예제다.

mod_example.c는 모든 콜백(callback) 구조와 호출 문법을 설명하는 파일이다. 당신은 모듈에 이 모든 콜백을 구현할 필요가 없다. 사실 정반대다!

example 모듈은 실제로 동작하는 모듈이다. 이 모듈을 서버에 연결하고 특정 위치에 "example-handler" 핸들러를 할당하여 그곳을 브라우징하면 example 모듈의 여러 콜백을 확인할 수 있다.

example 모듈 컴파일하기

서버에 example 모듈을 포함하려면 다음 과정을 거친다:

  1. src/Configuration 파일 아래 부분에 있는 "AddModule modules/example/mod_example" 줄의 주석처리를 없앤다. 이런 줄이 없다면, 다음과 같은 줄을 추가한다.

    AddModule modules/example/mod_example.o

  2. src/Configure 스크립트를 실행한다 ("cd src; ./Configure"). 그러면 서버 자체 Makefile을 만들고, 하위디렉토리에 있는 요청한 추가 모듈을 src/modules/Makefile에 추가한다.
  3. 서버를 컴파일한다 (src 디렉토리에 있는 "make"를 실행한다).

자신이 만든 모듈을 추가하려면:

  1. mkdir src/modules/mymodule
  2. cp src/modules/example/* src/modules/mymodule
  3. 새로 만든 디렉토리에 있는 파일을 수정한다.
  4. 적절히 수정하여 위의 [1]에서 [3]까지 과정을 진행한다.

mod_example 모듈 사용하기

example 모듈을 사용하려면 srm.conf 파일에 다음과 같은 설정을 추가하라:

<Location /example-info>
SetHandler example-handler
</Location>

아니면 .htaccess 파일에 다음과 같은 내용을 추가하고, 그 위치에서 "test.example" 같은 파일을 요청하라:

AddHandler example-handler .example

서버를 재시작한 후 이 위치를 브라우징하면 앞에서 말한 내용을 보게될 것이다.

Example 지시어

설명: | 아파치 모듈 API를 설명하기위한 예제 지시어
문법: | Example
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
상태: | Experimental
모듈: | mod_example

Example 지시어는 example 모듈의 내용핸들러가 간단한 문구를 보일지 여부를 설정한다. 이 지시어는 아규먼트를 받지않는다. example 내용핸들러를 적용한 URL에 접속하면 문서 요청을 서비스하기위해 모듈안에 함수들이 어떻게 그리고 어떤 순서로 불리는지 알 수 있다. 이 지시어의 효과는 "Example directive declared here: YES/NO"로 확인할 수 있다.


mod_expires - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_expires

설명: | 사용자가 지정한 기준에 따라 Expires와 Cache-Control HTTP 헤더를 생성한다
상태: | Extension
모듈명: | expires_module
소스파일: | mod_expires.c

요약

이 모듈은 서버 응답의 Expires HTTP 헤더와 Cache-Control HTTP 헤더의 max-age 지시어 설정을 조절한다. 만기일을 파일이 마직막 수정된 시간 혹은 클라이언트가 접속한 시간에 상대적으로 설정할 수 있다.

이 HTTP 헤더들은 클라이언트에게 문서의 유효성과 지속성을 알려준다. 이 시간이 아직 지나지않았다면, 문서를 캐쉬에서 가져와도 된다. 만기일이 지났다면 캐쉬된 것을 "만료되고" 유효하지 않다고 간주하여, 소스에서 문서를 새로 얻어와야 한다.

Header 지시어를 사용하여 max-age 외의 다른 Cache-Control 지시어(RFC 2616, 14.9 절 참고)를 수정할 수 있다.

다른 내부 문법

ExpiresDefault와 ExpiresByType 지시어를 더 읽기 좋은 형식으로 기술할 수 있다:

ExpiresDefault "<base> [plus] {<num> <type>}*"
ExpiresByType type/encoding "<base> [plus] {<num> <type>}*"

<base>는 다음중 하나이다:

  • access
  • now ('access'와 같음)
  • modification

plus 키워드는 없어도 된다. <num>은 [atoi()에 사용할 수 있는] 정수값이다. <type>은 다음중 하나이다:

  • years
  • months
  • weeks
  • days
  • hours
  • minutes
  • seconds

예를 들어, 다음 모두는 문서가 기본적으로 접속된지 1달후에 만기된다고 설정한다:

ExpiresDefault "access plus 1 month"
ExpiresDefault "access plus 4 weeks"
ExpiresDefault "access plus 30 days"

'<num> <type>' 구문을 반복해서 사용하여 만기시간을 자세히 설정할 수 있다:

ExpiresByType text/html "access plus 1 month 15 days 2 hours"
ExpiresByType image/gif "modification plus 5 hours 3 minutes"

만약 수정시간(modification)을 기준으로 만기시간을 설정하는 경우 내용을 디스크에 있는 파일에서 가져오지 않는다면 Expires 헤더를 붙이지 않는다. 이 경우 내용에 수정시간이 없기 때문이다.

ExpiresActive 지시어

설명: | Expires 헤더를 생성한다
문법: | ExpiresActive On|Off
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Extension
모듈: | mod_expires

이 지시어는 해당 영역에 대해 (즉, .htaccess 파일에서 사용한다면 그 디렉토리 아래에 있는 문서들만 해당된다.) Expires와 Cache-Control 헤더를 생성할지 유무를 결정한다. (.htaccess 파일 등으로 더 하위 단계에서 서버설정을 변경하지않는 한) Off이면 해당 영역에 있는 문서에 이들 헤더를 생성하지 않는다. On이면 ExpiresByType과 ExpiresDefault 지시어로 (해당 항목을 참고하라) 지정한 규칙에 따라 서비스하려는 문서에 이 헤더들을 생성한다.

이 지시어가 Expires나 Cache-Control 헤더를 보장하지는 않는다. 규칙에 해당하지 않다면 마치 이 지시어가 없는 것처럼 헤더를 만들지 않는다.

ExpiresByType 지시어

설명: | MIME type으로 Expires 헤더값을 설정한다
문법: | ExpiresByType MIME-type <code>seconds
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Extension
모듈: | mod_expires

이 지시어는 특정 종류의 (에를 들어, text/html) 문서에 대한 Expires 헤더값과 Cache-Control 헤더의 max-age 지시어값을 정의한다. 두번째 아규먼트는 만기시간을 결정할때 기준 시간에 더할 초단위 값을 지정한다. Cache-Control: max-age는 만기시간에서 요청한 시간을 빼서 계산하고, 결과는 초단위로 표시한다.

기준 시간은 파일의 최근 수정시간 혹은 클라이언트가 문서에 접근한 시간이다. 이떤 것을 사용할지는 <code> 필드로 결정해야 한다. M은 기준 시간으로 파일의 최근 수정시간을 사용하고, A는 클라이언트의 접근 시간을 사용한다.

차이는 미묘하다. M을 사용하면 캐쉬에 있는 모든 복사본이 같은 시간에 만료된다. 그래서 항상 같은 URL로 찾아볼 수 있는 주간일정 같은 용도에 좋다. A를 사용하면 복사본의 만기시간이 각각 다르다. 이는 자주 수정되지않는 그림파일에, 특히 여러 문서에서 같은 그림을 참조할때 (예를 들어, 이미지는 상대적으로 짧은 기간동안 반복해서 접근된다), 유용하다.

예제:

# 만기헤더를 사용한다
ExpiresActive On
# 클라이언트 캐쉬의 GIF 그림은 한 달후에 만기한다
ExpiresByType image/gif A2592000
# HTML 문서는 변경후 일주일간 유효하다 ExpiresByType text/html M604800

이 지시어는 ExpiresActive On을 사용할때만 유효함을 주의하라. ExpiresDefault 지시어를 사용하여 특정 MIME type에 대해서만 만기시간을 설정할 수 있다.

앞에서 설명한 다른 문법을 사용하여 만기시간을 계산할 수도 있다.

ExpiresDefault 지시어

설명: | 만기시간을 계산하는 기본 알고리즘
문법: | ExpiresDefault <code>seconds
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Extension
모듈: | mod_expires

이 지시어는 해당 영역에 있는 모든 문서의 만기시간을 계산하는 기본 알고리즘을 지정한다. ExpiresByType 지시어를 사용하여 종류별로 설정할 수 있다. 아규먼트 문법에 대한 자세한 설명은 그 지시어와 다른 문법을 참고하라.


mod_ext_filter - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_ext_filter

설명: | 응답 내용을 외부 프로그램으로 처리한 후 클라이언트로 보낸다
상태: | Extension
모듈명: | ext_filter_module
소스파일: | mod_ext_filter.c

요약

mod_ext_filter를 사용하면 간단하고 익숙한 방법으로 필터를 만들 수 있다. 표준입력에서 읽고 표준출력에 쓰는 프로그램(즉, 유닉스식 필터 명령어)을 아파치 필터로 사용할 수 있다. 이런 필터는 아파치 API로 쓰여지고 아파치 서버 프로세스 안에서 실행되는 필터에 비해 매우 느리지만, 다음과 같은 장점이 있다:

  • 프로그래밍 모델이 매우 간단하다
  • 프로그램이 표준입력에서 읽고 표준출력에 쓸 수만 있다면 어떤 프로그래밍/스크립트 언어라도 사용할 수 있다
  • 이미 있는 프로그램을 수정없이 아파치 필터로 사용할 수 있다

실제 사용하기에는 성능이 떨어지지만, mod_ext_filter를 사용하여 필터를 빨리 만들어볼 수 있다.

참고

  • 필터

예제

다른 type의 응답을 HTML로 만든다

# mod_ext_filter 지시어를 가지고
# 외부 프로그램 /usr/bin/enscript를 사용하여
# 문서파일과 text/c 파일을 HTML로 만들고 결과의
# type을 text/html로 변경하는 필터를 정의한다
ExtFilterDefine c-to-html mode=output \
intype=text/c outtype=text/html \
cmd="/usr/bin/enscript --color -W html -Ec -o - -"
<Directory "/export/home/trawick/apacheinst/htdocs/c">
# 출력에 새로운 필터를 실행하는 core 지시어
SetOutputFilter c-to-html

# .c 파일의 type을 text/c로 만드는 mod_mime
# 지시어
AddType text/c .c

# 디버그 수준을 높여서 요청마다 현재 설정을
# 알려주는 로그문을 기록하는 mod_ext_filter
# 지시어
ExtFilterOptions DebugLevel=1
 </Directory>

content 인코딩 필터 구현하기

Note: 아래 gzip 예제는 단지 설명을 예로 든 것이다. 실제 서비스에 사용하려면 mod_deflate를 참고하길 바란다.

# 외부 필터를 정의하는 mod_ext_filter 지시어
ExtFilterDefine gzip mode=output cmd=/bin/gzip

<Location /gzipped>
# 출력할때 gzip 필터를 실행하는 core 지시어
SetOutputFilter gzip

# "Content-Encoding: gzip" 헤더를 추가하는
# mod_header 지시어
Header set Content-Encoding gzip
 </Location>

서버를 느리게 하기

# cat으로 모든 내용을 통과하는 필터를 정의하는
# mod_ext_filter 지시어; cat은 아무것도 수정하지
# 않는다; 단지 처리경로를 길게 하여 자원을 더 소모한다
ExtFilterDefine slowdown mode=output cmd=/bin/cat \
preservescontentlength
<Location />
# 출력할때 slowdown 필터를 여러번 실행하는 core 지시어
#
SetOutputFilter slowdown;slowdown;slowdown
 </Location>

sed를 사용하여 응답에서 글을 대체하기

# 응답에서 글을 대체하는 필터를 정의하는
# mod_ext_filter 지시어
#
ExtFilterDefine fixtext mode=output intype=text/html \
cmd="/bin/sed s/verdana/arial/g"
<Location />
# 출력할때 fixtext 필터를 실행하는 core 지시어
SetOutputFilter fixtext
 </Location>

다른 필터를 추적하기

# 압축 문제가 있는 특정 클라이언트(IP 192.168.1.31)에
# 대해 mod_deflate가 읽고 쓰는 자료를 추적한다.
# 이 필터는 mod_deflate로 보내기 전 자료를 추적한다.
ExtFilterDefine tracebefore \
cmd="/bin/tracefilter.pl /tmp/tracebefore" \
EnableEnv=trace_this_client
# 이 필터는 mod_deflate에서 나오는 자료를 추적한다.
# ftype 파라미터를 사용하지않는 경우, 기본 필터형
# AP_FTYPE_RESOURCE는 필터 순서를 mod_deflate *이전에*
# 둔다. AP_FTYPE_CONTENT_SET 보다 조금 높은 숫자값을
# 지정하면 mod_deflate 이후에 실행한다.
ExtFilterDefine traceafter \
cmd="/bin/tracefilter.pl /tmp/traceafter" \
EnableEnv=trace_this_client ftype=21
<Directory /usr/local/docs>
SetEnvIf Remote_Addr 192.168.1.31 trace_this_client
SetOutputFilter tracebefore;deflate;traceafter
 </Directory>

다음은 자료를 추적하는 필터이다:

#!/usr/local/bin/perl -w
use strict;

open(SAVE, ">$ARGV[0]")
or die "can't open $ARGV[0]: $?";
while (<STDIN>) {
print SAVE $_;
print $_;
 }

close(SAVE);

ExtFilterDefine 지시어

설명: | 외부 필터를 정의한다
문법: | ExtFilterDefine filtername parameters
사용장소: | 주서버설정
상태: | Extension
모듈: | mod_ext_filter

ExtFilterDefine 지시어는 외부 필터의 성질과 실행할 프로그램, 아규먼트를 정의한다.

filtername은 정의할 필터 이름을 지정한다. 이 이름을 SetOutputFilter 지시어에서 사용한다. 등록한 모든 필터들간에 이름이 겹치면 안된다. 현재 필터등록 API는 오류를 보고하지 않는다. 그래서 사용자는 이름이 겹치는 문제를 알지 못한다.

실행할 외부 명령어와 다른 성질을 정의하는 나머지 아규먼트는 어떤 순서로 나와도 가능하다. 단, cmd= 파라미터는 반드시 필요하다. 사용할 수 있는 파라미터는 다음과 같다:

cmd=cmdline
cmd= 키워드는 실행할 외부 명령어를 지정한다. 프로그램명 뒤에 아규먼트가 있다면 명령행을 쌍따옴표로 묶어야 한다 (예를 들어, cmd="/bin/mypgm arg1 arg2"). 쉘을 거치지않고 직접 프로그램을 실행하기때문에 일반적인 쉘 따옴표는 필요없다. 프로그램 아규먼트들은 공백으로 구분한다. 프로그램 아규먼트에 공백이 있다면 공백 앞에 백슬래쉬로 사용해야 한다. 백슬래쉬가 아규먼트의 일부라면 백슬래쉬를 두번 사용해야 한다. 프로그램을 실행할때 표준 CGI 환경변수와 추가로 DOCUMENT_URI, DOCUMENT_PATH_INFO, QUERY_STRING_UNESCAPED 변수를 설정한다.
mode=mode
mode는 현재 (기본값인) output만 가능하다. 미래에는 mode=input을 사용하여 요청 내용을 처리하는 필터를 지정할 수 있을 것이다.
intype=imt
이 파라미터는 필터로 처리할 문서의 인터넷 media type(즉, MIME type)을 지정한다. 기본적으로 모든 문서를 필터로 처리한다. intype=을 지정하면 다른 type의 문서는 필터로 처리하지 않는다.
outtype=imt
이 파라미터는 필터로 처리한 문서의 인터넷 media type(즉, MIME type)을 지정한다. 필터처리 작업중에 인터넷 media type을 변경할때 유용하다. 기본적으로, 인터넷 media type은 변하지 않는다.
PreservesContentLength
PreservesContentLength 키워드는 필터가 content length를 유지하도록 한다. 대부분의 필터가 content length를 변경하므로 이 키워드는 기본값이 아니다. 필터가 길이를 유지할때만 이 키워드를 사용해야 한다.
ftype=filtertype
이 파라미터는 필터 종류에 대한 숫자값을 지정한다. 대부분의 경우 기본값인 AP_FTYPE_RESOURCE가 적당하다. 필터를 실행하는 순서가 자원필터와 달라야하는 경우 이 파라미터가 필요하다. 적당한 값을 알려면 util_filter.h에 있는 AP_FTYPE_* 정의를 참고하라.
disableenv=env
이 파라미터로 설정한 환경변수가 정의되었다면 필터를 사용하지 않는다.
enableenv=env
이 파라미터로 설정한 환경변수가 정의된 경우 필터를 사용한다.

ExtFilterOptions 지시어

설명: | mod_ext_filter 옵션을 설정한다
문법: | ExtFilterOptions option [option] ...
기본값: | ExtFilterOptions DebugLevel=0 NoLogStderr
사용장소: | directory
상태: | Extension
모듈: | mod_ext_filter

ExtFilterOptions 지시어는 mod_ext_filter의 특별한 처리옵션을 지정한다. Option은 다음중 하나다.

DebugLevel=n
DebugLevel 키워드는 mod_ext_filter가 기록하는 디버그 문구 수준을 정한다. 기본값은 디버그문을 기록하지 않는다. 이는 DebugLevel=0과 같다. 높은 숫자를 사용할수록, 더 많은 디버그문이 기록되고 서버 성능이 떨어진다. 숫자값의 실제 의미는 mod_ext_filter.c 앞부분에 있는 DBGLVL_ 상수 정의에 설명되있다.

주의: 필터 로그를 기록하려면 core 지시어 LogLevel을 사용하여 디버그문을 아파치 오류로그에 기록해야 한다.

LogStderr | NoLogStderr
LogStderr 키워드는 외부 필터 프로그램이 표준오류로 출력하는 문구를 아파치 오류로그에 기록한다. NoLogStderr는 이 기능을 하지 않는다.

예제

ExtFilterOptions LogStderr DebugLevel=0

위의 설정을 사용하면 필터가 표준오류로 출력하는 문구를 아파치 오류로그에 기록하고, mod_ext_filter는 자체 디버그문을 기록하지 않는다.


mod_file_cache - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_file_cache

설명: | 메모리에 정적 파일들을 캐쉬
상태: | Experimental
모듈명: | file_cache_module
소스파일: | mod_file_cache.c

요약

이 모듈은 조심해서 사용해야 한다. mod_file_cache를 사용하여 사이트를 엉망으로 만들기 쉽기때문에 이 문서를 꼼꼼히 읽길 바란다.

거의 변하지 않고 자주 요청되는 파일을 캐쉬에 저장하여 서버 부하를 줄일 수 있다. mod_file_cache는 자주 요청되는 정적 파일을 두가지 방식으로 캐쉬에 저장한다. 설정 지시어를 사용하여 mod_file_cache가 파일을 열고(open) mmap()할지 아니면 파일을 열고 파일 핸들을 저장할지 결정한다. 두 방식 모두 파일을 서비스하기위해 필요한 작업의 일부를 (특히 파일 입출력 작업) 파일을 요청할 때마다 매번 하는 대신 서버가 시작할때 한번만 하여 서버 부하가 감소한다.

주의: 이 방법은 CGI 프로그램이나 특별한 내용핸들러를 통해 서비스하는 파일의 서비스 속도를 높일 수 없다. 이 방법은 보통 아파치 core 내용핸들러가 서비스하는 일반파일에만 적용된다.

이 모듈은 아파치 1.3에 있는 mod_mmap_static 모듈의 기능을 확장한 결과다.

mod_file_cache 사용하기

mod_file_cache는 주서버 설정에서 MMapFile과 CacheFile 지시어를 사용하여 설정한 정적 파일들을 캐쉬에 저장한다.

모든 플래폼이 두 지시어를 모두 지원하는 것은 아니다. 예를 들어, 윈도우즈용 아파치는 현재 MMapStatic 지시어를 지원하지 않지만, AIX 같은 다른 플래폼은 둘 모두를 지원한다. 지원하지않는 지시어를 사용할 경우 서버 오류 로그에 오류문을 남긴다. 지원하지않는 지시어를 사용해도 서버는 동작하지만 파일을 캐쉬에 저장하지 않는다. 두 지시어를 모두 지원하는 플래폼을 사용한다면 어떤 방식이 더 좋은지 실험해보라.

MMapFile 지시어

mod_file_cache의 MMapFile 지시어는 설정한 정적 파일들을 mmap() 시스템호출을 사용하여 메모리에 대응한다. 최신 유닉스류 운영체제라면 보통 이 시스템호출이 있지만, 없는 운영체제도 있다. 또, mmap()할 수 있는 파일 크기와 개수를 시스템이 제한할 수 있으므로 미리 실험해보는 것이 좋다.

서버는 시작할때와 재시작할때만 mmap()한다. 그래서 파일시스템에서 해당 파일중 하나라도 변경되면 서버를 재시작해야 한다 (중단과 재시작 문서 참고). 다시 말해서 파일이 변경되었는데 서버를 재시작하지 않으면 완전히 이상하게 요청을 서비스할지도 모른다. 이전 파일을 지우고(unlink) 그 자리에 새로운 파일을 만들는 방식으로 파일을 수정해야 한다. rdist나 mv와 같은 대다수의 도구가 이런 방식으로 동작한다. 매번 추가로 불필요한 stat() 검사가 필요하고 입출력 감소라는 원래 의도에 반하기때문에 이 모듈은 파일의 변화를 무시한다.

CacheFile 지시어

mod_file_cache의 CacheFile 지시어는 설정 지시어에 열거한 파일(과 파일들)을 열어서 파일의 핸들(handle) 혹은 파일 기술자(file descriptor)를 캐쉬에 저장한다. 파일을 요청하면 서버는 캐쉬에서 핸들을 찾아서 소켓 API sendfile()에 (윈도우즈에서는 TransmitFile()) 넘긴다.

서버는 시작할때와 재시작할때만 파일 핸들을 캐쉬한다. 그래서 파일시스템에서 캐쉬한 파일중 하나라도 변경되면 서버를 재시작해야 한다 (중단과 재시작 문서 참고). 다시 말해서 파일이 변경되었는데 서버를 재시작하지 않으면 완전히 이상하게 요청을 서비스할지도 모른다. 이전 파일을 지우고(unlink) 그 자리에 새로운 파일을 만드는 방식으로 파일을 수정해야 한다. rdist나 mv와 같은 대다수의 도구가 이런 방식으로 동작한다.

주의

디렉토리의 모든 파일을 재귀적으로 캐쉬에 저장하는 지시어는 없다. 대신 다음과 같이 해보라... Include 지시어를 참고하여 다음과 같은 명령어를 실행한다:

find /www/htdocs -type f -print \
| sed -e 's/.*/mmapfile &/' > /www/conf/mmap.conf

CacheFile 지시어

설명: | 시작시 여러 파일 핸들을 캐쉬한다
문법: | CacheFile file-path [file-path] ...
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_file_cache

CacheFile 지시어는 서버가 시작할때 여러 파일을 열고(open) 파일들의 핸들을 캐쉬에 저장한다. 서버 종료시 자동으로 캐쉬한 파일의 핸들을 닫는다(close). 파일시스템에서 파일이 변경되면 파일을 다시 캐쉬하기위해 서버를 재시작해야 한다.

file-path 아규먼트를 조심해라. 아규먼트는 아파치의 URL-파일명 변환 핸들러가 만든 파일시스템 경로와 정확히 일치해야 한다. 한번 더 불필요한 stat() 시스템호출이 필요하기때문에 inode나 심볼링크 등을 경로를 지정할 수 없다. 이 모듈은 mod_alias나 mod_rewrite로 재작성한 파일명을 다룰 수 있기도 없기도 하다.

예제

CacheFile /usr/local/apache/htdocs/index.html

MMapFile 지시어

설명: | 시작시 여러 파일을 메모리에 대응한다
문법: | MMapFile file-path [file-path] ...
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_file_cache

MMapFile 지시어는 서버가 시작할때 (공백으로 구분한 아규먼트로 지정한) 여러 파일을 메모리에 대응한다(map). 서버 종료시 자동으로 대응을 푼다(unmap). 파일시스템에서 파일이 변경되면 파일들을 다시 mmap()하기위해 최소한 서버에 HUP이나 USR1 시그널을 보내야 한다.

file-path 아규먼트를 조심해라. 아규먼트는 아파치의 URL-파일명 변환 핸들러가 만든 파일시스템 경로와 정확히 일치해야 한다. 한번 더 불필요한 stat() 시스템호출이 필요하기때문에 inode나 심볼링크 등을 경로를 지정할 수 없다. 이 모듈은 mod_alias나 mod_rewrite로 재작성한 파일명을 다룰 수 있기도 없기도 하다.

예제

MMapFile /usr/local/apache/htdocs/index.html


mod_headers - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_headers

설명: | HTTP 요청 헤더와 응답 헤더 수정
상태: | Extension
모듈명: | headers_module
소스파일: | mod_headers.c
지원: | RequestHeader는 아파치 2.0에만 있다

요약

이 모듈은 HTTP 요청 헤더와 응답 헤더를 조절하고 수정하는 지시어들을 제공한다. 헤더를 합치거나 대체, 제거할 수 있다.

처리 순서

mod_headers가 제공하는 지시어는 서버설정의 거의 모든 장소에서 사용할 수 있다. 지시어는 주서버설정, 가상호스트 섹션, <Directory>, <Location>, <Files> 섹션, .htaccess 파일에서 사용할 수 있다.

지시어는 아래 순서대로 처리된다.

  1. 주서버
  2. 가상호스트
  3. <Directory> 섹션과 .htaccess
  4. <Files>
  5. <Location>

순서는 중요하다. 다음 두 지시어를 반대로 적으면 효과가 달라진다.

RequestHeader append MirrorID "mirror 12"
RequestHeader unset MirrorID

위와 같이 적으면 MirrorID 헤더가 나오지 않는다. 반대로 적으면 MirrorID 헤더를 "mirror 12"로 설정한다.

예제

  1. "TS"로 시작하는 모든 요청 헤더를 응답 헤더로 복사한다.

    Header echo ^TS

  2. 응답에 요청을 받은 시간과 요청을 서비스하는데 걸릴 시간을 알려주는 MyHeader 헤더를 추가한다. 클라이언트는 이 헤더를 보고 서버의 부하를 추정하거나 클라이언트와 서버간의 병목점을 찾을 수 있다.

    Header add MyHeader "%D %t"

    응답에 다음과 같은 헤더가 생긴다.

    MyHeader: D=3775428 t=991424704447256

  3. Joe에게 안녕

    Header add MyHeader "Hello Joe. It took %D microseconds \
    for Apache to serve this request."

    응답에 다음과 같은 헤더가 생긴다.

    MyHeader: Hello Joe. It took D=3775428 microseconds for Apache to serve this request.

  4. 요청에 "MyRequestHeader" 헤더가 있는 경우에만 선택적으로 응답에 MyHeader를 보낸다. 특정 클라이언트에게만 응답에 헤더를 추가할때 유용하다. 이 예제가 동작하려면 mod_setenvif 모듈이 필요하다.

    SetEnvIf MyRequestHeader value HAVE_MyRequestHeader
    Header add MyHeader "%D %t mytext" env=HAVE_MyRequestHeader

    HTTP 요청에 MyRequestHeader: value 헤더가 있다면, 응답에 다음과 같은 헤더가 생긴다.

    MyHeader: D=3775428 t=991424704447256 mytext

Header 지시어

설명: | HTTP 응답 헤더를 구성한다
문법: | Header [condition] set|append|add|unset|echo header [value] [env=[!]variable]
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Extension
모듈: | mod_headers
지원: | Condition은 아파치 2.0.51 부터

이 지시어는 HTTP 응답 헤더를 합치거나 대체, 제거한다. 내용 핸들러와 출력 필터가 실행한 직후에 헤더를 수정하기때문에 보낼 헤더를 수정할 수 있다.

condition은 선택적으로 사용하며, 값으로 onsuccess 혹은 always를 사용한다. 이는 어떤 내부 헤더표에 동작할지를 결정한다. onsuccess는 2xx 상태코드를 뜻하고, always는 (2xx를 포함한) 모든 상태코드를 뜻한다. 특히 어떤 모듈이 설정한 헤더를 해제하고 싶다면, 둘중 어떤 것을 사용할지 잘 살펴봐야 한다.

두번째 아규먼트에 따라 기능이 다르다. 두번째 아규먼트로 아래 값중 하나를 사용할 수 있다.

set
응답 헤더를 설정한다. 같은 이름으로 이미 헤더가 있다면 대체한다. value에 형식문자열을 사용할 수 있다.
append
이미 존재하는 같은 이름의 응답 헤더에 추가한다. 기존 헤더에 새로운 값을 합치면, 기존 헤더와 새로운 값 사이에 쉼표를 붙인다. 이는 여러 헤더값을 지정하는 HTTP 표준 방식이다.
add
헤더가 이미 있더라도 응답 헤더를 추가한다. 그래서 같은 이름의 헤더가 두개 (혹은 많이) 생길 수 있다. 이 경우 의외의 결과가 발생할 수 있기때문에 보통 대신 append를 사용해야 한다.
unset
이런 이름의 응답 헤더가 있다면 삭제한다. 같은 이름을 가진 헤더가 여러개 있다면 모두 제거한다.
echo
이런 이름의 요청 헤더를 그대로 응답 헤더로 보낸다. header에 정규표현식을 사용할 수 있다.

아규먼트 뒤에 header 이름이 나온다. 헤더명 뒤에 콜론을 적을 수 있지만, 없어도 된다. set, append, add, unset에서 대소문자는 무시한다. echo의 header 이름은 대수문자를 구별하고 정규표현식을 사용할 수 있다.

add, append, set을 사용할때는 세번째 아규먼트 value가 필요하다. value 안에 공백이 있다면 쌍따옴표로 묶어야 한다. value는 일반 문자열이나 형식을 기술하는 문자열이며, 두가지를 같이 사용할 수도 있다. value에서 지원하는 형식기술자는 다음과 같다.

%t | 요청을 받은 시간을 국제표준시로 epoch (1970년 1월 1일) 이후 지난 마이크로초 단위로. 값 앞에 t=이 붙는다.
%D | 요청을 받은 시간부터 헤더를 네트웍에 쓸때까지 걸린 시간. 요청의 기간을 잰다. 값 앞에 D=이 붙는다.
%{FOOBAR}e | 환경변수 FOOBAR의 내용.

Header 지시어의 add, append, set 아규먼트를 사용하는 경우 네번째 아규먼트로 작업에 필요한 조건을 지정할 수 있다. env=... 아규먼트를 사용하면 해당 환경변수가 존재하는 경우에만 (아니면 env=!...에 나온 환경변수가 존재하지 않다면) Header 지시어가 동작한다. 그렇지 않으면 지시어는 요청에 아무 영향을 미치지 않는다.

응답을 네트웍으로 보내기 직전에 Header 지시어를 처리한다. 그래서 헤더 필터가 추가하는 헤더를 제외한 대부분의 헤더를 설정하거나 덮어쓸 수 있다.

RequestHeader 지시어

설명: | HTTP 요청 헤더를 구성한다
문법: | RequestHeader set|append|add|unset header [value]
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Extension
모듈: | mod_headers

이 지시어는 HTTP 요청 헤더를 합치거나 대체, 제거한다. 내용 핸들러가 실행하기 직전에 헤더를 수정하기때문에 받은 헤더를 수정할 수 있다. 첫번째 아규먼트에 따라 기능이 다르다. 첫번째 아규먼트로 아래 값중 하나를 사용할 수 있다.

set
요청 헤더를 설정한다. 같은 이름으로 이미 헤더가 있다면 대체한다
append
이미 존재하는 같은 이름의 요청 헤더에 추가한다. 기존 헤더에 새로운 값을 합치면, 기존 헤더와 새로운 값 사이에 쉼표를 붙인다. 이는 여러 헤더값을 지정하는 HTTP 표준 방식이다.
add
헤더가 이미 있더라도 요청 헤더를 추가한다. 그래서 같은 이름의 헤더가 두개 (혹은 많이) 생길 수 있다. 이 경우 의외의 결과가 발생할 수 있기때문에 보통 대신 append를 사용해야 한다.
unset
이런 이름의 요청 헤더가 있다면 삭제한다. 같은 이름을 가진 헤더가 여러개 있다면 모두 제거한다.

아규먼트 뒤에 헤더명이 나온다. 헤더명 뒤에 콜론을 적을 수 있지만, 없어도 된다. 대소문자는 무시한다. add, append, set을 사용할때는 세번째 아규먼트 value가 필요하다. value 안에 공백이 있다면 쌍따옴표로 묶어야 한다. unset을 사용할때는 value를 적으면 안된다.

fixup 단계에서 요청에 해당하는 핸들러를 실행하기 직전에 RequestHeader 지시어를 처리한다. 그래서 브라우저에 따라 혹은 아파치 입력필터가 헤더를 덮어쓰거나 수정할 수 있다.


mod_imap - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_imap

설명: | 서버측 이미지맵(imagemap) 처리
상태: | Base
모듈명: | imap_module
소스파일: | mod_imap.c

요약

이 모듈은 imagemap CGI 프로그램을 대신하여 .map 파일을 처리한다. 이 모듈은 (AddHandler나 SetHandler를 사용하여) imap-file 핸들러를 사용하도록 설정한 디렉토리나 문서를 처리한다.

아래 지시어는 .map으로 끝나는 파일을 이미지맵 파일로 설정한다.

AddHandler imap-file map

아직도 아래와 같은 설정을 지원한다.

AddType application/x-httpd-imap map

그러나 우리는 점차 "서버에게 특별한 의미가 있는 MIME type"을 제거하려고 하기때문에 이 방법은 없어질 것이다.

새로운 기능

이미지맵 모듈에는 이전 이미지맵 프로그램에는 없는 몇가지 새로운 기능이 있다.

  • Referer: 정보에 상대적인 URL 참조.
  • 새로운 base 맵지시어를 사용하여 기본 <base> 지정.
  • imagemap.conf 파일 필요없음.
  • 점(point) 참조.
  • 이미지맵 메뉴 조정 가능.

이미지맵 파일

이미지맵 파일은 아래와 같은 형식으로 작성한다.

directive value [x,y ...]
directive value "Menu text" [x,y ...]
directive value x,y ... "Menu text"

directive는 base, default, poly, circle, rect, point 중 하나다. value에는 절대 URL이나 상대 URL 혹은 아래에서 열거할 특수값을 사용한다. 좌표는 공백으로 구분한 x,y 쌍이다. 따옴표로 묶은 문구는 이미지맵 메뉴를 만들때 링크 제목으로 사용한다. '#'로 시작하는 줄은 주석이다.

이미지맵 파일 지시어

이미지맵 파일에서 6가지 지시어를 사용할 수 있다. 지시어는 특별한 순서없이 사용할 수 있지만, 이미지맵 파일에 나온 순서대로 처리한다.

base 지시어

<base href="value"> 기능을 한다. 맵파일에서 나오는 URL은 절대 URL이 아니라면 이 값에 상대 URL로 취급한다. base 지시어는 .htaccess 파일이나 서버설정파일에서 설정한 ImapBase 값을 무시한다. ImapBase 설정지시어가 없다면 기본 base 값은 http://server_name/이다.

base_uri는 base와 같다. URL에서 마지막 슬래쉬를 잊지마라.

default 지시어
해당 좌표가 poly, circle, rect 지시어에 해당하지 않고 point 지시어를 사용하지 않은 경우 행동을 지정한다. ImapDefault 설정이 없다면 기본값은 204 No Content 상태코드를 반환하는 nocontent이다. 이 경우 클라이언트는 동일한 페이지를 보여줘야 한다.
poly 지시어
점을 세개에서 백개까지 지정할 수 있다. 사용자가 이 점들로 이루어진 다각형 안의 좌표를 선택한 경우에 사용한다.
circle
원의 중심과 원위의 한 점의 좌표를 받는다. 사용자가 원 안의 좌표를 선택한 경우에 사용한다.
rect 지시어
사각형의 두 모서리 점의 좌표를 받는다. 사각형 안의 좌표를 선택한 경우에 사용한다.
point 지시어
한 점의 좌표를 받는다. 다른 지시어들을 만족하지 않은 경우 사용자가 선택한 좌표에 가장 가까운 point 지시어를 사용한다. point 지시어를 사용하고 유효한 좌표를 선택한 경우 default는 절대로 사용되지 않는다.

지시어에 사용할 수 있는 값들

지시어에 아래 value를 사용할 수 있다.

URL

상대 URL이나 절대 URL을 사용할 수 있다. 상대 URL에 '..'을 사용할 수 있으며, base 값을 기준으로 찾는다.

base를 설정할때는 현재 base값은 무시한다. 그러나, base mailto: 문은 사용할 수 있다.

map
이미지맵 파일 자체 URL과 같다. 좌표가 없고 ImapMenu가 none이 아니라면 메뉴를 만든다.
menu
map과 같다.
referer
참조(링크를 따라오기 전) 문서 URL과 같다. Referer: 헤더가 없다면 기본값은 http://servername/이다.
nocontent
클라이언트에게 동일한 페이지를 그대로 보여주라는 204 No Content 상태코드를 보낸다. base를 제외한 모든 지시어에서 사용할 수 있다.
error
실패를 나타내는 500 Server Error를 보낸다. base를 제외한 모든 지시어에서 사용할 수 있지만, default 외에는 사용할 일이 없다.

좌표

0,0 200,200
좌표는 쉼표로 구분한 x와 y 값이다. 좌표들은 서로 공백으로 구분한다. 이미지맵을 다루는 방식상 Lynx의 편의를 위해 사용자가 0,0 좌표를 선택하였다면 좌표를 선택하지 않은 것처럼 동작한다.

따옴표로 묶은 문구

"Menu Text"

value 뒤나 좌표 뒤에 쌍따옴표로 묶은 문구를 적을 수도 있다. 이 문자열은 메뉴를 만들때 링크 제목으로 사용한다.

<a href="http://foo.com/">Menu text</a>

따옴표로 묶은 문구가 없다면 다음과 같이 링크를 링크 제목으로 사용한다.

<a href="http://foo.com/">http://foo.com</a>

문구에 쌍따옴표를 쓰려면 &quot;와 같이 적어야 한다.

맵파일 예제

#'formatted'나 'semiformatted' 메뉴는 주석을 출력한다.
#그리고 주석에 html 태그를 쓸 수 있다. <hr>
base referer
poly map "메뉴를 보여주세요." 0,0 0,10 10,10 10,0
rect .. 0,0 77,27 "참조 문서가 있는 디렉토리"
circle http://www.inetnebr.com/lincoln/feedback/ 195,0 305,27
rect another_file "참조 문서와 같은 디렉토리에 있는" 306,0 419,27
point http://www.zyzzyva.com/ 100,100
point http://www.tripod.com/ 200,200
rect mailto:nate@tripod.com 100,150 200,0 "버그?"

맵파일 사용하기

HTML 에제

<a href="/maps/imagemap1.map">
<img ismap src="/images/imagemap1.gif">
 </a>

XHTML 예제

<a href="/maps/imagemap1.map">
<img ismap="ismap" src="/images/imagemap1.gif" />
 </a>

ImapBase 지시어

설명: | 이미지맵 파일에서 base 기본값
문법: | ImapBase map|referer|URL
기본값: | ImapBase http://servername/
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_imap

ImapBase 지시어는 이미지맵 파일에서 사용할 base 기본값을 설정한다. 이미지맵 파일 안에서 base 지시어를 사용하면 여기서 설정한 값은 무시한다. 둘 모두 없다면, base 기본값은 http://servername/이다.

참고

  • UseCanonicalName

ImapDefault 지시어

설명: | 이미지맵에 어느 영역에도 해당하지 않는 좌표를 준 경우 기본 행동
문법: | ImapDefault error|nocontent|map|referer|URL
기본값: | ImapDefault nocontent
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_imap

ImapDefault 지시어는 이미지맵 파일에서 사용할 default 기본값을 설정한다. 이미지맵 파일 안에서 default 지시어를 사용하면 여기서 설정한 값은 무시한다. 둘 모두 없다면, default 행동은 클라이언트에게 204 No Content를 보내는 nocontent이다. 이 경우 클라이언트는 원래 페이지를 그대로 보여줘야 한다.

ImapMenu 지시어

설명: | 좌표없이 이미지맵 요청시 취할 행동
문법: | ImapMenu none|formatted|semiformatted|unformatted
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Indexes
상태: | Base
모듈: | mod_imap

ImapMenu 지시어는 이미지맵 파일에 유효한 좌표를 주지 않은 경우 취할 행동을 결정한다.

none
ImapMenu가 none이면, 메뉴를 만들지않고 default 행동을 취한다.
formatted
formatted 메뉴는 가장 간단한 메뉴다. 이미지맵 파일의 주석은 무시한다. 가장 큰 표제와 수직선을 출력하고, 링크를 한줄씩 출력한다. 메뉴는 일관되고 평이하며, 디렉토리 목록과 흡사하다.
semiformatted
semiformatted 메뉴는 이미지맵 파일에 나오는 주석을 출력한다. 빈줄은 HTML 행바꿈으로 변환한다. 표제나 수직선을 그리지 않지만, 나머지는 formatted 메뉴와 같다.
unformatted
주석은 출력하고, 빈줄은 무시한다. 이미지맵 파일에 있는 내용만 출력한다. 이미지맵 파일의 주석에 필요한 모든 행바꿈과 표제를 적어야 한다. 메뉴의 외관을 가장 자유자제로 꾸밀 수 있지만, 이미지맵 파일을 사실상 일반 문자파일이 아닌 HTML로 봐야 한다.


mod_include - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_include

Description: | Server-parsed html documents (Server Side Includes)
Status: | Base
Module Identifier: | include_module
Source File: | mod_include.c
Compatibility: | Implemented as an output filter since Apache 2.0

Summary

This module provides a filter which will process files before they are sent to the client. The processing is controlled by specially formatted SGML comments, referred to as elements. These elements allow conditional text, the inclusion of other files or programs, as well as the setting and printing of environment variables.

See also

  • Options
  • AcceptPathInfo
  • International Customized Server Error Messages
  • Filters
  • SSI Tutorial

Enabling Server-Side Includes

Server Side Includes are implemented by the INCLUDES filter. If documents containing server-side include directives are given the extension .shtml, the following directives will make Apache parse them and assign the resulting document the mime type of text/html:

AddType text/html .shtml
AddOutputFilter INCLUDES .shtml

The following directive must be given for the directories containing the shtml files (typically in a <Directory> section, but this directive is also valid in .htaccess files if AllowOverride Options is set):

Options +Includes

For backwards compatibility, the server-parsed handler also activates the INCLUDES filter. As well, Apache will activate the INCLUDES filter for any document with mime type text/x-server-parsed-html or text/x-server-parsed-html3 (and the resulting output will have the mime type text/html).

For more information, see our Tutorial on Server Side Includes.

PATH_INFO with Server Side Includes

Files processed for server-side includes no longer accept requests with PATH_INFO (trailing pathname information) by default. You can use the AcceptPathInfo directive to configure the server to accept requests with PATH_INFO.

Basic Elements

The document is parsed as an HTML document, with special commands embedded as SGML comments. A command has the syntax:

<!--#element attribute=value attribute=value ... -->

The value will often be enclosed in double quotes, but single quotes (') and backticks (`) are also possible. Many commands only allow a single attribute-value pair. Note that the comment terminator (-->) should be preceded by whitespace to ensure that it isn't considered part of an SSI token. Note that the leading <!--# is one token and may not contain any whitespaces.

The allowed elements are listed in the following table:

Element | Description
config | configure output formats
echo | print variables
exec | execute external programs
fsize | print size of a file
flastmod | print last modification time of a file
include | include a file
printenv | print all available variables
set | set a value of a variable

SSI elements may be defined by modules other than mod_include. In fact, the exec element is provided by mod_cgi, and will only be available if this module is loaded.

The config Element

This command controls various aspects of the parsing. The valid attributes are:

errmsg
The value is a message that is sent back to the client if an error occurs while parsing the document. This overrides any SSIErrorMsg directives.
sizefmt
The value sets the format to be used which displaying the size of a file. Valid values are bytes for a count in bytes, or abbrev for a count in Kb or Mb as appropriate, for example a size of 1024 bytes will be printed as "1K".
timefmt
The value is a string to be used by the strftime(3) library routine when printing dates.

The echo Element

This command prints one of the include variables, defined below. If the variable is unset, the result is determined by the SSIUndefinedEcho directive. Any dates printed are subject to the currently configured timefmt.

Attributes:

var
The value is the name of the variable to print.
encoding

Specifies how Apache should encode special characters contained in the variable before outputting them. If set to none, no encoding will be done. If set to url, then URL encoding (also known as %-encoding; this is appropriate for use within URLs in links, etc.) will be performed. At the start of an echo element, the default is set to entity, resulting in entity encoding (which is appropriate in the context of a block-level HTML element, e.g. a paragraph of text). This can be changed by adding an encoding attribute, which will remain in effect until the next encoding attribute is encountered or the element ends, whichever comes first.

The encoding attribute must precede the corresponding var attribute to be effective, and only special characters as defined in the ISO-8859-1 character encoding will be encoded. This encoding process may not have the desired result if a different character encoding is in use.

In order to avoid cross-site scripting issues, you should always encode user supplied data.

The exec Element

The exec command executes a given shell command or CGI script. It requires mod_cgi to be present in the server. If Options IncludesNOEXEC is set, this command is completely disabled. The valid attributes are:

cgi

The value specifies a (%-encoded) URL-path to the CGI script. If the path does not begin with a slash (/), then it is taken to be relative to the current document. The document referenced by this path is invoked as a CGI script, even if the server would not normally recognize it as such. However, the directory containing the script must be enabled for CGI scripts (with ScriptAlias or Options ExecCGI).

The CGI script is given the PATH_INFO and query string (QUERY_STRING) of the original request from the client; these cannot be specified in the URL path. The include variables will be available to the script in addition to the standard CGI environment.

Example

<!--#exec cgi="/cgi-bin/example.cgi" -->

If the script returns a Location: header instead of output, then this will be translated into an HTML anchor.

The include virtual element should be used in preference to exec cgi. In particular, if you need to pass additional arguments to a CGI program, using the query string, this cannot be done with exec cgi, but can be done with include virtual, as shown here:

<!--#include virtual="/cgi-bin/example.cgi?argument=value" -->

cmd

The server will execute the given string using /bin/sh. The include variables are available to the command, in addition to the usual set of CGI variables.

The use of #include virtual is almost always prefered to using either #exec cgi or #exec cmd. The former (#include virtual) uses the standard Apache sub-request mechanism to include files or scripts. It is much better tested and maintained.

In addition, on some platforms, like Win32, and on unix when using suexec, you cannot pass arguments to a command in an exec directive, or otherwise include spaces in the command. Thus, while the following will work under a non-suexec configuration on unix, it will not produce the desired result under Win32, or when running suexec:

<!--#exec cmd="perl /path/to/perlscript arg1 arg2" -->

The fsize Element

This command prints the size of the specified file, subject to the sizefmt format specification. Attributes:

file
The value is a path relative to the directory containing the current document being parsed.
virtual
The value is a (%-encoded) URL-path. If it does not begin with a slash (/) then it is taken to be relative to the current document. Note, that this does not print the size of any CGI output, but the size of the CGI script itself.

The flastmod Element

This command prints the last modification date of the specified file, subject to the timefmt format specification. The attributes are the same as for the fsize command.

The include Element

This command inserts the text of another document or file into the parsed file. Any included file is subject to the usual access control. If the directory containing the parsed file has Options IncludesNOEXEC set, then only documents with a text MIME type (text/plain, text/html etc.) will be included. Otherwise CGI scripts are invoked as normal using the complete URL given in the command, including any query string.

An attribute defines the location of the document; the inclusion is done for each attribute given to the include command. The valid attributes are:

file
The value is a path relative to the directory containing the current document being parsed. It cannot contain ../, nor can it be an absolute path. Therefore, you cannot include files that are outside of the document root, or above the current document in the directory structure. The virtual attribute should always be used in preference to this one.
virtual

The value is a (%-encoded) URL-path. The URL cannot contain a scheme or hostname, only a path and an optional query string. If it does not begin with a slash (/) then it is taken to be relative to the current document.

A URL is constructed from the attribute, and the output the server would return if the URL were accessed by the client is included in the parsed output. Thus included files can be nested.

If the specified URL is a CGI program, the program will be executed and its output inserted in place of the directive in the parsed file. You may include a query string in a CGI url:

<!--#include virtual="/cgi-bin/example.cgi?argument=value" -->

include virtual should be used in preference to exec cgi to include the output of CGI programs into an HTML document.

The printenv Element

This prints out a listing of all existing variables and their values. Special characters are entity encoded (see the echo element for details) before being output. There are no attributes.

Example

<!--#printenv -->

The set Element

This sets the value of a variable. Attributes:

var
The name of the variable to set.
value
The value to give a variable.

Example

<!--#set var="category" value="help" -->

Include Variables

In addition to the variables in the standard CGI environment, these are available for the echo command, for if and elif, and to any program invoked by the document.

DATE_GMT
The current date in Greenwich Mean Time.
DATE_LOCAL
The current date in the local time zone.
DOCUMENT_NAME
The filename (excluding directories) of the document requested by the user.
DOCUMENT_URI
The (%-decoded) URL path of the document requested by the user. Note that in the case of nested include files, this is not the URL for the current document.
LAST_MODIFIED
The last modification date of the document requested by the user.
QUERY_STRING_UNESCAPED
If a query string is present, this variable contains the (%-decoded) query string, which is escaped for shell usage (special characters like & etc. are preceded by backslashes).

Variable Substitution

Variable substitution is done within quoted strings in most cases where they may reasonably occur as an argument to an SSI directive. This includes the config, exec, flastmod, fsize, include, echo, and set directives, as well as the arguments to conditional operators. You can insert a literal dollar sign into the string using backslash quoting:

<!--#if expr="$a = \$test" -->

If a variable reference needs to be substituted in the middle of a character sequence that might otherwise be considered a valid identifier in its own right, it can be disambiguated by enclosing the reference in braces, a la shell substitution:

<!--#set var="Zed" value="${REMOTE_HOST}_${REQUEST_METHOD}" -->

This will result in the Zed variable being set to "X_Y" if REMOTE_HOST is "X" and REQUEST_METHOD is "Y".

The below example will print "in foo" if the DOCUMENT_URI is /foo/file.html, "in bar" if it is /bar/file.html and "in neither" otherwise:

<!--#if expr='"$DOCUMENT_URI" = "/foo/file.html"' -->
in foo
 <!--#elif expr='"$DOCUMENT_URI" = "/bar/file.html"' -->
in bar
 <!--#else -->
in neither
 <!--#endif -->

Flow Control Elements

The basic flow control elements are:

<!--#if expr="test_condition" -->
<!--#elif expr="test_condition" -->
<!--#else -->
<!--#endif -->

The if element works like an if statement in a programming language. The test condition is evaluated and if the result is true, then the text until the next elif, else or endif element is included in the output stream.

The elif or else statements are be used to put text into the output stream if the original test_condition was false. These elements are optional.

The endif element ends the if element and is required.

test_condition is one of the following:

string
true if string is not empty
string1 = string2
string1 != string2

Compare string1 with string2. If string2 has the form /string2/ then it is treated as a regular expression. Regular expressions are implemented by the PCRE engine and have the same syntax as those in perl 5.

If you are matching positive (=), you can capture grouped parts of the regular expression. The captured parts are stored in the special variables $1 .. $9.

Example

<!--#if expr="$QUERY_STRING = /^sid=([a-zA-Z0-9]+)/" -->
<!--#set var="session" value="$1" -->
 <!--#endif -->

string1 < string2
string1 <= string2
string1 > string2
string1 >= string2
Compare string1 with string2. Note, that strings are compared literally (using strcmp(3)). Therefore the string "100" is less than "20".
( test_condition )
true if test_condition is true
! test_condition
true if test_condition is false
test_condition1 && test_condition2
true if both test_condition1 and test_condition2 are true
test_condition1 || test_condition2
true if either test_condition1 or test_condition2 is true

"=" and "!=" bind more tightly than "&&" and "||". "!" binds most tightly. Thus, the following are equivalent:

<!--#if expr="$a = test1 && $b = test2" -->
<!--#if expr="($a = test1) && ($b = test2)" -->

The boolean operators && and || share the same priority. So if you want to bind such an operator more tightly, you should use parentheses.

Anything that's not recognized as a variable or an operator is treated as a string. Strings can also be quoted: 'string'. Unquoted strings can't contain whitespace (blanks and tabs) because it is used to separate tokens such as variables. If multiple strings are found in a row, they are concatenated using blanks. So,

string1    string2 results in string1 string2

and

'string1    string2' results in string1    string2.

SSIEndTag Directive

Description: | String that ends an include element
Syntax: | SSIEndTag tag
Default: | SSIEndTag "-->"
Context: | server config, virtual host
Status: | Base
Module: | mod_include
Compatibility: | Available in version 2.0.30 and later.

This directive changes the string that mod_include looks for to mark the end of an include element.

Example

SSIEndTag "%>"

See also

  • SSIStartTag

SSIErrorMsg Directive

Description: | Error message displayed when there is an SSI error
Syntax: | SSIErrorMsg message
Default: | SSIErrorMsg "[an error occurred while processing this directive]"
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Base
Module: | mod_include
Compatibility: | Available in version 2.0.30 and later.

The SSIErrorMsg directive changes the error message displayed when mod_include encounters an error. For production servers you may consider changing the default error message to "<!-- Error -->" so that the message is not presented to the user.

This directive has the same effect as the <!--#config errmsg=message --> element.

Example

SSIErrorMsg "<!-- Error -->"

SSIStartTag Directive

Description: | String that starts an include element
Syntax: | SSIStartTag tag
Default: | SSIStartTag "<!--#"
Context: | server config, virtual host
Status: | Base
Module: | mod_include
Compatibility: | Available in version 2.0.30 and later.

This directive changes the string that mod_include looks for to mark an include element to process.

You may want to use this option if you have 2 servers parsing the output of a file each processing different commands (possibly at different times).

Example

SSIStartTag "<%"
SSIEndTag "%>"

The example given above, which also specifies a matching SSIEndTag, will allow you to use SSI directives as shown in the example below:

SSI directives with alternate start and end tags

<%printenv %>

See also

  • SSIEndTag

SSITimeFormat Directive

Description: | Configures the format in which date strings are displayed
Syntax: | SSITimeFormat formatstring
Default: | SSITimeFormat "%A, %d-%b-%Y %H:%M:%S %Z"
Context: | server config, virtual host, directory, .htaccess
Override: | All
Status: | Base
Module: | mod_include
Compatibility: | Available in version 2.0.30 and later.

This directive changes the format in which date strings are displayed when echoing DATE environment variables. The formatstring is as in strftime(3) from the C standard library.

This directive has the same effect as the <!--#config timefmt=formatstring --> element.

Example

SSITimeFormat "%R, %B %d, %Y"

The above directive would cause times to be displayed in the format "22:26, June 14, 2002".

SSIUndefinedEcho Directive

Description: | String displayed when an unset variable is echoed
Syntax: | SSIUndefinedEcho string
Default: | SSIUndefinedEcho "(none)"
Context: | server config, virtual host
Status: | Base
Module: | mod_include
Compatibility: | Available in version 2.0.34 and later.

This directive changes the string that mod_include displays when a variable is not set and "echoed".

Example

SSIUndefinedEcho "<!-- undef -->"

XBitHack Directive

Description: | Parse SSI directives in files with the execute bit set
Syntax: | XBitHack on|off|full
Default: | XBitHack off
Context: | server config, virtual host, directory, .htaccess
Override: | Options
Status: | Base
Module: | mod_include

The XBitHack directive controls the parsing of ordinary html documents. This directive only affects files associated with the MIME type text/html. XBitHack can take on the following values:

off
No special treatment of executable files.
on
Any text/html file that has the user-execute bit set will be treated as a server-parsed html document.
full
As for on but also test the group-execute bit. If it is set, then set the Last-modified date of the returned file to be the last modified time of the file. If it is not set, then no last-modified date is sent. Setting this bit allows clients and proxies to cache the result of the request.

Note

You would not want to use the full option, unless you assure the group-execute bit is unset for every SSI script which might #include a CGI or otherwise produces different output on each hit (or could potentially change on subsequent requests).


mod_info - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_info

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.
설명: | 서버 설정에 대한 종합적인 정보를 보여준다
상태: | Extension
모듈명: | info_module
소스파일: | mod_info.c

요약

mod_info를 사용하려면 httpd.conf 파일에 다음과 같이 추가한다.

<Location /server-info>
SetHandler server-info
 </Location>

서버 설정 정보를 아무나 볼 수 없도록 <Location> 지시어 안에 <Limit> 구문을 추가할 수 있다.

이렇게 설정하면 http://your.host.dom/server-info에 접근하여 서버에 대한 정보를 볼 수 있다.

모듈은 서버가 시작할때 설정파일을 읽기때문에, 서버를 재시작한 후에 파일을 수정하였다면 화면에 표시된 정보가 실행중인 서버의 실제 설정과 다를 수 있다. 또, 설정파일은 서버를 실행하는 사용자(User 지시어 참고)가 읽을 수 있어야 한다. 읽을 수 없다면 지시어 설정을 보여주지 못한다.

서버에 mod_info가 컴파일되있다면, 디렉토리별 설정파일(예를 들어, .htaccess)을 포함한 모든 설정파일에서 이 핸들러 기능을 사용할 수 있다. 그래서 사이트에 보안관련 문제가 될 수 있다.

특히 이 모듈은 시스템 경로, 사용자명/암호, 데이터베이스 이름과 같이 여러 아파치 모듈의 설정지시어에 기록한 민감한 정보를 유출할 수 있다. 모듈이 동작하는 방식상 이를 막을 방법이 없다. 그래서 이 모듈은 항상 주의해야 하며 통제된 환경에서만 사용해야 한다.

AddModuleInfo 지시어

설명: | 모듈에 대한 추가 정보를 server-info 핸들러가 보여주도록 추가한다
문법: | AddModuleInfo module-name string
사용장소: | 주서버설정, 가상호스트
상태: | Extension
모듈: | mod_info
지원: | 아파치 1.3 이후

module-name 모듈에 대한 추가 정보로 string의 내용을 HTML로 보여준다. 예를 들어,

AddModuleInfo mod_auth.c 'See <a \
href="http://www.apache.org/docs-2.0/mod/mod_auth.html">\
http://www.apache.org/docs-2.0/mod/mod_auth.html</a>'


mod_isapi - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_isapi

설명: | Windows용 아파치에서 ISAPI Extension 사용
상태: | Base
모듈명: | isapi_module
소스파일: | mod_isapi.c
지원: | Win32 only

요약

이 모듈은 Internet Server extension API를 구현한다. 그래서 제약은 있지만 Windows용 아파치에서 Internet Server extension을 (즉, ISAPI .dll 모듈) 사용할 수 있다.

ISAPI extension 모듈(.dll 파일)은 제삼자가 작성한다. Apache Group이 이들 모듈을 만들지 않았으며, 지원도 하지 않는다. ISAPI extension 사용에 관한 문제는 ISAPI 제작자에게 직접 연락하길 바란다. 제발 이런 문제를 아파치 메일링리스트나 버그보고 페이지에 올리지 마라.

사용법

서버설정파일에서 AddHandler 지시어를 사용하여 ISAPI 파일 확장자와 isapi-isa 핸들러를 연결한다. .dll 파일을 ISAPI extension으로 처리하려면 httpd.conf 파일에 다음과 같이 추가한다.

AddHandler isapi-isa .dll

아파치 서버는 요청한 모듈을 메모리에 계속 둘 수 없다. 그러나 httpd.conf에서 다음과 같은 설정으로 특정 모듈을 미리 읽어들일 수는 있다.

ISAPICacheFile c:/WebWork/Scripts/ISAPI/mytest.dll

ISAPI extension을 미리 읽어들이던지 미리 읽어들이지 않던지 관계없이 ISAPI extension은 CGI 스크립트와 동일한 권한과 제약을 따른다. 즉, ISAPI .dll 파일이 있는 디렉토리에 Options ExecCGI가 필요하다.

mod_isapi의 ISAPI 지원에 대한 자세한 내용과 설명은 추가 설명과 개발자 정보를 참고하라.

추가 설명

아파치 ISAPI 구현은 비동기 입출력에 대한 "마이크로소프트 특유의" 확장기능을 제외한 ISAPI 2.0 규약을 모두 만족한다. 아파치의 입출력 구조로는 ISAPI가 사용할 수 있는 방식으로 비동기 입출력을 할 수 없다. ISA가 비동기 입출력과 같이 지원하지 않는 기능을 사용하려 한다면, 디버깅에 도움을 주기위해 오류 로그에 기록을 남긴다. 로그가 매우 커질 수 있기때문에 ISAPILogNotSupported Off 지시어를 사용하면 로그에 기록하지 않는다.

Microsoft IIS와 같은 서버는 ISAPI extension을 메모리로 읽어들여서 메모리 사용량이 매우 많지 않거나 특별히 설정하지 않는한 그대로 메모리에 둔다. 아파치는 현재 ISAPICacheFile 지시어를 사용하지 않는다면 요청을 받을때마다 ISAPI extension을 메모리에 읽어들이고 버린다. 비효율적이지만, 아파치의 메모리 구조상 이것이 가장 효율적인 방법이다. 여러 ISAPI 모듈이 아파치 서버와 약간 호환이 안맞기때문에 서버의 안정성을 위해 모듈을 메모리에서 버린다.

또, 아파치는 ISAPI Extension을 지원하지만, ISAPI Filter를 지원하지 않음을 기억하라. 나중에 필터를 지원할 수 있지만, 현재는 계획이 없다.

개발자 정보

아파치 2.0 mod_isapi 모듈을 프로그래밍한다면, ServerSupportFunction 호출을 다음 지시어로 제한해야 한다.

HSE_REQ_SEND_URL_REDIRECT_RESP
사용자를 다른 위치로 리다이렉션한다.
완전한 URL을 사용해야 한다 (예를 들어, http://server/location).
HSE_REQ_SEND_URL
사용자를 다른 위치로 리다이렉션한다.
완전한 URL이 아니며, 프로토콜과 서버명을 넘길 수 없다 (예를 들어, /location같은 것만 가능).
브라우저가 아니라 서버가 리다이렉션을 처리한다.

경고

최근 문서를 보면 Microsoft가 두 HSE_REQ_SEND_URL 기능간의 차이를 없앤 것처럼 보인다. 아파치는 계속 이 둘의 아규먼트 조건과 행동을 다르게 처리할 것이다.

HSE_REQ_SEND_RESPONSE_HEADER
headers 문자열 아규먼트에 빈줄이 (줄바꿈문자가 두번 연속) 있다면 아파치는 헤더 다음 내용을 응답 내용으로 사용한다. headers 아규먼트가 NULL로 끝나기때문에, 응답 내용에 NULL을 사용할 수 없다.
HSE_REQ_DONE_WITH_SESSION
ISAPI가 처리를 마치면 세션이 끝나기때문에 아파치는 아무 일도 하지 않는다.
HSE_REQ_MAP_URL_TO_PATH
아파치는 가상 이름을 물리적(실제) 이름으로 변환한다.
HSE_APPEND_LOG_PARAMETER
문구를 아래 로그중 한곳에 남긴다.
  • CustomLog 지시어의 \"%{isapi-parameter}n\" 항목에
  • ISAPIAppendLogToQuery On 지시어를 사용하여 %q 로그 항목에
  • ISAPIAppendLogToErrors On 지시어를 사용하여 오류 로그에

첫번째로 나온 %{isapi-parameter}n 항목은 언제나 사용할 수 있으며 권장한다.

HSE_REQ_IS_KEEP_CONN
협상된 Keep-Alive 상태를 반환한다.
HSE_REQ_SEND_RESPONSE_HEADER_EX
fKeepConn 옵션을 무시하는 것을 제외하고는 문서에 나온데로 동작한다.
HSE_REQ_IS_CONNECTED
요청이 중간에 끊어졌다면 false를 반환한다.

지원하지 않는 ServerSupportFunction 호출을 하면 아파치는 FALSE를 반환하고 GetLastError 값을 ERROR_INVALID_PARAMETER로 설정한다.

ReadClient는 (ISAPIReadAheadBuffer로 정의한) 초기버퍼크기를 넘어선 요청 내용을 가져온다. ISAPIReadAheadBuffer 설정 (ISAPI 핸들러를 부르기전 버퍼의 바이트수) 보다 짧은 요청은 extension을 부를때 전부 전달된다. 요청이 길면, ISAPI extension은 ReadClient로 나머지 요청 내용을 가져와야 한다.

WriteClient를 지원하지만, HSE_IO_SYNC 옵션만 사용하거나 (0 값) 아무 옵션도 사용하지 않아야 한다. 다른 WriteClient 요청은 FALSE를 반환하며 실패하고, GetLastError 값은 ERROR_INVALID_PARAMETER가 된다.

GetServerVariable은 지원하지만, (다른 서버에서 정의하는) 확장 서버변수는 없다. GetServerVariable에서 모든 일반적인 아파치 CGI 환경변수와 ALL_HTTP, ALL_RAW 값을 사용할 수 있다.

아파치 2.0 mod_isapi는 이후 ISAPI 규약에 나온 추가 기능을 지원하고, 비동기 입출력과 TransmitFile 기능을 조금 흉내낸다. 또, ISAPI .dll을 미리 읽어들여서 성능을 높이는 아파치 1.3 mod_isapi에는 없는 기능을 지원한다.

ISAPIAppendLogToErrors 지시어

설명: | ISAPI exntension의 HSE_APPEND_LOG_PARAMETER 요청을 오류 로그에 기록한다
문법: | ISAPIAppendLogToErrors on|off
기본값: | ISAPIAppendLogToErrors off
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_isapi

ISAPI exntension의 HSE_APPEND_LOG_PARAMETER 요청을 오류 로그에 기록한다.

ISAPIAppendLogToQuery 지시어

설명: | ISAPI exntension의 HSE_APPEND_LOG_PARAMETER 요청을 질의문자열에 기록한다
문법: | ISAPIAppendLogToQuery on|off
기본값: | ISAPIAppendLogToQuery on
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_isapi

ISAPI exntension의 HSE_APPEND_LOG_PARAMETER 요청을 질의문자열에 기록한다 (CustomLog %q 항목에 덧붙인다).

ISAPICacheFile 지시어

설명: | 서버가 시작할때 메모리로 읽어들일 ISAPI .dll 파일들
문법: | ISAPICacheFile file-path [file-path] ...
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_isapi

아파치 서버가 시작할때 메모리로 읽어들여서 서버를 종료할때까지 메모리에 남아있을 파일명을 공백으로 구분하여 지정한다. 이 지시어는 ISAPI .dll 파일별로 여러번 사용할 수 있다. 파일의 전체 경로를 적는다. 절대 경로가 아니면 ServerRoot에 상대 경로로 받아들인다.

ISAPIFakeAsync 지시어

설명: | 비동기 ISAPI 콜백을 지원하는 척한다
문법: | ISAPIFakeAsync on|off
기본값: | ISAPIFakeAsync off
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_isapi

on으로 설정하면 비동기 ISAPI 콜백 지원을 흉내낸다.

ISAPILogNotSupported 지시어

설명: | ISAPI extension이 지원하지 않는 기능을 요청하면 로그에 기록한다
문법: | ISAPILogNotSupported on|off
기본값: | ISAPILogNotSupported off
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_isapi

ISAPI extension이 지원하지 않는 기능을 요청하면 서버 오류 로그에 기록한다. 나중에 관리자가 문제를 추적하는데 도움이 된다. 원하는 모든 ISAPI 모듈이 정상적으로 동작하면 다시 off로 되돌려야 한다.

ISAPIReadAheadBuffer 지시어

설명: | ISAPI extension의 미리읽기버퍼(read ahead buffer) 크기
문법: | ISAPIReadAheadBuffer size
기본값: | ISAPIReadAheadBuffer 49152
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_isapi

ISAPI extension을 처음 호출할때 미리읽기버퍼의 최대 크기를 지정한다. (이 크기보다 큰) 나머지 자료는 ReadClient 콜백을 사용하여 읽어야 한다. 어떤 ISAPI extension은 ReadClient 기능을 지원하지 않는다. 이 경우 ISAPI extension 제작자에게 문의하라.


mod_ldap - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_ldap

Description: | LDAP connection pooling and result caching services for use by other LDAP modules
Status: | Experimental
Module Identifier: | ldap_module
Source File: | util_ldap.c
Compatibility: | Available in version 2.0.41 and later

Summary

This module was created to improve the performance of websites relying on backend connections to LDAP servers. In addition to the functions provided by the standard LDAP libraries, this module adds an LDAP connection pool and an LDAP shared memory cache.

To enable this module, LDAP support must be compiled into apr-util. This is achieved by adding the --with-ldap flag to the configure script when building Apache.

SSL support requires that mod_ldap be linked with one of the following LDAP SDKs: OpenLDAP SDK (both 1.x and 2.x), Novell LDAP SDK or the iPlanet(Netscape) SDK.

Example Configuration

The following is an example configuration that uses mod_ldap to increase the performance of HTTP Basic authentication provided by mod_auth_ldap.

# Enable the LDAP connection pool and shared
# memory cache. Enable the LDAP cache status
# handler. Requires that mod_ldap and mod_auth_ldap
# be loaded. Change the "yourdomain.example.com" to
# match your domain.

LDAPSharedCacheSize 200000
LDAPCacheEntries 1024
LDAPCacheTTL 600
LDAPOpCacheEntries 1024
LDAPOpCacheTTL 600

<Location /ldap-status>
SetHandler ldap-status
Order deny,allow
Deny from all
Allow from yourdomain.example.com
AuthLDAPEnabled on
AuthLDAPURL ldap://127.0.0.1/dc=example,dc=com?uid?one
AuthLDAPAuthoritative on
require valid-user
 </Location>

LDAP Connection Pool

LDAP connections are pooled from request to request. This allows the LDAP server to remain connected and bound ready for the next request, without the need to unbind/connect/rebind. The performance advantages are similar to the effect of HTTP keepalives.

On a busy server it is possible that many requests will try and access the same LDAP server connection simultaneously. Where an LDAP connection is in use, Apache will create a new connection alongside the original one. This ensures that the connection pool does not become a bottleneck.

There is no need to manually enable connection pooling in the Apache configuration. Any module using this module for access to LDAP services will share the connection pool.

LDAP Cache

For improved performance, mod_ldap uses an aggressive caching strategy to minimize the number of times that the LDAP server must be contacted. Caching can easily double or triple the throughput of Apache when it is serving pages protected with mod_auth_ldap. In addition, the load on the LDAP server will be significantly decreased.

mod_ldap supports two types of LDAP caching during the search/bind phase with a search/bind cache and during the compare phase with two operation caches. Each LDAP URL that is used by the server has its own set of these three caches.

The Search/Bind Cache

The process of doing a search and then a bind is the most time-consuming aspect of LDAP operation, especially if the directory is large. The search/bind cache is used to cache all searches that resulted in successful binds. Negative results (i.e., unsuccessful searches, or searches that did not result in a successful bind) are not cached. The rationale behind this decision is that connections with invalid credentials are only a tiny percentage of the total number of connections, so by not caching invalid credentials, the size of the cache is reduced.

mod_ldap stores the username, the DN retrieved, the password used to bind, and the time of the bind in the cache. Whenever a new connection is initiated with the same username, mod_ldap compares the password of the new connection with the password in the cache. If the passwords match, and if the cached entry is not too old, mod_ldap bypasses the search/bind phase.

The search and bind cache is controlled with the LDAPCacheEntries and LDAPCacheTTL directives.

Operation Caches

During attribute and distinguished name comparison functions, mod_ldap uses two operation caches to cache the compare operations. The first compare cache is used to cache the results of compares done to test for LDAP group membership. The second compare cache is used to cache the results of comparisons done between distinguished names.

The behavior of both of these caches is controlled with the LDAPOpCacheEntries and LDAPOpCacheTTL directives.

Monitoring the Cache

mod_ldap has a content handler that allows administrators to monitor the cache performance. The name of the content handler is ldap-status, so the following directives could be used to access the mod_ldap cache information:

<Location /server/cache-info>
SetHandler ldap-status
 </Location>

By fetching the URL http://servername/cache-info, the administrator can get a status report of every cache that is used by mod_ldap cache. Note that if Apache does not support shared memory, then each httpd instance has its own cache, so reloading the URL will result in different information each time, depending on which httpd instance processes the request.

Using SSL

The ability to create an SSL connections to an LDAP server is defined by the directives LDAPTrustedCA and LDAPTrustedCAType. These directives specify the certificate file or database and the certificate type. Whenever the LDAP url includes ldaps://, mod_ldap will establish a secure connection to the LDAP server.

# Establish an SSL LDAP connection. Requires that
# mod_ldap and mod_auth_ldap be loaded. Change the
# "yourdomain.example.com" to match your domain.

LDAPTrustedCA /certs/certfile.der
LDAPTrustedCAType DER_FILE

<Location /ldap-status>
SetHandler ldap-status
Order deny,allow
Deny from all
Allow from yourdomain.example.com
AuthLDAPEnabled on
AuthLDAPURL ldaps://127.0.0.1/dc=example,dc=com?uid?one
AuthLDAPAuthoritative on
require valid-user
 </Location>

If mod_ldap is linked against the Netscape/iPlanet LDAP SDK, it will not talk to any SSL server unless that server has a certificate signed by a known Certificate Authority. As part of the configuration mod_ldap needs to be told where it can find a database containing the known CAs. This database is in the same format as Netscape Communicator's cert7.db database. The easiest way to get this file is to start up a fresh copy of Netscape, and grab the resulting $HOME/.netscape/cert7.db file.

LDAPCacheEntries Directive

Description: | Maximum number of entries in the primary LDAP cache
Syntax: | LDAPCacheEntries number
Default: | LDAPCacheEntries 1024
Context: | server config
Status: | Experimental
Module: | mod_ldap

Specifies the maximum size of the primary LDAP cache. This cache contains successful search/binds. Set it to 0 to turn off search/bind caching. The default size is 1024 cached searches.

LDAPCacheTTL Directive

Description: | Time that cached items remain valid
Syntax: | LDAPCacheTTL seconds
Default: | LDAPCacheTTL 600
Context: | server config
Status: | Experimental
Module: | mod_ldap

Specifies the time (in seconds) that an item in the search/bind cache remains valid. The default is 600 seconds (10 minutes).

LDAPConnectionTimeout Directive

Description: | Specifies the socket connection timeout in seconds
Syntax: | LDAPConnectionTimeout seconds
Context: | server config
Status: | Experimental
Module: | mod_ldap

Specifies the timeout value (in seconds) in which the module will attempt to connect to the LDAP server. If a connection is not successful with the timeout period, either an error will be returned or the module will attempt to connect to a secondary LDAP server if one is specified. The default is 10 seconds.

LDAPOpCacheEntries Directive

Description: | Number of entries used to cache LDAP compare operations
Syntax: | LDAPOpCacheEntries number
Default: | LDAPOpCacheEntries 1024
Context: | server config
Status: | Experimental
Module: | mod_ldap

This specifies the number of entries mod_ldap will use to cache LDAP compare operations. The default is 1024 entries. Setting it to 0 disables operation caching.

LDAPOpCacheTTL Directive

Description: | Time that entries in the operation cache remain valid
Syntax: | LDAPOpCacheTTL seconds
Default: | LDAPOpCacheTTL 600
Context: | server config
Status: | Experimental
Module: | mod_ldap

Specifies the time (in seconds) that entries in the operation cache remain valid. The default is 600 seconds.

LDAPSharedCacheFile Directive

Description: | Sets the shared memory cache file
Syntax: | LDAPSharedCacheFile directory-path/filename
Context: | server config
Status: | Experimental
Module: | mod_ldap

Specifies the directory path and file name of the shared memory cache file. If not set, anonymous shared memory will be used if the platform supports it.

LDAPSharedCacheSize Directive

Description: | Size in bytes of the shared-memory cache
Syntax: | LDAPSharedCacheSize bytes
Default: | LDAPSharedCacheSize 102400
Context: | server config
Status: | Experimental
Module: | mod_ldap

Specifies the number of bytes to allocate for the shared memory cache. The default is 100kb. If set to 0, shared memory caching will not be used.

LDAPTrustedCA Directive

Description: | Sets the file containing the trusted Certificate Authority certificate or database
Syntax: | LDAPTrustedCA directory-path/filename
Context: | server config
Status: | Experimental
Module: | mod_ldap

It specifies the directory path and file name of the trusted CA mod_ldap should use when establishing an SSL connection to an LDAP server. If using the Netscape/iPlanet Directory SDK, the file name should be cert7.db.

LDAPTrustedCAType Directive

Description: | Specifies the type of the Certificate Authority file
Syntax: | LDAPTrustedCAType type
Context: | server config
Status: | Experimental
Module: | mod_ldap

The following types are supported:
DER_FILE - file in binary DER format
BASE64_FILE - file in Base64 format
CERT7_DB_PATH - Netscape certificate database file ")


mod_log_config - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_log_config

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.
설명: | 서버로의 요청을 로그에 기록한다
상태: | Base
모듈명: | log_config_module
소스파일: | mod_log_config.c

요약

이 모듈은 클라이언트의 요청을 로그에 자유롭게 기록한다. 자신이 원하는 형식으로 로그를 기록할 수 있고, 파일이나 외부 프로그램에 직접 로그를 보낼 수도 있다. 조건적 로그를 사용하면 요청의 성격에 따라 요청을 로그에 추가하거나 제외할 수 있다.

이 모듈은 세가지 지시어를 제공한다. TransferLog는 로그파일을 만들고, LogFormat은 원하는 형식을 정하고, CustomLog는 한번에 로그파일과 형식을 모두 지정한다. TransferLog와 CustomLog 지시어를 여러번 사용하면 요청을 여러 파일에 기록할 수 있다.

참고

  • 아파치 로그파일

로그 형식 지정하기

LogFormat과 CustomLog 지시어의 형식 아규먼트는 문자열이다. 이 문자열에 따라 요청을 로그파일에 기록한다. 문자열에는 로그파일에 그대로 복사되는 문자와 행바꿈과 탭을 나타내는 C의 "\n"과 "\t" 제어문자를 사용할 수 있다. 로그파일에 따옴표나 백슬래쉬를 쓰려면 앞에 반드시 백슬래쉬를 적어줘야 한다.

요청의 특징은 형식 문자열에 "%" 지시어를 사용하여 기록한다. 이 지시어는 로그파일에서 다음과 같이 변경된다.

형식 문자열 | 설명
%% 퍼센트 기호 (아파치 2.0.44 이후)
%...a | 원격 IP-주소
%...A | (서버) IP-주소
%...B | HTTP 헤더를 제외한 전송 바이트수.
%...b | HTTP 헤더를 제외한 전송 바이트수. CLF 형식과 같이 전송한 내용이 없는 경우 0 대신 '-'가 나온다.
%...{Foobar}C | 서버가 수신한 요청에서 Foobar 쿠키의 내용.
%...D | 요청을 처리하는데 걸린 시간 (마이크로초 단위).
%...{FOOBAR}e | 환경변수 FOOBAR의 내용
%...f | 파일명
%...h | 원격 호스트
%...H | 요청 프로토콜
%...{Foobar}i | 서버가 수신한 요청에서 Foobar: 헤더의 내용.
%...l | (있다면 identd가 제공한) 원격 로그인명. IdentityCheck가 On이 아니면 빼기기호를 기록한다.
%...m | 요청 메써드
%...{Foobar}n | 다른 모듈이 기록한 Foobar 노트(note) 내용.
%...{Foobar}o | 응답의 Foobar: 헤더 내용.
%...p | 요청을 서비스하는 서버의 정규 포트
%...P | 요청을 서비스하는 자식의 프로세스 ID.
%...{format}P | 요청을 서비스하는 자식의 프로세스 ID 혹은 쓰레드 ID. format에는 pid와 tid가 가능하다. (아파치 2.0.46 이후)
%...q | 질의문자열 (질의문자열이 있다면 앞에 ?를 붙이고, 없다면 빈 문자열)
%...r | 요청의 첫번째 줄
%...s | 상태(status). 내부 리다이렉션된 요청의 경우 *원래* 요청의 상태이다. 최종 요청의 상태는 %...>s.
%...t | common log format 시간 형식(표준 영어 형식)의 시간
%...{format}t | strftime(3) 형식 format의 시간. (지역시간일 수 있음)
%...T | 요청을 처리하는데 걸린 시간 (초 단위).
%...u | 원격 사용자 (auth가 제공하며, 상태(%s)가 401인 경우 이상한 값을 나올 수 있음)
%...U | 질의문자열을 제외한 요청 URL 경로.
%...v | 요청을 서비스한 서버의 정규 ServerName.
%...V | UseCanonicalName 설정에 따른 서버명.
%...X 응답을 마쳤을때 연결 상태.
X = | 응답을 마치기 전에 연결이 끊어졌다.
+ = | 응답을 보낸후에도 연결이 살아있다(keep alive).
- = | 응답을 보낸후 연결이 끊어졌다.

(아파치 1.3 후반 버전에서 이 지시어는 %...c였지만, 전통적인 ssl %...{var}c 문법과 겹쳐서 변경했다.)

%...I | 요청과 헤더를 포함한 수신 바이트수로 0일 수 없다. 이를 사용하려면 mod_logio가 필요하다.
%...O | 헤더를 포함한 송신 바이트수로 0일 수 없다. 이를 사용하려면 mod_logio가 필요하다.

"..."에는 (예를 들어, "%h %u %r %s %b") 아무것도 없거나, 항목을 포함할 조건이 나온다 (조건을 만족하지 않으면 자리에 "-"를 기록한다). 조건은 앞에 "!"를 붙이거나 안붙인 HTTP 상태코드 목록으로 작성한다. 예를 들어, "%400,501{User-agent}i"는 400 (Bad Request) 오류와 501 (Not Implemented) 오류일때만 User-agent:를 로그에 남기고, "%!200,304,302{Referer}i"는 정상적인 상태가 아닌 모든 요청에 대해 Referer:를 로그에 남긴다.

수정자 "<"와 ">"는 내부 리다이렉션된 요청에서 각각 처음 요청을 말할지 마지막 요청을 말할지 선택한다. 기본적으로 %s, %U, %T, %D, %r은 처음 요청을 보고, 나머지 % 지시어는 마지막 요청을 본다. 그래서 %>s는 요청의 마지막 상태(status)를 기록하고, %<u는 인증으로 보호하지 않는 자원으로 내부 라다이렉션된 경우에도 처음에 인증한 사용자를 기록한다.

2.0.46 이전의 httpd 2.0 버전은 %...r, %...i, %...o의 결과 문자열을 그대로 두었다. 이유는 Common Log Format의 요구사항을 따르기위해서였다. 즉, 클라이언트가 제어문자를 로그에 집어넣을 수 있기때문에 로그파일을 그대로 다룰 때는 조심해야 한다.

보안상 이유로 2.0.46부터 출력할 수 없는 문자나 다른 특수문자를 \xhh로 표현한다. 여기서 hh는 해당 바이트의 16진수 표현을 나타낸다. 이 규칙의 예외는 백슬래쉬를 앞에 붙이는 "와 \, 그리고 C언어 형식의 공백문자들(\n, \t 등)이다.

일반적으로 많이 사용하는 로그 형식은 다음과 같다.

Common Log Format (CLF)
"%h %l %u %t \"%r\" %>s %b"
가상호스트 정보를 포함한 Common Log Format
"%v %h %l %u %t \"%r\" %>s %b"
NCSA extended/combined 로그 형식
"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
Referer 로그 형식
"%{Referer}i -> %U"
Agent (브라우저) 로그 형식
"%{User-agent}i"

요청을 서비스하는 서버의 정규 ServerName과 Listen은 각각 %v와 %p를 사용한다. 로그분석 프로그램이 실제로 요청을 서비스하는 호스트를 알기위해 가상호스트 찾기 알고리즘을 가질 필요없도록 이들 값은 UseCanonicalName 설정과 무관하다.

보안상 고려할 점

서버를 시작하는 사용자외에 다른 사용자가 로그파일을 저장하는 디렉토리에 쓰기 권한을 가질때 왜 보안에 문제가 생기는지 보안 팁 문서를 참고하라.

CookieLog 지시어

설명: | 쿠키를 로그에 남기기위해 사용할 파일명을 설정한다
문법: | CookieLog filename
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_log_config
지원: | 이 지시어는 사용되지 않는다.

CookieLog 지시어는 쿠키를 로그에 남기기위해 사용할 파일명을 설정한다. 파일명은 ServerRoot에 상대경로이다. 이 지시어는 mod_cookies와 호환을 위해 포함했을뿐, 실제 사용되지 않는다.

CustomLog 지시어

설명: | 로그파일 이름과 형식을 지정한다
문법: | CustomLog file|pipe format|nickname [env=[!]environment-variable]
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_log_config

서버가 요청을 로그에 남길때 CustomLog 지시어를 사용한다. 로그 형식을 지정하고, 환경변수를 사용하여 요청의 특징에 따라 선택적으로 로그를 남길 수도 있다.

로그를 기록할 장소를 지정하는 첫번째 아규먼트에는 다음 둘중 하나를 사용한다.

file
ServerRoot에 상대적인 파일명.
pipe
파이프문자 "|"뒤에 로그 정보를 표준입력으로 받을 프로그램 경로를 적는다.

보안:

프로그램을 사용한다면 프로그램은 웹서버를 시작한 사용자 권한으로 실행된다. 서버를 root로 시작한다면 프로그램도 root로 실행하므로 프로그램이 안전한지 확인하라.

주의

유닉스가 아닌 플래폼에서 파일경로를 입력할때 플래폼이 백슬래쉬를 사용하더라도 반드시 슬래쉬를 사용해야 한다. 일반적으로 설정파일에서는 항상 슬래쉬를 사용하는 것이 좋다.

두번째 아규먼트는 로그파일에 기록할 내용을 지정한다. 전에 LogFormat으로 정의한 nickname을 사용하거나 직접 로그 형식 절에서 설명한 format 문자열을 사용할 수 있다.

예를 들어, 다음 두 지시어는 똑같은 일을 한다.

# 형식 별칭을 사용한 CustomLog
LogFormat "%h %l %u %t \"%r\" %>s %b" common
CustomLog logs/access_log common

# 직접 형식 문자열을 사용한 CustomLog
CustomLog logs/access_log "%h %l %u %t \"%r\" %>s %b"

세번째 아규먼트는 없어도 되며, 특정 서버 환경변수 유무에 따라 요청을 로그에 기록할지 여부를 결정한다. 요청에 지정한 환경변수가 정의되있다면 (혹은 'env=!name'를 사용한 경우 없다면) 요청을 로그에 기록한다.

mod_setenvif나 mod_rewrite 모듈을 사용하여 요청별로 환경변수를 설정할 수 있다. 예를 들어, 서버가 GIF 그림에 대한 모든 요청을 주서버 로그가 아닌 다른 로그파일에 기록하려면,

SetEnvIf Request_URI \.gif$ gif-image
CustomLog gif-requests.log common env=gif-image
CustomLog nongif-requests.log common env=!gif-image

LogFormat 지시어

설명: | 로그파일에 사용할 형식을 기술한다
문법: | LogFormat format|nickname [nickname]
기본값: | LogFormat "%h %l %u %t \"%r\" %>s %b"
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_log_config

이 지시어는 접근 로그파일의 형식을 지정한다.

LogFormat 지시어는 두가지 형식으로 사용한다. 첫번째 형식은 아규먼트를 한개만 사용하여 다음 TransferLog 지시어들이 사용할 로그 형식을 지정한다. 이 아규먼트에 위의 로그 형식 지정하기 절에서 설명한 format을 직접 사용하거나, 다음에 설명할 LogFormat 지시어로 미리 정의한 (로그 형식을 지칭하는) nickname을 사용할 수 있다.

LogFormat 지시어의 두번째 형식은 format과 nickname을 연결한다. 그러면 뒤에서 사용하는 LogFormat이나 CustomLog 지시어에 반복해서 형식 문자열을 모두 입력하는 대신 nickname을 사용할 수 있다. 별칭을 정의하는 LogFormat 지시어는 이 외에는 아무 기능을 하지 않는다. 즉, 별칭만을 정의하며, 실제로 형식을 적용하거나 형식을 기본값으로 만들지 않는다. 그러므로 다음에 나오는 TransferLog 지시어에 영향을 주지 않는다. 또, LogFormat은 별칭으로 다른 별칭을 정의할 수 있다. 별칭 이름에는 퍼센트 기호(%)를 사용할 수 없음을 주의하라.

예제

LogFormat "%v %h %l %u %t \"%r\" %>s %b" vhost_common

TransferLog 지시어

설명: | 로그파일 위치를 설정한다
문법: | TransferLog file|pipe
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_log_config

이 지시어는 CustomLog 지시어와 아규먼트와 기능이 비슷하지만, 로그 형식을 직접 지정하거나 요청을 조건에 따라 로그에 남길 수 없다. 대신 가장 최근 사용한 (별칭을 정의하지 않은) LogFormat 지시어가 지정한 로그 형식을 사용한다. 미리 형식을 지정하지 않았다면 Common Log Format을 사용한다.

예제

LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\""
TransferLog logs/access_log


mod_log_forensic - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_log_forensic

Description: | Forensic Logging of the requests made to the server
Status: | Extension
Module Identifier: | log_forensic_module
Source File: | mod_log_forensic.c
Compatibility: | Available in version 2.0.50 and later

Summary

This module provides for forensic logging of client requests. Logging is done before and after processing a request, so the forensic log contains two log lines for each request. The forensic logger is very strict, which means:

  • The format is fixed. You cannot modify the logging format at runtime.
  • If it cannot write its data, the child process exits immediately and may dump core (depending on your CoreDumpDirectory configuration).

The check_forensic script, which can be found in the distribution's support directory, may be helpful in evaluating the forensic log output.

This module was backported from version 2.1 which uses a more powerful APR version in order to generate the forensic IDs. If you want to run mod_log_forensic in version 2.0, you need to include mod_unique_id as well.

See also

  • Apache Log Files
  • mod_log_config

Forensic Log Format

Each request is logged two times. The first time is before it's processed further (that is, after receiving the headers). The second log entry is written after the request processing at the same time where normal logging occurs.

In order to identify each request, a unique request ID is assigned. This forensic ID can be cross logged in the normal transfer log using the %{forensic-id}n format string. If you're using mod_unique_id, its generated ID will be used.

The first line logs the forensic ID, the request line and all received headers, separated by pipe characters (|). A sample line looks like the following (all on one line):

+yQtJf8CoAB4AAFNXBIEAAAAA|GET /manual/de/images/down.gif HTTP/1.1|Host:localhost%3a8080|User-Agent:Mozilla/5.0 (X11; U; Linux i686; en-US; rv%3a1.6) Gecko/20040216 Firefox/0.8|Accept:image/png, etc...

The plus character at the beginning indicates that this is the first log line of this request. The second line just contains a minus character and the ID again:

-yQtJf8CoAB4AAFNXBIEAAAAA

The check_forensic script takes as its argument the name of the logfile. It looks for those +/- ID pairs and complains if a request was not completed.

Security Considerations

See the security tips document for details on why your security could be compromised if the directory where logfiles are stored is writable by anyone other than the user that starts the server.

ForensicLog Directive

Description: | Sets filename of the forensic log
Syntax: | ForensicLog filename|pipe
Context: | server config, virtual host
Status: | Extension
Module: | mod_log_forensic

The ForensicLog directive is used to log requests to the server for forensic analysis. Each log entry is assigned a unique ID which can be associated with the request using the normal CustomLog directive. mod_log_forensic takes the unique ID from mod_unique_id, so you need to load this module as well. (This requirement will not be necessary in version 2.1 and later, because of a more powerful APR version.) The ID token is attached to the request under the name forensic-id, which can be added to the transfer log using the %{forensic-id}n format string.

The argument, which specifies the location to which the logs will be written, can take one of the following two types of values:

filename
A filename, relative to the ServerRoot.
pipe
The pipe character "|", followed by the path to a program to receive the log information on its standard input. The program name can be specified relative to the ServerRoot directive.

Security:

If a program is used, then it will be run as the user who started httpd. This will be root if the server was started by root; be sure that the program is secure or switches to a less privileged user.

Note

When entering a file path on non-Unix platforms, care should be taken to make sure that only forward slashed are used even though the platform may allow the use of back slashes. In general it is a good idea to always use forward slashes throughout the configuration files.


mod_logio - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_logio

설명: | 요청당 입출력 바이트수를 기록
상태: | Extension
모듈명: | logio_module
소스파일: | mod_logio.c

요약

이 모듈은 요청당 입출력 바이트수를 기록한다. 숫자는 네트웍에서 실제로 주고받은 바이트수를 나타내며, 요청과 응답의 헤더와 내용을 포함한다. 개수는 입력의 경우 SSL/TLS 이전에, 출력의 경우 SSL/TLS 이후에 세기때문에 암호화의 결과도 올바로 반영된다.

이 모듈을 사용하려면 mod_log_config이 필요하다.

참고

  • mod_log_config
  • 아파치 로그파일

사용자정의 로그 형식

이 모듈은 두가지 새로운 로그지시어를 추가한다. 요청자체의 특성은 형식문자열에 "%" 지시어를 사용하여 기록한다. 지시어는 로그파일에 다음과 같은 값을 기록한다:

형식문자열 | 설명
%...I | 요청과 헤더를 포함하여 받은 바이트수. 0일 수 없다.
%...O | 헤더를 포함하여 보낸 바이트수. 0일 수 없다.

보통 다음과 같이 사용한다:

결합된 입출력 로그 형식:
"%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" %I %O"


mod_mem_cache - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_mem_cache

설명: | URI를 키로 사용하여 내용을 캐쉬한다.
상태: | Experimental
모듈명: | mem_cache_module
소스파일: | mod_mem_cache.c

요약

이 모듈은 실험적인 상태이다. 문서는 아직 작업중이다...

이 모듈을 사용하려면 mod_cache가 필요하다. 이 모듈은 mod_cache를 지원하며 메모리기반 저장관리자를 제공한다. mod_mem_cache는 파일기술자를 캐쉬에 저장하거나 객체를 힙 공간에 캐쉬하는 두가지 방식으로 동작한다. mod_mem_cache는 직접 서버가 생성한 페이지를 캐쉬하거나 ProxyPass로 설정한 (역프록시(reverse proxy)) mod_proxy의 뒷단 서버내용을 캐쉬할때 주로 사용한다.

내용은 URI를 키로 사용하여 캐쉬에 저장하고 가져온다. 접근을 제어하는 내용은 캐쉬에 저장하지 않는다.

참고

  • mod_cache
  • mod_disk_cache

MCacheMaxObjectCount 지시어

설명: | 캐쉬에 저장할 수 있는 최대 객체개수
문법: | MCacheMaxObjectCount value
기본값: | MCacheMaxObjectCount 1009
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_mem_cache

MCacheMaxObjectCount 지시어는 캐쉬할 수 있는 최대 객체개수를 설정한다. 이 값은 해쉬테이블을 만들때 사용한다. 새로운 객체를 캐쉬에 추가해야 하는데 최대 객체개수에 도달하였다면, 새로운 객체를 캐쉬할 수 있도록 다른 객체를 제거한다. MCacheRemovalAlgorithm으로 지정한 알고리즘을 사용하여 제거할 객체를 선택한다.

예제

MCacheMaxObjectCount 13001

MCacheMaxObjectSize 지시어

설명: | 캐쉬에 저장할 문서의 최대 크기 (바이트 단위)
문법: | MCacheMaxObjectSize bytes
기본값: | MCacheMaxObjectSize 10000
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_mem_cache

MCacheMaxObjectSize 지시어는 캐쉬에 저장할 문서의 최대 크기를 바이트 단위로 지정한다.

예제

MCacheMaxObjectSize 6400000

Note

MCacheMaxObjectSize 값은 MCacheMinObjectSize 지시어로 지정한 값보다 커야 한다.

MCacheMaxStreamingBuffer 지시어

설명: | 응답을 캐쉬안한다고 결정하기 전까지 메모리 버퍼에 저장할 스트림 응답의 최대 크기
문법: | MCacheMaxStreamingBuffer size_in_bytes
기본값: | MCacheMaxStreamingBuffer 100000과 MCacheMaxObjectSize 중에 작은 값
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_mem_cache

MCacheMaxStreamingBuffer 지시어는 응답이 너무 커서 캐쉬할 수 없을때까지 버퍼에 저장할 스트림 응답의 최대 바이트수를 설정한다. 스트림 응답(streamed response)은 전체 내용을 즉시 알 수 없고 Content-Length도 모르는 응답이다. 프록시된 응답이나 CGI 스크립트의 출력이 스트림 응답에 속한다. 기본적으로 Content-Length 헤더가 없다면 스트림 응답을 캐쉬에 저장하지 않는다. 이유는 캐쉬에 저장하기에 너무 큰 응답의 일부를 버퍼에 저장하기위해 많은 메모리를 낭비하지 않기위해서이다. MCacheMaxStreamingBuffer 지시어를 사용하면 Content-Length가 없는 스트림 응답을 지정한 크기까지만 버퍼에 저장한다. 최대 크기를 넘어서면 버퍼 내용을 버리고 캐쉬하지 않는다.

주의:

MCacheMaxStreamingBuffer에 0이 아닌 값을 설정하여도 클라이언트로 응답을 늦게 보내지 않는다. mod_mem_cache는 스트림 응답의 일부를 버퍼에 복사하자마자 클라이언트로 보내기위해 다음 출력필터로 보낸다.

# 스트림 응답을 64KB까지 캐쉬한다:
MCacheMaxStreamingBuffer 65536

MCacheMinObjectSize 지시어

설명: | 캐쉬에 저장할 문서의 최소 크기 (바이트 단위)
문법: | MCacheMinObjectSize bytes
기본값: | MCacheMinObjectSize 0
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_mem_cache

MCacheMinObjectSize 지시어는 캐쉬에 저장할 문서의 최소 크기를 바이트 단위로 지정한다.

예제

MCacheMinObjectSize 10000

MCacheRemovalAlgorithm 지시어

설명: | 캐쉬에서 제거할 문서를 찾는 알고리즘
문법: | MCacheRemovalAlgorithm LRU|GDSF
기본값: | MCacheRemovalAlgorithm GDSF
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_mem_cache

MCacheRemovalAlgorithm 지시어는 캐쉬에서 제거할 문서를 찾는 알고리즘을 지정한다.

LRU (Least Recently Used)
LRU는 가장 오래동안 접근하지 않은 문서를 먼저 제거한다.
GDSF (GreadyDual-Size)
GDSF는 캐쉬 실패(cache miss) 비용과 문서의 크기를 가지고 캐쉬한 문서에 우선순위를 부여한다. 가장 우선순위가 낮은 문서를 먼저 제거한다.

예제

MCacheRemovalAlgorithm GDSF
MCacheRemovalAlgorithm LRU

MCacheSize 지시어

설명: | 캐쉬에 사용할 최대 메모리량 (KByte 단위)
문법: | MCacheSize KBytes
기본값: | MCacheSize 100
사용장소: | 주서버설정
상태: | Experimental
모듈: | mod_mem_cache

MCacheSize 지시어는 캐쉬에 사용할 최대 메모리량을 KByte 단위로 (1024 바이트 단위) 설정한다. 새로운 객체을 캐쉬에 추가해야 하는데 객체의 크기가 남은 메모리보다 크다면 새로운 객체을 캐쉬할 수 있을때까지 다른 객체를 제거한다. MCacheRemovalAlgorithm으로 지정한 알고리즘을 사용하여 제거할 객체를 선택한다.

예제

MCacheSize 700000

주의

MCacheSize 값은 MCacheMaxObjectSize 지시어로 지정한 값보다 커야 한다.


mod_mime - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_mime

Description: | Associates the requested filename's extensions with the file's behavior (handlers and filters) and content (mime-type, language, character set and encoding)
Status: | Base
Module Identifier: | mime_module
Source File: | mod_mime.c

Summary

This module is used to associate various bits of "meta information" with files by their filename extensions. This information relates the filename of the document to it's mime-type, language, character set and encoding. This information is sent to the browser, and participates in content negotiation, so the user's preferences are respected when choosing one of several possible files to serve. See mod_negotiation for more information about content negotiation.

The directives AddCharset, AddEncoding, AddLanguage and AddType are all used to map file extensions onto the meta-information for that file. Respectively they set the character set, content-encoding, content-language, and MIME-type (content-type) of documents. The directive TypesConfig is used to specify a file which also maps extensions onto MIME types.

In addition, mod_mime may define the handler and filters that originate and process content. The directives AddHandler, AddOutputFilter, and AddInputFilter control the modules or scripts that serve the document. The MultiviewsMatch directive allows mod_negotiation to consider these file extensions to be included when testing Multiviews matches.

While mod_mime associates meta-information with filename extensions, the core server provides directives that are used to associate all the files in a given container (e.g., <Location>, <Directory>, or <Files>) with particular meta-information. These directives include ForceType, SetHandler, SetInputFilter, and SetOutputFilter. The core directives override any filename extension mappings defined in mod_mime.

Note that changing the meta-information for a file does not change the value of the Last-Modified header. Thus, previously cached copies may still be used by a client or proxy, with the previous headers. If you change the meta-information (language, content type, character set or encoding) you may need to 'touch' affected files (updating their last modified date) to ensure that all visitors are receive the corrected content headers.

See also

  • MimeMagicFile
  • AddDefaultCharset
  • ForceType
  • DefaultType
  • SetHandler
  • SetInputFilter
  • SetOutputFilter

Files with Multiple Extensions

Files can have more than one extension, and the order of the extensions is normally irrelevant. For example, if the file welcome.html.fr maps onto content type text/html and language French then the file welcome.fr.html will map onto exactly the same information. If more than one extension is given which maps onto the same type of meta-information, then the one to the right will be used, except for languages and content encodings. For example, if .gif maps to the MIME-type image/gif and .html maps to the MIME-type text/html, then the file welcome.gif.html will be associated with the MIME-type text/html.

Languages and content encodings are treated accumulative, because one can assign more than one language or encoding to a particular ressource. For example, the file welcome.html.en.de will be delivered with Content-Language: en, de and Content-Type: text/html.

Care should be taken when a file with multiple extensions gets associated with both a MIME-type and a handler. This will usually result in the request being by the module associated with the handler. For example, if the .imap extension is mapped to the handler imap-file (from mod_imap) and the .html extension is mapped to the MIME-type text/html, then the file world.imap.html will be associated with both the imap-file handler and text/html MIME-type. When it is processed, the imap-file handler will be used, and so it will be treated as a mod_imap imagemap file.

Content encoding

A file of a particular MIME type can additionally be encoded a particular way to simplify transmission over the Internet. While this usually will refer to compression, such as gzip, it can also refer to encryption, such a pgp or to an encoding such as UUencoding, which is designed for transmitting a binary file in an ASCII (text) format.

The HTTP/1.1 RFC, section 14.11 puts it this way:

The Content-Encoding entity-header field is used as a modifier to the media-type. When present, its value indicates what additional content codings have been applied to the entity-body, and thus what decoding mechanisms must be applied in order to obtain the media-type referenced by the Content-Type header field. Content-Encoding is primarily used to allow a document to be compressed without losing the identity of its underlying media type.

By using more than one file extension (see section above about multiple file extensions), you can indicate that a file is of a particular type, and also has a particular encoding.

For example, you may have a file which is a Microsoft Word document, which is pkzipped to reduce its size. If the .doc extension is associated with the Microsoft Word file type, and the .zip extension is associated with the pkzip file encoding, then the file Resume.doc.zip would be known to be a pkzip'ed Word document.

Apache sends a Content-encoding header with the resource, in order to tell the client browser about the encoding method.

Content-encoding: pkzip

Character sets and languages

In addition to file type and the file encoding, another important piece of information is what language a particular document is in, and in what character set the file should be displayed. For example, the document might be written in the Vietnamese alphabet, or in Cyrillic, and should be displayed as such. This information, also, is transmitted in HTTP headers.

The character set, language, encoding and mime type are all used in the process of content negotiation (See mod_negotiation) to determine which document to give to the client, when there are alternative documents in more than one character set, language, encoding or mime type. All filename extensions associations created with AddCharset, AddEncoding, AddLanguage and AddType directives (and extensions listed in the MimeMagicFile) participate in this select process. Filename extensions that are only associated using the AddHandler, AddInputFilter or AddOutputFilter directives may be included or excluded from matching by using the MultiviewsMatch directive.

Charset

To convey this further information, Apache optionally sends a Content-Language header, to specify the language that the document is in, and can append additional information onto the Content-Type header to indicate the particular character set that should be used to correctly render the information.

Content-Language: en, fr
Content-Type: text/plain; charset=ISO-8859-1

The language specification is the two-letter abbreviation for the language. The charset is the name of the particular character set which should be used.

AddCharset Directive

Description: | Maps the given filename extensions to the specified content charset
Syntax: | AddCharset charset extension [extension] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

The AddCharset directive maps the given filename extensions to the specified content charset. charset is the MIME charset parameter of filenames containing extension. This mapping is added to any already in force, overriding any mappings that already exist for the same extension.

Example

AddLanguage ja .ja
AddCharset EUC-JP .euc
AddCharset ISO-2022-JP .jis
AddCharset SHIFT_JIS .sjis

Then the document xxxx.ja.jis will be treated as being a Japanese document whose charset is ISO-2022-JP (as will the document xxxx.jis.ja). The AddCharset directive is useful for both to inform the client about the character encoding of the document so that the document can be interpreted and displayed appropriately, and for content negotiation, where the server returns one from several documents based on the client's charset preference.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

See also

  • mod_negotiation
  • AddDefaultCharset

AddEncoding Directive

Description: | Maps the given filename extensions to the specified encoding type
Syntax: | AddEncoding MIME-enc extension [extension] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

The AddEncoding directive maps the given filename extensions to the specified encoding type. MIME-enc is the MIME encoding to use for documents containing the extension. This mapping is added to any already in force, overriding any mappings that already exist for the same extension.

Example

AddEncoding x-gzip .gz
AddEncoding x-compress .Z

This will cause filenames containing the .gz extension to be marked as encoded using the x-gzip encoding, and filenames containing the .Z extension to be marked as encoded with x-compress.

Old clients expect x-gzip and x-compress, however the standard dictates that they're equivalent to gzip and compress respectively. Apache does content encoding comparisons by ignoring any leading x-. When responding with an encoding Apache will use whatever form (i.e., x-foo or foo) the client requested. If the client didn't specifically request a particular form Apache will use the form given by the AddEncoding directive. To make this long story short, you should always use x-gzip and x-compress for these two specific encodings. More recent encodings, such as deflate should be specified without the x-.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

AddHandler Directive

Description: | Maps the filename extensions to the specified handler
Syntax: | AddHandler handler-name extension [extension] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

Files having the name extension will be served by the specified handler-name. This mapping is added to any already in force, overriding any mappings that already exist for the same extension. For example, to activate CGI scripts with the file extension .cgi, you might use:

AddHandler cgi-script .cgi

Once that has been put into your httpd.conf file, any file containing the .cgi extension will be treated as a CGI program.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

See also

  • SetHandler

AddInputFilter Directive

Description: | Maps filename extensions to the filters that will process client requests
Syntax: | AddInputFilter filter[;filter...] extension [extension] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime
Compatibility: | AddInputFilter is only available in Apache 2.0.26 and later.

AddInputFilter maps the filename extension extension to the filters which will process client requests and POST input when they are received by the server. This is in addition to any filters defined elsewhere, including the SetInputFilter directive. This mapping is merged over any already in force, overriding any mappings that already exist for the same extension.

If more than one filter is specified, they must be separated by semicolons in the order in which they should process the content. Both the filter and extension arguments are case-insensitive, and the extension may be specified with or without a leading dot.

See also

  • RemoveInputFilter
  • SetInputFilter

AddLanguage Directive

Description: | Maps the given filename extension to the specified content language
Syntax: | AddLanguage MIME-lang extension [extension] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

The AddLanguage directive maps the given filename extension to the specified content language. MIME-lang is the MIME language of filenames containing extension. This mapping is added to any already in force, overriding any mappings that already exist for the same extension.

Example

AddEncoding x-compress .Z
AddLanguage en .en
AddLanguage fr .fr

Then the document xxxx.en.Z will be treated as being a compressed English document (as will the document xxxx.Z.en). Although the content language is reported to the client, the browser is unlikely to use this information. The AddLanguage directive is more useful for content negotiation, where the server returns one from several documents based on the client's language preference.

If multiple language assignments are made for the same extension, the last one encountered is the one that is used. That is, for the case of:

AddLanguage en .en
AddLanguage en-gb .en
AddLanguage en-us .en

documents with the extension .en would be treated as being en-us.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

See also

  • mod_negotiation

AddOutputFilter Directive

Description: | Maps filename extensions to the filters that will process responses from the server
Syntax: | AddOutputFilter filter[;filter...] extension [extension] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime
Compatibility: | AddOutputFilter is only available in Apache 2.0.26 and later.

The AddOutputFilter directive maps the filename extension extension to the filters which will process responses from the server before they are sent to the client. This is in addition to any filters defined elsewhere, including SetOutputFilter and AddOutputFilterByType directive. This mapping is merged over any already in force, overriding any mappings that already exist for the same extension.

For example, the following configuration will process all .shtml files for server-side includes and will then compress the output using mod_deflate.

AddOutputFilter INCLUDES;DEFLATE shtml

If more than one filter is specified, they must be separated by semicolons in the order in which they should process the content. Both the filter and extension arguments are case-insensitive, and the extension may be specified with or without a leading dot.

See also

  • RemoveOutputFilter
  • SetOutputFilter

AddType Directive

Description: | Maps the given filename extensions onto the specified content type
Syntax: | AddType MIME-type extension [extension] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

The AddType directive maps the given filename extensions onto the specified content type. MIME-type is the MIME type to use for filenames containing extension. This mapping is added to any already in force, overriding any mappings that already exist for the same extension. This directive can be used to add mappings not listed in the MIME types file (see the TypesConfig directive).

Example

AddType image/gif .gif

It is recommended that new MIME types be added using the AddType directive rather than changing the TypesConfig file.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

See also

  • DefaultType
  • ForceType

DefaultLanguage Directive

Description: | Sets all files in the given scope to the specified language
Syntax: | DefaultLanguage MIME-lang
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

The DefaultLanguage directive tells Apache that all files in the directive's scope (e.g., all files covered by the current <Directory> container) that don't have an explicit language extension (such as .fr or .de as configured by AddLanguage) should be considered to be in the specified MIME-lang language. This allows entire directories to be marked as containing Dutch content, for instance, without having to rename each file. Note that unlike using extensions to specify languages, DefaultLanguage can only specify a single language.

If no DefaultLanguage directive is in force, and a file does not have any language extensions as configured by AddLanguage, then that file will be considered to have no language attribute.

Example

DefaultLanguage en

See also

  • mod_negotiation

ModMimeUsePathInfo Directive

Description: | Tells mod_mime to treat path_info components as part of the filename
Syntax: | ModMimeUsePathInfo On|Off
Default: | ModMimeUsePathInfo Off
Context: | directory
Status: | Base
Module: | mod_mime
Compatibility: | Available in Apache 2.0.41 and later

The ModMimeUsePathInfo directive is used to combine the filename with the path_info URL component to apply mod_mime's directives to the request. The default value is Off - therefore, the path_info component is ignored.

This directive is recommended when you have a virtual filesystem.

Example

ModMimeUsePathInfo On

If you have a request for /bar/foo.shtml where /bar is a Location and ModMimeUsePathInfo is On, mod_mime will treat the incoming request as /bar/foo.shtml and directives like AddOutputFilter INCLUDES .shtml will add the INCLUDES filter to the request. If ModMimeUsePathInfo is not set, the INCLUDES filter will not be added.

See also

  • AcceptPathInfo

MultiviewsMatch Directive

Description: | The types of files that will be included when searching for a matching file with MultiViews
Syntax: | MultiviewsMatch Any|NegotiatedOnly|Filters|Handlers [Handlers|Filters]
Default: | MultiviewsMatch NegotiatedOnly
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime
Compatibility: | Available in Apache 2.0.26 and later.

MultiviewsMatch permits three different behaviors for mod_negotiation's Multiviews feature. Multiviews allows a request for a file, e.g. index.html, to match any negotiated extensions following the base request, e.g. index.html.en, index.html.fr, or index.html.gz.

The NegotiatedOnly option provides that every extension following the base name must correlate to a recognized mod_mime extension for content negotation, e.g. Charset, Content-Type, Language, or Encoding. This is the strictest implementation with the fewest unexpected side effects, and is the default behavior.

To include extensions associated with Handlers and/or Filters, set the MultiviewsMatch directive to either Handlers, Filters, or both option keywords. If all other factors are equal, the smallest file will be served, e.g. in deciding between index.html.cgi of 500 bytes and index.html.pl of 1000 bytes, the .cgi file would win in this example. Users of .asis files might prefer to use the Handler option, if .asis files are associated with the asis-handler.

You may finally allow Any extensions to match, even if mod_mime doesn't recognize the extension. This was the behavior in Apache 1.3, and can cause unpredicatable results, such as serving .old or .bak files the webmaster never expected to be served.

For example, the following configuration will allow handlers and filters to participate in Multviews, but will exclude unknown files:

MultiviewsMatch Handlers Filters

See also

  • Options
  • mod_negotiation

RemoveCharset Directive

Description: | Removes any character set associations for a set of file extensions
Syntax: | RemoveCharset extension [extension] ...
Context: | virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime
Compatibility: | RemoveCharset is only available in Apache 2.0.24 and later.

The RemoveCharset directive removes any character set associations for files with the given extensions. This allows .htaccess files in subdirectories to undo any associations inherited from parent directories or the server config files.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

Example

RemoveCharset .html .shtml

RemoveEncoding Directive

Description: | Removes any content encoding associations for a set of file extensions
Syntax: | RemoveEncoding extension [extension] ...
Context: | virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

The RemoveEncoding directive removes any encoding associations for files with the given extensions. This allows .htaccess files in subdirectories to undo any associations inherited from parent directories or the server config files. An example of its use might be:

/foo/.htaccess:

AddEncoding x-gzip .gz
AddType text/plain .asc
<Files *.gz.asc>
RemoveEncoding .gz
 </Files>

This will cause foo.gz to be marked as being encoded with the gzip method, but foo.gz.asc as an unencoded plaintext file.

Note

RemoveEncoding directives are processed after any AddEncoding directives, so it is possible they may undo the effects of the latter if both occur within the same directory configuration.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

RemoveHandler Directive

Description: | Removes any handler associations for a set of file extensions
Syntax: | RemoveHandler extension [extension] ...
Context: | virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

The RemoveHandler directive removes any handler associations for files with the given extensions. This allows .htaccess files in subdirectories to undo any associations inherited from parent directories or the server config files. An example of its use might be:

/foo/.htaccess:

AddHandler server-parsed .html

/foo/bar/.htaccess:

RemoveHandler .html

This has the effect of returning .html files in the /foo/bar directory to being treated as normal files, rather than as candidates for parsing (see the mod_include module).

The extension argument is case-insensitive, and can be specified with or without a leading dot.

RemoveInputFilter Directive

Description: | Removes any input filter associations for a set of file extensions
Syntax: | RemoveInputFilter extension [extension] ...
Context: | virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime
Compatibility: | RemoveInputFilter is only available in Apache 2.0.26 and later.

The RemoveInputFilter directive removes any input filter associations for files with the given extensions. This allows .htaccess files in subdirectories to undo any associations inherited from parent directories or the server config files.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

See also

  • AddInputFilter
  • SetInputFilter

RemoveLanguage Directive

Description: | Removes any language associations for a set of file extensions
Syntax: | RemoveLanguage extension [extension] ...
Context: | virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime
Compatibility: | RemoveLanguage is only available in Apache 2.0.24 and later.

The RemoveLanguage directive removes any language associations for files with the given extensions. This allows .htaccess files in subdirectories to undo any associations inherited from parent directories or the server config files.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

RemoveOutputFilter Directive

Description: | Removes any output filter associations for a set of file extensions
Syntax: | RemoveOutputFilter extension [extension] ...
Context: | virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime
Compatibility: | RemoveOutputFilter is only available in Apache 2.0.26 and later.

The RemoveOutputFilter directive removes any output filter associations for files with the given extensions. This allows .htaccess files in subdirectories to undo any associations inherited from parent directories or the server config files.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

Example

RemoveOutputFilter shtml

See also

  • AddOutputFilter

RemoveType Directive

Description: | Removes any content type associations for a set of file extensions
Syntax: | RemoveType extension [extension] ...
Context: | virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_mime

The RemoveType directive removes any MIME type associations for files with the given extensions. This allows .htaccess files in subdirectories to undo any associations inherited from parent directories or the server config files. An example of its use might be:

/foo/.htaccess:

RemoveType .cgi

This will remove any special handling of .cgi files in the /foo/ directory and any beneath it, causing the files to be treated as being of the DefaultType.

Note

RemoveType directives are processed after any AddType directives, so it is possible they may undo the effects of the latter if both occur within the same directory configuration.

The extension argument is case-insensitive, and can be specified with or without a leading dot.

TypesConfig Directive

Description: | The location of the mime.types file
Syntax: | TypesConfig file-path
Default: | TypesConfig conf/mime.types
Context: | server config
Status: | Base
Module: | mod_mime

The TypesConfig directive sets the location of the MIME types configuration file. File-path is relative to the ServerRoot. This file sets the default list of mappings from filename extensions to content types. Most administrators use the provided mime.types file, which associates common filename extensions with IANA registered content types. The current list is maintained at http://www.iana.org/assignments/media-types/index.html. This simplifies the httpd.conf file by providing the majority of media-type definitions, and may be overridden by AddType directives as needed. You should not edit the mime.types file, because it may be replaced when you upgrade your server.

The file contains lines in the format of the arguments to an AddType directive:

MIME-type [extension] ...

The case of the extension does not matter. Blank lines, and lines beginning with a hash character (#) are ignored.

Please do not send requests to the Apache HTTP Server Project to add any new entries in the distributed mime.types file unless (1) they are already registered with IANA, and (2) they use widely accepted, non-conflicting filename extensions across platforms. category/x-subtype requests will be automatically rejected, as will any new two-letter extensions as they will likely conflict later with the already crowded language and character set namespace.

See also

  • mod_mime_magic


mod_mime_magic - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_mime_magic

Description: | Determines the MIME type of a file by looking at a few bytes of its contents
Status: | Extension
Module Identifier: | mime_magic_module
Source File: | mod_mime_magic.c

Summary

This module determines the MIME type of files in the same way the Unix file(1) command works: it looks at the first few bytes of the file. It is intended as a "second line of defense" for cases that mod_mime can't resolve.

This module is derived from a free version of the file(1) command for Unix, which uses "magic numbers" and other hints from a file's contents to figure out what the contents are. This module is active only if the magic file is specified by the MimeMagicFile directive.

Format of the Magic File

The contents of the file are plain ASCII text in 4-5 columns. Blank lines are allowed but ignored. Commented lines use a hash mark (#). The remaining lines are parsed for the following columns:

Column | Description
1 byte number to begin checking from
">" indicates a dependency upon the previous non-">" line
2

type of data to match

byte | single character
short | machine-order 16-bit integer
long | machine-order 32-bit integer
string | arbitrary-length string
date | long integer date (seconds since Unix epoch/1970)
beshort | big-endian 16-bit integer
belong | big-endian 32-bit integer
bedate | big-endian 32-bit integer date
leshort | little-endian 16-bit integer
lelong | little-endian 32-bit integer
ledate | little-endian 32-bit integer date
3 | contents of data to match
4 | MIME type if matched
5 | MIME encoding if matched (optional)

For example, the following magic file lines would recognize some audio formats:

# Sun/NeXT audio data
0      string      .snd
>12    belong      1       audio/basic
>12    belong      2       audio/basic
>12    belong      3       audio/basic
>12    belong      4       audio/basic
>12    belong      5       audio/basic
>12    belong      6       audio/basic
>12    belong      7       audio/basic
>12    belong     23       audio/x-adpcm

Or these would recognize the difference between *.doc files containing Microsoft Word or FrameMaker documents. (These are incompatible file formats which use the same file suffix.)

# Frame
0  string  \<MakerFile        application/x-frame
0  string  \<MIFFile          application/x-frame
0  string  \<MakerDictionary  application/x-frame
0  string  \<MakerScreenFon   application/x-frame
0  string  \<MML              application/x-frame
0  string  \<Book             application/x-frame
0  string  \<Maker            application/x-frame

# MS-Word
0  string  \376\067\0\043            application/msword
0  string  \320\317\021\340\241\261  application/msword
0  string  \333\245-\0\0\0           application/msword

An optional MIME encoding can be included as a fifth column. For example, this can recognize gzipped files and set the encoding for them.

# gzip (GNU zip, not to be confused with
#       [Info-ZIP/PKWARE] zip archiver)

0  string  \037\213  application/octet-stream  x-gzip

Performance Issues

This module is not for every system. If your system is barely keeping up with its load or if you're performing a web server benchmark, you may not want to enable this because the processing is not free.

However, an effort was made to improve the performance of the original file(1) code to make it fit in a busy web server. It was designed for a server where there are thousands of users who publish their own documents. This is probably very common on intranets. Many times, it's helpful if the server can make more intelligent decisions about a file's contents than the file name allows ...even if just to reduce the "why doesn't my page work" calls when users improperly name their own files. You have to decide if the extra work suits your environment.

Notes

The following notes apply to the mod_mime_magic module and are included here for compliance with contributors' copyright restrictions that require their acknowledgment.

mod_mime_magic: MIME type lookup via file magic numbers
Copyright (c) 1996-1997 Cisco Systems, Inc.

This software was submitted by Cisco Systems to the Apache Group in July 1997. Future revisions and derivatives of this source code must acknowledge Cisco Systems as the original contributor of this module. All other licensing and usage conditions are those of the Apache Group.

Some of this code is derived from the free version of the file command originally posted to comp.sources.unix. Copyright info for that program is included below as required.

- Copyright (c) Ian F. Darwin, 1987. Written by Ian F. Darwin.

This software is not subject to any license of the American Telephone and Telegraph Company or of the Regents of the University of California.

Permission is granted to anyone to use this software for any purpose on any computer system, and to alter it and redistribute it freely, subject to the following restrictions:

  1. The author is not responsible for the consequences of use of this software, no matter how awful, even if they arise from flaws in it.
  2. The origin of this software must not be misrepresented, either by explicit claim or by omission. Since few users ever read sources, credits must appear in the documentation.
  3. Altered versions must be plainly marked as such, and must not be misrepresented as being the original software. Since few users ever read sources, credits must appear in the documentation.
  4. This notice may not be removed or altered.

For compliance with Mr Darwin's terms: this has been very significantly modified from the free "file" command.

  • all-in-one file for compilation convenience when moving from one version of Apache to the next.
  • Memory allocation is done through the Apache API's pool structure.
  • All functions have had necessary Apache API request or server structures passed to them where necessary to call other Apache API routines. (i.e., usually for logging, files, or memory allocation in itself or a called function.)
  • struct magic has been converted from an array to a single-ended linked list because it only grows one record at a time, it's only accessed sequentially, and the Apache API has no equivalent of realloc().
  • Functions have been changed to get their parameters from the server configuration instead of globals. (It should be reentrant now but has not been tested in a threaded environment.)
  • Places where it used to print results to stdout now saves them in a list where they're used to set the MIME type in the Apache request record.
  • Command-line flags have been removed since they will never be used here.

MimeMagicFile Directive

Description: | Enable MIME-type determination based on file contents using the specified magic file
Syntax: | MimeMagicFile file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_mime_magic

The MimeMagicFile directive can be used to enable this module, the default file is distributed at conf/magic. Non-rooted paths are relative to the ServerRoot. Virtual hosts will use the same file as the main server unless a more specific setting is used, in which case the more specific setting overrides the main server's file.

Example

MimeMagicFile conf/magic


mod_negotiation - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_negotiation

Description: | Provides for content negotiation
Status: | Base
Module Identifier: | negotiation_module
Source File: | mod_negotiation.c

Summary

Content negotiation, or more accurately content selection, is the selection of the document that best matches the clients capabilities, from one of several available documents. There are two implementations of this.

  • A type map (a file with the handler type-map) which explicitly lists the files containing the variants.
  • A MultiViews search (enabled by the MultiViews Options), where the server does an implicit filename pattern match, and choose from amongst the results.

See also

  • Options
  • mod_mime
  • Content Negotiation
  • Environment Variables

Type maps

A type map has a format similar to RFC822 mail headers. It contains document descriptions separated by blank lines, with lines beginning with a hash character ('#') treated as comments. A document description consists of several header records; records may be continued on multiple lines if the continuation lines start with spaces. The leading space will be deleted and the lines concatenated. A header record consists of a keyword name, which always ends in a colon, followed by a value. Whitespace is allowed between the header name and value, and between the tokens of value. The headers allowed are:

Content-Encoding:
The encoding of the file. Apache only recognizes encodings that are defined by an AddEncoding directive. This normally includes the encodings x-compress for compress'd files, and x-gzip for gzip'd files. The x- prefix is ignored for encoding comparisons.
Content-Language:
The language(s) of the variant, as an Internet standard language tag (RFC 1766). An example is en, meaning English. If the variant contains more than one language, they are separated by a comma.
Content-Length:
The length of the file, in bytes. If this header is not present, then the actual length of the file is used.
Content-Type:
The MIME media type of the document, with optional parameters. Parameters are separated from the media type and from one another by a semi-colon, with a syntax of name=value. Common parameters include:
level
an integer specifying the version of the media type. For text/html this defaults to 2, otherwise 0.
qs
a floating-point number with a value in the range 0.0 to 1.0, indicating the relative 'quality' of this variant compared to the other available variants, independent of the client's capabilities. For example, a jpeg file is usually of higher source quality than an ascii file if it is attempting to represent a photograph. However, if the resource being represented is ascii art, then an ascii file would have a higher source quality than a jpeg file. All qs values are therefore specific to a given resource.

Example

Content-Type: image/jpeg; qs=0.8

URI:
uri of the file containing the variant (of the given media type, encoded with the given content encoding). These are interpreted as URLs relative to the map file; they must be on the same server (!), and they must refer to files to which the client would be granted access if they were to be requested directly.
Body:
New in Apache 2.0, the actual content of the resource may be included in the type-map file using the Body header. This header must contain a string that designates a delimiter for the body content. Then all following lines in the type map file will be considered part of the resource body until the delimiter string is found.

Example:

Body:----xyz----
<html>
<body>
<p>Content of the page.</p>
</body>
</html>
----xyz----

MultiViews

A MultiViews search is enabled by the MultiViews Options. If the server receives a request for /some/dir/foo and /some/dir/foo does not exist, then the server reads the directory looking for all files named foo.*, and effectively fakes up a type map which names all those files, assigning them the same media types and content-encodings it would have if the client had asked for one of them by name. It then chooses the best match to the client's requirements, and returns that document.

The MultiViewsMatch directive configures whether Apache will consider files that do not have content negotiation meta-information assigned to them when choosing files.

CacheNegotiatedDocs Directive

Description: | Allows content-negotiated documents to be cached by proxy servers
Syntax: | CacheNegotiatedDocs On|Off
Default: | CacheNegotiatedDocs Off
Context: | server config, virtual host
Status: | Base
Module: | mod_negotiation
Compatibility: | The syntax changed in version 2.0.

If set, this directive allows content-negotiated documents to be cached by proxy servers. This could mean that clients behind those proxys could retrieve versions of the documents that are not the best match for their abilities, but it will make caching more efficient.

This directive only applies to requests which come from HTTP/1.0 browsers. HTTP/1.1 provides much better control over the caching of negotiated documents, and this directive has no effect in responses to HTTP/1.1 requests.

Prior to version 2.0, CacheNegotiatedDocs did not take an argument; it was turned on by the presence of the directive by itself.

ForceLanguagePriority Directive

Description: | Action to take if a single acceptable document is not found
Syntax: | ForceLanguagePriority None|Prefer|Fallback [Prefer|Fallback]
Default: | ForceLanguagePriority Prefer
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_negotiation
Compatibility: | Available in version 2.0.30 and later

The ForceLanguagePriority directive uses the given LanguagePriority to satisfy negotation where the server could otherwise not return a single matching document.

ForceLanguagePriority Prefer uses LanguagePriority to serve a one valid result, rather than returning an HTTP result 300 (MULTIPLE CHOICES) when there are several equally valid choices. If the directives below were given, and the user's Accept-Language header assigned en and de each as quality .500 (equally acceptable) then the first matching variant, en, will be served.

LanguagePriority en fr de
ForceLanguagePriority Prefer

ForceLanguagePriority Fallback uses LanguagePriority to serve a valid result, rather than returning an HTTP result 406 (NOT ACCEPTABLE). If the directives below were given, and the user's Accept-Language only permitted an es language response, but such a variant isn't found, then the first variant from the LanguagePriority list below will be served.

LanguagePriority en fr de
ForceLanguagePriority Fallback

Both options, Prefer and Fallback, may be specified, so either the first matching variant from LanguagePriority will be served if more than one variant is acceptable, or first available document will be served if none of the variants matched the client's acceptable list of languages.

See also

  • AddLanguage

LanguagePriority Directive

Description: | The precendence of language variants for cases where the client does not express a preference
Syntax: | LanguagePriority MIME-lang [MIME-lang] ...
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Base
Module: | mod_negotiation

The LanguagePriority sets the precedence of language variants for the case where the client does not express a preference, when handling a MultiViews request. The list of MIME-lang are in order of decreasing preference.

Example:

LanguagePriority en fr de

For a request for foo.html, where foo.html.fr and foo.html.de both existed, but the browser did not express a language preference, then foo.html.fr would be returned.

Note that this directive only has an effect if a 'best' language cannot be determined by any other means or the ForceLanguagePriority directive is not None. In general, the client determines the language preference, not the server.

See also

  • AddLanguage


mod_nw_ssl - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_nw_ssl

Description: | Enable SSL encryption for NetWare
Status: | Base
Module Identifier: | nwssl_module
Source File: | mod_nw_ssl.c
Compatibility: | NetWare only

Summary

This module enables SSL encryption for a specified port. It takes advantage of the SSL encryption functionality that is built into the NetWare operating system.

NWSSLTrustedCerts Directive

Description: | List of additional client certificates
Syntax: | NWSSLTrustedCerts filename [filename] ...
Context: | server config
Status: | Base
Module: | mod_nw_ssl

Specifies a list of client certificate files (DER format) that are used when creating a proxied SSL connection. Each client certificate used by a server must be listed separately in its own .der file.

NWSSLUpgradeable Directive

Description: | Allows a connection to be upgraded to an SSL connection upon request
Syntax: | NWSSLUpgradeable [IP-address:]portnumber
Context: | server config
Status: | Base
Module: | mod_nw_ssl

Allow a connection that was created on the specified address and/or port to be upgraded to an SSL connection upon request from the client. The address and/or port must have already be defined previously with a Listen directive.

SecureListen Directive

Description: | Enables SSL encryption for the specified port
Syntax: | SecureListen [IP-address:]portnumber Certificate-Name [MUTUAL]
Context: | server config
Status: | Base
Module: | mod_nw_ssl

Specifies the port and the eDirectory based certificate name that will be used to enable SSL encryption. An optional third parameter also enables mutual authentication.


mod_proxy - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_proxy

Description: | HTTP/1.1 proxy/gateway server
Status: | Extension
Module Identifier: | proxy_module
Source File: | mod_proxy.c

Summary

Warning

Do not enable proxying with ProxyRequests until you have secured your server. Open proxy servers are dangerous both to your network and to the Internet at large.

This module implements a proxy/gateway for Apache. It implements proxying capability for FTP, CONNECT (for SSL), HTTP/0.9, HTTP/1.0, and HTTP/1.1. The module can be configured to connect to other proxy modules for these and other protocols.

Apache's proxy features are divided into several modules in addition to mod_proxy: mod_proxy_http, mod_proxy_ftp and mod_proxy_connect. Thus, if you want to use one or more of the particular proxy functions, load mod_proxy and the appropriate module(s) into the server (either statically at compile-time or dynamically via the LoadModule directive).

In addition, extended features are provided by other modules. Caching is provided by mod_cache and related modules. The ability to contact remote servers using the SSL/TLS protocol is provided by the SSLProxy* directives of mod_ssl. These additional modules will need to be loaded and configured to take advantage of these features.

See also

  • mod_cache
  • mod_proxy_http
  • mod_proxy_ftp
  • mod_proxy_connect
  • mod_ssl

Forward and Reverse Proxies

Apache can be configured in both a forward and reverse proxy mode.

An ordinary forward proxy is an intermediate server that sits between the client and the origin server. In order to get content from the origin server, the client sends a request to the proxy naming the origin server as the target and the proxy then requests the content from the origin server and returns it to the client. The client must be specially configured to use the forward proxy to access other sites.

A typical usage of a forward proxy is to provide Internet access to internal clients that are otherwise restricted by a firewall. The forward proxy can also use caching (as provided by mod_cache) to reduce network usage.

The forward proxy is activated using the ProxyRequests directive. Because forward proxys allow clients to access arbitrary sites through your server and to hide their true origin, it is essential that you secure your server so that only authorized clients can access the proxy before activating a forward proxy.

A reverse proxy, by contrast, appears to the client just like an ordinary web server. No special configuration on the client is necessary. The client makes ordinary requests for content in the name-space of the reverse proxy. The reverse proxy then decides where to send those requests, and returns the content as if it was itself the origin.

A typical usage of a reverse proxy is to provide Internet users access to a server that is behind a firewall. Reverse proxies can also be used to balance load among several back-end servers, or to provide caching for a slower back-end server. In addition, reverse proxies can be used simply to bring several servers into the same URL space.

A reverse proxy is activated using the ProxyPass directive or the [P] flag to the RewriteRule directive. It is not necessary to turn ProxyRequests on in order to configure a reverse proxy.

Basic Examples

The examples below are only a very basic idea to help you get started. Please read the documentation on the individual directives.

In addition, if you wish to have caching enabled, consult the documentation from mod_cache.

Forward Proxy

ProxyRequests On
ProxyVia On

<Proxy *>
Order deny,allow
Deny from all
Allow from internal.example.com
 </Proxy>

Reverse Proxy

ProxyRequests Off

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

ProxyPass /foo http://foo.example.com/bar
ProxyPassReverse /foo http://foo.example.com/bar

Controlling access to your proxy

You can control who can access your proxy via the <Proxy> control block as in the following example:

<Proxy *>
Order Deny,Allow
Deny from all
Allow from 192.168.0
 </Proxy>

For more information on access control directives, see mod_access.

Strictly limiting access is essential if you are using a forward proxy (using the ProxyRequests directive). Otherwise, your server can be used by any client to access arbitrary hosts while hiding his or her true identity. This is dangerous both for your network and for the Internet at large. When using a reverse proxy (using the ProxyPass directive with ProxyRequests Off), access control is less critical because clients can only contact the hosts that you have specifically configured.

FTP Proxy

Why doesn't file type xxx download via FTP?

You probably don't have that particular file type defined as application/octet-stream in your proxy's mime.types configuration file. A useful line can be

application/octet-stream   bin dms lha lzh exe class tgz taz

How can I force an FTP ASCII download of File xxx?

In the rare situation where you must download a specific file using the FTP ASCII transfer method (while the default transfer is in binary mode), you can override mod_proxy's default by suffixing the request with ;type=a to force an ASCII transfer. (FTP Directory listings are always executed in ASCII mode, however.)

How can I access FTP files outside of my home directory?

An FTP URI is interpreted relative to the home directory of the user who is logging in. Alas, to reach higher directory levels you cannot use /../, as the dots are interpreted by the browser and not actually sent to the FTP server. To address this problem, the so called Squid %2f hack was implemented in the Apache FTP proxy; it is a solution which is also used by other popular proxy servers like the Squid Proxy Cache. By prepending /%2f to the path of your request, you can make such a proxy change the FTP starting directory to / (instead of the home directory). For example, to retrieve the file /etc/motd, you would use the URL:

ftp://user@host/%2f/etc/motd

How can I hide the FTP cleartext password in my browser's URL line?

To log in to an FTP server by username and password, Apache uses different strategies. In absense of a user name and password in the URL altogether, Apache sends an anonymous login to the FTP server, i.e.,

user: anonymous
password: apache_proxy@

This works for all popular FTP servers which are configured for anonymous access.

For a personal login with a specific username, you can embed the user name into the URL, like in:

ftp://username@host/myfile

If the FTP server asks for a password when given this username (which it should), then Apache will reply with a 401 (Authorization required) response, which causes the Browser to pop up the username/password dialog. Upon entering the password, the connection attempt is retried, and if successful, the requested resource is presented. The advantage of this procedure is that your browser does not display the password in cleartext (which it would if you had used

ftp://username:password@host/myfile

in the first place).

Note

The password which is transmitted in such a way is not encrypted on its way. It travels between your browser and the Apache proxy server in a base64-encoded cleartext string, and between the Apache proxy and the FTP server as plaintext. You should therefore think twice before accessing your FTP server via HTTP (or before accessing your personal files via FTP at all!) When using unsecure channels, an eavesdropper might intercept your password on its way.

Slow Startup

If you're using the ProxyBlock directive, hostnames' IP addresses are looked up and cached during startup for later match test. This may take a few seconds (or more) depending on the speed with which the hostname lookups occur.

Intranet Proxy

An Apache proxy server situated in an intranet needs to forward external requests through the company's firewall (for this, configure the ProxyRemote directive to forward the respective scheme to the firewall proxy). However, when it has to access resources within the intranet, it can bypass the firewall when accessing hosts. The NoProxy directive is useful for specifying which hosts belong to the intranet and should be accessed directly.

Users within an intranet tend to omit the local domain name from their WWW requests, thus requesting "http://somehost/" instead of http://somehost.example.com/. Some commercial proxy servers let them get away with this and simply serve the request, implying a configured local domain. When the ProxyDomain directive is used and the server is configured for proxy service, Apache can return a redirect response and send the client to the correct, fully qualified, server address. This is the preferred method since the user's bookmark files will then contain fully qualified hosts.

Protocol Adjustments

For circumstances where you have a application server which doesn't implement keepalives or HTTP/1.1 properly, there are 2 environment variables which when set send a HTTP/1.0 with no keepalive. These are set via the SetEnv directive.

These are the force-proxy-request-1.0 and proxy-nokeepalive notes.

<Location /buggyappserver/>
ProxyPass http://buggyappserver:7001/foo/
SetEnv force-proxy-request-1.0 1
SetEnv proxy-nokeepalive 1
 </Location>

AllowCONNECT Directive

Description: | Ports that are allowed to CONNECT through the proxy
Syntax: | AllowCONNECT port [port] ...
Default: | AllowCONNECT 443 563
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

The AllowCONNECT directive specifies a list of port numbers to which the proxy CONNECT method may connect. Today's browsers use this method when a https connection is requested and proxy tunneling over HTTP is in effect.

By default, only the default https port (443) and the default snews port (563) are enabled. Use the AllowCONNECT directive to override this default and allow connections to the listed ports only.

Note that you'll need to have mod_proxy_connect present in the server in order to get the support for the CONNECT at all.

NoProxy Directive

Description: | Hosts, domains, or networks that will be connected to directly
Syntax: | NoProxy host [host] ...
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

This directive is only useful for Apache proxy servers within intranets. The NoProxy directive specifies a list of subnets, IP addresses, hosts and/or domains, separated by spaces. A request to a host which matches one or more of these is always served directly, without forwarding to the configured ProxyRemote proxy server(s).

Example

ProxyRemote * http://firewall.mycompany.com:81
NoProxy .mycompany.com 192.168.112.0/21

The host arguments to the NoProxy directive are one of the following type list:

Domain

A Domain is a partially qualified DNS domain name, preceded by a period. It represents a list of hosts which logically belong to the same DNS domain or zone (i.e., the suffixes of the hostnames are all ending in Domain).

Examples

.com .apache.org.

To distinguish Domains from Hostnames (both syntactically and semantically; a DNS domain can have a DNS A record, too!), Domains are always written with a leading period.

Note

Domain name comparisons are done without regard to the case, and Domains are always assumed to be anchored in the root of the DNS tree, therefore two domains .MyDomain.com and .mydomain.com. (note the trailing period) are considered equal. Since a domain comparison does not involve a DNS lookup, it is much more efficient than subnet comparison.

SubNet

A SubNet is a partially qualified internet address in numeric (dotted quad) form, optionally followed by a slash and the netmask, specified as the number of significant bits in the SubNet. It is used to represent a subnet of hosts which can be reached over a common network interface. In the absence of the explicit net mask it is assumed that omitted (or zero valued) trailing digits specify the mask. (In this case, the netmask can only be multiples of 8 bits wide.) Examples:

192.168 or 192.168.0.0
the subnet 192.168.0.0 with an implied netmask of 16 valid bits (sometimes used in the netmask form 255.255.0.0)
192.168.112.0/21
the subnet 192.168.112.0/21 with a netmask of 21 valid bits (also used in the form 255.255.248.0)

As a degenerate case, a SubNet with 32 valid bits is the equivalent to an IPAddr, while a SubNet with zero valid bits (e.g., 0.0.0.0/0) is the same as the constant _Default_, matching any IP address.

IPAddr

A IPAddr represents a fully qualified internet address in numeric (dotted quad) form. Usually, this address represents a host, but there need not necessarily be a DNS domain name connected with the address.

Example

192.168.123.7

Note

An IPAddr does not need to be resolved by the DNS system, so it can result in more effective apache performance.

Hostname

A Hostname is a fully qualified DNS domain name which can be resolved to one or more IPAddrs via the DNS domain name service. It represents a logical host (in contrast to Domains, see above) and must be resolvable to at least one IPAddr (or often to a list of hosts with different IPAddrs).

Examples

prep.ai.mit.edu
www.apache.org

Note

In many situations, it is more effective to specify an IPAddr in place of a Hostname since a DNS lookup can be avoided. Name resolution in Apache can take a remarkable deal of time when the connection to the name server uses a slow PPP link.

Hostname comparisons are done without regard to the case, and Hostnames are always assumed to be anchored in the root of the DNS tree, therefore two hosts WWW.MyDomain.com and www.mydomain.com. (note the trailing period) are considered equal.

See also

  • DNS Issues

<Proxy> Directive

Description: | Container for directives applied to proxied resources
Syntax: | <Proxy wildcard-url> ...</Proxy>
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

Directives placed in <Proxy> sections apply only to matching proxied content. Shell-style wildcards are allowed.

For example, the following will allow only hosts in yournetwork.example.com to access content via your proxy server:

<Proxy *>
Order Deny,Allow
Deny from all
Allow from yournetwork.example.com
 </Proxy>

The following example will process all files in the foo directory of example.com through the INCLUDES filter when they are sent through the proxy server:

<Proxy http://example.com/foo/*>
SetOutputFilter INCLUDES
 </Proxy>

ProxyBadHeader Directive

Description: | Determines how to handle bad header lines in a response
Syntax: | ProxyBadHeader IsError|Ignore|StartBody
Default: | ProxyBadHeader IsError
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy
Compatibility: | available in Apache 2.0.44 and later

The ProxyBadHeader directive determines the behaviour of mod_proxy if it receives syntactically invalid header lines (i.e. containing no colon). The following arguments are possible:

IsError
Abort the request and end up with a 502 (Bad Gateway) response. This is the default behaviour.
Ignore
Treat bad header lines as if they weren't sent.
StartBody
When receiving the first bad header line, finish reading the headers and treat the remainder as body. This helps to work around buggy backend servers which forget to insert an empty line between the headers and the body.

ProxyBlock Directive

Description: | Words, hosts, or domains that are banned from being proxied
Syntax: | ProxyBlock *|word|host|domain [word|host|domain] ...
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

The ProxyBlock directive specifies a list of words, hosts and/or domains, separated by spaces. HTTP, HTTPS, and FTP document requests to sites whose names contain matched words, hosts or domains are blocked by the proxy server. The proxy module will also attempt to determine IP addresses of list items which may be hostnames during startup, and cache them for match test as well. That may slow down the startup time of the server.

Example

ProxyBlock joes-garage.com some-host.co.uk rocky.wotsamattau.edu

rocky.wotsamattau.edu would also be matched if referenced by IP address.

Note that wotsamattau would also be sufficient to match wotsamattau.edu.

Note also that

ProxyBlock *

blocks connections to all sites.

ProxyDomain Directive

Description: | Default domain name for proxied requests
Syntax: | ProxyDomain Domain
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

This directive is only useful for Apache proxy servers within intranets. The ProxyDomain directive specifies the default domain which the apache proxy server will belong to. If a request to a host without a domain name is encountered, a redirection response to the same host with the configured Domain appended will be generated.

Example

ProxyRemote * http://firewall.mycompany.com:81
NoProxy .mycompany.com 192.168.112.0/21
ProxyDomain .mycompany.com

ProxyErrorOverride Directive

Description: | Override error pages for proxied content
Syntax: | ProxyErrorOverride On|Off
Default: | ProxyErrorOverride Off
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy
Compatibility: | Available in version 2.0 and later

This directive is useful for reverse-proxy setups, where you want to have a common look and feel on the error pages seen by the end user. This also allows for included files (via mod_include's SSI) to get the error code and act accordingly (default behavior would display the error page of the proxied server, turning this on shows the SSI Error message).

ProxyIOBufferSize Directive

Description: | Determine size of internal data throughput buffer
Syntax: | ProxyIOBufferSize bytes
Default: | ProxyIOBufferSize 8192
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

The ProxyIOBufferSize directive adjusts the size of the internal buffer, which is used as a scratchpad for the data between input and output. The size must be less or equal 8192.

In almost every case there's no reason to change that value.

<ProxyMatch> Directive

Description: | Container for directives applied to regular-expression-matched proxied resources
Syntax: | <ProxyMatch regex> ...</ProxyMatch>
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

The <ProxyMatch> directive is identical to the <Proxy> directive, except it matches URLs using regular expressions.

ProxyMaxForwards Directive

Description: | Maximium number of proxies that a request can be forwarded through
Syntax: | ProxyMaxForwards number
Default: | ProxyMaxForwards 10
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy
Compatibility: | Available in Apache 2.0 and later

The ProxyMaxForwards directive specifies the maximum number of proxies through which a request may pass, if there's no Max-Forwards header supplied with the request. This is set to prevent infinite proxy loops, or a DoS attack.

Example

ProxyMaxForwards 15

ProxyPass Directive

Description: | Maps remote servers into the local server URL-space
Syntax: | ProxyPass [path] !|url
Context: | server config, virtual host, directory
Status: | Extension
Module: | mod_proxy

This directive allows remote servers to be mapped into the space of the local server; the local server does not act as a proxy in the conventional sense, but appears to be a mirror of the remote server. path is the name of a local virtual path; url is a partial URL for the remote server and cannot include a query string.

Suppose the local server has address http://example.com/; then

ProxyPass /mirror/foo/ http://backend.example.com/

will cause a local request for http://example.com/mirror/foo/bar to be internally converted into a proxy request to http://backend.example.com/bar.

The ! directive is useful in situations where you don't want to reverse-proxy a subdirectory, e.g.

ProxyPass /mirror/foo/i !
ProxyPass /mirror/foo http://backend.example.com

will proxy all requests to /mirror/foo to backend.example.com except requests made to /mirror/foo/i.

Note

Order is important. you need to put the exclusions before the general proxypass directive.

When used inside a <Location> section, the first argument is omitted and the local directory is obtained from the <Location>.

The ProxyRequests directive should usually be set off when using ProxyPass.

If you require a more flexible reverse-proxy configuration, see the RewriteRule directive with the [P] flag.

ProxyPassReverse Directive

Description: | Adjusts the URL in HTTP response headers sent from a reverse proxied server
Syntax: | ProxyPassReverse [path] url
Context: | server config, virtual host, directory
Status: | Extension
Module: | mod_proxy

This directive lets Apache adjust the URL in the Location, Content-Location and URI headers on HTTP redirect responses. This is essential when Apache is used as a reverse proxy to avoid by-passing the reverse proxy because of HTTP redirects on the backend servers which stay behind the reverse proxy.

Only the HTTP response headers specifically mentioned above will be rewritten. Apache will not rewrite other response headers, nor will it rewrite URL references inside HTML pages. This means that if the proxied content contains absolute URL references, they will by-pass the proxy. A third-party module that will look inside the HTML and rewrite URL references is Nick Kew's mod_proxy_html.

path is the name of a local virtual path. url is a partial URL for the remote server - the same way they are used for the ProxyPass directive.

For example, suppose the local server has address http://example.com/; then

ProxyPass /mirror/foo/ http://backend.example.com/
ProxyPassReverse /mirror/foo/ http://backend.example.com/

will not only cause a local request for the http://example.com/mirror/foo/bar to be internally converted into a proxy request to http://backend.example.com/bar (the functionality ProxyPass provides here). It also takes care of redirects the server backend.example.com sends: when http://backend.example.com/bar is redirected by him to http://backend.example.com/quux Apache adjusts this to http://example.com/mirror/foo/quux before forwarding the HTTP redirect response to the client. Note that the hostname used for constructing the URL is chosen in respect to the setting of the UseCanonicalName directive.

Note that this ProxyPassReverse directive can also be used in conjunction with the proxy pass-through feature (RewriteRule ... [P]) from mod_rewrite because its doesn't depend on a corresponding ProxyPass directive.

When used inside a <Location> section, the first argument is omitted and the local directory is obtained from the <Location>.

ProxyPreserveHost Directive

Description: | Use incoming Host HTTP request header for proxy request
Syntax: | ProxyPreserveHost On|Off
Default: | ProxyPreserveHost Off
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy
Compatibility: | Available in Apache 2.0.31 and later.

When enabled, this option will pass the Host: line from the incoming request to the proxied host, instead of the hostname specified in the proxypass line.

This option should normally be turned Off. It is mostly useful in special configurations like proxied mass name-based virtual hosting, where the original Host header needs to be evaluated by the backend server.

ProxyReceiveBufferSize Directive

Description: | Network buffer size for proxied HTTP and FTP connections
Syntax: | ProxyReceiveBufferSize bytes
Default: | ProxyReceiveBufferSize 0
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

The ProxyReceiveBufferSize directive specifies an explicit (TCP/IP) network buffer size for proxied HTTP and FTP connections, for increased throughput. It has to be greater than 512 or set to 0 to indicate that the system's default buffer size should be used.

Example

ProxyReceiveBufferSize 2048

ProxyRemote Directive

Description: | Remote proxy used to handle certain requests
Syntax: | ProxyRemote match remote-server
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

This defines remote proxies to this proxy. match is either the name of a URL-scheme that the remote server supports, or a partial URL for which the remote server should be used, or * to indicate the server should be contacted for all requests. remote-server is a partial URL for the remote server. Syntax:

remote-server = scheme://hostname[:port]

scheme is effectively the protocol that should be used to communicate with the remote server; only http is supported by this module.

Example

ProxyRemote http://goodguys.com/ http://mirrorguys.com:8000
ProxyRemote * http://cleversite.com
ProxyRemote ftp http://ftpproxy.mydomain.com:8080

In the last example, the proxy will forward FTP requests, encapsulated as yet another HTTP proxy request, to another proxy which can handle them.

This option also supports reverse proxy configuration - a backend webserver can be embedded within a virtualhost URL space even if that server is hidden by another forward proxy.

ProxyRemoteMatch Directive

Description: | Remote proxy used to handle requests matched by regular expressions
Syntax: | ProxyRemoteMatch regex remote-server
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

The ProxyRemoteMatch is identical to the ProxyRemote directive, except the first argument is a regular expression match against the requested URL.

ProxyRequests Directive

Description: | Enables forward (standard) proxy requests
Syntax: | ProxyRequests On|Off
Default: | ProxyRequests Off
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

This allows or prevents Apache from functioning as a forward proxy server. (Setting ProxyRequests to Off does not disable use of the ProxyPass directive.)

In a typical reverse proxy configuration, this option should be set to Off.

In order to get the functionality of proxying HTTP or FTP sites, you need also mod_proxy_http or mod_proxy_ftp (or both) present in the server.

Warning

Do not enable proxying with ProxyRequests until you have secured your server. Open proxy servers are dangerous both to your network and to the Internet at large.

ProxyTimeout Directive

Description: | Network timeout for proxied requests
Syntax: | ProxyTimeout seconds
Default: | ProxyTimeout 300
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy
Compatibility: | Available in Apache 2.0.31 and later

This directive allows a user to specifiy a timeout on proxy requests. This is useful when you have a slow/buggy appserver which hangs, and you would rather just return a timeout and fail gracefully instead of waiting however long it takes the server to return.

ProxyVia Directive

Description: | Information provided in the Via HTTP response header for proxied requests
Syntax: | ProxyVia On|Off|Full|Block
Default: | ProxyVia Off
Context: | server config, virtual host
Status: | Extension
Module: | mod_proxy

This directive controls the use of the Via: HTTP header by the proxy. Its intended use is to control the flow of of proxy requests along a chain of proxy servers. See RFC 2616 (HTTP/1.1), section 14.45 for an explanation of Via: header lines.

  • If set to Off, which is the default, no special processing is performed. If a request or reply contains a Via: header, it is passed through unchanged.
  • If set to On, each request and reply will get a Via: header line added for the current host.
  • If set to Full, each generated Via: header line will additionally have the Apache server version shown as a Via: comment field.
  • If set to Block, every proxy request will have all its Via: header lines removed. No new Via: header will be generated.


mod_proxy_connect - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_proxy_connect

Description: | mod_proxy extension for CONNECT request handling
Status: | Extension
Module Identifier: | proxy_connect_module
Source File: | proxy_connect.c

Summary

This module requires the service of mod_proxy. It provides support for the CONNECT HTTP method. This method is mainly used to tunnel SSL requests through proxy servers.

Thus, in order to get the ability of handling CONNECT requests, mod_proxy and mod_proxy_connect have to be present in the server.

Warning

Do not enable proxying until you have secured your server. Open proxy servers are dangerous both to your network and to the Internet at large.

See also

  • AllowCONNECT
  • mod_proxy


mod_proxy_ftp - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_proxy_ftp

Description: | FTP support module for mod_proxy
Status: | Extension
Module Identifier: | proxy_ftp_module
Source File: | proxy_ftp.c

Summary

This module requires the service of mod_proxy. It provides support for the proxying FTP sites.

Thus, in order to get the ability of handling FTP proxy requests, mod_proxy and mod_proxy_ftp have to be present in the server.

Warning

Do not enable proxying until you have secured your server. Open proxy servers are dangerous both to your network and to the Internet at large.

See also

  • mod_proxy


mod_proxy_http - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_proxy_http

Description: | HTTP support module for mod_proxy
Status: | Extension
Module Identifier: | proxy_http_module
Source File: | proxy_http.c

Summary

This module requires the service of mod_proxy. It provides the features used for proxying HTTP requests. mod_proxy_http supports HTTP/0.9, HTTP/1.0 and HTTP/1.1. It does not provide any caching abilities. If you want to set up a caching proxy, you might want to use the additional service of the mod_cache module.

Thus, in order to get the ability of handling HTTP proxy requests, mod_proxy and mod_proxy_http have to be present in the server.

Warning

Do not enable proxying until you have secured your server. Open proxy servers are dangerous both to your network and to the Internet at large.

See also

  • mod_proxy
  • mod_proxy_connect


mod_rewrite - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_rewrite

Description: | Provides a rule-based rewriting engine to rewrite requested URLs on the fly
Status: | Extension
Module Identifier: | rewrite_module
Source File: | mod_rewrite.c
Compatibility: | Available in Apache 1.3 and later

Summary

``The great thing about mod_rewrite is it gives you all the configurability and flexibility of Sendmail. The downside to mod_rewrite is that it gives you all the configurability and flexibility of Sendmail.''

-- Brian Behlendorf
Apache Group

`` Despite the tons of examples and docs, mod_rewrite is voodoo. Damned cool voodoo, but still voodoo. ''

-- Brian Moore
bem@news.cmc.net

Welcome to mod_rewrite, the Swiss Army Knife of URL manipulation!

This module uses a rule-based rewriting engine (based on a regular-expression parser) to rewrite requested URLs on the fly. It supports an unlimited number of rules and an unlimited number of attached rule conditions for each rule to provide a really flexible and powerful URL manipulation mechanism. The URL manipulations can depend on various tests, for instance server variables, environment variables, HTTP headers, time stamps and even external database lookups in various formats can be used to achieve a really granular URL matching.

This module operates on the full URLs (including the path-info part) both in per-server context (httpd.conf) and per-directory context (.htaccess) and can even generate query-string parts on result. The rewritten result can lead to internal sub-processing, external request redirection or even to an internal proxy throughput.

But all this functionality and flexibility has its drawback: complexity. So don't expect to understand this entire module in just one day.

This module was invented and originally written in April 1996 and gifted exclusively to the The Apache Group in July 1997 by

Ralf S. Engelschall
rse@engelschall.com
www.engelschall.com

Internal Processing

The internal processing of this module is very complex but needs to be explained once even to the average user to avoid common mistakes and to let you exploit its full functionality.

API Phases

First you have to understand that when Apache processes a HTTP request it does this in phases. A hook for each of these phases is provided by the Apache API. Mod_rewrite uses two of these hooks: the URL-to-filename translation hook which is used after the HTTP request has been read but before any authorization starts and the Fixup hook which is triggered after the authorization phases and after the per-directory config files (.htaccess) have been read, but before the content handler is activated.

So, after a request comes in and Apache has determined the corresponding server (or virtual server) the rewriting engine starts processing of all mod_rewrite directives from the per-server configuration in the URL-to-filename phase. A few steps later when the final data directories are found, the per-directory configuration directives of mod_rewrite are triggered in the Fixup phase. In both situations mod_rewrite rewrites URLs either to new URLs or to filenames, although there is no obvious distinction between them. This is a usage of the API which was not intended to be this way when the API was designed, but as of Apache 1.x this is the only way mod_rewrite can operate. To make this point more clear remember the following two points:

  1. Although mod_rewrite rewrites URLs to URLs, URLs to filenames and even filenames to filenames, the API currently provides only a URL-to-filename hook. In Apache 2.0 the two missing hooks will be added to make the processing more clear. But this point has no drawbacks for the user, it is just a fact which should be remembered: Apache does more in the URL-to-filename hook than the API intends for it.
  2. Unbelievably mod_rewrite provides URL manipulations in per-directory context, i.e., within .htaccess files, although these are reached a very long time after the URLs have been translated to filenames. It has to be this way because .htaccess files live in the filesystem, so processing has already reached this stage. In other words: According to the API phases at this time it is too late for any URL manipulations. To overcome this chicken and egg problem mod_rewrite uses a trick: When you manipulate a URL/filename in per-directory context mod_rewrite first rewrites the filename back to its corresponding URL (which is usually impossible, but see the RewriteBase directive below for the trick to achieve this) and then initiates a new internal sub-request with the new URL. This restarts processing of the API phases.

    Again mod_rewrite tries hard to make this complicated step totally transparent to the user, but you should remember here: While URL manipulations in per-server context are really fast and efficient, per-directory rewrites are slow and inefficient due to this chicken and egg problem. But on the other hand this is the only way mod_rewrite can provide (locally restricted) URL manipulations to the average user.

Don't forget these two points!

Ruleset Processing

Now when mod_rewrite is triggered in these two API phases, it reads the configured rulesets from its configuration structure (which itself was either created on startup for per-server context or during the directory walk of the Apache kernel for per-directory context). Then the URL rewriting engine is started with the contained ruleset (one or more rules together with their conditions). The operation of the URL rewriting engine itself is exactly the same for both configuration contexts. Only the final result processing is different.

The order of rules in the ruleset is important because the rewriting engine processes them in a special (and not very obvious) order. The rule is this: The rewriting engine loops through the ruleset rule by rule (RewriteRule directives) and when a particular rule matches it optionally loops through existing corresponding conditions (RewriteCond directives). For historical reasons the conditions are given first, and so the control flow is a little bit long-winded. See Figure 1 for more details.

[Needs graphics capability to display]
Figure 1:The control flow through the rewriting ruleset

As you can see, first the URL is matched against the Pattern of each rule. When it fails mod_rewrite immediately stops processing this rule and continues with the next rule. If the Pattern matches, mod_rewrite looks for corresponding rule conditions. If none are present, it just substitutes the URL with a new value which is constructed from the string Substitution and goes on with its rule-looping. But if conditions exist, it starts an inner loop for processing them in the order that they are listed. For conditions the logic is different: we don't match a pattern against the current URL. Instead we first create a string TestString by expanding variables, back-references, map lookups, etc. and then we try to match CondPattern against it. If the pattern doesn't match, the complete set of conditions and the corresponding rule fails. If the pattern matches, then the next condition is processed until no more conditions are available. If all conditions match, processing is continued with the substitution of the URL with Substitution.

Quoting Special Characters

As of Apache 1.3.20, special characters in TestString and Substitution strings can be escaped (that is, treated as normal characters without their usual special meaning) by prefixing them with a slash ('\') character. In other words, you can include an actual dollar-sign character in a Substitution string by using '\$'; this keeps mod_rewrite from trying to treat it as a backreference.

Regex Back-Reference Availability

One important thing here has to be remembered: Whenever you use parentheses in Pattern or in one of the CondPattern, back-references are internally created which can be used with the strings $N and %N (see below). These are available for creating the strings Substitution and TestString. Figure 2 shows to which locations the back-references are transfered for expansion.

[Needs graphics capability to display]
Figure 2: The back-reference flow through a rule.

We know this was a crash course on mod_rewrite's internal processing. But you will benefit from this knowledge when reading the following documentation of the available directives.

Environment Variables

This module keeps track of two additional (non-standard) CGI/SSI environment variables named SCRIPT_URL and SCRIPT_URI. These contain the logical Web-view to the current resource, while the standard CGI/SSI variables SCRIPT_NAME and SCRIPT_FILENAME contain the physical System-view.

Notice: These variables hold the URI/URL as they were initially requested, i.e., before any rewriting. This is important because the rewriting process is primarily used to rewrite logical URLs to physical pathnames.

Example

SCRIPT_NAME=/sw/lib/w3s/tree/global/u/rse/.www/index.html
SCRIPT_FILENAME=/u/rse/.www/index.html
SCRIPT_URL=/u/rse/
SCRIPT_URI=http://en1.engelschall.com/u/rse/

Practical Solutions

We also have an URL Rewriting Guide available, which provides a collection of practical solutions for URL-based problems. There you can find real-life rulesets and additional information about mod_rewrite.

RewriteBase Directive

Description: | Sets the base URL for per-directory rewrites
Syntax: | RewriteBase URL-path
Default: | See usage for information.
Context: | directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_rewrite

The RewriteBase directive explicitly sets the base URL for per-directory rewrites. As you will see below, RewriteRule can be used in per-directory config files (.htaccess). There it will act locally, i.e., the local directory prefix is stripped at this stage of processing and your rewriting rules act only on the remainder. At the end it is automatically added back to the path. The default setting is; RewriteBase physical-directory-path

When a substitution occurs for a new URL, this module has to re-inject the URL into the server processing. To be able to do this it needs to know what the corresponding URL-prefix or URL-base is. By default this prefix is the corresponding filepath itself. But at most websites URLs are NOT directly related to physical filename paths, so this assumption will usually be wrong! There you have to use the RewriteBase directive to specify the correct URL-prefix.

If your webserver's URLs are not directly related to physical file paths, you have to use RewriteBase in every .htaccess files where you want to use RewriteRule directives.

For example, assume the following per-directory config file:

#
#  /abc/def/.htaccess -- per-dir config file for directory /abc/def
#  Remember: /abc/def is the physical path of /xyz, i.e., the server
#            has a 'Alias /xyz /abc/def' directive e.g.
#

RewriteEngine On

#  let the server know that we were reached via /xyz and not
#  via the physical path prefix /abc/def
RewriteBase   /xyz

#  now the rewriting rules
RewriteRule   ^oldstuff\.html$  newstuff.html

In the above example, a request to /xyz/oldstuff.html gets correctly rewritten to the physical file /abc/def/newstuff.html.

For Apache Hackers

The following list gives detailed information about the internal processing steps:

Request:
  /xyz/oldstuff.html

Internal Processing:
  /xyz/oldstuff.html     -> /abc/def/oldstuff.html  (per-server Alias)
  /abc/def/oldstuff.html -> /abc/def/newstuff.html  (per-dir    RewriteRule)
  /abc/def/newstuff.html -> /xyz/newstuff.html      (per-dir    RewriteBase)
  /xyz/newstuff.html     -> /abc/def/newstuff.html  (per-server Alias)

Result:
  /abc/def/newstuff.html

This seems very complicated but is the correct Apache internal processing, because the per-directory rewriting comes too late in the process. So, when it occurs the (rewritten) request has to be re-injected into the Apache kernel! BUT: While this seems like a serious overhead, it really isn't, because this re-injection happens fully internally to the Apache server and the same procedure is used by many other operations inside Apache. So, you can be sure the design and implementation is correct.

RewriteCond Directive

Description: | Defines a condition under which rewriting will take place
Syntax: | RewriteCond TestString CondPattern
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_rewrite

The RewriteCond directive defines a rule condition. Precede a RewriteRule directive with one or more RewriteCond directives. The following rewriting rule is only used if its pattern matches the current state of the URI and if these additional conditions apply too.

TestString is a string which can contains the following expanded constructs in addition to plain text:

  • RewriteRule backreferences: These are backreferences of the form

    $N

    (0 <= N <= 9) which provide access to the grouped parts (parenthesis!) of the pattern from the corresponding RewriteRule directive (the one following the current bunch of RewriteCond directives).
  • RewriteCond backreferences: These are backreferences of the form

    %N

    (1 <= N <= 9) which provide access to the grouped parts (parentheses!) of the pattern from the last matched RewriteCond directive in the current bunch of conditions.
  • RewriteMap expansions: These are expansions of the form

    ${mapname:key|default}

    See the documentation for RewriteMap for more details.
  • Server-Variables: These are variables of the form

    %{ NAME_OF_VARIABLE }

    where NAME_OF_VARIABLE can be a string taken from the following list:
    HTTP headers: connection & request:
    HTTP_USER_AGENT
    HTTP_REFERER
    HTTP_COOKIE
    HTTP_FORWARDED
    HTTP_HOST
    HTTP_PROXY_CONNECTION
    HTTP_ACCEPT
             REMOTE_ADDR
    REMOTE_HOST
    REMOTE_USER
    REMOTE_IDENT
    REQUEST_METHOD
    SCRIPT_FILENAME
    PATH_INFO
    QUERY_STRING
    AUTH_TYPE
    server internals: system stuff: specials:
    DOCUMENT_ROOT
    SERVER_ADMIN
    SERVER_NAME
    SERVER_ADDR
    SERVER_PORT
    SERVER_PROTOCOL
    SERVER_SOFTWARE
             TIME_YEAR
    TIME_MON
    TIME_DAY
    TIME_HOUR
    TIME_MIN
    TIME_SEC
    TIME_WDAY
    TIME
             API_VERSION
    THE_REQUEST
    REQUEST_URI
    REQUEST_FILENAME
    IS_SUBREQ
    HTTPS

    These variables all correspond to the similarly named HTTP MIME-headers, C variables of the Apache server or struct tm fields of the Unix system. Most are documented elsewhere in the Manual or in the CGI specification. Those that are special to mod_rewrite include:

    IS_SUBREQ
    Will contain the text "true" if the request currently being processed is a sub-request, "false" otherwise. Sub-requests may be generated by modules that need to resolve additional files or URIs in order to complete their tasks.
    API_VERSION
    This is the version of the Apache module API (the internal interface between server and module) in the current httpd build, as defined in include/ap_mmn.h. The module API version corresponds to the version of Apache in use (in the release version of Apache 1.3.14, for instance, it is 19990320:10), but is mainly of interest to module authors.
    THE_REQUEST
    The full HTTP request line sent by the browser to the server (e.g., "GET /index.html HTTP/1.1"). This does not include any additional headers sent by the browser.
    REQUEST_URI
    The resource requested in the HTTP request line. (In the example above, this would be "/index.html".)
    REQUEST_FILENAME
    The full local filesystem path to the file or script matching the request.
    HTTPS
    Will contain the text "on" if the connection is using SSL/TLS, or "off" otherwise. (This variable can be safely used regardless of whether mod_ssl is loaded).

Special Notes:

  1. The variables SCRIPT_FILENAME and REQUEST_FILENAME contain the same value, i.e., the value of the filename field of the internal request_rec structure of the Apache server. The first name is just the commonly known CGI variable name while the second is the consistent counterpart to REQUEST_URI (which contains the value of the uri field of request_rec).
  2. There is the special format: %{ENV:variable} where variable can be any environment variable. This is looked-up via internal Apache structures and (if not found there) via getenv() from the Apache server process.
  3. There is the special format: %{SSL:variable} where variable is the name of an SSL environment variable; this can be used whether or not mod_ssl is loaded, but will always expand to the empty string if it is not. Example: %{SSL:SSL_CIPHER_USEKEYSIZE} may expand to 128.
  4. There is the special format: %{HTTP:header} where header can be any HTTP MIME-header name. This is looked-up from the HTTP request. Example: %{HTTP:Proxy-Connection} is the value of the HTTP header ``Proxy-Connection:''.
  5. There is the special format %{LA-U:variable} for look-aheads which perform an internal (URL-based) sub-request to determine the final value of variable. Use this when you want to use a variable for rewriting which is actually set later in an API phase and thus is not available at the current stage. For instance when you want to rewrite according to the REMOTE_USER variable from within the per-server context (httpd.conf file) you have to use %{LA-U:REMOTE_USER} because this variable is set by the authorization phases which come after the URL translation phase where mod_rewrite operates. On the other hand, because mod_rewrite implements its per-directory context (.htaccess file) via the Fixup phase of the API and because the authorization phases come before this phase, you just can use %{REMOTE_USER} there.
  6. There is the special format: %{LA-F:variable} which performs an internal (filename-based) sub-request to determine the final value of variable. Most of the time this is the same as LA-U above.

CondPattern is the condition pattern, i.e., a regular expression which is applied to the current instance of the TestString, i.e., TestString is evaluated and then matched against CondPattern.

Remember: CondPattern is a perl compatible regular expression with some additions:

  1. You can prefix the pattern string with a '!' character (exclamation mark) to specify a non-matching pattern.
  2. There are some special variants of CondPatterns. Instead of real regular expression strings you can also use one of the following:
    • '<CondPattern' (is lexically lower)
      Treats the CondPattern as a plain string and compares it lexically to TestString. True if TestString is lexically lower than CondPattern.
    • '>CondPattern' (is lexically greater)
      Treats the CondPattern as a plain string and compares it lexically to TestString. True if TestString is lexically greater than CondPattern.
    • '=CondPattern' (is lexically equal)
      Treats the CondPattern as a plain string and compares it lexically to TestString. True if TestString is lexically equal to CondPattern, i.e the two strings are exactly equal (character by character). If CondPattern is just "" (two quotation marks) this compares TestString to the empty string.
    • '-d' (is directory)
      Treats the TestString as a pathname and tests if it exists and is a directory.
    • '-f' (is regular file)
      Treats the TestString as a pathname and tests if it exists and is a regular file.
    • '-s' (is regular file with size)
      Treats the TestString as a pathname and tests if it exists and is a regular file with size greater than zero.
    • '-l' (is symbolic link)
      Treats the TestString as a pathname and tests if it exists and is a symbolic link.
    • '-F' (is existing file via subrequest)
      Checks if TestString is a valid file and accessible via all the server's currently-configured access controls for that path. This uses an internal subrequest to determine the check, so use it with care because it decreases your servers performance!
    • '-U' (is existing URL via subrequest)
      Checks if TestString is a valid URL and accessible via all the server's currently-configured access controls for that path. This uses an internal subrequest to determine the check, so use it with care because it decreases your server's performance!

    Notice

    All of these tests can also be prefixed by an exclamation mark ('!') to negate their meaning.

Additionally you can set special flags for CondPattern by appending

[flags]

as the third argument to the RewriteCond directive. Flags is a comma-separated list of the following flags:

  • 'nocase|NC' (no case)
    This makes the test case-insensitive, i.e., there is no difference between 'A-Z' and 'a-z' both in the expanded TestString and the CondPattern. This flag is effective only for comparisons between TestString and CondPattern. It has no effect on filesystem and subrequest checks.
  • 'ornext|OR' (or next condition)
    Use this to combine rule conditions with a local OR instead of the implicit AND. Typical example:
    RewriteCond %{REMOTE_HOST}  ^host1.*  [OR]
RewriteCond %{REMOTE_HOST}  ^host2.*  [OR]
RewriteCond %{REMOTE_HOST}  ^host3.*
RewriteRule ...some special stuff for any of these hosts...
    Without this flag you would have to write the cond/rule three times.

Example:

To rewrite the Homepage of a site according to the ``User-Agent:'' header of the request, you can use the following:

RewriteCond  %{HTTP_USER_AGENT}  ^Mozilla.*
RewriteRule  ^/$                 /homepage.max.html  [L]

RewriteCond  %{HTTP_USER_AGENT}  ^Lynx.*
RewriteRule  ^/$                 /homepage.min.html  [L]

RewriteRule  ^/$                 /homepage.std.html  [L]

Interpretation: If you use Netscape Navigator as your browser (which identifies itself as 'Mozilla'), then you get the max homepage, which includes Frames, etc. If you use the Lynx browser (which is Terminal-based), then you get the min homepage, which contains no images, no tables, etc. If you use any other browser you get the standard homepage.

RewriteEngine Directive

Description: | Enables or disables runtime rewriting engine
Syntax: | RewriteEngine on|off
Default: | RewriteEngine off
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_rewrite

The RewriteEngine directive enables or disables the runtime rewriting engine. If it is set to off this module does no runtime processing at all. It does not even update the SCRIPT_URx environment variables.

Use this directive to disable the module instead of commenting out all the RewriteRule directives!

Note that, by default, rewrite configurations are not inherited. This means that you need to have a RewriteEngine on directive for each virtual host in which you wish to use it.

RewriteLock Directive

Description: | Sets the name of the lock file used for RewriteMap synchronization
Syntax: | RewriteLock file-path
Context: | server config
Status: | Extension
Module: | mod_rewrite

This directive sets the filename for a synchronization lockfile which mod_rewrite needs to communicate with RewriteMap programs. Set this lockfile to a local path (not on a NFS-mounted device) when you want to use a rewriting map-program. It is not required for other types of rewriting maps.

RewriteLog Directive

Description: | Sets the name of the file used for logging rewrite engine processing
Syntax: | RewriteLog file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_rewrite

The RewriteLog directive sets the name of the file to which the server logs any rewriting actions it performs. If the name does not begin with a slash ('/') then it is assumed to be relative to the Server Root. The directive should occur only once per server config.

To disable the logging of rewriting actions it is not recommended to set Filename to /dev/null, because although the rewriting engine does not then output to a logfile it still creates the logfile output internally. This will slow down the server with no advantage to the administrator! To disable logging either remove or comment out the RewriteLog directive or use RewriteLogLevel 0!

Security

See the Apache Security Tips document for details on why your security could be compromised if the directory where logfiles are stored is writable by anyone other than the user that starts the server.

Example

RewriteLog "/usr/local/var/apache/logs/rewrite.log"

RewriteLogLevel Directive

Description: | Sets the verbosity of the log file used by the rewrite engine
Syntax: | RewriteLogLevel Level
Default: | RewriteLogLevel 0
Context: | server config, virtual host
Status: | Extension
Module: | mod_rewrite

The RewriteLogLevel directive sets the verbosity level of the rewriting logfile. The default level 0 means no logging, while 9 or more means that practically all actions are logged.

To disable the logging of rewriting actions simply set Level to 0. This disables all rewrite action logs.

Using a high value for Level will slow down your Apache server dramatically! Use the rewriting logfile at a Level greater than 2 only for debugging!

Example

RewriteLogLevel 3

RewriteMap Directive

Description: | Defines a mapping function for key-lookup
Syntax: | RewriteMap MapName MapType:MapSource
Context: | server config, virtual host
Status: | Extension
Module: | mod_rewrite
Compatibility: | The choice of different dbm types is available in Apache 2.0.41 and later

The RewriteMap directive defines a Rewriting Map which can be used inside rule substitution strings by the mapping-functions to insert/substitute fields through a key lookup. The source of this lookup can be of various types.

The MapName is the name of the map and will be used to specify a mapping-function for the substitution strings of a rewriting rule via one of the following constructs:

${ MapName : LookupKey }
${ MapName : LookupKey | DefaultValue }

When such a construct occurs the map MapName is consulted and the key LookupKey is looked-up. If the key is found, the map-function construct is substituted by SubstValue. If the key is not found then it is substituted by DefaultValue or by the empty string if no DefaultValue was specified.

For example, you might define a RewriteMap as:

RewriteMap examplemap txt:/path/to/file/map.txt

You would then be able to use this map in a RewriteRule as follows:

RewriteRule ^/ex/(.*) ${examplemap:$1}

The following combinations for MapType and MapSource can be used:

  • Standard Plain Text
    MapType: txt, MapSource: Unix filesystem path to valid regular file

    This is the standard rewriting map feature where the MapSource is a plain ASCII file containing either blank lines, comment lines (starting with a '#' character) or pairs like the following - one per line.

    MatchingKey SubstValue

    Example

    ##
##  map.txt -- rewriting map
##

Ralf.S.Engelschall    rse   # Bastard Operator From Hell
Mr.Joe.Average        joe   # Mr. Average

    RewriteMap real-to-user txt:/path/to/file/map.txt

  • Randomized Plain Text
    MapType: rnd, MapSource: Unix filesystem path to valid regular file

    This is identical to the Standard Plain Text variant above but with a special post-processing feature: After looking up a value it is parsed according to contained ``|'' characters which have the meaning of ``or''. In other words they indicate a set of alternatives from which the actual returned value is chosen randomly. For example, you might use the following map file and directives to provide a random load balancing between several back-end server, via a reverse-proxy. Images are sent to one of the servers in the 'static' pool, while everything else is sent to one of the 'dynamic' pool.

    Example:

    Rewrite map file

    ##
##  map.txt -- rewriting map
##

static   www1|www2|www3|www4
dynamic  www5|www6

    Configuration directives

    RewriteMap servers rnd:/path/to/file/map.txt

    RewriteRule ^/(.*\.(png|gif|jpg)) http://${servers:static}/$1 [NC,P,L]
    RewriteRule ^/(.*) http://${servers:dynamic}/$1 [P,L]

  • Hash File
    MapType: dbm[=type], MapSource: Unix filesystem path to valid regular file

    Here the source is a binary format DBM file containing the same contents as a Plain Text format file, but in a special representation which is optimized for really fast lookups. The type can be sdbm, gdbm, ndbm, or db depending on compile-time settings. If the type is ommitted, the compile-time default will be chosen. You can create such a file with any DBM tool or with the following Perl script. Be sure to adjust it to create the appropriate type of DBM. The example creates an NDBM file.

    #!/path/to/bin/perl
##
##  txt2dbm -- convert txt map to dbm format
##

use NDBM_File;
use Fcntl;

($txtmap, $dbmmap) = @ARGV;

open(TXT, "<$txtmap") or die "Couldn't open $txtmap!\n";
tie (%DB, 'NDBM_File', $dbmmap,O_RDWR|O_TRUNC|O_CREAT, 0644)
  or die "Couldn't create $dbmmap!\n";

while (<TXT>) {
  next if (/^\s*#/ or /^\s*$/);
  $DB{$1} = $2 if (/^\s*(\S+)\s+(\S+)/);
}

untie %DB;
close(TXT);

    $ txt2dbm map.txt map.db

  • Internal Function
    MapType: int, MapSource: Internal Apache function

    Here the source is an internal Apache function. Currently you cannot create your own, but the following functions already exists:

    • toupper:
      Converts the looked up key to all upper case.
    • tolower:
      Converts the looked up key to all lower case.
    • escape:
      Translates special characters in the looked up key to hex-encodings.
    • unescape:
      Translates hex-encodings in the looked up key back to special characters.
  • External Rewriting Program
    MapType: prg, MapSource: Unix filesystem path to valid regular file

    Here the source is a program, not a map file. To create it you can use the language of your choice, but the result has to be a executable (i.e., either object-code or a script with the magic cookie trick '#!/path/to/interpreter' as the first line).

    This program is started once at startup of the Apache servers and then communicates with the rewriting engine over its stdin and stdout file-handles. For each map-function lookup it will receive the key to lookup as a newline-terminated string on stdin. It then has to give back the looked-up value as a newline-terminated string on stdout or the four-character string ``NULL'' if it fails (i.e., there is no corresponding value for the given key). A trivial program which will implement a 1:1 map (i.e., key == value) could be:

    #!/usr/bin/perl
$| = 1;
while (<STDIN>) {
    # ...put here any transformations or lookups...
    print $_;
}

    But be very careful:

    1. ``Keep it simple, stupid'' (KISS), because if this program hangs it will hang the Apache server when the rule occurs.
    2. Avoid one common mistake: never do buffered I/O on stdout! This will cause a deadloop! Hence the ``$|=1'' in the above example...
    3. Use the RewriteLock directive to define a lockfile mod_rewrite can use to synchronize the communication to the program. By default no such synchronization takes place.

The RewriteMap directive can occur more than once. For each mapping-function use one RewriteMap directive to declare its rewriting mapfile. While you cannot declare a map in per-directory context it is of course possible to use this map in per-directory context.

Note

For plain text and DBM format files the looked-up keys are cached in-core until the mtime of the mapfile changes or the server does a restart. This way you can have map-functions in rules which are used for every request. This is no problem, because the external lookup only happens once!

RewriteOptions Directive

Description: | Sets some special options for the rewrite engine
Syntax: | RewriteOptions Options
Default: | RewriteOptions MaxRedirects=10
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_rewrite
Compatibility: | MaxRedirects is available in Apache 2.0.45 and later

The RewriteOptions directive sets some special options for the current per-server or per-directory configuration. The Option strings can be one of the following:

inherit
This forces the current configuration to inherit the configuration of the parent. In per-virtual-server context this means that the maps, conditions and rules of the main server are inherited. In per-directory context this means that conditions and rules of the parent directory's .htaccess configuration are inherited.
MaxRedirects=number
In order to prevent endless loops of internal redirects issued by per-directory RewriteRules, mod_rewrite aborts the request after reaching a maximum number of such redirects and responds with an 500 Internal Server Error. If you really need more internal redirects than 10 per request, you may increase the default to the desired value.

RewriteRule Directive

Description: | Defines rules for the rewriting engine
Syntax: | RewriteRule Pattern Substitution
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_rewrite
Compatibility: | The cookie-flag is available in Apache 2.0.40 and later.

The RewriteRule directive is the real rewriting workhorse. The directive can occur more than once. Each directive then defines one single rewriting rule. The definition order of these rules is important, because this order is used when applying the rules at run-time.

Pattern is a perl compatible regular expression which gets applied to the current URL. Here ``current'' means the value of the URL when this rule gets applied. This may not be the originally requested URL, because any number of rules may already have matched and made alterations to it.

Some hints about the syntax of regular expressions:

Text:
  .           Any single character
  [chars]     Character class: One  of chars
  [^chars]    Character class: None of chars
  text1|text2 Alternative: text1 or text2

Quantifiers:
  ?           0 or 1 of the preceding text
  *           0 or N of the preceding text (N > 0)
  +           1 or N of the preceding text (N > 1)

Grouping:
  (text)      Grouping of text
              (either to set the borders of an alternative or
              for making backreferences where the Nth group can
              be used on the RHS of a RewriteRule with $N)

Anchors:
  ^           Start of line anchor
  $           End   of line anchor

Escaping:
  \char       escape that particular char
              (for instance to specify the chars ".[]()" etc.)

For more information about regular expressions have a look at the perl regular expression manpage ("perldoc perlre"). If you are interested in more detailed information about regular expressions and their variants (POSIX regex etc.) have a look at the following dedicated book on this topic:

Mastering Regular Expressions, 2nd Edition
Jeffrey E.F. Friedl
O'Reilly & Associates, Inc. 2002
ISBN 0-596-00289-0

Additionally in mod_rewrite the NOT character ('!') is a possible pattern prefix. This gives you the ability to negate a pattern; to say, for instance: ``if the current URL does NOT match this pattern''. This can be used for exceptional cases, where it is easier to match the negative pattern, or as a last default rule.

Notice

When using the NOT character to negate a pattern you cannot have grouped wildcard parts in the pattern. This is impossible because when the pattern does NOT match, there are no contents for the groups. In consequence, if negated patterns are used, you cannot use $N in the substitution string!

Substitution of a rewriting rule is the string which is substituted for (or replaces) the original URL for which Pattern matched. Beside plain text you can use

  1. back-references $N to the RewriteRule pattern
  2. back-references %N to the last matched RewriteCond pattern
  3. server-variables as in rule condition test-strings (%{VARNAME})
  4. mapping-function calls (${mapname:key|default})

Back-references are $N (N=0..9) identifiers which will be replaced by the contents of the Nth group of the matched Pattern. The server-variables are the same as for the TestString of a RewriteCond directive. The mapping-functions come from the RewriteMap directive and are explained there. These three types of variables are expanded in the order of the above list.

As already mentioned above, all the rewriting rules are applied to the Substitution (in the order of definition in the config file). The URL is completely replaced by the Substitution and the rewriting process goes on until there are no more rules unless explicitly terminated by a L flag - see below.

There is a special substitution string named '-' which means: NO substitution! Sounds silly? No, it is useful to provide rewriting rules which only match some URLs but do no substitution, e.g., in conjunction with the C (chain) flag to be able to have more than one pattern to be applied before a substitution occurs.

Query String

The Pattern will not match against the query string. Instead, you must use a RewriteCond with the %{QUERY_STRING} variable. You can, however, create URLs in the substitution string containing a query string part. Just use a question mark inside the substitution string to indicate that the following stuff should be re-injected into the query string. When you want to erase an existing query string, end the substitution string with just the question mark. To combine a new query string with an old one, use the [QSA] flag (see below).

Substitution of Absolute URLs

There is a special feature: When you prefix a substitution field with http://thishost[:thisport] then mod_rewrite automatically strips it out. This auto-reduction on implicit external redirect URLs is a useful and important feature when used in combination with a mapping-function which generates the hostname part. Have a look at the first example in the example section below to understand this.

Remember: An unconditional external redirect to your own server will not work with the prefix http://thishost because of this feature. To achieve such a self-redirect, you have to use the R-flag (see below).

Additionally you can set special flags for Substitution by appending

[flags]

as the third argument to the RewriteRule directive. Flags is a comma-separated list of the following flags:

  • 'chain|C' (chained with next rule)
    This flag chains the current rule with the next rule (which itself can be chained with the following rule, etc.). This has the following effect: if a rule matches, then processing continues as usual, i.e., the flag has no effect. If the rule does not match, then all following chained rules are skipped. For instance, use it to remove the ``.www'' part inside a per-directory rule set when you let an external redirect happen (where the ``.www'' part should not to occur!).
  • 'cookie|CO=NAME:VAL:domain[:lifetime[:path]]' (set cookie)
    This sets a cookie on the client's browser. The cookie's name is specified by NAME and the value is VAL. The domain field is the domain of the cookie, such as '.apache.org',the optional lifetime is the lifetime of the cookie in minutes, and the optional path is the path of the cookie
  • 'env|E=VAR:VAL' (set environment variable)
    This forces an environment variable named VAR to be set to the value VAL, where VAL can contain regexp backreferences $N and %N which will be expanded. You can use this flag more than once to set more than one variable. The variables can be later dereferenced in many situations, but usually from within XSSI (via <!--#echo var="VAR"-->) or CGI (e.g. $ENV{'VAR'}). Additionally you can dereference it in a following RewriteCond pattern via %{ENV:VAR}. Use this to strip but remember information from URLs.
  • 'forbidden|F' (force URL to be forbidden)
    This forces the current URL to be forbidden, i.e., it immediately sends back a HTTP response of 403 (FORBIDDEN). Use this flag in conjunction with appropriate RewriteConds to conditionally block some URLs.
  • 'gone|G' (force URL to be gone)
    This forces the current URL to be gone, i.e., it immediately sends back a HTTP response of 410 (GONE). Use this flag to mark pages which no longer exist as gone.
  • 'last|L' (last rule)
    Stop the rewriting process here and don't apply any more rewriting rules. This corresponds to the Perl last command or the break command from the C language. Use this flag to prevent the currently rewritten URL from being rewritten further by following rules. For example, use it to rewrite the root-path URL ('/') to a real one, e.g., '/e/www/'.
  • 'next|N' (next round)
    Re-run the rewriting process (starting again with the first rewriting rule). Here the URL to match is again not the original URL but the URL from the last rewriting rule. This corresponds to the Perl next command or the continue command from the C language. Use this flag to restart the rewriting process, i.e., to immediately go to the top of the loop.
    But be careful not to create an infinite loop!
  • 'nocase|NC' (no case)
    This makes the Pattern case-insensitive, i.e., there is no difference between 'A-Z' and 'a-z' when Pattern is matched against the current URL.
  • 'noescape|NE' (no URI escaping of output)
    This flag keeps mod_rewrite from applying the usual URI escaping rules to the result of a rewrite. Ordinarily, special characters (such as '%', '$', ';', and so on) will be escaped into their hexcode equivalents ('%25', '%24', and '%3B', respectively); this flag prevents this from being done. This allows percent symbols to appear in the output, as in

    RewriteRule /foo/(.*) /bar?arg=P1\%3d$1 [R,NE]

    which would turn '/foo/zed' into a safe request for '/bar?arg=P1=zed'.
  • 'nosubreq|NS' (used only if no internal sub-request)
    This flag forces the rewriting engine to skip a rewriting rule if the current request is an internal sub-request. For instance, sub-requests occur internally in Apache when mod_include tries to find out information about possible directory default files (index.xxx). On sub-requests it is not always useful and even sometimes causes a failure to if the complete set of rules are applied. Use this flag to exclude some rules.

    Use the following rule for your decision: whenever you prefix some URLs with CGI-scripts to force them to be processed by the CGI-script, the chance is high that you will run into problems (or even overhead) on sub-requests. In these cases, use this flag.

  • 'proxy|P' (force proxy)
    This flag forces the substitution part to be internally forced as a proxy request and immediately (i.e., rewriting rule processing stops here) put through the proxy module. You have to make sure that the substitution string is a valid URI (e.g., typically starting with http://hostname) which can be handled by the Apache proxy module. If not you get an error from the proxy module. Use this flag to achieve a more powerful implementation of the ProxyPass directive, to map some remote stuff into the namespace of the local server.

    Notice: To use this functionality make sure you have the proxy module compiled into your Apache server program. If you don't know please check whether mod_proxy.c is part of the ``httpd -l'' output. If yes, this functionality is available to mod_rewrite. If not, then you first have to rebuild the ``httpd'' program with mod_proxy enabled.

  • 'passthrough|PT' (pass through to next handler)
    This flag forces the rewriting engine to set the uri field of the internal request_rec structure to the value of the filename field. This flag is just a hack to be able to post-process the output of RewriteRule directives by Alias, ScriptAlias, Redirect, etc. directives from other URI-to-filename translators. A trivial example to show the semantics: If you want to rewrite /abc to /def via the rewriting engine of mod_rewrite and then /def to /ghi with mod_alias:

    RewriteRule ^/abc(.*) /def$1 [PT]
    Alias /def /ghi

    If you omit the PT flag then mod_rewrite will do its job fine, i.e., it rewrites uri=/abc/... to filename=/def/... as a full API-compliant URI-to-filename translator should do. Then mod_alias comes and tries to do a URI-to-filename transition which will not work.

    Note: You have to use this flag if you want to intermix directives of different modules which contain URL-to-filename translators. The typical example is the use of mod_alias and mod_rewrite..

  • 'qsappend|QSA' (query string append)
    This flag forces the rewriting engine to append a query string part in the substitution string to the existing one instead of replacing it. Use this when you want to add more data to the query string via a rewrite rule.
  • 'redirect|R [=code]' (force redirect)
    Prefix Substitution with http://thishost[:thisport]/ (which makes the new URL a URI) to force a external redirection. If no code is given a HTTP response of 302 (MOVED TEMPORARILY) is used. If you want to use other response codes in the range 300-400 just specify them as a number or use one of the following symbolic names: temp (default), permanent, seeother. Use it for rules which should canonicalize the URL and give it back to the client, e.g., translate ``/~'' into ``/u/'' or always append a slash to /u/user, etc.

    Note: When you use this flag, make sure that the substitution field is a valid URL! If not, you are redirecting to an invalid location! And remember that this flag itself only prefixes the URL with http://thishost[:thisport]/, rewriting continues. Usually you also want to stop and do the redirection immediately. To stop the rewriting you also have to provide the 'L' flag.

  • 'skip|S=num' (skip next rule(s))
    This flag forces the rewriting engine to skip the next num rules in sequence when the current rule matches. Use this to make pseudo if-then-else constructs: The last rule of the then-clause becomes skip=N where N is the number of rules in the else-clause. (This is not the same as the 'chain|C' flag!)
  • 'type|T=MIME-type' (force MIME type)
    Force the MIME-type of the target file to be MIME-type. For instance, this can be used to setup the content-type based on some conditions. For example, the following snippet allows .php files to be displayed by mod_php if they are called with the .phps extension:

    RewriteRule ^(.+\.php)s$ $1 [T=application/x-httpd-php-source]

Note

Never forget that Pattern is applied to a complete URL in per-server configuration files. But in per-directory configuration files, the per-directory prefix (which always is the same for a specific directory!) is automatically removed for the pattern matching and automatically added after the substitution has been done. This feature is essential for many sorts of rewriting, because without this prefix stripping you have to match the parent directory which is not always possible.

There is one exception: If a substitution string starts with ``http://'' then the directory prefix will not be added and an external redirect or proxy throughput (if flag P is used!) is forced!

Note

To enable the rewriting engine for per-directory configuration files you need to set ``RewriteEngine On'' in these files and ``Options FollowSymLinks'' must be enabled. If your administrator has disabled override of FollowSymLinks for a user's directory, then you cannot use the rewriting engine. This restriction is needed for security reasons.

Here are all possible substitution combinations and their meanings:

Inside per-server configuration (httpd.conf)
for request ``GET /somepath/pathinfo'':

Given Rule                                      Resulting Substitution
----------------------------------------------  ----------------------------------
^/somepath(.*) otherpath$1                      not supported, because invalid!

^/somepath(.*) otherpath$1  [R]                 not supported, because invalid!

^/somepath(.*) otherpath$1  [P]                 not supported, because invalid!
----------------------------------------------  ----------------------------------
^/somepath(.*) /otherpath$1                     /otherpath/pathinfo

^/somepath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
                                                via external redirection

^/somepath(.*) /otherpath$1 [P]                 not supported, because silly!
----------------------------------------------  ----------------------------------
^/somepath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^/somepath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
                                                via external redirection

^/somepath(.*) http://thishost/otherpath$1 [P]  not supported, because silly!
----------------------------------------------  ----------------------------------
^/somepath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
                                                via external redirection

^/somepath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
                                                via external redirection
                                                (the [R] flag is redundant)

^/somepath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
                                                via internal proxy

Inside per-directory configuration for /somepath
(i.e., file .htaccess in dir /physical/path/to/somepath containing RewriteBase /somepath)
for request ``GET /somepath/localpath/pathinfo'':

Given Rule                                      Resulting Substitution
----------------------------------------------  ----------------------------------
^localpath(.*) otherpath$1                      /somepath/otherpath/pathinfo

^localpath(.*) otherpath$1  [R]                 http://thishost/somepath/otherpath/pathinfo
                                                via external redirection

^localpath(.*) otherpath$1  [P]                 not supported, because silly!
----------------------------------------------  ----------------------------------
^localpath(.*) /otherpath$1                     /otherpath/pathinfo

^localpath(.*) /otherpath$1 [R]                 http://thishost/otherpath/pathinfo
                                                via external redirection

^localpath(.*) /otherpath$1 [P]                 not supported, because silly!
----------------------------------------------  ----------------------------------
^localpath(.*) http://thishost/otherpath$1      /otherpath/pathinfo

^localpath(.*) http://thishost/otherpath$1 [R]  http://thishost/otherpath/pathinfo
                                                via external redirection

^localpath(.*) http://thishost/otherpath$1 [P]  not supported, because silly!
----------------------------------------------  ----------------------------------
^localpath(.*) http://otherhost/otherpath$1     http://otherhost/otherpath/pathinfo
                                                via external redirection

^localpath(.*) http://otherhost/otherpath$1 [R] http://otherhost/otherpath/pathinfo
                                                via external redirection
                                                (the [R] flag is redundant)

^localpath(.*) http://otherhost/otherpath$1 [P] http://otherhost/otherpath/pathinfo
                                                via internal proxy

Example:

We want to rewrite URLs of the form

/ Language /~ Realname /.../ File

into

/u/ Username /.../ File . Language

We take the rewrite mapfile from above and save it under /path/to/file/map.txt. Then we only have to add the following lines to the Apache server configuration file:

RewriteLog   /path/to/file/rewrite.log
RewriteMap   real-to-user               txt:/path/to/file/map.txt
RewriteRule  ^/([^/]+)/~([^/]+)/(.*)$   /u/${real-to-user:$2|nobody}/$3.$1


mod_setenvif - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_setenvif

설명: | 요청의 성격에 따라 환경변수 설정을 변경한다
상태: | Base
모듈명: | setenvif_module
소스파일: | mod_setenvif.c

요약

mod_setenvif 모듈은 요청의 성격이 정규표현식에 해당하는지 여부로 환경변수를 설정한다. 서버의 다른 부분이 행동을 결정할때 이 환경변수를 사용할 수 있다.

설정파일에 나오는 순서대로 지시어를 처리한다. 그래서 브라우저가 MSIE가 아니라 mozilla인 경우 netscape를 설정하는 아래 예와 같이 여러 지시어를 함께 사용할 수 있다.

BrowserMatch ^Mozilla netscape
BrowserMatch MSIE !netscape

참고

  • 아파치의 환경변수

BrowserMatch 지시어

설명: | HTTP User-Agent에 따라 환경변수를 설정한다
문법: | BrowserMatch regex [!]env-variable[=value] [[!]env-variable[=value]] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_setenvif

BrowserMatch는 SetEnvIf 지시어의 특별한 경우로, HTTP 요청 헤더 User-Agent에 따라 환경변수를 설정한다. 다음 두 줄은 같다:

BrowserMatchNoCase Robot is_a_robot
SetEnvIfNoCase User-Agent Robot is_a_robot

추가 예제:

BrowserMatch ^Mozilla forms jpeg=yes browser=netscape
BrowserMatch "^Mozilla/[2-3]" tables agif frames javascript
BrowserMatch MSIE !javascript

BrowserMatchNoCase 지시어

설명: | 대소문자를 구별하지않고 User-Agent에 따라 환경변수를 설정한다
문법: | BrowserMatchNoCase regex [!]env-variable[=value] [[!]env-variable[=value]] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_setenvif
지원: | 아파치 1.2 이상 (아파치 1.2에서 이 지시어는 현재 없어진 mod_browser 모듈에 있었다)

BrowserMatchNoCase 지시어는 BrowserMatch 지시어와 의미상 같다. 그러나 이 지시어는 대소문자를 구별하지않는다. 예를 들어:

BrowserMatchNoCase mac platform=macintosh
BrowserMatchNoCase win platform=windows

BrowserMatch와 BrowserMatchNoCase 지시어는 SetEnvIf와 SetEnvIfNoCase 지시어의 특별한 경우다. 다음 주 줄은 같다:

BrowserMatchNoCase Robot is_a_robot
SetEnvIfNoCase User-Agent Robot is_a_robot

SetEnvIf 지시어

설명: | 요청의 성질에 따라 환경변수를 설정한다
문법: | SetEnvIf attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_setenvif

SetEnvIf 지시어는 요청의 성질에 따라 환경변수를 정의한다. 첫번째 아규먼트 attribute는 다음 세가지중 하나다:

  1. HTTP 요청 헤더 (더 자세한 정보는 RFC2616 참고); 예를 들어: Host, User-Agent, Referer, Accept-Language. 정규표현식을 사용하여 여러 요청 헤더를 지칭할 수 있다.
  2. 요청의 다음 성질중 하나:
    • Remote_Host - (있다면) 요청하는 클라이언트의 호스트명
    • Remote_Addr - 요청하는 클라이언트의 IP 주소
    • Server_Addr - 요청을 받는 서버의 IP 주소 (2.0.43 버전 이후에만)
    • Request_Method - 사용한 메써드 이름 (GET, POST, 등등)
    • Request_Protocol - 요청의 프로토콜 이름과 버전 (예를 들어, "HTTP/0.9", "HTTP/1.1", 등.)
    • Request_URI - HTTP 요청에서 요청한 자원 -- 일반적으로 URL에서 질의문자열을 제외한 스킴(scheme)과 호스트 이후 부분
  3. 요청과 연관된 환경변수 이름. 그래서 SetEnvIf 지시어는 이전 지시어의 결과를 검사할 수 있다. 이전에 SetEnvIf[NoCase] 지시어로 정의한 환경변수만을 검사할 수 있다. '이전'이란 (서버전역과 같이) 더 넓은 영역 혹은 지시어의 현재 영역 이전을 뜻한다. 요청 성질이 아니고 정규표현식이 아닌 attribute는 환경변수로 취급한다.

두번째 아규먼트는 (regex) Perl 호환 정규표현식이다. 이는 POSIX.2 egrep의 정규표현식과 비슷하다. regex가 attribute에 대응하면 나머지 아규먼트를 처리한다.

나머지 아규먼트는 설정할 변수명과 (선택적인) 설정값들이다. 다음과 같은 형식이다

  1. varname, 혹은
  2. !varname, 혹은
  3. varname=value

첫번째 형태는 값으로 "1"을 사용한다. 두번째 형태는 변수가 이미 정의된 경우 변수를 제거하고, 세번째는 변수의 값으로 value를 설정한다. 아파치 2.0.51부터 value에 있는 $1..$9를 regex의 괄호친 하위표현식으로 대체한다.

예제:

SetEnvIf Request_URI "\.gif$" object_is_image=gif
SetEnvIf Request_URI "\.jpg$" object_is_image=jpg
SetEnvIf Request_URI "\.xbm$" object_is_image=xbm
:
SetEnvIf Referer www\.mydomain\.com intra_site_referral
:
SetEnvIf object_is_image xbm XBIT_PROCESSING=1
:
SetEnvIf ^TS* ^[a-z].* HAVE_TS

처음 세 줄은 이미지 파일을 요청한 경우 환경변수 object_is_image를 설정한다. 네번째 줄은 페이지를 www.mydomain.com 웹사이트에서 참조한 경우 intra_site_referral을 설정한다.

마지막 예는 요청에 이름에 "TS"로 시작하고 값이 [a-z] 중 하나로 시작하는 헤더가 있는 경우 환경변수 HAVE_TS를 설정한다.

참고

  • 아파치의 환경변수에 더 많은 예제가 있다.

SetEnvIfNoCase 지시어

설명: | 대소문자를 구별하지않고 요청의 성질에 따라 환경변수를 설정한다
문법: | SetEnvIfNoCase attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ...
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | FileInfo
상태: | Base
모듈: | mod_setenvif
지원: | 아파치 1.3 이후

SetEnvIfNoCase는 의미상 SetEnvIf 지시어와 같지만, 대소문자를 구별하지않고 정규표현식을 찾는다. 예를 들어:

SetEnvIfNoCase Host Apache\.Org site=apache

이 경우 HTTP 요청 헤더 Host:가 Apache.Org, apache.org 등을 포함하면 site 환경변수를 "apache"로 설정한다.


mod_so - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_so

설명: | 시작할때 혹은 재시작할때 실행가능한 코드와 모듈을 서버로 읽어들인다
상태: | Extension
모듈명: | so_module
소스파일: | mod_so.c
지원: | 윈도우즈에서 (항상 포함하는) Base 모듈이다.

요약

몇몇 운영체제에서 아파치는 동적공유객체 (DSO) 기술을 사용하여 서버를 다시 컴파일하지 않고도 실행중에 모듈을 읽어들일 수 있다.

읽어들일 코드는, 유닉스에서는 (.so 확장자를 가진) 일반적인 공유객체파일이고, 윈도우즈에서는 .so 혹은 .dll 확장자를 가진다.

경고

아파치 1.3 모듈을 아파치 2.0에서 사용할 수 없다. 아파치 2.0이 동적으로 읽어들이거나 아파치와 같이 컴파일하려면 모듈을 수정해야 한다.

윈도우즈에서 읽어들일 모듈 만들기

주의

윈도우즈의 모듈명 형식은 아파치 1.3.15와 2.0에서 변경되었다. 모듈명은 이제 mod_foo.so식이다.

mod_so는 아직도 ApacheModuleFoo.dll 식의 모듈을 읽어들일 수 있지만, 새로운 이름 규칙을 선호한다. 모듈을 2.0에 맞게 수정한다면 이름을 2.0 규칙에 알맞게 고치길 바란다.

아파치 모듈 API는 유닉스 버전이거나 윈도우즈 버전이거나 같다. 몇몇 API는 윈도우즈에 없는 유닉스 구조에 의존하기때문에 사용할 수 없지만, 유닉스에서 실행되는 많은 모듈을 수정없이 혹은 조금 수정하여 윈도우즈에서 사용할 수 있다.

모듈은 두가지 방법으로 서버에 추가할 수 있다. 유닉스에서는 모듈을 서버와 같이 컴파일할 수 있다. 윈도우즈용 아파치는 유닉스와 달리 Configure 프로그램이 없기때문에 모듈의 소스파일을 ApacheCore 프로젝트 파일에 추가하고, 심볼을 os\win32\modules.c 파일에 추가해야 한다.

두번째 방법은 모듈을 서버가 LoadModule 지시어를 사용하여 시작할때 읽어들일 수 있는 공유라이브러리 DLL로 만드는 것이다. 이 모듈 DLL을 배포하면 서버를 재컴파일하지 않고 어떤 윈도우즈용 아파치에서도 모듈을 사용할 수 있다.

모듈 DLL을 만들기위해서는 모듈의 소스파일을 조금 수정해야 한다. DLL은 module record를 export해야 한다. (아래 참고) 이를 위해 모듈의 module record 정의에 (아파치 헤더파일에 정의된) AP_MODULE_DECLARE_DATA를 추가한다. 예를 들어, 다음과 같은 모듈이 있다면:

module foo_module;

다음과 같이 수정한다:

module AP_MODULE_DECLARE_DATA foo_module;

이 부분은 윈도우즈에서만 사용하기때문에 변경하여도 유닉스에서 소스를 그대로 사용할 수 있다. 또, .DEF 파일에 익숙하다면 대신 이 파일을 사용하여 module record를 export할 수도 있다.

이제 모듈을 포함한 DLL을 만든다. 이를 공유라이브러리 libhttpd.dll을 컴파일할때 만든 libhttpd.lib export 라이브러리와 링크한다. 아파치 헤더파일을 올바로 찾도록 컴파일러 설정을 수정해야 할지도 모른다. 서버의 modules 디렉토리에서 이 라이브러리를 찾을 수 있다. 컴파일환경을 올바로 설정하기위해 기존 모듈의 .dsp 파일을 가져다 쓰거나 직접 만든 .dsp와 컴파일러/링커 옵션을 비교하는 것이 좋다.

이제 모듈을 DLL로 만든다. 이것을 서버의 modules 디렉토리에 두고, LoadModule 지시어를 사용하여 읽어들인다.

LoadFile 지시어

설명: | 지정한 목적파일이나 라이브러리를 읽어들인다
문법: | LoadFile filename [filename] ...
사용장소: | 주서버설정
상태: | Extension
모듈: | mod_so

LoadFile 지시어는 서버가 시작하거나 재시작할때 지정한 목적파일이나 라이브러리를 읽어들인다(link in). 이 지시어는 어떤 모듈이 동작하기위해 필요한 코드를 추가로 읽어들일때 사용한다. Filename은 절대경로이거나 ServerRoot에 대한 상대경로이다.

예를 들어:

LoadFile libexec/libxmlparse.so

LoadModule 지시어

설명: | 목적파일이나 라이브러리를 읽어들이고, 사용가능한 모듈 목록에 추가한다
문법: | LoadModule module filename
사용장소: | 주서버설정
상태: | Extension
모듈: | mod_so

LoadModule 지시어는 목적파일 혹은 라이브러리 filename을 읽어들이고, 사용가능한 모듈 목록에 module이라는 모듈 구조체를 추가한다. Module은 파일의 module 자료형 외부변수명이며, 모듈 문서의 모듈명에 나온다. 예를 들면:

LoadModule status_module modules/mod_status.so

ServerRoot의 modules 하위디렉토리에서 지정한 모듈을 읽어들인다.


mod_speling - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_speling

설명: | 사용자가 대소문자를 잘못 사용하거나 맞춤법이 틀리는 것을 한번까지 허용하여 잘못된 URL을 고치려고 시도한다
상태: | Extension
모듈명: | speling_module
소스파일: | mod_speling.c

요약

종종 맞춤법이 틀리거나 대소문자를 잘못 사용하여 아파치가 문서 요청을 서비스할 수 없는 경우가 있다. 이 모듈은 다른 모든 모듈들이 포기한 요청에 해당하는 문서를 찾는다. 모듈은 요청한 디렉토리 안에 있는 모든 문서를 요청한 문서이름과 대소문자 구별없이 (문자 첨가 / 생략 / 교체 혹은 잘못된 문자 ) 맞춤법이 한번까지 틀려도 봐주며 비교한다. 이런 방법으로 문서목록을 만든다.

디렉토리를 살펴본 후에,

  • 문서를 찾지못하면, 아파치는 일반적인 "document not found (문서를 찾을 수 없음)" 오류를 반환한다.
  • 요청에 "거의" 일치하는 문서를 하나만 찾은 경우, 그 문서로 리다이렉션 응답을 한다.
  • 근접한 문서를 여러개 찾은 경우, 클라이언트가 올바른 문서를 선택할 수 있도록 문서목록을 보낸다.

CheckSpelling 지시어

설명: | 맞춤법 모듈을 사용한다
문법: | CheckSpelling on|off
기본값: | CheckSpelling Off
사용장소: | 주서버설정, 가상호스트, directory, .htaccess
Override 옵션: | Options
상태: | Extension
모듈: | mod_speling
지원: | 아파치 1.1은 CheckSpelling을 별도로 제공하였지만, 대소문자가 다른 경우만을 처리할 수 있었다. 아파치 1.3에서 아파치 배포본의 일부가 되었다. 아파치 1.3.2 이전에는 CheckSpelling 지시어를 "주서버"와 "가상호스트" 사용장소에서만 사용할 수 있었다.

이 지시어는 맞춤법 모듈의 사용여부를 결정한다. 사용한다면 다음을 주의하라

  • 맞춤법 교정을 위해 디렉토리를 살펴보는 작업을 동시에 여러번 할 경우 서버 성능에 영향을 준다.
  • 문서중에 맞춤법 "교정"으로 우연히 보여질 수 있는 기밀문서가 없어야 한다.
  • 모듈은 파일명과 디렉토리명만을 교정할 수 있으며, (http://my.host/~apahce/와 같이) 맞춤법이 틀린 사용자명을 교정하지 못한다.
  • 맞춤법 교정은 존재하는 파일에만 적용된다. 그래서 <Location /status>에 대한 요청을 내용협상을 거친 "/stats.html" 파일로 오인할 수 있다.


mod_ssl - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_ssl

Description: | Strong cryptography using the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols
Status: | Extension
Module Identifier: | ssl_module
Source File: | mod_ssl.c

Summary

This module provides SSL v2/v3 and TLS v1 support for the Apache HTTP Server. It was contributed by Ralf S. Engeschall based on his mod_ssl project and originally derived from work by Ben Laurie.

This module relies on OpenSSL to provide the cryptography engine.

Further details, discussion, and examples are provided in the SSL documentation.

Environment Variables

This module provides a lot of SSL information as additional environment variables to the SSI and CGI namespace. The generated variables are listed in the table below. For backward compatibility the information can be made available under different names, too. Look in the Compatibility chapter for details on the compatibility variables.

Variable Name: | Value Type: | Description:
HTTPS | flag | HTTPS is being used.
SSL_PROTOCOL | string | The SSL protocol version (SSLv2, SSLv3, TLSv1)
SSL_SESSION_ID | string | The hex-encoded SSL session id
SSL_CIPHER | string | The cipher specification name
SSL_CIPHER_EXPORT | string | true if cipher is an export cipher
SSL_CIPHER_USEKEYSIZE | number | Number of cipher bits (actually used)
SSL_CIPHER_ALGKEYSIZE | number | Number of cipher bits (possible)
SSL_VERSION_INTERFACE | string | The mod_ssl program version
SSL_VERSION_LIBRARY | string | The OpenSSL program version
SSL_CLIENT_M_VERSION | string | The version of the client certificate
SSL_CLIENT_M_SERIAL | string | The serial of the client certificate
SSL_CLIENT_S_DN | string | Subject DN in client's certificate
SSL_CLIENT_S_DN_x509 | string | Component of client's Subject DN
SSL_CLIENT_I_DN | string | Issuer DN of client's certificate
SSL_CLIENT_I_DN_x509 | string | Component of client's Issuer DN
SSL_CLIENT_V_START | string | Validity of client's certificate (start time)
SSL_CLIENT_V_END | string | Validity of client's certificate (end time)
SSL_CLIENT_A_SIG | string | Algorithm used for the signature of client's certificate
SSL_CLIENT_A_KEY | string | Algorithm used for the public key of client's certificate
SSL_CLIENT_CERT | string | PEM-encoded client certificate
SSL_CLIENT_CERT_CHAIN n | string | PEM-encoded certificates in client certificate chain
SSL_CLIENT_VERIFY | string | NONE, SUCCESS, GENEROUS or FAILED:reason
SSL_SERVER_M_VERSION | string | The version of the server certificate
SSL_SERVER_M_SERIAL | string | The serial of the server certificate
SSL_SERVER_S_DN | string | Subject DN in server's certificate
SSL_SERVER_S_DN_x509 | string | Component of server's Subject DN
SSL_SERVER_I_DN | string | Issuer DN of server's certificate
SSL_SERVER_I_DN_x509 | string | Component of server's Issuer DN
SSL_SERVER_V_START | string | Validity of server's certificate (start time)
SSL_SERVER_V_END | string | Validity of server's certificate (end time)
SSL_SERVER_A_SIG | string | Algorithm used for the signature of server's certificate
SSL_SERVER_A_KEY | string | Algorithm used for the public key of server's certificate
SSL_SERVER_CERT | string | PEM-encoded server certificate

[ where x509 is a component of a X.509 DN: C,ST,L,O,OU,CN,T,I,G,S,D,UID,Email ]

Custom Log Formats

When mod_ssl is built into Apache or at least loaded (under DSO situation) additional functions exist for the Custom Log Format of mod_log_config. First there is an additional ``%{varname}x'' eXtension format function which can be used to expand any variables provided by any module, especially those provided by mod_ssl which can you find in the above table.

For backward compatibility there is additionally a special ``%{name}c'' cryptography format function provided. Information about this function is provided in the Compatibility chapter.

Example:

CustomLog logs/ssl_request_log \ "%t %h %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %b"

SSLCACertificateFile Directive

Description: | File of concatenated PEM-encoded CA Certificates for Client Auth
Syntax: | SSLCACertificateFile file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the all-in-one file where you can assemble the Certificates of Certification Authorities (CA) whose clients you deal with. These are used for Client Authentication. Such a file is simply the concatenation of the various PEM-encoded Certificate files, in order of preference. This can be used alternatively and/or additionally to SSLCACertificatePath.

Example

SSLCACertificateFile /usr/local/apache2/conf/ssl.crt/ca-bundle-client.crt

SSLCACertificatePath Directive

Description: | Directory of PEM-encoded CA Certificates for Client Auth
Syntax: | SSLCACertificatePath directory-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the directory where you keep the Certificates of Certification Authorities (CAs) whose clients you deal with. These are used to verify the client certificate on Client Authentication.

The files in this directory have to be PEM-encoded and are accessed through hash filenames. So usually you can't just place the Certificate files there: you also have to create symbolic links named hash-value.N. And you should always make sure this directory contains the appropriate symbolic links. Use the Makefile which comes with mod_ssl to accomplish this task.

Example

SSLCACertificatePath /usr/local/apache2/conf/ssl.crt/

SSLCARevocationFile Directive

Description: | File of concatenated PEM-encoded CA CRLs for Client Auth
Syntax: | SSLCARevocationFile file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the all-in-one file where you can assemble the Certificate Revocation Lists (CRL) of Certification Authorities (CA) whose clients you deal with. These are used for Client Authentication. Such a file is simply the concatenation of the various PEM-encoded CRL files, in order of preference. This can be used alternatively and/or additionally to SSLCARevocationPath.

Example

SSLCARevocationFile /usr/local/apache2/conf/ssl.crl/ca-bundle-client.crl

SSLCARevocationPath Directive

Description: | Directory of PEM-encoded CA CRLs for Client Auth
Syntax: | SSLCARevocationPath directory-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the directory where you keep the Certificate Revocation Lists (CRL) of Certification Authorities (CAs) whose clients you deal with. These are used to revoke the client certificate on Client Authentication.

The files in this directory have to be PEM-encoded and are accessed through hash filenames. So usually you have not only to place the CRL files there. Additionally you have to create symbolic links named hash-value.rN. And you should always make sure this directory contains the appropriate symbolic links. Use the Makefile which comes with mod_ssl to accomplish this task.

Example

SSLCARevocationPath /usr/local/apache2/conf/ssl.crl/

SSLCertificateChainFile Directive

Description: | File of PEM-encoded Server CA Certificates
Syntax: | SSLCertificateChainFile file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the optional all-in-one file where you can assemble the certificates of Certification Authorities (CA) which form the certificate chain of the server certificate. This starts with the issuing CA certificate of of the server certificate and can range up to the root CA certificate. Such a file is simply the concatenation of the various PEM-encoded CA Certificate files, usually in certificate chain order.

This should be used alternatively and/or additionally to SSLCACertificatePath for explicitly constructing the server certificate chain which is sent to the browser in addition to the server certificate. It is especially useful to avoid conflicts with CA certificates when using client authentication. Because although placing a CA certificate of the server certificate chain into SSLCACertificatePath has the same effect for the certificate chain construction, it has the side-effect that client certificates issued by this same CA certificate are also accepted on client authentication. That's usually not one expect.

But be careful: Providing the certificate chain works only if you are using a single (either RSA or DSA) based server certificate. If you are using a coupled RSA+DSA certificate pair, this will work only if actually both certificates use the same certificate chain. Else the browsers will be confused in this situation.

Example

SSLCertificateChainFile /usr/local/apache2/conf/ssl.crt/ca.crt

SSLCertificateFile Directive

Description: | Server PEM-encoded X.509 Certificate file
Syntax: | SSLCertificateFile file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive points to the PEM-encoded Certificate file for the server and optionally also to the corresponding RSA or DSA Private Key file for it (contained in the same file). If the contained Private Key is encrypted the Pass Phrase dialog is forced at startup time. This directive can be used up to two times (referencing different filenames) when both a RSA and a DSA based server certificate is used in parallel.

Example

SSLCertificateFile /usr/local/apache2/conf/ssl.crt/server.crt

SSLCertificateKeyFile Directive

Description: | Server PEM-encoded Private Key file
Syntax: | SSLCertificateKeyFile file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive points to the PEM-encoded Private Key file for the server. If the Private Key is not combined with the Certificate in the SSLCertificateFile, use this additional directive to point to the file with the stand-alone Private Key. When SSLCertificateFile is used and the file contains both the Certificate and the Private Key this directive need not be used. But we strongly discourage this practice. Instead we recommend you to separate the Certificate and the Private Key. If the contained Private Key is encrypted, the Pass Phrase dialog is forced at startup time. This directive can be used up to two times (referencing different filenames) when both a RSA and a DSA based private key is used in parallel.

Example

SSLCertificateKeyFile /usr/local/apache2/conf/ssl.key/server.key

SSLCipherSuite Directive

Description: | Cipher Suite available for negotiation in SSL handshake
Syntax: | SSLCipherSuite cipher-spec
Default: | SSLCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
Context: | server config, virtual host, directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl

This complex directive uses a colon-separated cipher-spec string consisting of OpenSSL cipher specifications to configure the Cipher Suite the client is permitted to negotiate in the SSL handshake phase. Notice that this directive can be used both in per-server and per-directory context. In per-server context it applies to the standard SSL handshake when a connection is established. In per-directory context it forces a SSL renegotation with the reconfigured Cipher Suite after the HTTP request was read but before the HTTP response is sent.

An SSL cipher specification in cipher-spec is composed of 4 major attributes plus a few extra minor ones:

  • Key Exchange Algorithm:
    RSA or Diffie-Hellman variants.
  • Authentication Algorithm:
    RSA, Diffie-Hellman, DSS or none.
  • Cipher/Encryption Algorithm:
    DES, Triple-DES, RC4, RC2, IDEA or none.
  • MAC Digest Algorithm:
    MD5, SHA or SHA1.

An SSL cipher can also be an export cipher and is either a SSLv2 or SSLv3/TLSv1 cipher (here TLSv1 is equivalent to SSLv3). To specify which ciphers to use, one can either specify all the Ciphers, one at a time, or use aliases to specify the preference and order for the ciphers (see Table 1).

Tag | Description
Key Exchange Algorithm:
kRSA | RSA key exchange
kDHr | Diffie-Hellman key exchange with RSA key
kDHd | Diffie-Hellman key exchange with DSA key
kEDH | Ephemeral (temp.key) Diffie-Hellman key exchange (no cert)
Authentication Algorithm:
aNULL | No authentication
aRSA | RSA authentication
aDSS | DSS authentication
aDH | Diffie-Hellman authentication
Cipher Encoding Algorithm:
eNULL | No encoding
DES | DES encoding
3DES | Triple-DES encoding
RC4 | RC4 encoding
RC2 | RC2 encoding
IDEA | IDEA encoding
MAC Digest Algorithm:
MD5 | MD5 hash function
SHA1 | SHA1 hash function
SHA | SHA hash function
Aliases:
SSLv2 | all SSL version 2.0 ciphers
SSLv3 | all SSL version 3.0 ciphers
TLSv1 | all TLS version 1.0 ciphers
EXP | all export ciphers
EXPORT40 | all 40-bit export ciphers only
EXPORT56 | all 56-bit export ciphers only
LOW | all low strength ciphers (no export, single DES)
MEDIUM | all ciphers with 128 bit encryption
HIGH | all ciphers using Triple-DES
RSA | all ciphers using RSA key exchange
DH | all ciphers using Diffie-Hellman key exchange
EDH | all ciphers using Ephemeral Diffie-Hellman key exchange
ADH | all ciphers using Anonymous Diffie-Hellman key exchange
DSS | all ciphers using DSS authentication
NULL | all ciphers using no encryption

Now where this becomes interesting is that these can be put together to specify the order and ciphers you wish to use. To speed this up there are also aliases (SSLv2, SSLv3, TLSv1, EXP, LOW, MEDIUM, HIGH) for certain groups of ciphers. These tags can be joined together with prefixes to form the cipher-spec. Available prefixes are:

  • none: add cipher to list
  • +: add ciphers to list and pull them to current location in list
  • -: remove cipher from list (can be added later again)
  • !: kill cipher from list completely (can not be added later again)

A simpler way to look at all of this is to use the ``openssl ciphers -v'' command which provides a nice way to successively create the correct cipher-spec string. The default cipher-spec string is ``ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP'' which means the following: first, remove from consideration any ciphers that do not authenticate, i.e. for SSL only the Anonymous Diffie-Hellman ciphers. Next, use ciphers using RC4 and RSA. Next include the high, medium and then the low security ciphers. Finally pull all SSLv2 and export ciphers to the end of the list.

$ openssl ciphers -v 'ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP'
NULL-SHA                SSLv3 Kx=RSA      Au=RSA  Enc=None      Mac=SHA1
NULL-MD5                SSLv3 Kx=RSA      Au=RSA  Enc=None      Mac=MD5
EDH-RSA-DES-CBC3-SHA    SSLv3 Kx=DH       Au=RSA  Enc=3DES(168) Mac=SHA1
...                     ...               ...     ...           ...
EXP-RC4-MD5             SSLv3 Kx=RSA(512) Au=RSA  Enc=RC4(40)   Mac=MD5  export
EXP-RC2-CBC-MD5         SSLv2 Kx=RSA(512) Au=RSA  Enc=RC2(40)   Mac=MD5  export
EXP-RC4-MD5             SSLv2 Kx=RSA(512) Au=RSA  Enc=RC4(40)   Mac=MD5  export

The complete list of particular RSA & DH ciphers for SSL is given in Table 2.

Example

SSLCipherSuite RSA:!EXP:!NULL:+HIGH:+MEDIUM:-LOW

Cipher-Tag | Protocol | Key Ex. | Auth. | Enc. | MAC | Type
RSA Ciphers:
DES-CBC3-SHA | SSLv3 | RSA | RSA | 3DES(168) | SHA1 |
DES-CBC3-MD5 | SSLv2 | RSA | RSA | 3DES(168) | MD5 |
IDEA-CBC-SHA | SSLv3 | RSA | RSA | IDEA(128) | SHA1 |
RC4-SHA | SSLv3 | RSA | RSA | RC4(128) | SHA1 |
RC4-MD5 | SSLv3 | RSA | RSA | RC4(128) | MD5 |
IDEA-CBC-MD5 | SSLv2 | RSA | RSA | IDEA(128) | MD5 |
RC2-CBC-MD5 | SSLv2 | RSA | RSA | RC2(128) | MD5 |
RC4-MD5 | SSLv2 | RSA | RSA | RC4(128) | MD5 |
DES-CBC-SHA | SSLv3 | RSA | RSA | DES(56) | SHA1 |
RC4-64-MD5 | SSLv2 | RSA | RSA | RC4(64) | MD5 |
DES-CBC-MD5 | SSLv2 | RSA | RSA | DES(56) | MD5 |
EXP-DES-CBC-SHA | SSLv3 | RSA(512) | RSA | DES(40) | SHA1 | export
EXP-RC2-CBC-MD5 | SSLv3 | RSA(512) | RSA | RC2(40) | MD5 | export
EXP-RC4-MD5 | SSLv3 | RSA(512) | RSA | RC4(40) | MD5 | export
EXP-RC2-CBC-MD5 | SSLv2 | RSA(512) | RSA | RC2(40) | MD5 | export
EXP-RC4-MD5 | SSLv2 | RSA(512) | RSA | RC4(40) | MD5 | export
NULL-SHA | SSLv3 | RSA | RSA | None | SHA1 |
NULL-MD5 | SSLv3 | RSA | RSA | None | MD5 |
Diffie-Hellman Ciphers:
ADH-DES-CBC3-SHA | SSLv3 | DH | None | 3DES(168) | SHA1 |
ADH-DES-CBC-SHA | SSLv3 | DH | None | DES(56) | SHA1 |
ADH-RC4-MD5 | SSLv3 | DH | None | RC4(128) | MD5 |
EDH-RSA-DES-CBC3-SHA | SSLv3 | DH | RSA | 3DES(168) | SHA1 |
EDH-DSS-DES-CBC3-SHA | SSLv3 | DH | DSS | 3DES(168) | SHA1 |
EDH-RSA-DES-CBC-SHA | SSLv3 | DH | RSA | DES(56) | SHA1 |
EDH-DSS-DES-CBC-SHA | SSLv3 | DH | DSS | DES(56) | SHA1 |
EXP-EDH-RSA-DES-CBC-SHA | SSLv3 | DH(512) | RSA | DES(40) | SHA1 | export
EXP-EDH-DSS-DES-CBC-SHA | SSLv3 | DH(512) | DSS | DES(40) | SHA1 | export
EXP-ADH-DES-CBC-SHA | SSLv3 | DH(512) | None | DES(40) | SHA1 | export
EXP-ADH-RC4-MD5 | SSLv3 | DH(512) | None | RC4(40) | MD5 | export

SSLEngine Directive

Description: | SSL Engine Operation Switch
Syntax: | SSLEngine on|off
Default: | SSLEngine off
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive toggles the usage of the SSL/TLS Protocol Engine. This is usually used inside a <VirtualHost> section to enable SSL/TLS for a particular virtual host. By default the SSL/TLS Protocol Engine is disabled for both the main server and all configured virtual hosts.

Example

<VirtualHost _default_:443>
SSLEngine on
...
</VirtualHost>

SSLMutex Directive

Description: | Semaphore for internal mutual exclusion of operations
Syntax: | SSLMutex type
Default: | SSLMutex none
Context: | server config
Status: | Extension
Module: | mod_ssl

This configures the SSL engine's semaphore (aka. lock) which is used for mutual exclusion of operations which have to be done in a synchronized way between the pre-forked Apache server processes. This directive can only be used in the global server context because it's only useful to have one global mutex. This directive is designed to closely match the AcceptMutex directive

The following Mutex types are available:

  • none | no

    This is the default where no Mutex is used at all. Use it at your own risk. But because currently the Mutex is mainly used for synchronizing write access to the SSL Session Cache you can live without it as long as you accept a sometimes garbled Session Cache. So it's not recommended to leave this the default. Instead configure a real Mutex.

  • posixsem

    This is an elegant Mutex variant where a Posix Semaphore is used when possible. It is only available when the underlying platform and APR supports it.

  • sysvsem

    This is a somewhat elegant Mutex variant where a SystemV IPC Semaphore is used when possible. It is possible to "leak" SysV semaphores if processes crash before the semaphore is removed. It is only available when the underlying platform and APR supports it.

  • sem

    This directive tells the SSL Module to pick the "best" semaphore implementation available to it, choosing between Posix and SystemV IPC, in that order. It is only available when the underlying platform and APR supports at least one of the 2.

  • pthread

    This directive tells the SSL Module to use Posix thread mutexes. It is only available if the underlying platform and APR supports it.

  • fcntl:/path/to/mutex

    This is a portable Mutex variant where a physical (lock-)file and the fcntl() fucntion are used as the Mutex. Always use a local disk filesystem for /path/to/mutex and never a file residing on a NFS- or AFS-filesystem. It is only available when the underlying platform and APR supports it. Note: Internally, the Process ID (PID) of the Apache parent process is automatically appended to /path/to/mutex to make it unique, so you don't have to worry about conflicts yourself. Notice that this type of mutex is not available under the Win32 environment. There you have to use the semaphore mutex.

  • flock:/path/to/mutex

    This is similar to the fcntl:/path/to/mutex method with the exception that the flock() function is used to provide file locking. It is only available when the underlying platform and APR supports it.

  • file:/path/to/mutex

    This directive tells the SSL Module to pick the "best" file locking implementation available to it, choosing between fcntl and flock, in that order. It is only available when the underlying platform and APR supports at least one of the 2.

  • default | yes

    This directive tells the SSL Module to pick the default locking implementation as determined by the platform and APR.

Example

SSLMutex file:/usr/local/apache/logs/ssl_mutex

SSLOptions Directive

Description: | Configure various SSL engine run-time options
Syntax: | SSLOptions [+|-]option ...
Context: | server config, virtual host, directory, .htaccess
Override: | Options
Status: | Extension
Module: | mod_ssl

This directive can be used to control various run-time options on a per-directory basis. Normally, if multiple SSLOptions could apply to a directory, then the most specific one is taken completely; the options are not merged. However if all the options on the SSLOptions directive are preceded by a plus (+) or minus (-) symbol, the options are merged. Any options preceded by a + are added to the options currently in force, and any options preceded by a - are removed from the options currently in force.

The available options are:

  • StdEnvVars

    When this option is enabled, the standard set of SSL related CGI/SSI environment variables are created. This per default is disabled for performance reasons, because the information extraction step is a rather expensive operation. So one usually enables this option for CGI and SSI requests only.

  • CompatEnvVars

    When this option is enabled, additional CGI/SSI environment variables are created for backward compatibility to other Apache SSL solutions. Look in the Compatibility chapter for details on the particular variables generated.

  • ExportCertData

    When this option is enabled, additional CGI/SSI environment variables are created: SSL_SERVER_CERT, SSL_CLIENT_CERT and SSL_CLIENT_CERT_CHAIN n (with n = 0,1,2,..). These contain the PEM-encoded X.509 Certificates of server and client for the current HTTPS connection and can be used by CGI scripts for deeper Certificate checking. Additionally all other certificates of the client certificate chain are provided, too. This bloats up the environment a little bit which is why you have to use this option to enable it on demand.

  • FakeBasicAuth

    When this option is enabled, the Subject Distinguished Name (DN) of the Client X509 Certificate is translated into a HTTP Basic Authorization username. This means that the standard Apache authentication methods can be used for access control. The user name is just the Subject of the Client's X509 Certificate (can be determined by running OpenSSL's openssl x509 command: openssl x509 -noout -subject -in certificate.crt). Note that no password is obtained from the user. Every entry in the user file needs this password: ``xxj31ZMTZzkVA'', which is the DES-encrypted version of the word `password''. Those who live under MD5-based encryption (for instance under FreeBSD or BSD/OS, etc.) should use the following MD5 hash of the same word: ``$1$OXLyS...$Owx8s2/m9/gfkcRVXzgoE/''.

  • StrictRequire

    This forces forbidden access when SSLRequireSSL or SSLRequire successfully decided that access should be forbidden. Usually the default is that in the case where a ``Satisfy any'' directive is used, and other access restrictions are passed, denial of access due to SSLRequireSSL or SSLRequire is overridden (because that's how the Apache Satisfy mechanism should work.) But for strict access restriction you can use SSLRequireSSL and/or SSLRequire in combination with an ``SSLOptions +StrictRequire''. Then an additional ``Satisfy Any'' has no chance once mod_ssl has decided to deny access.

  • OptRenegotiate

    This enables optimized SSL connection renegotiation handling when SSL directives are used in per-directory context. By default a strict scheme is enabled where every per-directory reconfiguration of SSL parameters causes a full SSL renegotiation handshake. When this option is used mod_ssl tries to avoid unnecessary handshakes by doing more granular (but still safe) parameter checks. Nevertheless these granular checks sometimes maybe not what the user expects, so enable this on a per-directory basis only, please.

Example

SSLOptions +FakeBasicAuth -StrictRequire
<Files ~ "\.(cgi|shtml)$">
SSLOptions +StdEnvVars +CompatEnvVars -ExportCertData
<Files>

SSLPassPhraseDialog Directive

Description: | Type of pass phrase dialog for encrypted private keys
Syntax: | SSLPassPhraseDialog type
Default: | SSLPassPhraseDialog builtin
Context: | server config
Status: | Extension
Module: | mod_ssl

When Apache starts up it has to read the various Certificate (see SSLCertificateFile) and Private Key (see SSLCertificateKeyFile) files of the SSL-enabled virtual servers. Because for security reasons the Private Key files are usually encrypted, mod_ssl needs to query the administrator for a Pass Phrase in order to decrypt those files. This query can be done in two ways which can be configured by type:

  • builtin

    This is the default where an interactive terminal dialog occurs at startup time just before Apache detaches from the terminal. Here the administrator has to manually enter the Pass Phrase for each encrypted Private Key file. Because a lot of SSL-enabled virtual hosts can be configured, the following reuse-scheme is used to minimize the dialog: When a Private Key file is encrypted, all known Pass Phrases (at the beginning there are none, of course) are tried. If one of those known Pass Phrases succeeds no dialog pops up for this particular Private Key file. If none succeeded, another Pass Phrase is queried on the terminal and remembered for the next round (where it perhaps can be reused).

    This scheme allows mod_ssl to be maximally flexible (because for N encrypted Private Key files you can use N different Pass Phrases - but then you have to enter all of them, of course) while minimizing the terminal dialog (i.e. when you use a single Pass Phrase for all N Private Key files this Pass Phrase is queried only once).

  • exec:/path/to/program

    Here an external program is configured which is called at startup for each encrypted Private Key file. It is called with two arguments (the first is of the form ``servername:portnumber'', the second is either ``RSA'' or ``DSA''), which indicate for which server and algorithm it has to print the corresponding Pass Phrase to stdout. The intent is that this external program first runs security checks to make sure that the system is not compromised by an attacker, and only when these checks were passed successfully it provides the Pass Phrase.

    Both these security checks, and the way the Pass Phrase is determined, can be as complex as you like. Mod_ssl just defines the interface: an executable program which provides the Pass Phrase on stdout. Nothing more or less! So, if you're really paranoid about security, here is your interface. Anything else has to be left as an exercise to the administrator, because local security requirements are so different.

    The reuse-algorithm above is used here, too. In other words: The external program is called only once per unique Pass Phrase.

Example:

SSLPassPhraseDialog exec:/usr/local/apache/sbin/pp-filter

SSLProtocol Directive

Description: | Configure usable SSL protocol flavors
Syntax: | SSLProtocol [+|-]protocol ...
Default: | SSLProtocol all
Context: | server config, virtual host
Override: | Options
Status: | Extension
Module: | mod_ssl

This directive can be used to control the SSL protocol flavors mod_ssl should use when establishing its server environment. Clients then can only connect with one of the provided protocols.

The available (case-insensitive) protocols are:

  • SSLv2

    This is the Secure Sockets Layer (SSL) protocol, version 2.0. It is the original SSL protocol as designed by Netscape Corporation.

  • SSLv3

    This is the Secure Sockets Layer (SSL) protocol, version 3.0. It is the successor to SSLv2 and the currently (as of February 1999) de-facto standardized SSL protocol from Netscape Corporation. It's supported by almost all popular browsers.

  • TLSv1

    This is the Transport Layer Security (TLS) protocol, version 1.0. It is the successor to SSLv3 and currently (as of February 1999) still under construction by the Internet Engineering Task Force (IETF). It's still not supported by any popular browsers.

  • All

    This is a shortcut for ``+SSLv2 +SSLv3 +TLSv1'' and a convinient way for enabling all protocols except one when used in combination with the minus sign on a protocol as the example above shows.

Example

# enable SSLv3 and TLSv1, but not SSLv2
SSLProtocol all -SSLv2

SSLProxyCACertificateFile Directive

Description: | File of concatenated PEM-encoded CA Certificates for Remote Server Auth
Syntax: | SSLProxyCACertificateFile file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the all-in-one file where you can assemble the Certificates of Certification Authorities (CA) whose remote servers you deal with. These are used for Remote Server Authentication. Such a file is simply the concatenation of the various PEM-encoded Certificate files, in order of preference. This can be used alternatively and/or additionally to SSLProxyCACertificatePath.

Example

SSLProxyCACertificateFile /usr/local/apache2/conf/ssl.crt/ca-bundle-remote-server.crt

SSLProxyCACertificatePath Directive

Description: | Directory of PEM-encoded CA Certificates for Remote Server Auth
Syntax: | SSLProxyCACertificatePath directory-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the directory where you keep the Certificates of Certification Authorities (CAs) whose remote servers you deal with. These are used to verify the remote server certificate on Remote Server Authentication.

The files in this directory have to be PEM-encoded and are accessed through hash filenames. So usually you can't just place the Certificate files there: you also have to create symbolic links named hash-value.N. And you should always make sure this directory contains the appropriate symbolic links. Use the Makefile which comes with mod_ssl to accomplish this task.

Example

SSLProxyCACertificatePath /usr/local/apache2/conf/ssl.crt/

SSLProxyCARevocationFile Directive

Description: | File of concatenated PEM-encoded CA CRLs for Remote Server Auth
Syntax: | SSLProxyCARevocationFile file-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the all-in-one file where you can assemble the Certificate Revocation Lists (CRL) of Certification Authorities (CA) whose remote servers you deal with. These are used for Remote Server Authentication. Such a file is simply the concatenation of the various PEM-encoded CRL files, in order of preference. This can be used alternatively and/or additionally to SSLProxyCARevocationPath.

Example

SSLProxyCARevocationFile /usr/local/apache2/conf/ssl.crl/ca-bundle-remote-server.crl

SSLProxyCARevocationPath Directive

Description: | Directory of PEM-encoded CA CRLs for Remote Server Auth
Syntax: | SSLProxyCARevocationPath directory-path
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the directory where you keep the Certificate Revocation Lists (CRL) of Certification Authorities (CAs) whose remote servers you deal with. These are used to revoke the remote server certificate on Remote Server Authentication.

The files in this directory have to be PEM-encoded and are accessed through hash filenames. So usually you have not only to place the CRL files there. Additionally you have to create symbolic links named hash-value.rN. And you should always make sure this directory contains the appropriate symbolic links. Use the Makefile which comes with mod_ssl to accomplish this task.

Example

SSLProxyCARevocationPath /usr/local/apache2/conf/ssl.crl/

SSLProxyCipherSuite Directive

Description: | Cipher Suite available for negotiation in SSL proxy handshake
Syntax: | SSLProxyCipherSuite cipher-spec
Default: | SSLProxyCipherSuite ALL:!ADH:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP
Context: | server config, virtual host, directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl

Equivalent to SSLCipherSuite, but for the proxy connection. Please refer to SSLCipherSuite for additional information.

SSLProxyEngine Directive

Description: | SSL Proxy Engine Operation Switch
Syntax: | SSLProxyEngine on|off
Default: | SSLProxyEngine off
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive toggles the usage of the SSL/TLS Protocol Engine for proxy. This is usually used inside a <VirtualHost> section to enable SSL/TLS for proxy usage in a particular virtual host. By default the SSL/TLS Protocol Engine is disabled for proxy image both for the main server and all configured virtual hosts.

Example

<VirtualHost _default_:443>
SSLProxyEngine on
...
</VirtualHost>

SSLProxyMachineCertificateFile Directive

Description: | File of concatenated PEM-encoded client certificates and keys to be used by the proxy
Syntax: | SSLProxyMachineCertificateFile filename
Context: | server config
Override: | Not applicable
Status: | Extension
Module: | mod_ssl

This directive sets the all-in-one file where you keep the certificates and keys used for authentication of the proxy server to remote servers.

This referenced file is simply the concatenation of the various PEM-encoded certificate files, in order of preference. Use this directive alternatively or additionally to SSLProxyMachineCertificatePath.

Currently there is no support for encrypted private keys

Example:

SSLProxyMachineCertificateFile /usr/local/apache2/conf/ssl.crt/proxy.pem

SSLProxyMachineCertificatePath Directive

Description: | Directory of PEM-encoded client certificates and keys to be used by the proxy
Syntax: | SSLProxyMachineCertificatePath directory
Context: | server config
Override: | Not applicable
Status: | Extension
Module: | mod_ssl

This directive sets the directory where you keep the certificates and keys used for authentication of the proxy server to remote servers.

The files in this directory must be PEM-encoded and are accessed through hash filenames. Additionally, you must create symbolic links named hash-value.N. And you should always make sure this directory contains the appropriate symbolic links. Use the Makefile which comes with mod_ssl to accomplish this task.

Currently there is no support for encrypted private keys

Example:

SSLProxyMachineCertificatePath /usr/local/apache2/conf/proxy.crt/

SSLProxyProtocol Directive

Description: | Configure usable SSL protocol flavors for proxy usage
Syntax: | SSLProxyProtocol [+|-]protocol ...
Default: | SSLProxyProtocol all
Context: | server config, virtual host
Override: | Options
Status: | Extension
Module: | mod_ssl

This directive can be used to control the SSL protocol flavors mod_ssl should use when establishing its server environment for proxy . It will only connect to servers using one of the provided protocols.

Please refer to SSLProtocol for additional information.

SSLProxyVerify Directive

Description: | Type of remote server Certificate verification
Syntax: | SSLProxyVerify level
Default: | SSLProxyVerify none
Context: | server config, virtual host, directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl

This directive sets the Certificate verification level for the remote server Authentication. Notice that this directive can be used both in per-server and per-directory context. In per-server context it applies to the remote server authentication process used in the standard SSL handshake when a connection is established. In per-directory context it forces a SSL renegotation with the reconfigured remote server verification level after the HTTP request was read but before the HTTP response is sent.

The following levels are available for level:

  • none: no remote server Certificate is required at all
  • optional: the remote server may present a valid Certificate
  • require: the remote server has to present a valid Certificate
  • optional_no_ca: the remote server may present a valid Certificate
    but it need not to be (successfully) verifiable.

In practice only levels none and require are really interesting, because level optional doesn't work with all servers and level optional_no_ca is actually against the idea of authentication (but can be used to establish SSL test pages, etc.)

Example

SSLProxyVerify require

SSLProxyVerifyDepth Directive

Description: | Maximum depth of CA Certificates in Remote Server Certificate verification
Syntax: | SSLProxyVerifyDepth number
Default: | SSLProxyVerifyDepth 1
Context: | server config, virtual host, directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl

This directive sets how deeply mod_ssl should verify before deciding that the remote server does not have a valid certificate. Notice that this directive can be used both in per-server and per-directory context. In per-server context it applies to the client authentication process used in the standard SSL handshake when a connection is established. In per-directory context it forces a SSL renegotation with the reconfigured remote server verification depth after the HTTP request was read but before the HTTP response is sent.

The depth actually is the maximum number of intermediate certificate issuers, i.e. the number of CA certificates which are max allowed to be followed while verifying the remote server certificate. A depth of 0 means that self-signed remote server certificates are accepted only, the default depth of 1 means the remote server certificate can be self-signed or has to be signed by a CA which is directly known to the server (i.e. the CA's certificate is under SSLProxyCACertificatePath), etc.

Example

SSLProxyVerifyDepth 10

SSLRandomSeed Directive

Description: | Pseudo Random Number Generator (PRNG) seeding source
Syntax: | SSLRandomSeed context source [bytes]
Context: | server config
Status: | Extension
Module: | mod_ssl

This configures one or more sources for seeding the Pseudo Random Number Generator (PRNG) in OpenSSL at startup time (context is startup) and/or just before a new SSL connection is established (context is connect). This directive can only be used in the global server context because the PRNG is a global facility.

The following source variants are available:

  • builtin

    This is the always available builtin seeding source. It's usage consumes minimum CPU cycles under runtime and hence can be always used without drawbacks. The source used for seeding the PRNG contains of the current time, the current process id and (when applicable) a randomly choosen 1KB extract of the inter-process scoreboard structure of Apache. The drawback is that this is not really a strong source and at startup time (where the scoreboard is still not available) this source just produces a few bytes of entropy. So you should always, at least for the startup, use an additional seeding source.

  • file:/path/to/source

    This variant uses an external file /path/to/source as the source for seeding the PRNG. When bytes is specified, only the first bytes number of bytes of the file form the entropy (and bytes is given to /path/to/source as the first argument). When bytes is not specified the whole file forms the entropy (and 0 is given to /path/to/source as the first argument). Use this especially at startup time, for instance with an available /dev/random and/or /dev/urandom devices (which usually exist on modern Unix derivates like FreeBSD and Linux).

    But be careful: Usually /dev/random provides only as much entropy data as it actually has, i.e. when you request 512 bytes of entropy, but the device currently has only 100 bytes available two things can happen: On some platforms you receive only the 100 bytes while on other platforms the read blocks until enough bytes are available (which can take a long time). Here using an existing /dev/urandom is better, because it never blocks and actually gives the amount of requested data. The drawback is just that the quality of the received data may not be the best.

    On some platforms like FreeBSD one can even control how the entropy is actually generated, i.e. by which system interrupts. More details one can find under rndcontrol(8) on those platforms. Alternatively, when your system lacks such a random device, you can use tool like EGD (Entropy Gathering Daemon) and run it's client program with the exec:/path/to/program/ variant (see below) or use egd:/path/to/egd-socket (see below).

  • exec:/path/to/program

    This variant uses an external executable /path/to/program as the source for seeding the PRNG. When bytes is specified, only the first bytes number of bytes of its stdout contents form the entropy. When bytes is not specified, the entirety of the data produced on stdout form the entropy. Use this only at startup time when you need a very strong seeding with the help of an external program (for instance as in the example above with the truerand utility you can find in the mod_ssl distribution which is based on the AT&T truerand library). Using this in the connection context slows down the server too dramatically, of course. So usually you should avoid using external programs in that context.

  • egd:/path/to/egd-socket (Unix only)

    This variant uses the Unix domain socket of the external Entropy Gathering Daemon (EGD) (see http://www.lothar.com/tech /crypto/) to seed the PRNG. Use this if no random device exists on your platform.

Example

SSLRandomSeed startup builtin
SSLRandomSeed startup file:/dev/random
SSLRandomSeed startup file:/dev/urandom 1024
SSLRandomSeed startup exec:/usr/local/bin/truerand 16
SSLRandomSeed connect builtin
SSLRandomSeed connect file:/dev/random
SSLRandomSeed connect file:/dev/urandom 1024

SSLRequire Directive

Description: | Allow access only when an arbitrarily complex boolean expression is true
Syntax: | SSLRequire expression
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl

This directive specifies a general access requirement which has to be fulfilled in order to allow access. It's a very powerful directive because the requirement specification is an arbitrarily complex boolean expression containing any number of access checks.

The expression must match the following syntax (given as a BNF grammar notation):

expr     ::= "true" | "false"
           | "!" expr
           | expr "&&" expr
           | expr "||" expr
           | "(" expr ")"
           | comp

comp     ::= word "==" word | word "eq" word
           | word "!=" word | word "ne" word
           | word "<"  word | word "lt" word
           | word "<=" word | word "le" word
           | word ">"  word | word "gt" word
           | word ">=" word | word "ge" word
           | word "in" "{" wordlist "}"
           | word "=~" regex
           | word "!~" regex

wordlist ::= word
           | wordlist "," word

word     ::= digit
           | cstring
           | variable
           | function

digit    ::= [0-9]+
cstring  ::= "..."
variable ::= "%{" varname "}"
function ::= funcname "(" funcargs ")"

while for varname any variable from Table 3 can be used. Finally for funcname the following functions are available:

  • file(filename)

    This function takes one string argument and expands to the contents of the file. This is especially useful for matching this contents against a regular expression, etc.

Notice that expression is first parsed into an internal machine representation and then evaluated in a second step. Actually, in Global and Per-Server Class context expression is parsed at startup time and at runtime only the machine representation is executed. For Per-Directory context this is different: here expression has to be parsed and immediately executed for every request.

Example

SSLRequire ( %{SSL_CIPHER} !~ m/^(EXP|NULL)-/ \
and %{SSL_CLIENT_S_DN_O} eq "Snake Oil, Ltd." \
and %{SSL_CLIENT_S_DN_OU} in {"Staff", "CA", "Dev"} \
and %{TIME_WDAY} >= 1 and %{TIME_WDAY} <= 5 \
and %{TIME_HOUR} >= 8 and %{TIME_HOUR} <= 20 ) \
or %{REMOTE_ADDR} =~ m/^192\.76\.162\.[0-9]+$/

Standard CGI/1.0 and Apache variables:

HTTP_USER_AGENT        PATH_INFO             AUTH_TYPE
HTTP_REFERER           QUERY_STRING          SERVER_SOFTWARE
HTTP_COOKIE            REMOTE_HOST           API_VERSION
HTTP_FORWARDED         REMOTE_IDENT          TIME_YEAR
HTTP_HOST              IS_SUBREQ             TIME_MON
HTTP_PROXY_CONNECTION  DOCUMENT_ROOT         TIME_DAY
HTTP_ACCEPT            SERVER_ADMIN          TIME_HOUR
HTTP:headername        SERVER_NAME           TIME_MIN
THE_REQUEST            SERVER_PORT           TIME_SEC
REQUEST_METHOD         SERVER_PROTOCOL       TIME_WDAY
REQUEST_SCHEME         REMOTE_ADDR           TIME
REQUEST_URI            REMOTE_USER           ENV:variablename
REQUEST_FILENAME

SSL-related variables:

HTTPS                  SSL_CLIENT_M_VERSION   SSL_SERVER_M_VERSION
                       SSL_CLIENT_M_SERIAL    SSL_SERVER_M_SERIAL
SSL_PROTOCOL           SSL_CLIENT_V_START     SSL_SERVER_V_START
SSL_SESSION_ID         SSL_CLIENT_V_END       SSL_SERVER_V_END
SSL_CIPHER             SSL_CLIENT_S_DN        SSL_SERVER_S_DN
SSL_CIPHER_EXPORT      SSL_CLIENT_S_DN_C      SSL_SERVER_S_DN_C
SSL_CIPHER_ALGKEYSIZE  SSL_CLIENT_S_DN_ST     SSL_SERVER_S_DN_ST
SSL_CIPHER_USEKEYSIZE  SSL_CLIENT_S_DN_L      SSL_SERVER_S_DN_L
SSL_VERSION_LIBRARY    SSL_CLIENT_S_DN_O      SSL_SERVER_S_DN_O
SSL_VERSION_INTERFACE  SSL_CLIENT_S_DN_OU     SSL_SERVER_S_DN_OU
                       SSL_CLIENT_S_DN_CN     SSL_SERVER_S_DN_CN
                       SSL_CLIENT_S_DN_T      SSL_SERVER_S_DN_T
                       SSL_CLIENT_S_DN_I      SSL_SERVER_S_DN_I
                       SSL_CLIENT_S_DN_G      SSL_SERVER_S_DN_G
                       SSL_CLIENT_S_DN_S      SSL_SERVER_S_DN_S
                       SSL_CLIENT_S_DN_D      SSL_SERVER_S_DN_D
                       SSL_CLIENT_S_DN_UID    SSL_SERVER_S_DN_UID
                       SSL_CLIENT_S_DN_Email  SSL_SERVER_S_DN_Email
                       SSL_CLIENT_I_DN        SSL_SERVER_I_DN
                       SSL_CLIENT_I_DN_C      SSL_SERVER_I_DN_C
                       SSL_CLIENT_I_DN_ST     SSL_SERVER_I_DN_ST
                       SSL_CLIENT_I_DN_L      SSL_SERVER_I_DN_L
                       SSL_CLIENT_I_DN_O      SSL_SERVER_I_DN_O
                       SSL_CLIENT_I_DN_OU     SSL_SERVER_I_DN_OU
                       SSL_CLIENT_I_DN_CN     SSL_SERVER_I_DN_CN
                       SSL_CLIENT_I_DN_T      SSL_SERVER_I_DN_T
                       SSL_CLIENT_I_DN_I      SSL_SERVER_I_DN_I
                       SSL_CLIENT_I_DN_G      SSL_SERVER_I_DN_G
                       SSL_CLIENT_I_DN_S      SSL_SERVER_I_DN_S
                       SSL_CLIENT_I_DN_D      SSL_SERVER_I_DN_D
                       SSL_CLIENT_I_DN_UID    SSL_SERVER_I_DN_UID
                       SSL_CLIENT_I_DN_Email  SSL_SERVER_I_DN_Email
                       SSL_CLIENT_A_SIG       SSL_SERVER_A_SIG
                       SSL_CLIENT_A_KEY       SSL_SERVER_A_KEY
                       SSL_CLIENT_CERT        SSL_SERVER_CERT
                       SSL_CLIENT_CERT_CHAINn
                       SSL_CLIENT_VERIFY

SSLRequireSSL Directive

Description: | Deny access when SSL is not used for the HTTP request
Syntax: | SSLRequireSSL
Context: | directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl

This directive forbids access unless HTTP over SSL (i.e. HTTPS) is enabled for the current connection. This is very handy inside the SSL-enabled virtual host or directories for defending against configuration errors that expose stuff that should be protected. When this directive is present all requests are denied which are not using SSL.

Example

SSLRequireSSL

SSLSessionCache Directive

Description: | Type of the global/inter-process SSL Session Cache
Syntax: | SSLSessionCache type
Default: | SSLSessionCache none
Context: | server config
Status: | Extension
Module: | mod_ssl

This configures the storage type of the global/inter-process SSL Session Cache. This cache is an optional facility which speeds up parallel request processing. For requests to the same server process (via HTTP keep-alive), OpenSSL already caches the SSL session information locally. But because modern clients request inlined images and other data via parallel requests (usually up to four parallel requests are common) those requests are served by different pre-forked server processes. Here an inter-process cache helps to avoid unneccessary session handshakes.

The following two storage types are currently supported:

  • none

    This is the default and just disables the global/inter-process Session Cache. There is no drawback in functionality, but a noticeable speed penalty can be observed.

  • dbm:/path/to/datafile

    This makes use of a DBM hashfile on the local disk to synchronize the local OpenSSL memory caches of the server processes. The slight increase in I/O on the server results in a visible request speedup for your clients, so this type of storage is generally recommended.

  • shm:/path/to/datafile[(size)]

    This makes use of a high-performance hash table (approx. size bytes in size) inside a shared memory segment in RAM (established via /path/to/datafile) to synchronize the local OpenSSL memory caches of the server processes. This storage type is not available on all platforms.

Examples

SSLSessionCache dbm:/usr/local/apache/logs/ssl_gcache_data
SSLSessionCache shm:/usr/local/apache/logs/ssl_gcache_data(512000)

SSLSessionCacheTimeout Directive

Description: | Number of seconds before an SSL session expires in the Session Cache
Syntax: | SSLSessionCacheTimeout seconds
Default: | SSLSessionCacheTimeout 300
Context: | server config, virtual host
Status: | Extension
Module: | mod_ssl

This directive sets the timeout in seconds for the information stored in the global/inter-process SSL Session Cache and the OpenSSL internal memory cache. It can be set as low as 15 for testing, but should be set to higher values like 300 in real life.

Example

SSLSessionCacheTimeout 600

SSLUserName Directive

Description: | Variable name to determine user name
Syntax: | SSLUserName varname
Context: | server config, directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl
Compatibility: | Available in Apache 2.0.51 and later

This directive sets the "user" field in the Apache request object. This is used by lower modules to identify the user with a character string. In particular, this may cause the environment variable REMOTE_USER to be set. The varname can be any of the SSL environment variables.

Example

SSLUserName SSL_CLIENT_S_DN_CN

SSLVerifyClient Directive

Description: | Type of Client Certificate verification
Syntax: | SSLVerifyClient level
Default: | SSLVerifyClient none
Context: | server config, virtual host, directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl

This directive sets the Certificate verification level for the Client Authentication. Notice that this directive can be used both in per-server and per-directory context. In per-server context it applies to the client authentication process used in the standard SSL handshake when a connection is established. In per-directory context it forces a SSL renegotation with the reconfigured client verification level after the HTTP request was read but before the HTTP response is sent.

The following levels are available for level:

  • none: no client Certificate is required at all
  • optional: the client may present a valid Certificate
  • require: the client has to present a valid Certificate
  • optional_no_ca: the client may present a valid Certificate
    but it need not to be (successfully) verifiable.

In practice only levels none and require are really interesting, because level optional doesn't work with all browsers and level optional_no_ca is actually against the idea of authentication (but can be used to establish SSL test pages, etc.)

Example

SSLVerifyClient require

SSLVerifyDepth Directive

Description: | Maximum depth of CA Certificates in Client Certificate verification
Syntax: | SSLVerifyDepth number
Default: | SSLVerifyDepth 1
Context: | server config, virtual host, directory, .htaccess
Override: | AuthConfig
Status: | Extension
Module: | mod_ssl

This directive sets how deeply mod_ssl should verify before deciding that the clients don't have a valid certificate. Notice that this directive can be used both in per-server and per-directory context. In per-server context it applies to the client authentication process used in the standard SSL handshake when a connection is established. In per-directory context it forces a SSL renegotation with the reconfigured client verification depth after the HTTP request was read but before the HTTP response is sent.

The depth actually is the maximum number of intermediate certificate issuers, i.e. the number of CA certificates which are max allowed to be followed while verifying the client certificate. A depth of 0 means that self-signed client certificates are accepted only, the default depth of 1 means the client certificate can be self-signed or has to be signed by a CA which is directly known to the server (i.e. the CA's certificate is under SSLCACertificatePath), etc.

Example

SSLVerifyDepth 10


mod_status - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_status

설명: | 서버 활동과 성능에 대한 정보를 제공한다
상태: | Base
모듈명: | status_module
소스파일: | mod_status.c

요약

Status 모듈은 서버 관리자에게 서버의 상태를 보여준다. 쉽게 읽을 수 있는 HTML 페이지로 현재 서버통계를 보여준다. 필요하다면 (표준을 따르는 브라우저에서) 페이지를 자동으로 갱신할 수 있다. 현재 서버 상태를 컴퓨터가 읽을 수 있는 간단한 목록으로 보여줄 수도 있다.

알려주는 정보는:

  • 요청을 서비스하는 worker의 개수
  • 쉬고 있는(idle) worker의 개수
  • 각 worker들의 상태, worker가 처리한 요청의 개수와 worker가 서비스한 전체 바이트수 (*)
  • 총 접근 횟수와 서비스한 바이트수 (*)
  • 서버가 시작혹은 재시작한 시간과 동작한 시간
  • 초당 요청수 평균, 초당 서비스한 바이트수와 요청당 바이트수 평균 (*)
  • 현재 아파치 전체와 각 worker들의 CPU 비율 (*)
  • 현재 처리하고 있는 호스트와 요청 (*)

표준 아파치에는 "(*)"로 표시한 통계를 얻을 수 없다. 이 정보를 보려면 컴파일시 옵션을 사용해야 한다.

Status 사용하기

foo.com 도메인에서 접근한 브라우저에게만 상태를 보여주려면 httpd.conf 설정파일에 다음과 같이 추가한다

<Location /server-status>
SetHandler server-status

Order Deny,Allow
Deny from all
Allow from .foo.com
</Location>

이제 웹브라우저로 http://your.server.name/server-status 페이지에 접근하면 서버 통계를 볼 수 있다.

자동 갱신

브라우저가 "재갱신"을 지원한다면 status 페이지를 자동으로 갱신할 수 있다. N 초마다 갱신하려면 http://your.server.name/server-status?refresh=N 페이지를 사용하라.

컴퓨터가 읽을 수 있는 Status 파일

http://your.server.name/server-status?auto에서 컴퓨터가 쉽게 읽을 수 있는 status 파일을 얻을 수 있다. 이 형식은 아파치 /support 디렉토리에 있는 log_server_status Perl 프로그램과 같이 자동으로 실행하는 프로그램에 유용하다.

mod_status를 서버와 같이 컴파일하였다면 디렉토리별 설정파일을 (예를 들어, .htaccess) 포함하여 모든 설정파일에서 핸들러를 사용할 수 있다. 그래서 사이트에 보안 문제가 발생할 수 있다.

ExtendedStatus 지시어

설명: | 각 요청에 대한 자세한 상태 정보를 기록한다
문법: | ExtendedStatus On|Off
기본값: | ExtendedStatus Off
사용장소: | 주서버설정
상태: | Base
모듈: | mod_status
지원: | ExtendedStatus는 아파치 1.3.2 이후에만 있다.

이 설정은 서버 전체에 적용되며, 가상호스트별로 키고 끌 수 없다. 자세한 상태 정보를 모으면 서버가 느려질 수 있다.


mod_suexec - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_suexec

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.
설명: | CGI 스크립트를 특정 사용자와 그룹 권한으로 실행한다
상태: | Extension
모듈명: | suexec_module
소스파일: | mod_suexec.c
지원: | 아파치 2.0 이후부터

요약

이 모듈은 suexec 지원 프로그램을 사용하여 CGI 스크립트를 특정 사용자와 그룹 권한으로 실행한다.

참고

  • SuEXEC 지원

SuexecUserGroup 지시어

설명: | CGI 프로그램이 사용할 사용자와 그룹 권한
문법: | SuexecUserGroup User Group
사용장소: | 주서버설정, 가상호스트
상태: | Extension
모듈: | mod_suexec
지원: | SuexecUserGroup은 2.0 이후에만 있다.

SuexecUserGroup 지시어는 CGI 프로그램이 사용할 사용자와 그룹을 설정한다. CGI가 아닌 요청은 계속 User 지시어로 지정한 사용자가 처리한다. 이 지시어는 아파치 1.3에서 VirtualHost 안에 사용한 User와 Group 지시어를 대체한다.

예제

SuexecUserGroup nobody nogroup


mod_unique_id - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_unique_id

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.
설명: | 각 요청마다 유일한 식별자를 가지는 환경변수를 제공한다
상태: | Extension
모듈명: | unique_id_module
소스파일: | mod_unique_id.c

요약

이 모듈은 어떤 특별한 상황에서도 "모든" 요청중에서 유일하도록 보장된 식별자(identifier)를 모든 요청에 제공한다. 심지어 이 식별자는 특별하게 구성한 클러스터의 여러 컴퓨터들 중에서도 유일하다. 각 요청마다 환경변수 UNIQUE_ID를 설정한다. 유일한 식별자는 여러가지 용도로 사용할 수 있지만, 설명은 이 문서의 범위를 넘어선다.

이론

먼저 유닉스 시스템에서 아파치 서버가 어떻게 동작하는지 간략히 살펴보자. Windows NT는 현재 이 기능을 지원하지 않는다. 유닉스에서 아파치는 여러 자식을 만들고, 자식 프로세스는 한번에 한 요청씩 처리한다. 자식은 실행중에 여러 요청을 처리한다. 여기서 중요한 것은 자식들이 서로 자료를 공유하지 않는다는 점이다. 앞으로 자식을 httpd 프로세스라고 한다.

여러 컴퓨터로 웹사이트를 서비스한다면 클러스터(cluster)라고 부른다. 각 컴퓨터는 여러 아파치를 실행할 수 있다. 이들 모두를 "우주"로 보면, 클러스터에 있는 컴퓨터들간에 많은 통신없이 각 요청마다 우주에서 유일한 식별자를 만들 수 있다.

클러스터에 있는 컴퓨터는 다음 요구사항을 만족해야 한다. (컴퓨터를 한대만 사용하더라도 컴퓨터 시간을 NTP와 동기해야 한다.)

  • 컴퓨터 시간은 NTP나 다른 네트웍 시간 프로토콜과 동기화된다.
  • 컴퓨터의 호스트명이 모두 다르다. 그래서 모듈이 호스트명으로 찾으면 클러스터에 있는 각 컴퓨터마다 다른 IP 주소를 얻는다.

운영체제에서 pid (프로세스 id)가 32비트에 들어간다고 가정한다. 운영체제가 pid로 32비트 이상을 사용한다면 간단하지만 코드를 수정해야 한다.

이런 가정하에 우리는 어떤 시점에서 클러스터의 어떤 컴퓨터에 있는 어떤 httpd 프로세스를 다른 모든 httpd 프로세스들과 구별할 수 있다. 컴퓨터의 IP 주소와 httpd 프로세스의 pid만으로도 충분히 구별할 수 있다. 그래서 요청에 대해 유일한 구별자를 만드려면 시간차를 구별할 수만 있으면 된다.

시간을 구별하기위해 유닉스 시간(timestamp, 세계 표준시로 1970년 1월 1일 이후 지난 초)과 16비트 카운터를 사용한다. 유닉스 시간은 초단위이고, 카운터는 일 초동안 65536까지 증가한다. ( ip_addr, pid, time_stamp, counter ) 묶음은 어떤 httpd 프로세스에서 일 초동안 65536 요청을 구별할 수 있다. 그러나 카운터는 pid를 재사용하는 문제를 해결해야 한다.

httpd 자식을 만들면 카운터는 ( 현재 밀리초 나누기 10 )을 65536으로 나눈 나머지가 된다. (몇몇 시스템의 밀리초 시간에서 하위 비트가 일치하지않는 문제때문에 이 공식을 만들었다.) 유일한 식별자를 만들때 사용하는 시간은 웹서버가 요청을 받은 시간이다. 카운터는 식별자를 만들때마다 증가한다 (그리고 다시 시작한다).

커널은 프로세스를 포크할때(fork) 각 프로세스에 pid를 할당하고, pid는 다시 시작할 수 있다. (pid는 많은 유닉스에서 16비트이지만, 최근 시스템은 32비트로 확장했다.) 그래서 시간이 지나면 같은 pid를 재사용할 수 있다. 그러나 같은 시간에 pid를 재사용하지 않는다면 위의 묶음은 유일하다. 즉, 우리는 시스템이 일초동안 프로세스를 65536개 이상 만들지 않는다고 가정한다. (어떤 유닉스에서는 32768개 이상 프로세스를 만들면 pid 재사용 문제가 발생할 수 있지만, 이것조차도 일어날 것같지 않다.)

시간이 어떤 이유에서건 반복된다고 가정해보자. 즉, 시스템 시계가 꼬여서 시간이 과거로 돌아가는 (혹은 시계가 너무 앞서가서 올바로 재설정한후 미래에 같은 시간이 되는) 경우다. 이 경우 pid와 시간을 모두 재사용할 수 있다. 카운터의 초기화 공식은 이 문제를 해결하려고 고안되었다. 우리는 실제 무작위 숫자로 카운터를 초기화하길 원하지만, 많은 시스템에서 이런 수를 쉽게 얻을 수 없다. (예를 들어, seed가 필요하기때문에 rand()를 사용할 수 없고, 시간은 최소한 일초 단위이기때문에 시간으로 seed로 사용할 수 없다.) 즉 완벽한 해결책이 없다.

그럼 이 방법은 얼마나 괜찮을까? 컴퓨터중 하나가 요청을 초당 최대 500개 (시스템은 일반적으로 정적인 파일을 전송하는 것 이상의 작업을 하므로 이 글을 쓰는 시점에서 상당히 높은 값이다.) 서비스한다고 가정하자. 동시에 얼마만큼의 클라이언트를 처리하는가에 따라 자식의 개수가 결정된다. 그러나 우리는 비관적으로 한 자식이 요청을 초당 500개 처리할 수 있다고 가정한다. 재사용한 pid를 가진 자식의 500개 요청과 이전 자식의 500개 요청의 카운터값이 겹칠 수 있는 카운터 시작값 경우수는 1000개이다. 그래서 (초단위에서) 자식이 카운터값을 반복하여 유일성이 깨질 확률은 1.5%이다. 이것은 매우 비관적인 가정이며, 실제 이럴 경우는 상당히 더 낮다. 그래도 시스템에서 이런 일이 발생할 것 같다면 (소스를 수정하여) 카운터를 32비트로 만들어라.

섬머타임때문에 시계가 "뒤로 가는" 것을 걱정할지도 모른다. 그러나 여기서 사용하는 시간은 국제 표준시(UTC), 즉 시간이 "항상" 앞으로 가므로 문제가 없다. x86기반 유닉스에서는 적절한 설정이 필요하다. 메인보드 시계가 UTC를 사용하도록 설정해야 한다. 그러나 NTP를 사용한다면 재시작후 조금 지나면 UTC 시간에 올바로 맞춘다.

환경변수 UNIQUE_ID는 MIME base64 인코딩과 비슷한 방법으로 112비트 (32비트 IP 주소, 32비트 pid, 32비트 시간, 16비트 카운터) 묶음을 알파벳 [A-Za-z0-9@-]로 표현한다. 실제 MIME base64 알파벳은 [A-Za-z0-9+/]이지만 +와 /는 URL에서 특별한 의미로 사용하므로 제외했다. 모든 값을 네트웍 바이트순서로 인코딩하기때문에 다른 바이트순서를 사용하는 아키텍쳐간에 값이 같다. 실제 인코딩 순서는 시간, IP 주소, pid, 카운터 순서이다. 이 순서에는 어떤 목적이 있지만, 프로그램은 인코딩 순서에 의존하여 값들을 분석하면 안됨을 강조한다. 프로그램은 인코딩된 UNIQUE_ID 전체를 한 단위로 생각하고, 다른 UNIQUE_ID와 동일한지만 비교할 수 있다.

순서는 앞으로 기존의 UNIQUE_ID 데이터베이스와 충돌을 염려하지않고 인코딩을 변경할 수 있도록 고안했다. 새로운 인코딩은 첫 항목으로 시간을 사용하거나, 같은 알파벳과 비트 길이를 사용할 수도 있다. 시간이 기본적으로 증가하는 값이므로 클러스터에 있는 모든 컴퓨터가 요청 서비스를 중단하고 이전 인코딩 형식을 그만 사용하기위해 기준 초(flag second)만으로 충분하다. 이후 요청을 재게하고 새로운 인코딩을 시작할 수 있다.

우리는 이 방법이 이 문제에 대하여 상대적으로 포팅가능한 해결책이라고 믿는다. 이 방법은 Windows NT와 같은 멀티쓰레드 시스템으로 확장할 수 있고, 앞으로 용도에 따라 확장할 수 있다. 미래에 필요한만큼 더 긴 식별자를 만들 수 있기때문에 생성한 식별자는 기본적으로 영원한 수명을 가진다. 기본적으로 클러스터의 컴퓨터들 사이에 통신이 필요없고 (부하가 작은 NTP 동기만 필요하다), httpd 프로세스 사이에 통신도 필요없다 (커널이 부여하는 pid값이 암묵적인 통신이다). 매우 특이한 상황이라면 인식자 크기를 줄일 수 있지만 더 많은 정보를 가정해야 한다. (예를 들어, 어떤 사이트에서 32비트 IP 주소 구분은 불필요하게 크지만, 이를 줄이는 방법은 상황에 따라 다르다.)


mod_userdir - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

아파치 모듈 mod_userdir

설명: | 사용자별 디렉토리
상태: | Base
모듈명: | userdir_module
소스파일: | mod_userdir.c

요약

이 모듈을 사용하면 http://example.com/~user/ 식으로 사용자별 디렉토리에 접근할 수 있다.

참고

  • URL을 파일시스템에 대응
  • public_html 투토리얼

UserDir 지시어

설명: | 사용자별 디렉토리 위치
문법: | UserDir directory-filename
기본값: | UserDir public_html
사용장소: | 주서버설정, 가상호스트
상태: | Base
모듈: | mod_userdir

UserDir 지시어는 사용자의 문서에 대한 요청을 받을때 사용자 홈디렉토리 안에서 사용할 실제 디렉토리를 지정한다. Directory-filename은 다음 중 하나이다:

  • 아래와 같은 디렉토리명 혹은 패턴.
  • disabled 키워드. enabled 키워드로 (아래 참고) 직접 이름을 지정하지 않았다면 모든 사용자명-디렉토리 변환을 하지 않는다.
  • disabled 키워드 뒤에 공백으로 구분한 사용자명 목록. 사용자명이 enabled 구문에 있다고 하더라도, 이 목록에 있는 사용자명은 디렉토리 변환을 하지 않는다.
  • enabled 키워드 뒤에 공백으로 구분한 사용자명 목록. 전체 disable을 사용하고 사용자명이 disabled 구문에 없더라도, 사용자명을 디렉토리 변환한다.

Userdir 지시어에 enabled나 disabled 키워드를 사용하지 않으면, 아규먼트를 파일명 패턴으로 처리하여 디렉토리로 변환한다. http://www.foo.com/~bob/one/two.html에 대한 요청은 다음과 같이 변환된다:

사용한 UserDir 지시어 | 변환한 경로
UserDir public_html | ~bob/public_html/one/two.html
UserDir /usr/web | /usr/web/bob/one/two.html
UserDir /home/*/www | /home/bob/www/one/two.html

다음 지시어는 클라이언트에게 리다이렉션을 보낸다:

사용한 UserDir 지시어 | 변환한 경로
UserDir http://www.foo.com/users | http://www.foo.com/users/bob/one/two.html
UserDir http://www.foo.com/*/usr | http://www.foo.com/bob/usr/one/two.html
UserDir http://www.foo.com/~*/ | http://www.foo.com/~bob/one/two.html
이 지시어를 사용할때 주의하라; 예를 들어, "UserDir ./"는 "/~root"를 아마도 바람직하지 않게 "/"로 변환한다. 설정에 "UserDir disabled root"를 포함하길 강력히 권한다. 자세한 정보를 알려면 Directory 지시어와 보안 팁도 참고하라.

추가 예제:

몇몇 사용자에게만 UserDir 디렉토리를 허용한다면, 다음과 같다:

UserDir disabled
UserDir enabled user1 user2 user3

대부분의 사용자에게 UserDir 디렉토리를 허용하고 일부만 거부한다면, 다음과 같다:

UserDir enabled
UserDir disabled user4 user5 user6

다른 사용자 디렉토리를 지정할 수도 있다. 다음과 같은 명령어를 사용한다면:

Userdir public_html /usr/web http://www.foo.com/

http://www.foo.com/~bob/one/two.html 요청을 하면, 먼저 ~bob/public_html/one/two.html 페이지를 찾고, /usr/web/bob/one/two.html을 찾은 후, 마지막으로 http://www.foo.com/bob/one/two.html으로 리다이렉션을 보낸다.

리다이렉션을 사용한다면 목록의 마지막에 두어야 한다. 아파치는 리다이렉션이 성공했는지 알 수 없기때문에, 리다이렉션을 목록 앞에 두면 항상 리다이렉션을 사용하게 된다.

참고

  • public_html 투토리얼


mod_usertrack - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_usertrack

Description: | Clickstream logging of user activity on a site
Status: | Extension
Module Identifier: | usertrack_module
Source File: | mod_usertrack.c

Summary

Previous releases of Apache have included a module which generates a 'clickstream' log of user activity on a site using cookies. This was called the "cookies" module, mod_cookies. In Apache 1.2 and later this module has been renamed the "user tracking" module, mod_usertrack. This module has been simplified and new directives added.

Logging

Previously, the cookies module (now the user tracking module) did its own logging, using the CookieLog directive. In this release, this module does no logging at all. Instead, a configurable log format file should be used to log user click-streams. This is possible because the logging module now allows multiple log files. The cookie itself is logged by using the text %{cookie}n in the log file format. For example:

CustomLog logs/clickstream "%{cookie}n %r %t"

For backward compatibility the configurable log module implements the old CookieLog directive, but this should be upgraded to the above CustomLog directive.

2-digit or 4-digit dates for cookies?

(the following is from message <022701bda43d$9d32bbb0$1201a8c0@christian.office.sane.com> in the new-httpd archives)

From: "Christian Allen" <christian@sane.com>
Subject: Re: Apache Y2K bug in mod_usertrack.c
Date: Tue, 30 Jun 1998 11:41:56 -0400

Did some work with cookies and dug up some info that might be useful.

True, Netscape claims that the correct format NOW is four digit dates, and
four digit dates do in fact work... for Netscape 4.x (Communicator), that
is.  However, 3.x and below do NOT accept them.  It seems that Netscape
originally had a 2-digit standard, and then with all of the Y2K hype and
probably a few complaints, changed to a four digit date for Communicator.
Fortunately, 4.x also understands the 2-digit format, and so the best way to
ensure that your expiration date is legible to the client's browser is to
use 2-digit dates.

However, this does not limit expiration dates to the year 2000; if you use
an expiration year of "13", for example, it is interpreted as 2013, NOT
1913!  In fact, you can use an expiration year of up to "37", and it will be
understood as "2037" by both MSIE and Netscape versions 3.x and up (not sure
about versions previous to those).  Not sure why Netscape used that
particular year as its cut-off point, but my guess is that it was in respect
to UNIX's 2038 problem.  Netscape/MSIE 4.x seem to be able to understand
2-digit years beyond that, at least until "50" for sure (I think they
understand up until about "70", but not for sure).

Summary:  Mozilla 3.x and up understands two digit dates up until "37"
(2037).  Mozilla 4.x understands up until at least "50" (2050) in 2-digit
form, but also understands 4-digit years, which can probably reach up until
9999.  Your best bet for sending a long-life cookie is to send it for some
time late in the year "37".

CookieDomain Directive

Description: | The domain to which the tracking cookie applies
Syntax: | CookieDomain domain
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_usertrack

This directive controls the setting of the domain to which the tracking cookie applies. If not present, no domain is included in the cookie header field.

The domain string must begin with a dot, and must include at least one embedded dot. That is, ".foo.com" is legal, but "foo.bar.com" and ".com" are not.

CookieExpires Directive

Description: | Expiry time for the tracking cookie
Syntax: | CookieExpires expiry-period
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_usertrack

When used, this directive sets an expiry time on the cookie generated by the usertrack module. The expiry-period can be given either as a number of seconds, or in the format such as "2 weeks 3 days 7 hours". Valid denominations are: years, months, weeks, days, hours, minutes and seconds. If the expiry time is in any format other than one number indicating the number of seconds, it must be enclosed by double quotes.

If this directive is not used, cookies last only for the current browser session.

CookieName Directive

Description: | Name of the tracking cookie
Syntax: | CookieName token
Default: | CookieName Apache
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_usertrack

This directive allows you to change the name of the cookie this module uses for its tracking purposes. By default the cookie is named "Apache".

You must specify a valid cookie name; results are unpredictable if you use a name containing unusual characters. Valid characters include A-Z, a-z, 0-9, "_", and "-".

CookieStyle Directive

Description: | Format of the cookie header field
Syntax: | CookieStyle Netscape|Cookie|Cookie2|RFC2109|RFC2965
Default: | CookieStyle Netscape
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_usertrack

This directive controls the format of the cookie header field. The three formats allowed are:

  • Netscape, which is the original but now deprecated syntax. This is the default, and the syntax Apache has historically used.
  • Cookie or RFC2109, which is the syntax that superseded the Netscape syntax.
  • Cookie2 or RFC2965, which is the most current cookie syntax.

Not all clients can understand all of these formats. but you should use the newest one that is generally acceptable to your users' browsers.

CookieTracking Directive

Description: | Enables tracking cookie
Syntax: | CookieTracking on|off
Default: | CookieTracking off
Context: | server config, virtual host, directory, .htaccess
Override: | FileInfo
Status: | Extension
Module: | mod_usertrack

When the user track module is compiled in, and "CookieTracking on" is set, Apache will start sending a user-tracking cookie for all new requests. This directive can be used to turn this behavior on or off on a per-server or per-directory basis. By default, compiling mod_usertrack will not activate cookies.


mod_vhost_alias - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Modules

Apache Module mod_vhost_alias

Description: | Provides for dynamically configured mass virtual hosting
Status: | Extension
Module Identifier: | vhost_alias_module
Source File: | mod_vhost_alias.c

Summary

This module creates dynamically configured virtual hosts, by allowing the IP address and/or the Host: header of the HTTP request to be used as part of the pathname to determine what files to serve. This allows for easy use of a huge number of virtual hosts with similar configurations.

Note

If mod_alias or mod_userdir are used for translating URIs to filenames, they will override the directives of mod_vhost_alias described below. For example, the following configuration will map /cgi-bin/script.pl to /usr/local/apache2/cgi-bin/script.pl in all cases:

ScriptAlias /cgi-bin/ /usr/local/apache2/cgi-bin/
VirtualScriptAlias /never/found/%0/cgi-bin/

See also

  • UseCanonicalName
  • Dynamically configured mass virtual hosting

Directory Name Interpolation

All the directives in this module interpolate a string into a pathname. The interpolated string (henceforth called the "name") may be either the server name (see the UseCanonicalName directive for details on how this is determined) or the IP address of the virtual host on the server in dotted-quad format. The interpolation is controlled by specifiers inspired by printf which have a number of formats:

%% | insert a %
%p | insert the port number of the virtual host
%N.M | insert (part of) the name

N and M are used to specify substrings of the name. N selects from the dot-separated components of the name, and M selects characters within whatever N has selected. M is optional and defaults to zero if it isn't present; the dot must be present if and only if M is present. The interpretation is as follows:

0 | the whole name
1 | the first part
2 | the second part
-1 | the last part
-2 | the penultimate part
2+ | the second and all subsequent parts
-2+ | the penultimate and all preceding parts
1+ and -1+ | the same as 0

If N or M is greater than the number of parts available a single underscore is interpolated.

Examples

For simple name-based virtual hosts you might use the following directives in your server configuration file:

UseCanonicalName Off
VirtualDocumentRoot /usr/local/apache/vhosts/%0

A request for http://www.example.com/directory/file.html will be satisfied by the file /usr/local/apache/vhosts/www.example.com/directory/file.html.

For a very large number of virtual hosts it is a good idea to arrange the files to reduce the size of the vhosts directory. To do this you might use the following in your configuration file:

UseCanonicalName Off
VirtualDocumentRoot /usr/local/apache/vhosts/%3+/%2.1/%2.2/%2.3/%2

A request for http://www.domain.example.com/directory/file.html will be satisfied by the file /usr/local/apache/vhosts/example.com/d/o/m/domain/directory/file.html.

A more even spread of files can be achieved by hashing from the end of the name, for example:

VirtualDocumentRoot /usr/local/apache/vhosts/%3+/%2.-1/%2.-2/%2.-3/%2

The example request would come from /usr/local/apache/vhosts/example.com/n/i/a/domain/directory/file.html.

Alternatively you might use:

VirtualDocumentRoot /usr/local/apache/vhosts/%3+/%2.1/%2.2/%2.3/%2.4+

The example request would come from /usr/local/apache/vhosts/example.com/d/o/m/ain/directory/file.html.

For IP-based virtual hosting you might use the following in your configuration file:

UseCanonicalName DNS
VirtualDocumentRootIP /usr/local/apache/vhosts/%1/%2/%3/%4/docs
VirtualScriptAliasIP /usr/local/apache/vhosts/%1/%2/%3/%4/cgi-bin

A request for http://www.domain.example.com/directory/file.html would be satisfied by the file /usr/local/apache/vhosts/10/20/30/40/docs/directory/file.html if the IP address of www.domain.example.com were 10.20.30.40. A request for http://www.domain.example.com/cgi-bin/script.pl would be satisfied by executing the program /usr/local/apache/vhosts/10/20/30/40/cgi-bin/script.pl.

If you want to include the . character in a VirtualDocumentRoot directive, but it clashes with a % directive, you can work around the problem in the following way:

VirtualDocumentRoot /usr/local/apache/vhosts/%2.0.%3.0

A request for http://www.domain.example.com/directory/file.html will be satisfied by the file /usr/local/apache/vhosts/domain.example/directory/file.html.

The LogFormat directives %V and %A are useful in conjunction with this module.

VirtualDocumentRoot Directive

Description: | Dynamically configure the location of the document root for a given virtual host
Syntax: | VirtualDocumentRoot interpolated-directory|none
Default: | VirtualDocumentRoot none
Context: | server config, virtual host
Status: | Extension
Module: | mod_vhost_alias

The VirtualDocumentRoot directive allows you to determine where Apache will find your documents based on the value of the server name. The result of expanding interpolated-directory is used as the root of the document tree in a similar manner to the DocumentRoot directive's argument. If interpolated-directory is none then VirtualDocumentRoot is turned off. This directive cannot be used in the same context as VirtualDocumentRootIP.

VirtualDocumentRootIP Directive

Description: | Dynamically configure the location of the document root for a given virtual host
Syntax: | VirtualDocumentRootIP interpolated-directory|none
Default: | VirtualDocumentRootIP none
Context: | server config, virtual host
Status: | Extension
Module: | mod_vhost_alias

The VirtualDocumentRootIP directive is like the VirtualDocumentRoot directive, except that it uses the IP address of the server end of the connection for directory interpolation instead of the server name.

VirtualScriptAlias Directive

Description: | Dynamically configure the location of the CGI directory for a given virtual host
Syntax: | VirtualScriptAlias interpolated-directory|none
Default: | VirtualScriptAlias none
Context: | server config, virtual host
Status: | Extension
Module: | mod_vhost_alias

The VirtualScriptAlias directive allows you to determine where Apache will find CGI scripts in a similar manner to VirtualDocumentRoot does for other documents. It matches requests for URIs starting /cgi-bin/, much like ScriptAlias /cgi-bin/ would.

VirtualScriptAliasIP Directive

Description: | Dynamically configure the location of the cgi directory for a given virtual host
Syntax: | VirtualScriptAliasIP interpolated-directory|none
Default: | VirtualScriptAliasIP none
Context: | server config, virtual host
Status: | Extension
Module: | mod_vhost_alias

The VirtualScriptAliasIP directive is like the VirtualScriptAlias directive, except that it uses the IP address of the server end of the connection for directory interpolation instead of the server name.


Developer Documentation for Apache 2.0 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

Developer Documentation for Apache 2.0

Many of the documents on these Developer pages are lifted from Apache 1.3's documentation. While they are all being updated to Apache 2.0, they are in different stages of progress. Please be patient, and point out any discrepancies or errors on the developer/ pages directly to the dev@httpd.apache.org mailing list.

Topics

  • Apache 1.3 API Notes
  • Apache 2.0 Hook Functions
  • Request Processing in Apache 2.0
  • How filters work in Apache 2.0
  • Converting Modules from Apache 1.3 to Apache 2.0
  • Debugging Memory Allocation in APR
  • Documenting Apache 2.0
  • Apache 2.0 Thread Safety Issues

External Resources

  • Tools provided by Ian Holsman:
    • Apache 2 cross reference
    • Autogenerated Apache 2 code documentation
  • Module Development Tutorials by Kevin O'Donnell
    • Integrating a module into the Apache build system
    • Handling configuration directives
  • Some notes on Apache module development by Ryan Bloom


Apache 1.3 API notes - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Developer Documentation

Apache 1.3 API notes

Warning

This document has not been updated to take into account changes made in the 2.0 version of the Apache HTTP Server. Some of the information may still be relevant, but please use it with care.

These are some notes on the Apache API and the data structures you have to deal with, etc. They are not yet nearly complete, but hopefully, they will help you get your bearings. Keep in mind that the API is still subject to change as we gain experience with it. (See the TODO file for what might be coming). However, it will be easy to adapt modules to any changes that are made. (We have more modules to adapt than you do).

A few notes on general pedagogical style here. In the interest of conciseness, all structure declarations here are incomplete -- the real ones have more slots that I'm not telling you about. For the most part, these are reserved to one component of the server core or another, and should be altered by modules with caution. However, in some cases, they really are things I just haven't gotten around to yet. Welcome to the bleeding edge.

Finally, here's an outline, to give you some bare idea of what's coming up, and in what order:

  • Basic concepts.
    • Handlers, Modules, and Requests
    • A brief tour of a module
  • How handlers work
    • A brief tour of the request_rec
    • Where request_rec structures come from
    • Handling requests, declining, and returning error codes
    • Special considerations for response handlers
    • Special considerations for authentication handlers
    • Special considerations for logging handlers
  • Resource allocation and resource pools
  • Configuration, commands and the like
    • Per-directory configuration structures
    • Command handling
    • Side notes --- per-server configuration, virtual servers, etc.

Basic concepts

We begin with an overview of the basic concepts behind the API, and how they are manifested in the code.

Handlers, Modules, and Requests

Apache breaks down request handling into a series of steps, more or less the same way the Netscape server API does (although this API has a few more stages than NetSite does, as hooks for stuff I thought might be useful in the future). These are:

  • URI -> Filename translation
  • Auth ID checking [is the user who they say they are?]
  • Auth access checking [is the user authorized here?]
  • Access checking other than auth
  • Determining MIME type of the object requested
  • `Fixups' -- there aren't any of these yet, but the phase is intended as a hook for possible extensions like SetEnv, which don't really fit well elsewhere.
  • Actually sending a response back to the client.
  • Logging the request

These phases are handled by looking at each of a succession of modules, looking to see if each of them has a handler for the phase, and attempting invoking it if so. The handler can typically do one of three things:

  • Handle the request, and indicate that it has done so by returning the magic constant OK.
  • Decline to handle the request, by returning the magic integer constant DECLINED. In this case, the server behaves in all respects as if the handler simply hadn't been there.
  • Signal an error, by returning one of the HTTP error codes. This terminates normal handling of the request, although an ErrorDocument may be invoked to try to mop up, and it will be logged in any case.

Most phases are terminated by the first module that handles them; however, for logging, `fixups', and non-access authentication checking, all handlers always run (barring an error). Also, the response phase is unique in that modules may declare multiple handlers for it, via a dispatch table keyed on the MIME type of the requested object. Modules may declare a response-phase handler which can handle any request, by giving it the key */* (i.e., a wildcard MIME type specification). However, wildcard handlers are only invoked if the server has already tried and failed to find a more specific response handler for the MIME type of the requested object (either none existed, or they all declined).

The handlers themselves are functions of one argument (a request_rec structure. vide infra), which returns an integer, as above.

A brief tour of a module

At this point, we need to explain the structure of a module. Our candidate will be one of the messier ones, the CGI module -- this handles both CGI scripts and the ScriptAlias config file command. It's actually a great deal more complicated than most modules, but if we're going to have only one example, it might as well be the one with its fingers in every place.

Let's begin with handlers. In order to handle the CGI scripts, the module declares a response handler for them. Because of ScriptAlias, it also has handlers for the name translation phase (to recognize ScriptAliased URIs), the type-checking phase (any ScriptAliased request is typed as a CGI script).

The module needs to maintain some per (virtual) server information, namely, the ScriptAliases in effect; the module structure therefore contains pointers to a functions which builds these structures, and to another which combines two of them (in case the main server and a virtual server both have ScriptAliases declared).

Finally, this module contains code to handle the ScriptAlias command itself. This particular module only declares one command, but there could be more, so modules have command tables which declare their commands, and describe where they are permitted, and how they are to be invoked.

A final note on the declared types of the arguments of some of these commands: a pool is a pointer to a resource pool structure; these are used by the server to keep track of the memory which has been allocated, files opened, etc., either to service a particular request, or to handle the process of configuring itself. That way, when the request is over (or, for the configuration pool, when the server is restarting), the memory can be freed, and the files closed, en masse, without anyone having to write explicit code to track them all down and dispose of them. Also, a cmd_parms structure contains various information about the config file being read, and other status information, which is sometimes of use to the function which processes a config-file command (such as ScriptAlias). With no further ado, the module itself:

        /* Declarations of handlers. */

int translate_scriptalias (request_rec *);
int type_scriptalias (request_rec *);
int cgi_handler (request_rec *);

/* Subsidiary dispatch table for response-phase
* handlers, by MIME type */

handler_rec cgi_handlers[] = {
{ "application/x-httpd-cgi", cgi_handler },
{ NULL }
};

/* Declarations of routines to manipulate the
* module's configuration info.  Note that these are
* returned, and passed in, as void *'s; the server
* core keeps track of them, but it doesn't, and can't,
* know their internal structure.
*/

void *make_cgi_server_config (pool *);
void *merge_cgi_server_config (pool *, void *, void *);

/* Declarations of routines to handle config-file commands */

extern char *script_alias(cmd_parms *, void *per_dir_config, char *fake,
                                  char *real);

command_rec cgi_cmds[] = {
{ "ScriptAlias", script_alias, NULL, RSRC_CONF, TAKE2,
"a fakename and a realname"},
{ NULL }
};

module cgi_module = {

  STANDARD_MODULE_STUFF,
  NULL,                     /* initializer */
  NULL,                     /* dir config creator */
  NULL,                     /* dir merger */
  make_cgi_server_config,   /* server config */
  merge_cgi_server_config,  /* merge server config */
  cgi_cmds,                 /* command table */
  cgi_handlers,             /* handlers */
  translate_scriptalias,    /* filename translation */
  NULL,                     /* check_user_id */
  NULL,                     /* check auth */
  NULL,                     /* check access */
  type_scriptalias,         /* type_checker */
  NULL,                     /* fixups */
  NULL,                     /* logger */
  NULL                      /* header parser */
};

How handlers work

The sole argument to handlers is a request_rec structure. This structure describes a particular request which has been made to the server, on behalf of a client. In most cases, each connection to the client generates only one request_rec structure.

A brief tour of the request_rec

The request_rec contains pointers to a resource pool which will be cleared when the server is finished handling the request; to structures containing per-server and per-connection information, and most importantly, information on the request itself.

The most important such information is a small set of character strings describing attributes of the object being requested, including its URI, filename, content-type and content-encoding (these being filled in by the translation and type-check handlers which handle the request, respectively).

Other commonly used data items are tables giving the MIME headers on the client's original request, MIME headers to be sent back with the response (which modules can add to at will), and environment variables for any subprocesses which are spawned off in the course of servicing the request. These tables are manipulated using the ap_table_get and ap_table_set routines.

Note that the Content-type header value cannot be set by module content-handlers using the ap_table_*() routines. Rather, it is set by pointing the content_type field in the request_rec structure to an appropriate string. e.g.,

r->content_type = "text/html";

Finally, there are pointers to two data structures which, in turn, point to per-module configuration structures. Specifically, these hold pointers to the data structures which the module has built to describe the way it has been configured to operate in a given directory (via .htaccess files or <Directory> sections), for private data it has built in the course of servicing the request (so modules' handlers for one phase can pass `notes' to their handlers for other phases). There is another such configuration vector in the server_rec data structure pointed to by the request_rec, which contains per (virtual) server configuration data.

Here is an abridged declaration, giving the fields most commonly used:

struct request_rec {

pool *pool;
conn_rec *connection;
server_rec *server;

/* What object is being requested */

char *uri;
char *filename;
char *path_info;

char *args;           /* QUERY_ARGS, if any */
struct stat finfo;    /* Set by server core;
                       * st_mode set to zero if no such file */

char *content_type;
char *content_encoding;

/* MIME header environments, in and out. Also,
 * an array containing environment variables to
 * be passed to subprocesses, so people can write
 * modules to add to that environment.
 *
 * The difference between headers_out and
 * err_headers_out is that the latter are printed
 * even on error, and persist across internal
 * redirects (so the headers printed for
 * ErrorDocument handlers will have them).
 */

table *headers_in;
table *headers_out;
table *err_headers_out;
table *subprocess_env;

/* Info about the request itself... */

int header_only;     /* HEAD request, as opposed to GET */
char *protocol;      /* Protocol, as given to us, or HTTP/0.9 */
char *method;        /* GET, HEAD, POST, etc. */
int method_number;   /* M_GET, M_POST, etc. */

/* Info for logging */

char *the_request;
int bytes_sent;

/* A flag which modules can set, to indicate that
 * the data being returned is volatile, and clients
 * should be told not to cache it.
 */

int no_cache;

/* Various other config info which may change
 * with .htaccess files
 * These are config vectors, with one void*
 * pointer for each module (the thing pointed
 * to being the module's business).
 */

void *per_dir_config;   /* Options set in config files, etc. */
void *request_config;   /* Notes on *this* request */

};

Where request_rec structures come from

Most request_rec structures are built by reading an HTTP request from a client, and filling in the fields. However, there are a few exceptions:

  • If the request is to an imagemap, a type map (i.e., a *.var file), or a CGI script which returned a local `Location:', then the resource which the user requested is going to be ultimately located by some URI other than what the client originally supplied. In this case, the server does an internal redirect, constructing a new request_rec for the new URI, and processing it almost exactly as if the client had requested the new URI directly.
  • If some handler signaled an error, and an ErrorDocument is in scope, the same internal redirect machinery comes into play.

  • Finally, a handler occasionally needs to investigate `what would happen if' some other request were run. For instance, the directory indexing module needs to know what MIME type would be assigned to a request for each directory entry, in order to figure out what icon to use.

    Such handlers can construct a sub-request, using the functions ap_sub_req_lookup_file, ap_sub_req_lookup_uri, and ap_sub_req_method_uri; these construct a new request_rec structure and processes it as you would expect, up to but not including the point of actually sending a response. (These functions skip over the access checks if the sub-request is for a file in the same directory as the original request).

    (Server-side includes work by building sub-requests and then actually invoking the response handler for them, via the function ap_run_sub_req).

Handling requests, declining, and returning error codes

As discussed above, each handler, when invoked to handle a particular request_rec, has to return an int to indicate what happened. That can either be

  • OK -- the request was handled successfully. This may or may not terminate the phase.
  • DECLINED -- no erroneous condition exists, but the module declines to handle the phase; the server tries to find another.
  • an HTTP error code, which aborts handling of the request.

Note that if the error code returned is REDIRECT, then the module should put a Location in the request's headers_out, to indicate where the client should be redirected to.

Special considerations for response handlers

Handlers for most phases do their work by simply setting a few fields in the request_rec structure (or, in the case of access checkers, simply by returning the correct error code). However, response handlers have to actually send a request back to the client.

They should begin by sending an HTTP response header, using the function ap_send_http_header. (You don't have to do anything special to skip sending the header for HTTP/0.9 requests; the function figures out on its own that it shouldn't do anything). If the request is marked header_only, that's all they should do; they should return after that, without attempting any further output.

Otherwise, they should produce a request body which responds to the client as appropriate. The primitives for this are ap_rputc and ap_rprintf, for internally generated output, and ap_send_fd, to copy the contents of some FILE * straight to the client.

At this point, you should more or less understand the following piece of code, which is the handler which handles GET requests which have no more specific handler; it also shows how conditional GETs can be handled, if it's desirable to do so in a particular response handler -- ap_set_last_modified checks against the If-modified-since value supplied by the client, if any, and returns an appropriate code (which will, if nonzero, be USE_LOCAL_COPY). No similar considerations apply for ap_set_content_length, but it returns an error code for symmetry.

        int default_handler (request_rec *r)
{
int errstatus;
FILE *f;

if (r->method_number != M_GET) return DECLINED;
if (r->finfo.st_mode == 0) return NOT_FOUND;

if ((errstatus = ap_set_content_length (r, r->finfo.st_size))
||
             (errstatus = ap_set_last_modified (r, r->finfo.st_mtime)))
return errstatus;

f = fopen (r->filename, "r");

if (f == NULL) {
log_reason("file permissions deny server access", r->filename, r);
return FORBIDDEN;
}

register_timeout ("send", r);
ap_send_http_header (r);

if (!r->header_only) send_fd (f, r);
ap_pfclose (r->pool, f);
return OK;
}

Finally, if all of this is too much of a challenge, there are a few ways out of it. First off, as shown above, a response handler which has not yet produced any output can simply return an error code, in which case the server will automatically produce an error response. Secondly, it can punt to some other handler by invoking ap_internal_redirect, which is how the internal redirection machinery discussed above is invoked. A response handler which has internally redirected should always return OK.

(Invoking ap_internal_redirect from handlers which are not response handlers will lead to serious confusion).

Special considerations for authentication handlers

Stuff that should be discussed here in detail:

  • Authentication-phase handlers not invoked unless auth is configured for the directory.
  • Common auth configuration stored in the core per-dir configuration; it has accessors ap_auth_type, ap_auth_name, and ap_requires.
  • Common routines, to handle the protocol end of things, at least for HTTP basic authentication (ap_get_basic_auth_pw, which sets the connection->user structure field automatically, and ap_note_basic_auth_failure, which arranges for the proper WWW-Authenticate: header to be sent back).

Special considerations for logging handlers

When a request has internally redirected, there is the question of what to log. Apache handles this by bundling the entire chain of redirects into a list of request_rec structures which are threaded through the r->prev and r->next pointers. The request_rec which is passed to the logging handlers in such cases is the one which was originally built for the initial request from the client; note that the bytes_sent field will only be correct in the last request in the chain (the one for which a response was actually sent).

Resource allocation and resource pools

One of the problems of writing and designing a server-pool server is that of preventing leakage, that is, allocating resources (memory, open files, etc.), without subsequently releasing them. The resource pool machinery is designed to make it easy to prevent this from happening, by allowing resource to be allocated in such a way that they are automatically released when the server is done with them.

The way this works is as follows: the memory which is allocated, file opened, etc., to deal with a particular request are tied to a resource pool which is allocated for the request. The pool is a data structure which itself tracks the resources in question.

When the request has been processed, the pool is cleared. At that point, all the memory associated with it is released for reuse, all files associated with it are closed, and any other clean-up functions which are associated with the pool are run. When this is over, we can be confident that all the resource tied to the pool have been released, and that none of them have leaked.

Server restarts, and allocation of memory and resources for per-server configuration, are handled in a similar way. There is a configuration pool, which keeps track of resources which were allocated while reading the server configuration files, and handling the commands therein (for instance, the memory that was allocated for per-server module configuration, log files and other files that were opened, and so forth). When the server restarts, and has to reread the configuration files, the configuration pool is cleared, and so the memory and file descriptors which were taken up by reading them the last time are made available for reuse.

It should be noted that use of the pool machinery isn't generally obligatory, except for situations like logging handlers, where you really need to register cleanups to make sure that the log file gets closed when the server restarts (this is most easily done by using the function ap_pfopen, which also arranges for the underlying file descriptor to be closed before any child processes, such as for CGI scripts, are execed), or in case you are using the timeout machinery (which isn't yet even documented here). However, there are two benefits to using it: resources allocated to a pool never leak (even if you allocate a scratch string, and just forget about it); also, for memory allocation, ap_palloc is generally faster than malloc.

We begin here by describing how memory is allocated to pools, and then discuss how other resources are tracked by the resource pool machinery.

Allocation of memory in pools

Memory is allocated to pools by calling the function ap_palloc, which takes two arguments, one being a pointer to a resource pool structure, and the other being the amount of memory to allocate (in chars). Within handlers for handling requests, the most common way of getting a resource pool structure is by looking at the pool slot of the relevant request_rec; hence the repeated appearance of the following idiom in module code:

int my_handler(request_rec *r)
{
struct my_structure *foo;
...

foo = (foo *)ap_palloc (r->pool, sizeof(my_structure));
 }

Note that there is no ap_pfree -- ap_palloced memory is freed only when the associated resource pool is cleared. This means that ap_palloc does not have to do as much accounting as malloc(); all it does in the typical case is to round up the size, bump a pointer, and do a range check.

(It also raises the possibility that heavy use of ap_palloc could cause a server process to grow excessively large. There are two ways to deal with this, which are dealt with below; briefly, you can use malloc, and try to be sure that all of the memory gets explicitly freed, or you can allocate a sub-pool of the main pool, allocate your memory in the sub-pool, and clear it out periodically. The latter technique is discussed in the section on sub-pools below, and is used in the directory-indexing code, in order to avoid excessive storage allocation when listing directories with thousands of files).

Allocating initialized memory

There are functions which allocate initialized memory, and are frequently useful. The function ap_pcalloc has the same interface as ap_palloc, but clears out the memory it allocates before it returns it. The function ap_pstrdup takes a resource pool and a char * as arguments, and allocates memory for a copy of the string the pointer points to, returning a pointer to the copy. Finally ap_pstrcat is a varargs-style function, which takes a pointer to a resource pool, and at least two char * arguments, the last of which must be NULL. It allocates enough memory to fit copies of each of the strings, as a unit; for instance:

ap_pstrcat (r->pool, "foo", "/", "bar", NULL);

returns a pointer to 8 bytes worth of memory, initialized to "foo/bar".

Commonly-used pools in the Apache Web server

A pool is really defined by its lifetime more than anything else. There are some static pools in http_main which are passed to various non-http_main functions as arguments at opportune times. Here they are:

permanent_pool
never passed to anything else, this is the ancestor of all pools
pconf
  • subpool of permanent_pool
  • created at the beginning of a config "cycle"; exists until the server is terminated or restarts; passed to all config-time routines, either via cmd->pool, or as the "pool *p" argument on those which don't take pools
  • passed to the module init() functions
ptemp
  • sorry I lie, this pool isn't called this currently in 1.3, I renamed it this in my pthreads development. I'm referring to the use of ptrans in the parent... contrast this with the later definition of ptrans in the child.
  • subpool of permanent_pool
  • created at the beginning of a config "cycle"; exists until the end of config parsing; passed to config-time routines via cmd->temp_pool. Somewhat of a "bastard child" because it isn't available everywhere. Used for temporary scratch space which may be needed by some config routines but which is deleted at the end of config.
pchild
  • subpool of permanent_pool
  • created when a child is spawned (or a thread is created); lives until that child (thread) is destroyed
  • passed to the module child_init functions
  • destruction happens right after the child_exit functions are called... (which may explain why I think child_exit is redundant and unneeded)
ptrans
  • should be a subpool of pchild, but currently is a subpool of permanent_pool, see above
  • cleared by the child before going into the accept() loop to receive a connection
  • used as connection->pool
r->pool
  • for the main request this is a subpool of connection->pool; for subrequests it is a subpool of the parent request's pool.
  • exists until the end of the request (i.e., ap_destroy_sub_req, or in child_main after process_request has finished)
  • note that r itself is allocated from r->pool; i.e., r->pool is first created and then r is the first thing palloc()d from it

For almost everything folks do, r->pool is the pool to use. But you can see how other lifetimes, such as pchild, are useful to some modules... such as modules that need to open a database connection once per child, and wish to clean it up when the child dies.

You can also see how some bugs have manifested themself, such as setting connection->user to a value from r->pool -- in this case connection exists for the lifetime of ptrans, which is longer than r->pool (especially if r->pool is a subrequest!). So the correct thing to do is to allocate from connection->pool.

And there was another interesting bug in mod_include / mod_cgi. You'll see in those that they do this test to decide if they should use r->pool or r->main->pool. In this case the resource that they are registering for cleanup is a child process. If it were registered in r->pool, then the code would wait() for the child when the subrequest finishes. With mod_include this could be any old #include, and the delay can be up to 3 seconds... and happened quite frequently. Instead the subprocess is registered in r->main->pool which causes it to be cleaned up when the entire request is done -- i.e., after the output has been sent to the client and logging has happened.

Tracking open files, etc.

As indicated above, resource pools are also used to track other sorts of resources besides memory. The most common are open files. The routine which is typically used for this is ap_pfopen, which takes a resource pool and two strings as arguments; the strings are the same as the typical arguments to fopen, e.g.,

...
FILE *f = ap_pfopen (r->pool, r->filename, "r");

if (f == NULL) { ... } else { ... }

There is also a ap_popenf routine, which parallels the lower-level open system call. Both of these routines arrange for the file to be closed when the resource pool in question is cleared.

Unlike the case for memory, there are functions to close files allocated with ap_pfopen, and ap_popenf, namely ap_pfclose and ap_pclosef. (This is because, on many systems, the number of files which a single process can have open is quite limited). It is important to use these functions to close files allocated with ap_pfopen and ap_popenf, since to do otherwise could cause fatal errors on systems such as Linux, which react badly if the same FILE* is closed more than once.

(Using the close functions is not mandatory, since the file will eventually be closed regardless, but you should consider it in cases where your module is opening, or could open, a lot of files).

Other sorts of resources -- cleanup functions

More text goes here. Describe the the cleanup primitives in terms of which the file stuff is implemented; also, spawn_process.

Pool cleanups live until clear_pool() is called: clear_pool(a) recursively calls destroy_pool() on all subpools of a; then calls all the cleanups for a; then releases all the memory for a. destroy_pool(a) calls clear_pool(a) and then releases the pool structure itself. i.e., clear_pool(a) doesn't delete a, it just frees up all the resources and you can start using it again immediately.

Fine control -- creating and dealing with sub-pools, with a note on sub-requests

On rare occasions, too-free use of ap_palloc() and the associated primitives may result in undesirably profligate resource allocation. You can deal with such a case by creating a sub-pool, allocating within the sub-pool rather than the main pool, and clearing or destroying the sub-pool, which releases the resources which were associated with it. (This really is a rare situation; the only case in which it comes up in the standard module set is in case of listing directories, and then only with very large directories. Unnecessary use of the primitives discussed here can hair up your code quite a bit, with very little gain).

The primitive for creating a sub-pool is ap_make_sub_pool, which takes another pool (the parent pool) as an argument. When the main pool is cleared, the sub-pool will be destroyed. The sub-pool may also be cleared or destroyed at any time, by calling the functions ap_clear_pool and ap_destroy_pool, respectively. (The difference is that ap_clear_pool frees resources associated with the pool, while ap_destroy_pool also deallocates the pool itself. In the former case, you can allocate new resources within the pool, and clear it again, and so forth; in the latter case, it is simply gone).

One final note -- sub-requests have their own resource pools, which are sub-pools of the resource pool for the main request. The polite way to reclaim the resources associated with a sub request which you have allocated (using the ap_sub_req_... functions) is ap_destroy_sub_req, which frees the resource pool. Before calling this function, be sure to copy anything that you care about which might be allocated in the sub-request's resource pool into someplace a little less volatile (for instance, the filename in its request_rec structure).

(Again, under most circumstances, you shouldn't feel obliged to call this function; only 2K of memory or so are allocated for a typical sub request, and it will be freed anyway when the main request pool is cleared. It is only when you are allocating many, many sub-requests for a single main request that you should seriously consider the ap_destroy_... functions).

Configuration, commands and the like

One of the design goals for this server was to maintain external compatibility with the NCSA 1.3 server --- that is, to read the same configuration files, to process all the directives therein correctly, and in general to be a drop-in replacement for NCSA. On the other hand, another design goal was to move as much of the server's functionality into modules which have as little as possible to do with the monolithic server core. The only way to reconcile these goals is to move the handling of most commands from the central server into the modules.

However, just giving the modules command tables is not enough to divorce them completely from the server core. The server has to remember the commands in order to act on them later. That involves maintaining data which is private to the modules, and which can be either per-server, or per-directory. Most things are per-directory, including in particular access control and authorization information, but also information on how to determine file types from suffixes, which can be modified by AddType and DefaultType directives, and so forth. In general, the governing philosophy is that anything which can be made configurable by directory should be; per-server information is generally used in the standard set of modules for information like Aliases and Redirects which come into play before the request is tied to a particular place in the underlying file system.

Another requirement for emulating the NCSA server is being able to handle the per-directory configuration files, generally called .htaccess files, though even in the NCSA server they can contain directives which have nothing at all to do with access control. Accordingly, after URI -> filename translation, but before performing any other phase, the server walks down the directory hierarchy of the underlying filesystem, following the translated pathname, to read any .htaccess files which might be present. The information which is read in then has to be merged with the applicable information from the server's own config files (either from the <Directory> sections in access.conf, or from defaults in srm.conf, which actually behaves for most purposes almost exactly like <Directory />).

Finally, after having served a request which involved reading .htaccess files, we need to discard the storage allocated for handling them. That is solved the same way it is solved wherever else similar problems come up, by tying those structures to the per-transaction resource pool.

Per-directory configuration structures

Let's look out how all of this plays out in mod_mime.c, which defines the file typing handler which emulates the NCSA server's behavior of determining file types from suffixes. What we'll be looking at, here, is the code which implements the AddType and AddEncoding commands. These commands can appear in .htaccess files, so they must be handled in the module's private per-directory data, which in fact, consists of two separate tables for MIME types and encoding information, and is declared as follows:

typedef struct {
    table *forced_types;      /* Additional AddTyped stuff */
    table *encoding_types;    /* Added with AddEncoding... */
} mime_dir_config;

When the server is reading a configuration file, or <Directory> section, which includes one of the MIME module's commands, it needs to create a mime_dir_config structure, so those commands have something to act on. It does this by invoking the function it finds in the module's `create per-dir config slot', with two arguments: the name of the directory to which this configuration information applies (or NULL for srm.conf), and a pointer to a resource pool in which the allocation should happen.

(If we are reading a .htaccess file, that resource pool is the per-request resource pool for the request; otherwise it is a resource pool which is used for configuration data, and cleared on restarts. Either way, it is important for the structure being created to vanish when the pool is cleared, by registering a cleanup on the pool if necessary).

For the MIME module, the per-dir config creation function just ap_pallocs the structure above, and a creates a couple of tables to fill it. That looks like this:

void *create_mime_dir_config (pool *p, char *dummy)
{
mime_dir_config *new =
(mime_dir_config *) ap_palloc (p, sizeof(mime_dir_config));
new->forced_types = ap_make_table (p, 4);
new->encoding_types = ap_make_table (p, 4);

return new;
 }

Now, suppose we've just read in a .htaccess file. We already have the per-directory configuration structure for the next directory up in the hierarchy. If the .htaccess file we just read in didn't have any AddType or AddEncoding commands, its per-directory config structure for the MIME module is still valid, and we can just use it. Otherwise, we need to merge the two structures somehow.

To do that, the server invokes the module's per-directory config merge function, if one is present. That function takes three arguments: the two structures being merged, and a resource pool in which to allocate the result. For the MIME module, all that needs to be done is overlay the tables from the new per-directory config structure with those from the parent:

void *merge_mime_dir_configs (pool *p, void *parent_dirv, void *subdirv)
{
mime_dir_config *parent_dir = (mime_dir_config *)parent_dirv;
mime_dir_config *subdir = (mime_dir_config *)subdirv;
mime_dir_config *new =
(mime_dir_config *)ap_palloc (p, sizeof(mime_dir_config));
new->forced_types = ap_overlay_tables (p, subdir->forced_types,
parent_dir->forced_types);
 new->encoding_types = ap_overlay_tables (p, subdir->encoding_types,
parent_dir->encoding_types);
return new;
 }

As a note -- if there is no per-directory merge function present, the server will just use the subdirectory's configuration info, and ignore the parent's. For some modules, that works just fine (e.g., for the includes module, whose per-directory configuration information consists solely of the state of the XBITHACK), and for those modules, you can just not declare one, and leave the corresponding structure slot in the module itself NULL.

Command handling

Now that we have these structures, we need to be able to figure out how to fill them. That involves processing the actual AddType and AddEncoding commands. To find commands, the server looks in the module's command table. That table contains information on how many arguments the commands take, and in what formats, where it is permitted, and so forth. That information is sufficient to allow the server to invoke most command-handling functions with pre-parsed arguments. Without further ado, let's look at the AddType command handler, which looks like this (the AddEncoding command looks basically the same, and won't be shown here):

char *add_type(cmd_parms *cmd, mime_dir_config *m, char *ct, char *ext)
{
if (*ext == '.') ++ext;
ap_table_set (m->forced_types, ext, ct);
return NULL;
 }

This command handler is unusually simple. As you can see, it takes four arguments, two of which are pre-parsed arguments, the third being the per-directory configuration structure for the module in question, and the fourth being a pointer to a cmd_parms structure. That structure contains a bunch of arguments which are frequently of use to some, but not all, commands, including a resource pool (from which memory can be allocated, and to which cleanups should be tied), and the (virtual) server being configured, from which the module's per-server configuration data can be obtained if required.

Another way in which this particular command handler is unusually simple is that there are no error conditions which it can encounter. If there were, it could return an error message instead of NULL; this causes an error to be printed out on the server's stderr, followed by a quick exit, if it is in the main config files; for a .htaccess file, the syntax error is logged in the server error log (along with an indication of where it came from), and the request is bounced with a server error response (HTTP error status, code 500).

The MIME module's command table has entries for these commands, which look like this:

command_rec mime_cmds[] = {
{ "AddType", add_type, NULL, OR_FILEINFO, TAKE2,
"a mime type followed by a file extension" },
 { "AddEncoding", add_encoding, NULL, OR_FILEINFO, TAKE2,
"an encoding (e.g., gzip), followed by a file extension" },
 { NULL }
 };

The entries in these tables are:

  • The name of the command
  • The function which handles it
  • a (void *) pointer, which is passed in the cmd_parms structure to the command handler --- this is useful in case many similar commands are handled by the same function.
  • A bit mask indicating where the command may appear. There are mask bits corresponding to each AllowOverride option, and an additional mask bit, RSRC_CONF, indicating that the command may appear in the server's own config files, but not in any .htaccess file.
  • A flag indicating how many arguments the command handler wants pre-parsed, and how they should be passed in. TAKE2 indicates two pre-parsed arguments. Other options are TAKE1, which indicates one pre-parsed argument, FLAG, which indicates that the argument should be On or Off, and is passed in as a boolean flag, RAW_ARGS, which causes the server to give the command the raw, unparsed arguments (everything but the command name itself). There is also ITERATE, which means that the handler looks the same as TAKE1, but that if multiple arguments are present, it should be called multiple times, and finally ITERATE2, which indicates that the command handler looks like a TAKE2, but if more arguments are present, then it should be called multiple times, holding the first argument constant.
  • Finally, we have a string which describes the arguments that should be present. If the arguments in the actual config file are not as required, this string will be used to help give a more specific error message. (You can safely leave this NULL).

Finally, having set this all up, we have to use it. This is ultimately done in the module's handlers, specifically for its file-typing handler, which looks more or less like this; note that the per-directory configuration structure is extracted from the request_rec's per-directory configuration vector by using the ap_get_module_config function.

        int find_ct(request_rec *r)
{
int i;
char *fn = ap_pstrdup (r->pool, r->filename);
mime_dir_config *conf = (mime_dir_config *)
ap_get_module_config(r->per_dir_config, &mime_module);
char *type;

if (S_ISDIR(r->finfo.st_mode)) {
r->content_type = DIR_MAGIC_TYPE;
return OK;
}

if((i=ap_rind(fn,'.')) < 0) return DECLINED;
++i;

if ((type = ap_table_get (conf->encoding_types, &fn[i])))
{
r->content_encoding = type;

/* go back to previous extension to try to use it as a type */
fn[i-1] = '\0';
if((i=ap_rind(fn,'.')) < 0) return OK;
++i;
}

if ((type = ap_table_get (conf->forced_types, &fn[i])))
{
r->content_type = type;
}

return OK;

        }

Side notes -- per-server configuration, virtual servers, etc.

The basic ideas behind per-server module configuration are basically the same as those for per-directory configuration; there is a creation function and a merge function, the latter being invoked where a virtual server has partially overridden the base server configuration, and a combined structure must be computed. (As with per-directory configuration, the default if no merge function is specified, and a module is configured in some virtual server, is that the base configuration is simply ignored).

The only substantial difference is that when a command needs to configure the per-server private module data, it needs to go to the cmd_parms data to get at it. Here's an example, from the alias module, which also indicates how a syntax error can be returned (note that the per-directory configuration argument to the command handler is declared as a dummy, since the module doesn't actually have per-directory config data):

char *add_redirect(cmd_parms *cmd, void *dummy, char *f, char *url)
{
server_rec *s = cmd->server;
alias_server_conf *conf = (alias_server_conf *)
ap_get_module_config(s->module_config,&alias_module);
 alias_entry *new = ap_push_array (conf->redirects);

if (!ap_is_url (url)) return "Redirect to non-URL";

new->fake = f; new->real = url;
return NULL;
 }


Debugging Memory Allocation in APR - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Developer Documentation

Debugging Memory Allocation in APR

The allocation mechanism's within APR have a number of debugging modes that can be used to assist in finding memory problems. This document describes the modes available and gives instructions on activating them.

Available debugging options

Allocation Debugging - ALLOC_DEBUG

Debugging support: Define this to enable code which helps detect re-use of free()d memory and other such nonsense.

The theory is simple. The FILL_BYTE (0xa5) is written over all malloc'd memory as we receive it, and is written over everything that we free up during a clear_pool. We check that blocks on the free list always have the FILL_BYTE in them, and we check during palloc() that the bytes still have FILL_BYTE in them. If you ever see garbage URLs or whatnot containing lots of 0xa5s then you know something used data that's been freed or uninitialized.

Malloc Support - ALLOC_USE_MALLOC

If defined all allocations will be done with malloc() and free()d appropriately at the end.

This is intended to be used with something like Electric Fence or Purify to help detect memory problems. Note that if you're using efence then you should also add in ALLOC_DEBUG. But don't add in ALLOC_DEBUG if you're using Purify because ALLOC_DEBUG would hide all the uninitialized read errors that Purify can diagnose.

Pool Debugging - POOL_DEBUG

This is intended to detect cases where the wrong pool is used when assigning data to an object in another pool.

In particular, it causes the table_{set,add,merge}n routines to check that their arguments are safe for the apr_table_t they're being placed in. It currently only works with the unix multiprocess model, but could be extended to others.

Table Debugging - MAKE_TABLE_PROFILE

Provide diagnostic information about make_table() calls which are possibly too small.

This requires a recent gcc which supports __builtin_return_address(). The error_log output will be a message such as:

table_push: apr_table_t created by 0x804d874 hit limit of 10

Use l *0x804d874 to find the source that corresponds to. It indicates that a apr_table_t allocated by a call at that address has possibly too small an initial apr_table_t size guess.

Allocation Statistics - ALLOC_STATS

Provide some statistics on the cost of allocations.

This requires a bit of an understanding of how alloc.c works.

Allowable Combinations

Not all the options outlined above can be activated at the same time. the following table gives more information.

 | ALLOC DEBUG | ALLOC USE MALLOC | POOL DEBUG | MAKE TABLE PROFILE | ALLOC STATS
ALLOC DEBUG | - | No | Yes | Yes | Yes
ALLOC USE MALLOC | No | - | No | No | No
POOL DEBUG | Yes | No | - | Yes | Yes
MAKE TABLE PROFILE | Yes | No | Yes | - | Yes
ALLOC STATS | Yes | No | Yes | Yes | -

Additionally the debugging options are not suitable for multi-threaded versions of the server. When trying to debug with these options the server should be started in single process mode.

Activating Debugging Options

The various options for debugging memory are now enabled in the apr_general.h header file in APR. The various options are enabled by uncommenting the define for the option you wish to use. The section of the code currently looks like this (contained in srclib/apr/include/apr_pools.h)

/*
#define ALLOC_DEBUG
#define POOL_DEBUG
#define ALLOC_USE_MALLOC
#define MAKE_TABLE_PROFILE
#define ALLOC_STATS
*/

typedef struct ap_pool_t {
union block_hdr *first;
union block_hdr *last;
struct cleanup *cleanups;
struct process_chain *subprocesses;
struct ap_pool_t *sub_pools;
struct ap_pool_t *sub_next;
struct ap_pool_t *sub_prev;
struct ap_pool_t *parent;
char *free_first_avail;
 #ifdef ALLOC_USE_MALLOC
void *allocation_list;
 #endif
#ifdef POOL_DEBUG
struct ap_pool_t *joined;
 #endif
int (*apr_abort)(int retcode);
struct datastruct *prog_data;
 } ap_pool_t;

To enable allocation debugging simply move the #define ALLOC_DEBUG above the start of the comments block and rebuild the server.

Note

In order to use the various options the server must be rebuilt after editing the header file.


Documenting Apache 2.0 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Developer Documentation

Documenting Apache 2.0

Apache 2.0 uses Doxygen to document the APIs and global variables in the the code. This will explain the basics of how to document using Doxygen.

Brief Description

To start a documentation block, use /**
To end a documentation block, use */

In the middle of the block, there are multiple tags we can use:

Description of this functions purpose
@param parameter_name description
@return description
@deffunc signature of the function

The deffunc is not always necessary. DoxyGen does not have a full parser in it, so any prototype that use a macro in the return type declaration is too complex for scandoc. Those functions require a deffunc. An example (using &gt; rather than >):

/**
 * return the final element of the pathname
 * @param pathname The path to get the final element of
 * @return the final element of the path
 * @tip Examples:
 * <pre>
 * "/foo/bar/gum" -&gt; "gum"
 * "/foo/bar/gum/" -&gt; ""
 * "gum" -&gt; "gum"
 * "wi\\n32\\stuff" -&gt; "stuff"
 * </pre>
 * @deffunc const char * ap_filename_of_pathname(const char *pathname)
 */

At the top of the header file, always include:

/**
 * @package Name of library header
 */

Doxygen uses a new HTML file for each package. The HTML files are named {Name_of_library_header}.html, so try to be concise with your names.

For a further discussion of the possibilities please refer to the Doxygen site.


Apache 2.0 Hook Functions - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Developer Documentation

Apache 2.0 Hook Functions

Warning

This document is still in development and may be partially out of date.

In general, a hook function is one that Apache will call at some point during the processing of a request. Modules can provide functions that are called, and specify when they get called in comparison to other modules.

Creating a hook function

In order to create a new hook, four things need to be done:

Declare the hook function

Use the AP_DECLARE_HOOK macro, which needs to be given the return type of the hook function, the name of the hook, and the arguments. For example, if the hook returns an int and takes a request_rec * and an int and is called do_something, then declare it like this:

AP_DECLARE_HOOK(int, do_something, (request_rec *r, int n))

This should go in a header which modules will include if they want to use the hook.

Create the hook structure

Each source file that exports a hook has a private structure which is used to record the module functions that use the hook. This is declared as follows:

APR_HOOK_STRUCT(
APR_HOOK_LINK(do_something)
...
 )

Implement the hook caller

The source file that exports the hook has to implement a function that will call the hook. There are currently three possible ways to do this. In all cases, the calling function is called ap_run_hookname().

Void hooks

If the return value of a hook is void, then all the hooks are called, and the caller is implemented like this:

AP_IMPLEMENT_HOOK_VOID(do_something, (request_rec *r, int n), (r, n))

The second and third arguments are the dummy argument declaration and the dummy arguments as they will be used when calling the hook. In other words, this macro expands to something like this:

void ap_run_do_something(request_rec *r, int n)
{
...
do_something(r, n);
 }

Hooks that return a value

If the hook returns a value, then it can either be run until the first hook that does something interesting, like so:

AP_IMPLEMENT_HOOK_RUN_FIRST(int, do_something, (request_rec *r, int n), (r, n), DECLINED)

The first hook that does not return DECLINED stops the loop and its return value is returned from the hook caller. Note that DECLINED is the tradition Apache hook return meaning "I didn't do anything", but it can be whatever suits you.

Alternatively, all hooks can be run until an error occurs. This boils down to permitting two return values, one of which means "I did something, and it was OK" and the other meaning "I did nothing". The first function that returns a value other than one of those two stops the loop, and its return is the return value. Declare these like so:

AP_IMPLEMENT_HOOK_RUN_ALL(int, do_something, (request_rec *r, int n), (r, n), OK, DECLINED)

Again, OK and DECLINED are the traditional values. You can use what you want.

Call the hook callers

At appropriate moments in the code, call the hook caller, like so:

int n, ret;
request_rec *r;

ret=ap_run_do_something(r, n);

Hooking the hook

A module that wants a hook to be called needs to do two things.

Implement the hook function

Include the appropriate header, and define a static function of the correct type:

static int my_something_doer(request_rec *r, int n)
{
...
return OK;
 }

Add a hook registering function

During initialisation, Apache will call each modules hook registering function, which is included in the module structure:

static void my_register_hooks()
{
ap_hook_do_something(my_something_doer, NULL, NULL, HOOK_MIDDLE);
 }

mode MODULE_VAR_EXPORT my_module =
{
...
my_register_hooks /* register hooks */
 };

Controlling hook calling order

In the example above, we didn't use the three arguments in the hook registration function that control calling order. There are two mechanisms for doing this. The first, rather crude, method, allows us to specify roughly where the hook is run relative to other modules. The final argument control this. There are three possible values: HOOK_FIRST, HOOK_MIDDLE and HOOK_LAST.

All modules using any particular value may be run in any order relative to each other, but, of course, all modules using HOOK_FIRST will be run before HOOK_MIDDLE which are before HOOK_LAST. Modules that don't care when they are run should use HOOK_MIDDLE. (I spaced these out so people could do stuff like HOOK_FIRST-2 to get in slightly earlier, but is this wise? - Ben)

Note that there are two more values, HOOK_REALLY_FIRST and HOOK_REALLY_LAST. These should only be used by the hook exporter.

The other method allows finer control. When a module knows that it must be run before (or after) some other modules, it can specify them by name. The second (third) argument is a NULL-terminated array of strings consisting of the names of modules that must be run before (after) the current module. For example, suppose we want "mod_xyz.c" and "mod_abc.c" to run before we do, then we'd hook as follows:

static void register_hooks()
{
static const char * const aszPre[] = { "mod_xyz.c", "mod_abc.c", NULL };

ap_hook_do_something(my_something_doer, aszPre, NULL, HOOK_MIDDLE);
 }

Note that the sort used to achieve this is stable, so ordering set by HOOK_ORDER is preserved, as far as is possible.

Ben Laurie, 15th August 1999


Converting Modules from Apache 1.3 to Apache 2.0 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Developer Documentation

Converting Modules from Apache 1.3 to Apache 2.0

This is a first attempt at writing the lessons I learned when trying to convert the mod_mmap_static module to Apache 2.0. It's by no means definitive and probably won't even be correct in some ways, but it's a start.

The easier changes ...

Cleanup Routines

These now need to be of type apr_status_t and return a value of that type. Normally the return value will be APR_SUCCESS unless there is some need to signal an error in the cleanup. Be aware that even though you signal an error not all code yet checks and acts upon the error.

Initialisation Routines

These should now be renamed to better signify where they sit in the overall process. So the name gets a small change from mmap_init to mmap_post_config. The arguments passed have undergone a radical change and now look like

  • apr_pool_t *p
  • apr_pool_t *plog
  • apr_pool_t *ptemp
  • server_rec *s

Data Types

A lot of the data types have been moved into the APR. This means that some have had a name change, such as the one shown above. The following is a brief list of some of the changes that you are likely to have to make.

  • pool becomes apr_pool_t
  • table becomes apr_table_t

The messier changes...

Register Hooks

The new architecture uses a series of hooks to provide for calling your functions. These you'll need to add to your module by way of a new function, static void register_hooks(void). The function is really reasonably straightforward once you understand what needs to be done. Each function that needs calling at some stage in the processing of a request needs to be registered, handlers do not. There are a number of phases where functions can be added, and for each you can specify with a high degree of control the relative order that the function will be called in.

This is the code that was added to mod_mmap_static:

static void register_hooks(void)
{
    static const char * const aszPre[]={ "http_core.c",NULL };
    ap_hook_post_config(mmap_post_config,NULL,NULL,HOOK_MIDDLE);
    ap_hook_translate_name(mmap_static_xlat,aszPre,NULL,HOOK_LAST);
};

This registers 2 functions that need to be called, one in the post_config stage (virtually every module will need this one) and one for the translate_name phase. note that while there are different function names the format of each is identical. So what is the format?

ap_hook_phase_name(function_name, predecessors, successors, position);

There are 3 hook positions defined...

  • HOOK_FIRST
  • HOOK_MIDDLE
  • HOOK_LAST

To define the position you use the position and then modify it with the predecessors and successors. Each of the modifiers can be a list of functions that should be called, either before the function is run (predecessors) or after the function has run (successors).

In the mod_mmap_static case I didn't care about the post_config stage, but the mmap_static_xlat must be called after the core module had done it's name translation, hence the use of the aszPre to define a modifier to the position HOOK_LAST.

Module Definition

There are now a lot fewer stages to worry about when creating your module definition. The old defintion looked like

module MODULE_VAR_EXPORT module_name_module =
{
    STANDARD_MODULE_STUFF,
    /* initializer */
    /* dir config creater */
    /* dir merger --- default is to override */
    /* server config */
    /* merge server config */
    /* command handlers */
    /* handlers */
    /* filename translation */
    /* check_user_id */
    /* check auth */
    /* check access */
    /* type_checker */
    /* fixups */
    /* logger */
    /* header parser */
    /* child_init */
    /* child_exit */
    /* post read-request */
};

The new structure is a great deal simpler...

module MODULE_VAR_EXPORT module_name_module =
{
    STANDARD20_MODULE_STUFF,
    /* create per-directory config structures */
    /* merge per-directory config structures  */
    /* create per-server config structures    */
    /* merge per-server config structures     */
    /* command handlers */
    /* handlers */
    /* register hooks */
};

Some of these read directly across, some don't. I'll try to summarise what should be done below.

The stages that read directly across :

/* dir config creater */
/* create per-directory config structures */
/* server config */
/* create per-server config structures */
/* dir merger */
/* merge per-directory config structures */
/* merge server config */
/* merge per-server config structures */
/* command table */
/* command apr_table_t */
/* handlers */
/* handlers */

The remainder of the old functions should be registered as hooks. There are the following hook stages defined so far...

ap_hook_post_config
this is where the old _init routines get registered
ap_hook_http_method
retrieve the http method from a request. (legacy)
ap_hook_open_logs
open any specified logs
ap_hook_auth_checker
check if the resource requires authorization
ap_hook_access_checker
check for module-specific restrictions
ap_hook_check_user_id
check the user-id and password
ap_hook_default_port
retrieve the default port for the server
ap_hook_pre_connection
do any setup required just before processing, but after accepting
ap_hook_process_connection
run the correct protocol
ap_hook_child_init
call as soon as the child is started
ap_hook_create_request
??
ap_hook_fixups
last chance to modify things before generating content
ap_hook_handler
generate the content
ap_hook_header_parser
lets modules look at the headers, not used by most modules, because they use post_read_request for this
ap_hook_insert_filter
to insert filters into the filter chain
ap_hook_log_transaction
log information about the request
ap_hook_optional_fn_retrieve
retrieve any functions registered as optional
ap_hook_post_read_request
called after reading the request, before any other phase
ap_hook_quick_handler
called before any request processing, used by cache modules.
ap_hook_translate_name
translate the URI into a filename
ap_hook_type_checker
determine and/or set the doc type


Request Processing in Apache 2.0 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Developer Documentation

Request Processing in Apache 2.0

Warning

Warning - this is a first (fast) draft that needs further revision!

Several changes in Apache 2.0 affect the internal request processing mechanics. Module authors need to be aware of these changes so they may take advantage of the optimizations and security enhancements.

The first major change is to the subrequest and redirect mechanisms. There were a number of different code paths in Apache 1.3 to attempt to optimize subrequest or redirect behavior. As patches were introduced to 2.0, these optimizations (and the server behavior) were quickly broken due to this duplication of code. All duplicate code has been folded back into ap_process_request_internal() to prevent the code from falling out of sync again.

This means that much of the existing code was 'unoptimized'. It is the Apache HTTP Project's first goal to create a robust and correct implementation of the HTTP server RFC. Additional goals include security, scalability and optimization. New methods were sought to optimize the server (beyond the performance of Apache 1.3) without introducing fragile or insecure code.

The Request Processing Cycle

All requests pass through ap_process_request_internal() in request.c, including subrequests and redirects. If a module doesn't pass generated requests through this code, the author is cautioned that the module may be broken by future changes to request processing.

To streamline requests, the module author can take advantage of the hooks offered to drop out of the request cycle early, or to bypass core Apache hooks which are irrelevant (and costly in terms of CPU.)

The Request Parsing Phase

Unescapes the URL

The request's parsed_uri path is unescaped, once and only once, at the beginning of internal request processing.

This step is bypassed if the proxyreq flag is set, or the parsed_uri.path element is unset. The module has no further control of this one-time unescape operation, either failing to unescape or multiply unescaping the URL leads to security reprecussions.

Strips Parent and This Elements from the URI

All /../ and /./ elements are removed by ap_getparents(). This helps to ensure the path is (nearly) absolute before the request processing continues.

This step cannot be bypassed.

Initial URI Location Walk

Every request is subject to an ap_location_walk() call. This ensures that <Location> sections are consistently enforced for all requests. If the request is an internal redirect or a sub-request, it may borrow some or all of the processing from the previous or parent request's ap_location_walk, so this step is generally very efficient after processing the main request.

translate_name

Modules can determine the file name, or alter the given URI in this step. For example, mod_vhost_alias will translate the URI's path into the configured virtual host, mod_alias will translate the path to an alias path, and if the request falls back on the core, the DocumentRoot is prepended to the request resource.

If all modules DECLINE this phase, an error 500 is returned to the browser, and a "couldn't translate name" error is logged automatically.

Hook: map_to_storage

After the file or correct URI was determined, the appropriate per-dir configurations are merged together. For example, mod_proxy compares and merges the appropriate <Proxy> sections. If the URI is nothing more than a local (non-proxy) TRACE request, the core handles the request and returns DONE. If no module answers this hook with OK or DONE, the core will run the request filename against the <Directory> and <Files> sections. If the request 'filename' isn't an absolute, legal filename, a note is set for later termination.

URI Location Walk

Every request is hardened by a second ap_location_walk() call. This reassures that a translated request is still subjected to the configured <Location> sections. The request again borrows some or all of the processing from its previous location_walk above, so this step is almost always very efficient unless the translated URI mapped to a substantially different path or Virtual Host.

Hook: header_parser

The main request then parses the client's headers. This prepares the remaining request processing steps to better serve the client's request.

The Security Phase

Needs Documentation. Code is:

switch (ap_satisfies(r)) {
case SATISFY_ALL:
case SATISFY_NOSPEC:
    if ((access_status = ap_run_access_checker(r)) != 0) {
        return decl_die(access_status, "check access", r);
    }

    if (ap_some_auth_required(r)) {
        if (((access_status = ap_run_check_user_id(r)) != 0)
            || !ap_auth_type(r)) {
            return decl_die(access_status, ap_auth_type(r)
                          ? "check user.  No user file?"
                          : "perform authentication. AuthType not set!",
                          r);
        }

        if (((access_status = ap_run_auth_checker(r)) != 0)
            || !ap_auth_type(r)) {
            return decl_die(access_status, ap_auth_type(r)
                          ? "check access.  No groups file?"
                          : "perform authentication. AuthType not set!",
                          r);
        }
    }
    break;

case SATISFY_ANY:
    if (((access_status = ap_run_access_checker(r)) != 0)) {
        if (!ap_some_auth_required(r)) {
            return decl_die(access_status, "check access", r);
        }

        if (((access_status = ap_run_check_user_id(r)) != 0)
            || !ap_auth_type(r)) {
            return decl_die(access_status, ap_auth_type(r)
                          ? "check user.  No user file?"
                          : "perform authentication. AuthType not set!",
                          r);
        }

        if (((access_status = ap_run_auth_checker(r)) != 0)
            || !ap_auth_type(r)) {
            return decl_die(access_status, ap_auth_type(r)
                          ? "check access.  No groups file?"
                          : "perform authentication. AuthType not set!",
                          r);
        }
    }
    break;
}

The Preparation Phase

Hook: type_checker

The modules have an opportunity to test the URI or filename against the target resource, and set mime information for the request. Both mod_mime and mod_mime_magic use this phase to compare the file name or contents against the administrator's configuration and set the content type, language, character set and request handler. Some modules may set up their filters or other request handling parameters at this time.

If all modules DECLINE this phase, an error 500 is returned to the browser, and a "couldn't find types" error is logged automatically.

Hook: fixups

Many modules are 'trounced' by some phase above. The fixups phase is used by modules to 'reassert' their ownership or force the request's fields to their appropriate values. It isn't always the cleanest mechanism, but occasionally it's the only option.

The Handler Phase

This phase is not part of the processing in ap_process_request_internal(). Many modules prepare one or more subrequests prior to creating any content at all. After the core, or a module calls ap_process_request_internal() it then calls ap_invoke_handler() to generate the request.

Hook: insert_filter

Modules that transform the content in some way can insert their values and override existing filters, such that if the user configured a more advanced filter out-of-order, then the module can move its order as need be. There is no result code, so actions in this hook better be trusted to always succeed.

Hook: handler

The module finally has a chance to serve the request in its handler hook. Note that not every prepared request is sent to the handler hook. Many modules, such as mod_autoindex, will create subrequests for a given URI, and then never serve the subrequest, but simply lists it for the user. Remember not to put required teardown from the hooks above into this module, but register pool cleanups against the request pool to free resources as required.


How filters work in Apache 2.0 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Developer Documentation

How filters work in Apache 2.0

Warning

This is a cut 'n paste job from an email (<022501c1c529$f63a9550$7f00000a@KOJ>) and only reformatted for better readability. It's not up to date but may be a good start for further research.

Filter Types

There are three basic filter types (each of these is actually broken down into two categories, but that comes later).

CONNECTION
Filters of this type are valid for the lifetime of this connection. (AP_FTYPE_CONNECTION, AP_FTYPE_NETWORK)
PROTOCOL
Filters of this type are valid for the lifetime of this request from the point of view of the client, this means that the request is valid from the time that the request is sent until the time that the response is received. (AP_FTYPE_PROTOCOL, AP_FTYPE_TRANSCODE)
RESOURCE
Filters of this type are valid for the time that this content is used to satisfy a request. For simple requests, this is identical to PROTOCOL, but internal redirects and sub-requests can change the content without ending the request. (AP_FTYPE_RESOURCE, AP_FTYPE_CONTENT_SET)

It is important to make the distinction between a protocol and a resource filter. A resource filter is tied to a specific resource, it may also be tied to header information, but the main binding is to a resource. If you are writing a filter and you want to know if it is resource or protocol, the correct question to ask is: "Can this filter be removed if the request is redirected to a different resource?" If the answer is yes, then it is a resource filter. If it is no, then it is most likely a protocol or connection filter. I won't go into connection filters, because they seem to be well understood. With this definition, a few examples might help:

Byterange
We have coded it to be inserted for all requests, and it is removed if not used. Because this filter is active at the beginning of all requests, it can not be removed if it is redirected, so this is a protocol filter.
http_header
This filter actually writes the headers to the network. This is obviously a required filter (except in the asis case which is special and will be dealt with below) and so it is a protocol filter.
Deflate
The administrator configures this filter based on which file has been requested. If we do an internal redirect from an autoindex page to an index.html page, the deflate filter may be added or removed based on config, so this is a resource filter.

The further breakdown of each category into two more filter types is strictly for ordering. We could remove it, and only allow for one filter type, but the order would tend to be wrong, and we would need to hack things to make it work. Currently, the RESOURCE filters only have one filter type, but that should change.

How are filters inserted?

This is actually rather simple in theory, but the code is complex. First of all, it is important that everybody realize that there are three filter lists for each request, but they are all concatenated together. So, the first list is r->output_filters, then r->proto_output_filters, and finally r->connection->output_filters. These correspond to the RESOURCE, PROTOCOL, and CONNECTION filters respectively. The problem previously, was that we used a singly linked list to create the filter stack, and we started from the "correct" location. This means that if I had a RESOURCE filter on the stack, and I added a CONNECTION filter, the CONNECTION filter would be ignored. This should make sense, because we would insert the connection filter at the top of the c->output_filters list, but the end of r->output_filters pointed to the filter that used to be at the front of c->output_filters. This is obviously wrong. The new insertion code uses a doubly linked list. This has the advantage that we never lose a filter that has been inserted. Unfortunately, it comes with a separate set of headaches.

The problem is that we have two different cases were we use subrequests. The first is to insert more data into a response. The second is to replace the existing response with an internal redirect. These are two different cases and need to be treated as such.

In the first case, we are creating the subrequest from within a handler or filter. This means that the next filter should be passed to make_sub_request function, and the last resource filter in the sub-request will point to the next filter in the main request. This makes sense, because the sub-request's data needs to flow through the same set of filters as the main request. A graphical representation might help:

Default_handler --> includes_filter --> byterange --> ...

If the includes filter creates a sub request, then we don't want the data from that sub-request to go through the includes filter, because it might not be SSI data. So, the subrequest adds the following:

Default_handler --> includes_filter -/-> byterange --> ...
                                    /
Default_handler --> sub_request_core

What happens if the subrequest is SSI data? Well, that's easy, the includes_filter is a resource filter, so it will be added to the sub request in between the Default_handler and the sub_request_core filter.

The second case for sub-requests is when one sub-request is going to become the real request. This happens whenever a sub-request is created outside of a handler or filter, and NULL is passed as the next filter to the make_sub_request function.

In this case, the resource filters no longer make sense for the new request, because the resource has changed. So, instead of starting from scratch, we simply point the front of the resource filters for the sub-request to the front of the protocol filters for the old request. This means that we won't lose any of the protocol filters, neither will we try to send this data through a filter that shouldn't see it.

The problem is that we are using a doubly-linked list for our filter stacks now. But, you should notice that it is possible for two lists to intersect in this model. So, you do you handle the previous pointer? This is a very difficult question to answer, because there is no "right" answer, either method is equally valid. I looked at why we use the previous pointer. The only reason for it is to allow for easier addition of new servers. With that being said, the solution I chose was to make the previous pointer always stay on the original request.

This causes some more complex logic, but it works for all cases. My concern in having it move to the sub-request, is that for the more common case (where a sub-request is used to add data to a response), the main filter chain would be wrong. That didn't seem like a good idea to me.

Asis

The final topic. :-) Mod_Asis is a bit of a hack, but the handler needs to remove all filters except for connection filters, and send the data. If you are using mod_asis, all other bets are off.

Explanations

The absolutely last point is that the reason this code was so hard to get right, was because we had hacked so much to force it to work. I wrote most of the hacks originally, so I am very much to blame. However, now that the code is right, I have started to remove some hacks. Most people should have seen that the reset_filters and add_required_filters functions are gone. Those inserted protocol level filters for error conditions, in fact, both functions did the same thing, one after the other, it was really strange. Because we don't lose protocol filters for error cases any more, those hacks went away. The HTTP_HEADER, Content-length, and Byterange filters are all added in the insert_filters phase, because if they were added earlier, we had some interesting interactions. Now, those could all be moved to be inserted with the HTTP_IN, CORE, and CORE_IN filters. That would make the code easier to follow.


용어 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

용어

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 문서는 웹 서비스 일반에 대한, 특히 아파치와 관련된, 용어들을 정의한다. 각 개념에 대한 자세한 정보는 링크를 참고하라. (역주; 현재 단어의 순서는 한글 순서가 아니라, 영문자 순서입니다. 용어번역표는 여기를 참고하길 바랍니다.)

정의

접근제어 (Access Control)
네트웍 영역에 대한 접근을 제한. 아파치에서는 보통 특정 URL의 접근을 제한하기위해 사용한다.
참고: 인증, 권한부여, 접근제어
알고리즘 (Algorithm)
유한한 단계를 거쳐 문제를 푸는 명확한 공식 혹은 규칙들. 암호화를 위한 알고리즘을 보통 암호기(Ciphers)라고 부른다.
APache eXtension Tool (apxs)
모듈 (module) 소스를 동적공유객체 (DSO)로 컴파일하고 아파치 웹서버에 설치하는 작업을 돕는 perl 스크립트.
참고: Manpage: apxs
인증 (Authentication)
서버, 클라이언트, 사용자 등 네트웍 실체에 대한 확인.
참고: 인증, 권한부여, 접근제어
인증서 (Certificate)
서버나 클라이언트와 같은 네트웍 실체를 인증하는 자료. 인증서에는 소유자 (subject라고 함), 서명 인증기관 (Certificate Authority) (issuer라고 함), 소유자의 공개키, CA가 만든 서명 등에 대한 X.509 정보가 있다. 네트웍 실체는 CA 인증서를 사용하여 서명을 검사한다.
참고: SSL/TLS 암호화
인증 서명 요청 (Certificate Signing Request, CSR)
인증기관 (Certification Authority)에 제출하여 CA 인증서 (Certificate)의 개인키 (Private Key)로 서명될 아직 서명되지않은 인증서. CSR이 서명되면 실제 인증서가 된다.
참고: SSL/TLS 암호화
인증기관 (Certification Authority, CA)
안전한 방법으로 네트웍 실체에 대한 인증을 서명하는 신뢰하는 제삼자. 다른 네트웍 실체들은 서명으로 CA가 인증서 소유자를 인증했는지 확인할 수 있다.
참고: SSL/TLS 암호화
암호기 (Cipher)
자료를 암호화하는 알고리즘이나 시스템. 예를 들어, DES, IDEA, RC4 등이 있다.
참고: SSL/TLS 암호화
암호문 (Ciphertext)
평문 (Plaintext)을 암호기 (Cipher)로 처리한 결과.
참고: SSL/TLS 암호화
공통 게이트웨이 인터페이스 (Common Gateway Interface, CGI)
외부 프로그램이 요청을 서비스할 수 있도록 만든 웹서버와 외부 프로그램 사이의 인터페이스 표준. 인터페이스는 원래 NCSA가 정의했지만, RFC 프로젝트이기도 하다.
참고: CGI로 동적 페이지 생성
설정 지시어 (Configuration Directive)
참고: 지시어
설정파일 (Configuration File)
아파치를 설정하는 지시어 (directive)를 적어둔 텍스트파일.
참고: 설정파일
CONNECT
HTTP를 통해 자료흐름을 프록시하는 HTTP 메써드 (method). SSL 프로토콜 등 다른 프로토콜을 감싸기위해 사용한다.
사용장소 (Context)
설정파일 (configuration file)에서 특정 지시어 (directive)를 사용할 수 있는 장소.
참고: 아파치 지시어를 설명하는데 사용한 용어정의
전자서명 (Digital Signature)
인증서나 다른 파일을 검사하는 암호화된 문자들. 인증기관 (Certification Authority)은 인증서 (Certificate)에 포함된 공개키 (Public Key)를 해쉬한 결과를 자신의 개인키 (Private Key)로 암호화하여 서명을 만든다. 오직 CA의 공개키만이 서명을 풀 수 있기때문에, CA가 인증서 (Certificate)를 가진 네트웍 실체를 인증했음을 증명할 수 있다.
참고: SSL/TLS 암호화
지시어 (Directive)
아파치의 여러 기능을 조절하는 설정 명령어. 지시어는 설정파일 (Configuration File)에서 사용한다.
참고: 지시어 목록
동적공유객체 (Dynamic Shared Object) (DSO)
아파치 httpd 실행파일과 별도로 컴파일하여 필요할때 읽어들일 수 있는 모듈 (Module).
참고: 동적공유객체 지원
환경변수 (Environment Variable) (env-variable)
정보를 저장하고 프로그램간에 통신을 위해 운영체제 쉘이 관리하는 변수. 아파치에도 환경변수라는 내부 변수가 있지만, 쉘 환경이 아니라 아파치 내부에 저장된다.
참고: 아파치의 환경변수
수출용 (Export-Crippled)
미국 수출관리규제(Export Administration Regulations, EAR)를 준수하기위해 암호(와 보안)의 강도를 낮춤. 수출용 암호화 소프트웨어는 키 크기가 작게 제한되어, 암호문 (Ciphertext)을 무식한 방법(brute force)으로 풀 수 있다.
참고: SSL/TLS 암호화 (SSL/TLS Encryption)
필터 (Filter)
서버가 보내거나 받는 자료를 처리하는 과정. 입력필터는 클라이언트가 서버로 보내는 자료를 처리하고, 출력필터는 서버가 클라이언트에게 보낼 문서를 처리한다. 예를 들어, INCLUDES 출력필터는 문서의 Server Side Includes를 처리한다.
참고: 필터
완전한 도메인명 (Fully-Qualified Domain-Name) (FQDN)
IP 주소에 대응하는, 호스트명과 도메인명으로 구성된 네트웍 실체의 유일한 이름. 예를 들어, www가 호스트명이고 example.com이 도메인명일때, www.example.com은 완전한 도메인명이다.
핸들러 (Handler)
파일을 요청할때 수행하는 작업에 대한 아파치 내부 표현. 일반적으로 파일은 파일 종류에 따라 암묵적인 핸들러를 가진다. 보통 모든 파일은 서버가 간단히 서비스하지만, 어떤 파일 종류는 따로 "처리된다(handled)". 예를 들어, cgi-script 핸들러는 CGI로 처리할 파일을 지정한다.
참고: 아파치에서 핸들러 사용
헤더 (Header)
HTTP 요청과 응답에서 실제 내용 이전에 보내는 부분으로 내용을 설명하는 정보가 있다.
.htaccess
웹문서들 안에 있는 설정파일 (configuration file)로, 설정 지시어 (directive)를 자신이 위치한 디렉토리와 모든 하위디렉토리에 적용한다. 이름과 달리 이 파일에서는 단순한 접근제어 지시어외에 거의 모든 종류의 지시어를 사용할 수 있다.
참고: 설정파일
httpd.conf
아파치 주 설정파일 (configuration file). 기본적인 위치는 /usr/local/apache2/conf/httpd.conf이지만, 실행할때 혹은 컴파일때 설정으로 변경할 수 있다.
참고: 설정파일
HyperText Transfer Protocol (HTTP)
월드와이드웹에서 사용하는 표준 전송 프로토콜. 아파치는 RFC 2616에서 정의한 HTTP/1.1이라는 프로토콜의 1.1 버전을 구현한다.
HTTPS
월드화이드웹의 표준 암호통신 방법, HyperText Transfer Protocol (Secure). 사실 밑단에 SSL을 사용한 HTTP이다.
참고: SSL/TLS 암호화
메써드 (Method)
클라이언트가 보내는 HTTP 요청줄이 자원에 수행하도록 지시한 행동. HTTP 메써드에는 GET, POST, PUT 등이 있다.
메시지 요약 (Message Digest)
메시지 내용이 전송중 변경되지 않았음을 증명하기위한 메시지의 해쉬.
참고: SSL/TLS 암호화
MIME-type
전송할 문서의 종류를 설명하는 방식. Multipurpose Internet Mail Extensions 형식을 빌려왔기때문에 이렇게 이름을 지었다. 슬래쉬를 사이에 둔 major type과 minor type으로 이루어진다. 예를 들면, text/html, image/gif, application/octet-stream 등이다. MIME-type은 HTTP의 Content-Type 헤더 (header)로 전송한다.
참고: mod_mime
모듈 (Module)
프로그램의 독립된 부분. 많은 아파치 기능은 당신이 포함여부를 선택할 수 있는 모듈에 들어있다. 아파치 httpd 실행파일과 같이 컴파일한 모듈을 정적 모듈이라고 하며, 따로 분리되어 실행시 선택적으로 읽어들일 수 있는 모듈을 동적 모듈 혹은 DSO라고 한다. 기본적으로 포함하는 모듈을 base 모듈이라고 한다. 아파치 웹서버 타볼 (tarball)과 같이 배포되지는 않지만 아파치에는 많은 모듈들이 있다. 이들을 제삼자가 만든(third-party) 모듈이라고 한다.
참고: 모듈 목록
모듈 마법수 (Module Magic Number) (MMN)
모듈 마법수는 아파치 소스코드가 정의한 상수로, 모듈의 이진호환성과 관련이 있다. 모듈 마법수는 이진호환성을 더 이상 보장할 수 없도록 아파치 내부 구조나 함수 호출, 다른 API 일부가 변경된 경우에 바뀐다. MMN이 변하면 제삼자가 만든 모듈은 모두 최소한 다시 컴파일되야 한다. 새 아파치 버전에 맞도록 조금 수정해야할 경우도 있다.
OpenSSL
SSL/TLS를 위한 오픈소스 도구
참고 http://www.openssl.org/
Pass Phrase
개인키 파일을 보호하는 문구. 인증하지않은 사용자가 이 개인키 파일을 사용하여 암호화하지 못하도록 한다. 보통 암호기 (Ciphers)가 사용하는 비밀스런 암호/해독 키이다.
참고: SSL/TLS 암호화
평문 (Plaintext)
암호화하지 않은 글.
개인키 (Private Key)
받은 자료를 해독하고 보내는 자료를 서명하기위한 공개키 암호화 (Public Key Cryptography) 시스템의 암호키.
참고: SSL/TLS 암호화
프록시 (Proxy)
클라이언트와 실제 서버 사이에 있는 중간 서버. 클라이언트에게 요청을 받아 실제 서버로 보내고, 실제 서버에게서 받은 응답을 다시 클라이언트에게 보낸다. 여러 클라이언트가 같은 내용을 요청하면 프록시는 매번 서버에 요청하지않고 캐쉬에 저장된 내용을 사용하여 응답시간을 줄일 수 있다.
참고: mod_proxy
공개키 (Public Key)
공개키 암호화 (Public Key Cryptography) 시스템에서 키의 소유자에게 보내는 문구를 암호화하거나 소유자가 만든 서명을 풀기위한 공개된 키.
참고: SSL/TLS 암호화
공개키 암호화 (Public Key Cryptography)
암호와 해독에 서로 다른 키를 사용하는 비대칭(asymmetric) 암호화 시스템의 연구 및 활용. 암호와 해독에 사용하는 두개의 키는 키쌍(key pair)을 이룬다. 비대칭 암호화라고도 부른다.
참고: SSL/TLS 암호화
정규표현식 (Regular Expression) (Regex)
글의 패턴을 기술하는 방식. 예를 들어, "문자 A로 시작하는 모든 단어", "숫자 10개로된 전화번호", 심지어 "쉼표가 두개있고 대문자 Q가 없는 문장" 등을 표현할 수 있다. 정규표현식을 사용하면 매우 유연하게 파일이나 자원에 어떤 성질을 적용할 수 있다. 예를 들어, "images"란 디렉토리 아래에 있는 모든 .gif와 .jpg 파일은 "/images/.*(jpg|gif)$"로 지칭할 수 있다. 아파치는 PCRE 라이브러리를 사용하여 Perl호환 정규표현식을 지원한다.
역프록시 (Reverse Proxy)
클라이언트에게 실제 서버처럼 보이는 프록시 (proxy) 서버. 보안상 이유 혹은 부하를 분산하기위해 클라이언트에게 실제 서버를 숨길때 유용하다.
Secure Sockets Layer (SSL)
Netscape Communications사가 TCP/IP 네트웍의 일반적인 통신 인증과 암호화를 위해 만든 프로토콜. 가장 일반적인 용도는 HTTPS (HyperText Transfer Protocol (HTTP) over SSL)이다.
참고: SSL/TLS 암호화
Server Side Includes (SSI)
HTML 파일 안에 처리지시어를 포함하는 기술.
참고: Server Side Includes 소개
세션 (Session)
일반적으로 통신의 상황(context) 정보.
SSLeay
Eric A. Young이 개발한 원래 SSL/TLS 구현 라이브러리
대칭적 암호법 (Symmetric Cryptography)
암호와 해독 작업에 같은 암호키를 사용하는 암호기 (Ciphers)의 연구 및 활용.
참고: SSL/TLS Encryption
타볼 (Tarball)
tar 도구를 사용하여 파일들을 모은 묶음. 아파치는 tar 파일을 압축하거나 pkzip으로 압축하여 배포된다.
Transport Layer Security (TLS)
인터넷기술 관련 국제표준화기구(Internet Engineering Task Force, IETF)가 TCP/IP 네트웍의 일반적인 통신 인증과 암호화를 위해 만든 SSL의 후속 프로토콜. TLS 버전 1은 SSL 버전 3과 거의 유사하다.
참고: SSL/TLS 암호화
Uniform Resource Locator (URL)
인터넷에 있는 자원의 이름/주소. 정식으로는 Uniform Resource Identifier라고 하는 것의 일상적인 비공식 명칭이다. 보통 URL은 http나 https같은 스킴(scheme), 호스트명, 경로로 구성된다. 이 페이지의 URL은 http://httpd.apache.org/docs-2.0/glossary.html이다.
Uniform Resource Identifier (URI)
추상적인 자원이나 실제 자원을 지칭하기위한 간결한 문자열. 공식적으로 RFC 2396에서 정의한다. 월드와이드웹에서 사용하는 URI를 보통 URL이라고 부른다.
가상호스트 (Virtual Hosting)
아파치 하나로 여러 웹사이트를 서비스하기. IP 가상호스트는 웹사이트마다 IP 주소가 다르다. 이름기반(name-based) 가상호스트는 호스트명만을 사용하므로 한 IP 주소에서 여러 사이트를 서비스할 수 있다.
참고: 아파치 가상호스트 문서
X.509
국제전기통신연합(International Telecommunication Union, ITU-T)이 권장하는 인증서 양식. SSL/TLS 인증에서 사용한다.
참고: SSL/TLS 암호화


모듈 목록 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

모듈 목록

다음은 아파치 배포본에 포함된 모든 모듈 목록이다. 모든 아파치 지시어 목록도 참고하라.

참고

  • 다중처리모듈 (MPM)
  • 지시어 빠른참고

핵심 기능과 다중처리 모듈

core
Core Apache HTTP Server features that are always available
mpm_common
A collection of directives that are implemented by more than one multi-processing module (MPM)
beos
BeOS에 최적화된 다중처리 모듈.
leader
표준 worker MPM의 실험적인 변형
mpm_netware
Multi-Processing Module implementing an exclusively threaded web server optimized for Novell NetWare
mpmt_os2
Hybrid multi-process, multi-threaded MPM for OS/2
perchild
Multi-Processing Module allowing for daemon processes serving requests to be assigned a variety of different userids
prefork
Implements a non-threaded, pre-forking web server
threadpool
Yet another experimental variant of the standard worker MPM
mpm_winnt
This Multi-Processing Module is optimized for Windows NT.
worker
Multi-Processing Module implementing a hybrid multi-threaded multi-process web server

다른 모듈

A | C | D | E | F | H | I | L | M | N | P | R | S | U | V

mod_access
Provides access control based on client hostname, IP address, or other characteristics of the client request.
mod_actions
이 모듈은 미디어종류나 요청메서드에 따라 CGI 스크립트를 실행한다.
mod_alias
파일시스템의 다른 부분들을 문서 계층구조에 포함하고, URL 리다이렉션을 제공한다
mod_asis
HTTP 헤더를 포함한 파일을 보낸다
mod_auth
User authentication using text files
mod_auth_anon
Allows "anonymous" user access to authenticated areas
mod_auth_dbm
Provides for user authentication using DBM files
mod_auth_digest
MD5 Digest Authentication을 사용한 사용자인증.
mod_auth_ldap
Allows an LDAP directory to be used to store the database for HTTP Basic authentication.
mod_autoindex
자동으로 유닉스의 ls 명령어나 Win32의 dir 쉘명령어와 유사한 디렉토리 목록을 만든다
mod_cache
Content cache keyed to URIs.
mod_cern_meta
CERN 웹서버 메타파일 지원
mod_cgi
CGI 스크립트 실행
mod_cgid
외부 CGI 데몬을 사용하여 CGI 스크립트를 실행
mod_charset_lite
문자집합 변환을 지정
mod_dav
Distributed Authoring and Versioning (WebDAV) 기능
mod_dav_fs
mod_dav을 위한 파일시스템 제공자
mod_deflate
내용을 클라이언트로 보내기 전에 압축한다
mod_dir
"마지막 슬래쉬" 리다이렉션을 제공하고 디렉토리 index 파일을 서비스한다
mod_disk_cache
Content cache storage manager keyed to URIs
mod_dumpio
Dumps all I/O to error log as desired.
mod_echo
프로토콜 모듈을 설명하기위한 간단한 echo 서버
mod_env
CGI 스크립트나 SSI 페이지에 전달할 환경변수를 수정한다
mod_example
아파치 모듈 API를 설명한다
mod_expires
사용자가 지정한 기준에 따라 Expires와 Cache-Control HTTP 헤더를 생성한다
mod_ext_filter
응답 내용을 외부 프로그램으로 처리한 후 클라이언트로 보낸다
mod_file_cache
메모리에 정적 파일들을 캐쉬
mod_headers
HTTP 요청 헤더와 응답 헤더 수정
mod_imap
서버측 이미지맵(imagemap) 처리
mod_include
Server-parsed html documents (Server Side Includes)
mod_info
서버 설정에 대한 종합적인 정보를 보여준다
mod_isapi
Windows용 아파치에서 ISAPI Extension 사용
mod_ldap
LDAP connection pooling and result caching services for use by other LDAP modules
mod_log_config
서버로의 요청을 로그에 기록한다
mod_log_forensic
Forensic Logging of the requests made to the server
mod_logio
요청당 입출력 바이트수를 기록
mod_mem_cache
URI를 키로 사용하여 내용을 캐쉬한다.
mod_mime
Associates the requested filename's extensions with the file's behavior (handlers and filters) and content (mime-type, language, character set and encoding)
mod_mime_magic
Determines the MIME type of a file by looking at a few bytes of its contents
mod_negotiation
Provides for content negotiation
mod_nw_ssl
Enable SSL encryption for NetWare
mod_proxy
HTTP/1.1 proxy/gateway server
mod_proxy_connect
mod_proxy extension for CONNECT request handling
mod_proxy_ftp
FTP support module for mod_proxy
mod_proxy_http
HTTP support module for mod_proxy
mod_rewrite
Provides a rule-based rewriting engine to rewrite requested URLs on the fly
mod_setenvif
요청의 성격에 따라 환경변수 설정을 변경한다
mod_so
시작할때 혹은 재시작할때 실행가능한 코드와 모듈을 서버로 읽어들인다
mod_speling
사용자가 대소문자를 잘못 사용하거나 맞춤법이 틀리는 것을 한번까지 허용하여 잘못된 URL을 고치려고 시도한다
mod_ssl
Strong cryptography using the Secure Sockets Layer (SSL) and Transport Layer Security (TLS) protocols
mod_status
서버 활동과 성능에 대한 정보를 제공한다
mod_suexec
CGI 스크립트를 특정 사용자와 그룹 권한으로 실행한다
mod_unique_id
각 요청마다 유일한 식별자를 가지는 환경변수를 제공한다
mod_userdir
사용자별 디렉토리
mod_usertrack
Clickstream logging of user activity on a site
mod_vhost_alias
Provides for dynamically configured mass virtual hosting


지시어 목록 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

지시어 목록

다음은 표준 아파치 배포본에서 사용가능한 지시어 목록이다. 이들을 동일한 형식으로 설명하였고, 설명에 사용한 용어 사전도 있다.

각 지시어를 요약하여 설명한 지시어 빠른참조도 있다.

A | B | C | D | E | F | G | H | I | K | L | M | N | O | P | R | S | T | U | V | W | X

  • AcceptMutex
  • AcceptPathInfo
  • AccessFileName
  • Action
  • AddAlt
  • AddAltByEncoding
  • AddAltByType
  • AddCharset
  • AddDefaultCharset
  • AddDescription
  • AddEncoding
  • AddHandler
  • AddIcon
  • AddIconByEncoding
  • AddIconByType
  • AddInputFilter
  • AddLanguage
  • AddModuleInfo
  • AddOutputFilter
  • AddOutputFilterByType
  • AddType
  • Alias
  • AliasMatch
  • Allow
  • AllowCONNECT
  • AllowEncodedSlashes
  • AllowOverride
  • Anonymous
  • Anonymous_Authoritative
  • Anonymous_LogEmail
  • Anonymous_MustGiveEmail
  • Anonymous_NoUserID
  • Anonymous_VerifyEmail
  • AssignUserID
  • AuthAuthoritative
  • AuthDBMAuthoritative
  • AuthDBMGroupFile
  • AuthDBMType
  • AuthDBMUserFile
  • AuthDigestAlgorithm
  • AuthDigestDomain
  • AuthDigestFile
  • AuthDigestGroupFile
  • AuthDigestNcCheck
  • AuthDigestNonceFormat
  • AuthDigestNonceLifetime
  • AuthDigestQop
  • AuthDigestShmemSize
  • AuthGroupFile
  • AuthLDAPAuthoritative
  • AuthLDAPBindDN
  • AuthLDAPBindPassword
  • AuthLDAPCharsetConfig
  • AuthLDAPCompareDNOnServer
  • AuthLDAPDereferenceAliases
  • AuthLDAPEnabled
  • AuthLDAPFrontPageHack
  • AuthLDAPGroupAttribute
  • AuthLDAPGroupAttributeIsDN
  • AuthLDAPRemoteUserIsDN
  • AuthLDAPUrl
  • AuthName
  • AuthType
  • AuthUserFile
  • BrowserMatch
  • BrowserMatchNoCase
  • BS2000Account
  • CacheDefaultExpire
  • CacheDirLength
  • CacheDirLevels
  • CacheDisable
  • CacheEnable
  • CacheExpiryCheck
  • CacheFile
  • CacheForceCompletion
  • CacheGcClean
  • CacheGcDaily
  • CacheGcInterval
  • CacheGcMemUsage
  • CacheGcUnused
  • CacheIgnoreCacheControl
  • CacheIgnoreNoLastMod
  • CacheLastModifiedFactor
  • CacheMaxExpire
  • CacheMaxFileSize
  • CacheMinFileSize
  • CacheNegotiatedDocs
  • CacheRoot
  • CacheSize
  • CacheTimeMargin
  • CGIMapExtension
  • CharsetDefault
  • CharsetOptions
  • CharsetSourceEnc
  • CheckSpelling
  • ChildPerUserID
  • ContentDigest
  • CookieDomain
  • CookieExpires
  • CookieLog
  • CookieName
  • CookieStyle
  • CookieTracking
  • CoreDumpDirectory
  • CustomLog
  • Dav
  • DavDepthInfinity
  • DavLockDB
  • DavMinTimeout
  • DefaultIcon
  • DefaultLanguage
  • DefaultType
  • DeflateBufferSize
  • DeflateCompressionLevel
  • DeflateFilterNote
  • DeflateMemLevel
  • DeflateWindowSize
  • Deny
  • <Directory>
  • DirectoryIndex
  • <DirectoryMatch>
  • DirectorySlash
  • DocumentRoot
  • DumpIOInput
  • DumpIOOutput
  • EnableExceptionHook
  • EnableMMAP
  • EnableSendfile
  • ErrorDocument
  • ErrorLog
  • Example
  • ExpiresActive
  • ExpiresByType
  • ExpiresDefault
  • ExtendedStatus
  • ExtFilterDefine
  • ExtFilterOptions
  • FileETag
  • <Files>
  • <FilesMatch>
  • ForceLanguagePriority
  • ForceType
  • ForensicLog
  • Group
  • Header
  • HeaderName
  • HostnameLookups
  • IdentityCheck
  • <IfDefine>
  • <IfModule>
  • ImapBase
  • ImapDefault
  • ImapMenu
  • Include
  • IndexIgnore
  • IndexOptions
  • IndexOrderDefault
  • ISAPIAppendLogToErrors
  • ISAPIAppendLogToQuery
  • ISAPICacheFile
  • ISAPIFakeAsync
  • ISAPILogNotSupported
  • ISAPIReadAheadBuffer
  • KeepAlive
  • KeepAliveTimeout
  • LanguagePriority
  • LDAPCacheEntries
  • LDAPCacheTTL
  • LDAPConnectionTimeout
  • LDAPOpCacheEntries
  • LDAPOpCacheTTL
  • LDAPSharedCacheFile
  • LDAPSharedCacheSize
  • LDAPTrustedCA
  • LDAPTrustedCAType
  • <Limit>
  • <LimitExcept>
  • LimitInternalRecursion
  • LimitRequestBody
  • LimitRequestFields
  • LimitRequestFieldSize
  • LimitRequestLine
  • LimitXMLRequestBody
  • Listen
  • ListenBackLog
  • LoadFile
  • LoadModule
  • <Location>
  • <LocationMatch>
  • LockFile
  • LogFormat
  • LogLevel
  • MaxClients
  • MaxKeepAliveRequests
  • MaxMemFree
  • MaxRequestsPerChild
  • MaxRequestsPerThread
  • MaxSpareServers
  • MaxSpareThreads
  • MaxThreads
  • MaxThreadsPerChild
  • MCacheMaxObjectCount
  • MCacheMaxObjectSize
  • MCacheMaxStreamingBuffer
  • MCacheMinObjectSize
  • MCacheRemovalAlgorithm
  • MCacheSize
  • MetaDir
  • MetaFiles
  • MetaSuffix
  • MimeMagicFile
  • MinSpareServers
  • MinSpareThreads
  • MMapFile
  • ModMimeUsePathInfo
  • MultiviewsMatch
  • NameVirtualHost
  • NoProxy
  • NumServers
  • NWSSLTrustedCerts
  • NWSSLUpgradeable
  • Options
  • Order
  • PassEnv
  • PidFile
  • ProtocolEcho
  • <Proxy>
  • ProxyBadHeader
  • ProxyBlock
  • ProxyDomain
  • ProxyErrorOverride
  • ProxyIOBufferSize
  • <ProxyMatch>
  • ProxyMaxForwards
  • ProxyPass
  • ProxyPassReverse
  • ProxyPreserveHost
  • ProxyReceiveBufferSize
  • ProxyRemote
  • ProxyRemoteMatch
  • ProxyRequests
  • ProxyTimeout
  • ProxyVia
  • ReadmeName
  • Redirect
  • RedirectMatch
  • RedirectPermanent
  • RedirectTemp
  • RemoveCharset
  • RemoveEncoding
  • RemoveHandler
  • RemoveInputFilter
  • RemoveLanguage
  • RemoveOutputFilter
  • RemoveType
  • RequestHeader
  • Require
  • RewriteBase
  • RewriteCond
  • RewriteEngine
  • RewriteLock
  • RewriteLog
  • RewriteLogLevel
  • RewriteMap
  • RewriteOptions
  • RewriteRule
  • RLimitCPU
  • RLimitMEM
  • RLimitNPROC
  • Satisfy
  • ScoreBoardFile
  • Script
  • ScriptAlias
  • ScriptAliasMatch
  • ScriptInterpreterSource
  • ScriptLog
  • ScriptLogBuffer
  • ScriptLogLength
  • ScriptSock
  • SecureListen
  • SendBufferSize
  • ServerAdmin
  • ServerAlias
  • ServerLimit
  • ServerName
  • ServerPath
  • ServerRoot
  • ServerSignature
  • ServerTokens
  • SetEnv
  • SetEnvIf
  • SetEnvIfNoCase
  • SetHandler
  • SetInputFilter
  • SetOutputFilter
  • SSIEndTag
  • SSIErrorMsg
  • SSIStartTag
  • SSITimeFormat
  • SSIUndefinedEcho
  • SSLCACertificateFile
  • SSLCACertificatePath
  • SSLCARevocationFile
  • SSLCARevocationPath
  • SSLCertificateChainFile
  • SSLCertificateFile
  • SSLCertificateKeyFile
  • SSLCipherSuite
  • SSLEngine
  • SSLMutex
  • SSLOptions
  • SSLPassPhraseDialog
  • SSLProtocol
  • SSLProxyCACertificateFile
  • SSLProxyCACertificatePath
  • SSLProxyCARevocationFile
  • SSLProxyCARevocationPath
  • SSLProxyCipherSuite
  • SSLProxyEngine
  • SSLProxyMachineCertificateFile
  • SSLProxyMachineCertificatePath
  • SSLProxyProtocol
  • SSLProxyVerify
  • SSLProxyVerifyDepth
  • SSLRandomSeed
  • SSLRequire
  • SSLRequireSSL
  • SSLSessionCache
  • SSLSessionCacheTimeout
  • SSLUserName
  • SSLVerifyClient
  • SSLVerifyDepth
  • StartServers
  • StartThreads
  • SuexecUserGroup
  • ThreadLimit
  • ThreadsPerChild
  • ThreadStackSize
  • TimeOut
  • TraceEnable
  • TransferLog
  • TypesConfig
  • UnsetEnv
  • UseCanonicalName
  • User
  • UserDir
  • VirtualDocumentRoot
  • VirtualDocumentRootIP
  • <VirtualHost>
  • VirtualScriptAlias
  • VirtualScriptAliasIP
  • Win32DisableAcceptEx
  • XBitHack


지시어 빠른참조 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > 모듈

지시어 빠른참조

이 문서는 아파치 설정지시어 각각의 용도, 기본값, 상태, 사용장소를 보여준다. 이들은 지시어 사전에서 설명한다.

첫번째 열은 지시어 이름과 용도를 알려준다. 두번째 열은 지시어에 기본값이 있다면 기본값을 보여준다. 만약 기본값이 너무 길다면, "+" 기호로 생략했음을 알린다.

세번째와 네번째 열은 각각 아래 표에 따라 지시어를 사용할 수 있는 장소와 지시어의 상태를 나타낸다.

A | B | C | D | E | F | G | H | I | K | L | M | N | O | P | R | S | T | U | V | W | X
s | 주서버설정
v | 가상호스트
d | directory
h | .htaccess

C | Core
M | MPM
B | Base
E | Extension
X | Experimental
AcceptMutex Default|method | Default | s | M
Method that Apache uses to serialize multiple children accepting requests on network sockets
AcceptPathInfo On|Off|Default | Default | svdh | C
Resources accept trailing pathname information
AccessFileName filename [filename] ... | .htaccess | sv | C
Name of the distributed configuration file
Action action-type cgi-script |  | svdh | B
특정 핸들러나 content-type에 대해 CGI 스크립트를 사용한다
AddAlt string file [file] ... |  | svdh | B
파일명으로 선택한 아이콘대신 사용할 파일 설명글
AddAltByEncoding string MIME-encoding [MIME-encoding] ... |  | svdh | B
MIME-encoding으로 선택한 아이콘대신 사용할 파일 설명글
AddAltByType string MIME-type [MIME-type] ... |  | svdh | B
MIME content-type으로 선택한 아이콘대신 사용할 파일 설명글
AddCharset charset extension [extension] ... |  | svdh | B
Maps the given filename extensions to the specified content charset
AddDefaultCharset On|Off|charset | Off | svdh | C
Default charset parameter to be added when a response content-type is text/plain or text/html
AddDescription string file [file] ... |  | svdh | B
파일에 대한 설명
AddEncoding MIME-enc extension [extension] ... |  | svdh | B
Maps the given filename extensions to the specified encoding type
AddHandler handler-name extension [extension] ... |  | svdh | B
Maps the filename extensions to the specified handler
AddIcon icon name [name] ... |  | svdh | B
이름으로 선택한 파일에 사용할 아이콘
AddIconByEncoding icon MIME-encoding [MIME-encoding] ... |  | svdh | B
MIME content-encoding으로 선택한 파일에 사용할 아이콘
AddIconByType icon MIME-type [MIME-type] ... |  | svdh | B
MIME content-type으로 선택한 파일에 사용할 아이콘
AddInputFilter filter[;filter...] extension [extension] ... |  | svdh | B
Maps filename extensions to the filters that will process client requests
AddLanguage MIME-lang extension [extension] ... |  | svdh | B
Maps the given filename extension to the specified content language
AddModuleInfo module-name string |  | sv | E
모듈에 대한 추가 정보를 server-info 핸들러가 보여주도록 추가한다
AddOutputFilter filter[;filter...] extension [extension] ... |  | svdh | B
Maps filename extensions to the filters that will process responses from the server
AddOutputFilterByType filter[;filter...] MIME-type [MIME-type] ... |  | svdh | C
assigns an output filter to a particular MIME-type
AddType MIME-type extension [extension] ... |  | svdh | B
Maps the given filename extensions onto the specified content type
Alias URL-path file-path|directory-path |  | sv | B
URL을 특정 파일시스템 장소로 대응한다
AliasMatch regex file-path|directory-path |  | sv | B
정규표현식을 사용하여 URL을 파일시스템 장소로 대응한다
Allow from all|host|env=env-variable [host|env=env-variable] ... |  | dh | B
Controls which hosts can access an area of the server
AllowCONNECT port [port] ... | 443 563 | sv | E
Ports that are allowed to CONNECT through the proxy
AllowEncodedSlashes On|Off | Off | sv | C
Determines whether encoded path separators in URLs are allowed to be passed through
AllowOverride All|None|directive-type [directive-type] ... | All | d | C
Types of directives that are allowed in .htaccess files
Anonymous user [user] ... |  | dh | E
Specifies userIDs that are allowed access without password verification
Anonymous_Authoritative On|Off | Off | dh | E
Configures if authorization will fall-through to other methods
Anonymous_LogEmail On|Off | On | dh | E
Sets whether the password entered will be logged in the error log
Anonymous_MustGiveEmail On|Off | On | dh | E
Specifies whether blank passwords are allowed
Anonymous_NoUserID On|Off | Off | dh | E
Sets whether the userID field may be empty
Anonymous_VerifyEmail On|Off | Off | dh | E
Sets whether to check the password field for a correctly formatted email address
AssignUserID user-id group-id |  | v | M
Tie a virtual host to a user and group ID
AuthAuthoritative On|Off | On | dh | B
Sets whether authorization and authentication are passed to lower level modules
AuthDBMAuthoritative On|Off | On | dh | E
Sets whether authentication and authorization will be passed on to lower level modules
AuthDBMGroupFile file-path |  | dh | E
Sets the name of the database file containing the list of user groups for authentication
AuthDBMType default|SDBM|GDBM|NDBM|DB | default | dh | E
Sets the type of database file that is used to store passwords
AuthDBMUserFile file-path |  | dh | E
Sets thename of a database file containing the list of users and passwords for authentication
AuthDigestAlgorithm MD5|MD5-sess | MD5 | dh | X
digest authentication에서 challenge와 response hash를 계산하는 알고리즘을 선택한다
AuthDigestDomain URI [URI] ... |  | dh | X
digest authentication에서 같은 보호영역에 속하는 URI들
AuthDigestFile file-path |  | dh | X
digest authentication에 사용할 사용자명과 인코딩된 암호 목록을 저장한 문서파일 위치
AuthDigestGroupFile file-path |  | dh | X
digest authentication에 사용할 그룹 목록을 저장한 문서파일명
AuthDigestNcCheck On|Off | Off | s | X
서버가 보내는 nonce-count를 검사할지 여부
AuthDigestNonceFormat format |  | dh | X
nonce를 만드는 방법을 결정한다
AuthDigestNonceLifetime seconds | 300 | dh | X
서버 nonce가 유효한 기간
AuthDigestQop none|auth|auth-int [auth|auth-int] | auth | dh | X
digest authentication가 사용할 보호수준(quality-of-protection)을 지정한다.
AuthDigestShmemSize size | 1000 | s | X
클라이언트를 추적하기위해 할당하는 공유메모리량
AuthGroupFile file-path |  | dh | B
Sets the name of a text file containing the list of user groups for authentication
AuthLDAPAuthoritative on|off | on | dh | X
Prevent other authentication modules from authenticating the user if this one fails
AuthLDAPBindDN distinguished-name |  | dh | X
Optional DN to use in binding to the LDAP server
AuthLDAPBindPassword password |  | dh | X
Password used in conjuction with the bind DN
AuthLDAPCharsetConfig file-path |  | s | X
Language to charset conversion configuration file
AuthLDAPCompareDNOnServer on|off | on | dh | X
Use the LDAP server to compare the DNs
AuthLDAPDereferenceAliases never|searching|finding|always | Always | dh | X
When will the module de-reference aliases
AuthLDAPEnabled on|off | on | dh | X
Turn on or off LDAP authentication
AuthLDAPFrontPageHack on|off | off | dh | X
Allow LDAP authentication to work with MS FrontPage
AuthLDAPGroupAttribute attribute |  | dh | X
LDAP attributes used to check for group membership
AuthLDAPGroupAttributeIsDN on|off | on | dh | X
Use the DN of the client username when checking for group membership
AuthLDAPRemoteUserIsDN on|off | off | dh | X
Use the DN of the client username to set the REMOTE_USER environment variable
AuthLDAPUrl url |  | dh | X
URL specifying the LDAP search parameters
AuthName auth-domain |  | dh | C
Authorization realm for use in HTTP authentication
AuthType Basic|Digest |  | dh | C
Type of user authentication
AuthUserFile file-path |  | dh | B
Sets the name of a text file containing the list of users and passwords for authentication
BrowserMatch regex [!]env-variable[=value] [[!]env-variable[=value]] ... |  | svdh | B
HTTP User-Agent에 따라 환경변수를 설정한다
BrowserMatchNoCase regex [!]env-variable[=value] [[!]env-variable[=value]] ... |  | svdh | B
대소문자를 구별하지않고 User-Agent에 따라 환경변수를 설정한다
BS2000Account account |  | s | M
Define the non-privileged account on BS2000 machines
CacheDefaultExpire seconds | 3600 (one hour) | sv | X
만기시간을 지정하지않은 문서를 캐쉬할 기본 기간.
CacheDirLength length | 2 | sv | X
하위디렉토리명의 문자개수
CacheDirLevels levels | 3 | sv | X
캐쉬의 하위디렉토리 깊이.
CacheDisable url-string |  | sv | X
특정 URL을 캐쉬하지 않는다
CacheEnable cache_type url-string |  | sv | X
지정한 저장관리자를 사용하여 지정한 URL을 캐쉬한다
CacheExpiryCheck On|Off | On | sv | X
캐쉬에서 파일을 찾을때 만기시간을 고려할지 여부
CacheFile file-path [file-path] ... |  | s | X
시작시 여러 파일 핸들을 캐쉬한다
CacheForceCompletion Percentage | 60 | sv | X
요청이 취소되더라도 서버가 파일을 계속 캐쉬하기위해 필요한 문서의 서비스률.
CacheGcClean hours url-string | ? | sv | X
URL에 해당하는 변하지않은 캐쉬파일을 유지할 시간
CacheGcDaily time | ? | sv | X
매일 가비지컬랙터를 실행할 반복 시간 (24시 시계)
CacheGcInterval hours |  | sv | X
가비지컬랙터를 실행하는 간격.
CacheGcMemUsage KBytes | ? | sv | X
가비지컬랙터가 사용할 최대 메모리량 (kilobyte 단위)
CacheGcUnused hours url-string | ? | sv | X
URL에 해당하는 참조되지않은 캐쉬파일을 유지할 기간.
CacheIgnoreCacheControl On|Off | Off | sv | X
클라이언트가 캐쉬하지않는 내용을 요청함을 무시한다.
CacheIgnoreNoLastMod On|Off | Off | sv | X
응답에 Last Modified 헤더가 없다는 사실을 무시한다.
CacheLastModifiedFactor float | 0.1 | sv | X
LastModified 시간으로 만기시간을 계산하는데 사용하는 계수.
CacheMaxExpire seconds | 86400 (하루) | sv | X
문서를 캐쉬하는 초단위 최대시간
CacheMaxFileSize bytes | 1000000 | sv | X
캐쉬에 저장할 문서의 최대크기 (바이트 단위)
CacheMinFileSize bytes | 1 | sv | X
캐쉬에 저장할 문서의 최소크기 (바이트 단위)
CacheNegotiatedDocs On|Off | Off | sv | B
Allows content-negotiated documents to be cached by proxy servers
CacheRoot directory |  | sv | X
캐쉬 파일을 저장할 디렉토리 root
CacheSize KBytes | 1000000 | sv | X
캐쉬로 사용할 최대 디스크공간 (KByte 단위)
CacheTimeMargin ? | ? | sv | X
문서를 캐쉬할 최소시간 한계
CGIMapExtension cgi-path .extension |  | dh | C
Technique for locating the interpreter for CGI scripts
CharsetDefault charset |  | svdh | X
변환할 문자집합
CharsetOptions option [option] ... | DebugLevel=0 NoImpl + | svdh | X
문자집합 변환 기능을 설정
CharsetSourceEnc charset |  | svdh | X
파일 원본의 문자집합
CheckSpelling on|off | Off | svdh | E
맞춤법 모듈을 사용한다
ChildPerUserID user-id group-id num-children |  | s | M
Specify user ID and group ID for a number of child processes
ContentDigest On|Off | Off | svdh | C
Enables the generation of Content-MD5 HTTP Response headers
CookieDomain domain |  | svdh | E
The domain to which the tracking cookie applies
CookieExpires expiry-period |  | svdh | E
Expiry time for the tracking cookie
CookieLog filename |  | sv | B
쿠키를 로그에 남기기위해 사용할 파일명을 설정한다
CookieName token | Apache | svdh | E
Name of the tracking cookie
CookieStyle Netscape|Cookie|Cookie2|RFC2109|RFC2965 | Netscape | svdh | E
Format of the cookie header field
CookieTracking on|off | off | svdh | E
Enables tracking cookie
CoreDumpDirectory directory |  | s | M
Directory where Apache attempts to switch before dumping core
CustomLog file|pipe format|nickname [env=[!]environment-variable] |  | sv | B
로그파일 이름과 형식을 지정한다
Dav On|Off|provider-name | Off | d | E
WebDAV HTTP 메써드를 시작한다
DavDepthInfinity on|off | off | svd | E
PROPFIND의 Depth: Infinity 요청을 허가한다
DavLockDB file-path |  | sv | E
DAV 잠금 데이터베이스 위치
DavMinTimeout seconds | 0 | svd | E
서버가 DAV 자원에 대해 유지할 잠금의 최소시간
DefaultIcon url-path |  | svdh | B
특정 아이콘을 설정하지않은 파일에 사용할 아이콘
DefaultLanguage MIME-lang |  | svdh | B
Sets all files in the given scope to the specified language
DefaultType MIME-type | text/plain | svdh | C
MIME content-type that will be sent if the server cannot determine a type in any other way
DeflateBufferSize value | 8096 | sv | E
zlib이 한번에 압축할 크기
DeflateCompressionLevel value |  | sv | E
출력을 어느정도 압축하는가
DeflateFilterNote [type] notename |  | sv | E
압축률을 로그에 기록한다
DeflateMemLevel value | 9 | sv | E
zlib이 압축할때 사용하는 메모리량
DeflateWindowSize value | 15 | sv | E
Zlib 압축 window size
Deny from all|host|env=env-variable [host|env=env-variable] ... |  | dh | B
Controls which hosts are denied access to the server
<Directory directory-path> ... </Directory> |  | sv | C
Enclose a group of directives that apply only to the named file-system directory and sub-directories
DirectoryIndex local-url [local-url] ... | index.html | svdh | B
클라이언트가 디렉토리를 요청할때 찾아볼 자원 목록
<DirectoryMatch regex> ... </DirectoryMatch> |  | sv | C
Enclose directives that apply to file-system directories matching a regular expression and their subdirectories
DirectorySlash On|Off | On | svdh | B
마지막 슬래쉬 리다이렉션을 키고 끈다
DocumentRoot directory-path | /usr/local/apache/h + | sv | C
Directory that forms the main document tree visible from the web
DumpIOInput On|Off | Off | s | X
Dump all input data to the error log
DumpIOOutput On|Off | Off | s | X
Dump all output data to the error log
EnableExceptionHook On|Off | Off | s | M
Enables a hook that runs exception handlers after a crash
EnableMMAP On|Off | On | svdh | C
Use memory-mapping to read files during delivery
EnableSendfile On|Off | On | svdh | C
Use the kernel sendfile support to deliver files to the client
ErrorDocument error-code document |  | svdh | C
What the server will return to the client in case of an error
ErrorLog file-path|syslog[:facility] | logs/error_log (Uni + | sv | C
Location where the server will log errors
Example |  | svdh | X
아파치 모듈 API를 설명하기위한 예제 지시어
ExpiresActive On|Off |  | svdh | E
Expires 헤더를 생성한다
ExpiresByType MIME-type <code>seconds |  | svdh | E
MIME type으로 Expires 헤더값을 설정한다
ExpiresDefault <code>seconds |  | svdh | E
만기시간을 계산하는 기본 알고리즘
ExtendedStatus On|Off | Off | s | B
각 요청에 대한 자세한 상태 정보를 기록한다
ExtFilterDefine filtername parameters |  | s | E
외부 필터를 정의한다
ExtFilterOptions option [option] ... | DebugLevel=0 NoLogS + | d | E
mod_ext_filter 옵션을 설정한다
FileETag component ... | INode MTime Size | svdh | C
File attributes used to create the ETag HTTP response header
<Files filename> ... </Files> |  | svdh | C
Contains directives that apply to matched filenames
<FilesMatch regex> ... </FilesMatch> |  | svdh | C
Contains directives that apply to regular-expression matched filenames
ForceLanguagePriority None|Prefer|Fallback [Prefer|Fallback] | Prefer | svdh | B
Action to take if a single acceptable document is not found
ForceType MIME-type|None |  | dh | C
Forces all matching files to be served with the specified MIME content-type
ForensicLog filename|pipe |  | sv | E
Sets filename of the forensic log
Group unix-group | #-1 | s | M
Group under which the server will answer requests
Header [condition] set|append|add|unset|echo header [value] [env=[!]variable] |  | svdh | E
HTTP 응답 헤더를 구성한다
HeaderName filename |  | svdh | B
파일목록 위에 삽입할 파일의 이름
HostnameLookups On|Off|Double | Off | svd | C
Enables DNS lookups on client IP addresses
IdentityCheck On|Off | Off | svd | C
Enables logging of the RFC1413 identity of the remote user
<IfDefine [!]parameter-name> ... </IfDefine> |  | svdh | C
Encloses directives that will be processed only if a test is true at startup
<IfModule [!]module-name> ... </IfModule> |  | svdh | C
Encloses directives that are processed conditional on the presence or absence of a specific module
ImapBase map|referer|URL | http://servername/ | svdh | B
이미지맵 파일에서 base 기본값
ImapDefault error|nocontent|map|referer|URL | nocontent | svdh | B
이미지맵에 어느 영역에도 해당하지 않는 좌표를 준 경우 기본 행동
ImapMenu none|formatted|semiformatted|unformatted |  | svdh | B
좌표없이 이미지맵 요청시 취할 행동
Include file-path|directory-path |  | svd | C
Includes other configuration files from within the server configuration files
IndexIgnore file [file] ... |  | svdh | B
디렉토리 목록에서 숨길 파일목록을 추가한다
IndexOptions [+|-]option [[+|-]option] ... |  | svdh | B
디렉토리 목록의 여러 설정들
IndexOrderDefault Ascending|Descending Name|Date|Size|Description | Ascending Name | svdh | B
디렉토리 목록의 기본 순서를 설정한다
ISAPIAppendLogToErrors on|off | off | svdh | B
ISAPI exntension의 HSE_APPEND_LOG_PARAMETER 요청을 오류 로그에 기록한다
ISAPIAppendLogToQuery on|off | on | svdh | B
ISAPI exntension의 HSE_APPEND_LOG_PARAMETER 요청을 질의문자열에 기록한다
ISAPICacheFile file-path [file-path] ... |  | sv | B
서버가 시작할때 메모리로 읽어들일 ISAPI .dll 파일들
ISAPIFakeAsync on|off | off | svdh | B
비동기 ISAPI 콜백을 지원하는 척한다
ISAPILogNotSupported on|off | off | svdh | B
ISAPI extension이 지원하지 않는 기능을 요청하면 로그에 기록한다
ISAPIReadAheadBuffer size | 49152 | svdh | B
ISAPI extension의 미리읽기버퍼(read ahead buffer) 크기
KeepAlive On|Off | On | sv | C
Enables HTTP persistent connections
KeepAliveTimeout seconds | 15 | sv | C
Amount of time the server will wait for subsequent requests on a persistent connection
LanguagePriority MIME-lang [MIME-lang] ... |  | svdh | B
The precendence of language variants for cases where the client does not express a preference
LDAPCacheEntries number | 1024 | s | X
Maximum number of entries in the primary LDAP cache
LDAPCacheTTL seconds | 600 | s | X
Time that cached items remain valid
LDAPConnectionTimeout seconds |  | s | X
Specifies the socket connection timeout in seconds
LDAPOpCacheEntries number | 1024 | s | X
Number of entries used to cache LDAP compare operations
LDAPOpCacheTTL seconds | 600 | s | X
Time that entries in the operation cache remain valid
LDAPSharedCacheFile directory-path/filename |  | s | X
Sets the shared memory cache file
LDAPSharedCacheSize bytes | 102400 | s | X
Size in bytes of the shared-memory cache
LDAPTrustedCA directory-path/filename |  | s | X
Sets the file containing the trusted Certificate Authority certificate or database
LDAPTrustedCAType type |  | s | X
Specifies the type of the Certificate Authority file
<Limit method [method] ... > ... </Limit> |  | svdh | C
Restrict enclosed access controls to only certain HTTP methods
<LimitExcept method [method] ... > ... </LimitExcept> |  | svdh | C
Restrict access controls to all HTTP methods except the named ones
LimitInternalRecursion number [number] | 10 | sv | C
Determine maximum number of internal redirects and nested subrequests
LimitRequestBody bytes | 0 | svdh | C
Restricts the total size of the HTTP request body sent from the client
LimitRequestFields number | 100 | s | C
Limits the number of HTTP request header fields that will be accepted from the client
LimitRequestFieldsize bytes |  | s | C
Limits the size of the HTTP request header allowed from the client
LimitRequestLine bytes | 8190 | s | C
Limit the size of the HTTP request line that will be accepted from the client
LimitXMLRequestBody bytes | 1000000 | svdh | C
Limits the size of an XML-based request body
Listen [IP-address:]portnumber |  | s | M
IP addresses and ports that the server listens to
ListenBacklog backlog |  | s | M
Maximum length of the queue of pending connections
LoadFile filename [filename] ... |  | s | E
지정한 목적파일이나 라이브러리를 읽어들인다
LoadModule module filename |  | s | E
목적파일이나 라이브러리를 읽어들이고, 사용가능한 모듈 목록에 추가한다
<Location URL-path|URL> ... </Location> |  | sv | C
Applies the enclosed directives only to matching URLs
<LocationMatch regex> ... </LocationMatch> |  | sv | C
Applies the enclosed directives only to regular-expression matching URLs
LockFile filename | logs/accept.lock | s | M
Location of the accept serialization lock file
LogFormat format|nickname [nickname] | "%h %l %u %t \"%r\" + | sv | B
로그파일에 사용할 형식을 기술한다
LogLevel level | warn | sv | C
Controls the verbosity of the ErrorLog
MaxClients number |  | s | M
Maximum number of child processes that will be created to serve requests
MaxKeepAliveRequests number | 100 | sv | C
Number of requests allowed on a persistent connection
MaxMemFree KBytes | 0 | s | M
Maximum amount of memory that the main allocator is allowed to hold without calling free()
MaxRequestsPerChild number | 10000 | s | M
Limit on the number of requests that an individual child server will handle during its life
MaxRequestsPerThread number | 0 | s | M
한 쓰레드가 실행하는 동안 처리할 요청개수 한계
MaxSpareServers number | 10 | s | M
Maximum number of idle child server processes
MaxSpareThreads number |  | s | M
Maximum number of idle threads
MaxThreads number | 2048 | s | M
Set the maximum number of worker threads
MaxThreadsPerChild number | 64 | s | M
Maximum number of threads per child process
MCacheMaxObjectCount value | 1009 | s | X
캐쉬에 저장할 수 있는 최대 객체개수
MCacheMaxObjectSize bytes | 10000 | s | X
캐쉬에 저장할 문서의 최대 크기 (바이트 단위)
MCacheMaxStreamingBuffer size_in_bytes | 100000과 MCacheMaxOb + | s | X
응답을 캐쉬안한다고 결정하기 전까지 메모리 버퍼에 저장할 스트림 응답의 최대 크기
MCacheMinObjectSize bytes | 0 | s | X
캐쉬에 저장할 문서의 최소 크기 (바이트 단위)
MCacheRemovalAlgorithm LRU|GDSF | GDSF | s | X
캐쉬에서 제거할 문서를 찾는 알고리즘
MCacheSize KBytes | 100 | s | X
캐쉬에 사용할 최대 메모리량 (KByte 단위)
MetaDir directory | .web | svdh | E
CERN 메타정보를 찾을 디렉토리 이름
MetaFiles on|off | off | svdh | E
CERN 메타파일을 처리한다
MetaSuffix suffix | .meta | svdh | E
CERN 메타정보를 저장하는 파일의 접미사
MimeMagicFile file-path |  | sv | E
Enable MIME-type determination based on file contents using the specified magic file
MinSpareServers number | 5 | s | M
Minimum number of idle child server processes
MinSpareThreads number |  | s | M
Minimum number of idle threads available to handle request spikes
MMapFile file-path [file-path] ... |  | s | X
시작시 여러 파일을 메모리에 대응한다
ModMimeUsePathInfo On|Off | Off | d | B
Tells mod_mime to treat path_info components as part of the filename
MultiviewsMatch Any|NegotiatedOnly|Filters|Handlers [Handlers|Filters] | NegotiatedOnly | svdh | B
The types of files that will be included when searching for a matching file with MultiViews
NameVirtualHost addr[:port] |  | s | C
Designates an IP address for name-virtual hosting
NoProxy host [host] ... |  | sv | E
Hosts, domains, or networks that will be connected to directly
NumServers number | 2 | s | M
Total number of children alive at the same time
NWSSLTrustedCerts filename [filename] ... |  | s | B
List of additional client certificates
NWSSLUpgradeable [IP-address:]portnumber |  | s | B
Allows a connection to be upgraded to an SSL connection upon request
Options [+|-]option [[+|-]option] ... | All | svdh | C
Configures what features are available in a particular directory
Order ordering | Deny,Allow | dh | B
Controls the default access state and the order in which Allow and Deny are evaluated.
PassEnv env-variable [env-variable] ... |  | svdh | B
쉘에서 환경변수를 가져온다
PidFile filename | logs/httpd.pid | s | M
File where the server records the process ID of the daemon
ProtocolEcho On|Off |  | sv | X
echo 서버를 키고 끈다
<Proxy wildcard-url> ...</Proxy> |  | sv | E
Container for directives applied to proxied resources
ProxyBadHeader IsError|Ignore|StartBody | IsError | sv | E
Determines how to handle bad header lines in a response
ProxyBlock *|word|host|domain [word|host|domain] ... |  | sv | E
Words, hosts, or domains that are banned from being proxied
ProxyDomain Domain |  | sv | E
Default domain name for proxied requests
ProxyErrorOverride On|Off | Off | sv | E
Override error pages for proxied content
ProxyIOBufferSize bytes | 8192 | sv | E
Determine size of internal data throughput buffer
<ProxyMatch regex> ...</ProxyMatch> |  | sv | E
Container for directives applied to regular-expression-matched proxied resources
ProxyMaxForwards number | 10 | sv | E
Maximium number of proxies that a request can be forwarded through
ProxyPass [path] !|url |  | svd | E
Maps remote servers into the local server URL-space
ProxyPassReverse [path] url |  | svd | E
Adjusts the URL in HTTP response headers sent from a reverse proxied server
ProxyPreserveHost On|Off | Off | sv | E
Use incoming Host HTTP request header for proxy request
ProxyReceiveBufferSize bytes | 0 | sv | E
Network buffer size for proxied HTTP and FTP connections
ProxyRemote match remote-server |  | sv | E
Remote proxy used to handle certain requests
ProxyRemoteMatch regex remote-server |  | sv | E
Remote proxy used to handle requests matched by regular expressions
ProxyRequests On|Off | Off | sv | E
Enables forward (standard) proxy requests
ProxyTimeout seconds | 300 | sv | E
Network timeout for proxied requests
ProxyVia On|Off|Full|Block | Off | sv | E
Information provided in the Via HTTP response header for proxied requests
ReadmeName filename |  | svdh | B
파일목록 마지막에 삽입할 파일의 이름
Redirect [status] URL-path URL |  | svdh | B
클라이언트가 다른 URL에 접속하도록 요청하는 외부 리다이렉션을 보낸다
RedirectMatch [status] regex URL |  | svdh | B
현재 URL이 정규표현식에 해당하면 외부 리다이렉션을 보낸다
RedirectPermanent URL-path URL |  | svdh | B
클라이언트가 다른 URL에 접속하도록 요청하는 외부 영구 리다이렉션을 보낸다
RedirectTemp URL-path URL |  | svdh | B
클라이언트가 다른 URL에 접속하도록 요청하는 외부 임시 리다이렉션을 보낸다
RemoveCharset extension [extension] ... |  | vdh | B
Removes any character set associations for a set of file extensions
RemoveEncoding extension [extension] ... |  | vdh | B
Removes any content encoding associations for a set of file extensions
RemoveHandler extension [extension] ... |  | vdh | B
Removes any handler associations for a set of file extensions
RemoveInputFilter extension [extension] ... |  | vdh | B
Removes any input filter associations for a set of file extensions
RemoveLanguage extension [extension] ... |  | vdh | B
Removes any language associations for a set of file extensions
RemoveOutputFilter extension [extension] ... |  | vdh | B
Removes any output filter associations for a set of file extensions
RemoveType extension [extension] ... |  | vdh | B
Removes any content type associations for a set of file extensions
RequestHeader set|append|add|unset header [value] |  | svdh | E
HTTP 요청 헤더를 구성한다
Require entity-name [entity-name] ... |  | dh | C
Selects which authenticated users can access a resource
RewriteBase URL-path |  | dh | E
Sets the base URL for per-directory rewrites
RewriteCond TestString CondPattern |  | svdh | E
Defines a condition under which rewriting will take place
RewriteEngine on|off | off | svdh | E
Enables or disables runtime rewriting engine
RewriteLock file-path |  | s | E
Sets the name of the lock file used for RewriteMap synchronization
RewriteLog file-path |  | sv | E
Sets the name of the file used for logging rewrite engine processing
RewriteLogLevel Level | 0 | sv | E
Sets the verbosity of the log file used by the rewrite engine
RewriteMap MapName MapType:MapSource |  | sv | E
Defines a mapping function for key-lookup
RewriteOptions Options | MaxRedirects=10 | svdh | E
Sets some special options for the rewrite engine
RewriteRule Pattern Substitution |  | svdh | E
Defines rules for the rewriting engine
RLimitCPU seconds|max [seconds|max] |  | svdh | C
Limits the CPU consumption of processes launched by Apache children
RLimitMEM bytes|max [bytes|max] |  | svdh | C
Limits the memory consumption of processes launched by Apache children
RLimitNPROC number|max [number|max] |  | svdh | C
Limits the number of processes that can be launched by processes launched by Apache children
Satisfy Any|All | All | dh | C
Interaction between host-level access control and user authentication
ScoreBoardFile file-path | logs/apache_status | s | M
Location of the file used to store coordination data for the child processes
Script method cgi-script |  | svd | B
특정 요청메서드에 대해 CGI 스크립트를 사용한다.
ScriptAlias URL-path file-path|directory-path |  | sv | B
URL을 특정 파일시스템 장소로 대응하고 대상이 CGI 스크립트라고 알린다
ScriptAliasMatch regex file-path|directory-path |  | sv | B
정규표현식을 사용하여 URL을 특정 파일시스템 장소로 대응하고 대상이 CGI 스크립트라고 알린다
ScriptInterpreterSource Registry|Registry-Strict|Script | Script | svdh | C
Technique for locating the interpreter for CGI scripts
ScriptLog file-path |  | sv | B
CGI 스크립트 오류로그파일의 위치
ScriptLogBuffer bytes | 1024 | sv | B
스크립트 로그에 기록할 PUT 혹은 POST 요청의 최대량
ScriptLogLength bytes | 10385760 | sv | B
CGI 스크립트 로그파일의 크기 제한
ScriptSock file-path | logs/cgisock | sv | B
cgi 데몬과 통신을 위해 사용할 소켓의 이름
SecureListen [IP-address:]portnumber Certificate-Name [MUTUAL] |  | s | B
Enables SSL encryption for the specified port
SendBufferSize bytes | 0 | s | M
TCP buffer size
ServerAdmin email-address |  | sv | C
Email address that the server includes in error messages sent to the client
ServerAlias hostname [hostname] ... |  | v | C
Alternate names for a host used when matching requests to name-virtual hosts
ServerLimit number |  | s | M
Upper limit on configurable number of processes
ServerName fully-qualified-domain-name[:port] |  | sv | C
Hostname and port that the server uses to identify itself
ServerPath URL-path |  | v | C
Legacy URL pathname for a name-based virtual host that is accessed by an incompatible browser
ServerRoot directory-path | /usr/local/apache | s | C
Base directory for the server installation
ServerSignature On|Off|EMail | Off | svdh | C
Configures the footer on server-generated documents
ServerTokens Major|Minor|Min[imal]|Prod[uctOnly]|OS|Full | Full | s | C
Configures the Server HTTP response header
SetEnv env-variable value |  | svdh | B
환경변수를 설정한다
SetEnvIf attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ... |  | svdh | B
요청의 성질에 따라 환경변수를 설정한다
SetEnvIfNoCase attribute regex [!]env-variable[=value] [[!]env-variable[=value]] ... |  | svdh | B
대소문자를 구별하지않고 요청의 성질에 따라 환경변수를 설정한다
SetHandler handler-name|None |  | svdh | C
Forces all matching files to be processed by a handler
SetInputFilter filter[;filter...] |  | svdh | C
Sets the filters that will process client requests and POST input
SetOutputFilter filter[;filter...] |  | svdh | C
Sets the filters that will process responses from the server
SSIEndTag tag | "-->" | sv | B
String that ends an include element
SSIErrorMsg message | "[an error occurred + | svdh | B
Error message displayed when there is an SSI error
SSIStartTag tag | "<!--#" | sv | B
String that starts an include element
SSITimeFormat formatstring | "%A, %d-%b-%Y %H:%M + | svdh | B
Configures the format in which date strings are displayed
SSIUndefinedEcho string | "(none)" | sv | B
String displayed when an unset variable is echoed
SSLCACertificateFile file-path |  | sv | E
File of concatenated PEM-encoded CA Certificates for Client Auth
SSLCACertificatePath directory-path |  | sv | E
Directory of PEM-encoded CA Certificates for Client Auth
SSLCARevocationFile file-path |  | sv | E
File of concatenated PEM-encoded CA CRLs for Client Auth
SSLCARevocationPath directory-path |  | sv | E
Directory of PEM-encoded CA CRLs for Client Auth
SSLCertificateChainFile file-path |  | sv | E
File of PEM-encoded Server CA Certificates
SSLCertificateFile file-path |  | sv | E
Server PEM-encoded X.509 Certificate file
SSLCertificateKeyFile file-path |  | sv | E
Server PEM-encoded Private Key file
SSLCipherSuite cipher-spec | ALL:!ADH:RC4+RSA:+H + | svdh | E
Cipher Suite available for negotiation in SSL handshake
SSLEngine on|off | off | sv | E
SSL Engine Operation Switch
SSLMutex type | none | s | E
Semaphore for internal mutual exclusion of operations
SSLOptions [+|-]option ... |  | svdh | E
Configure various SSL engine run-time options
SSLPassPhraseDialog type | builtin | s | E
Type of pass phrase dialog for encrypted private keys
SSLProtocol [+|-]protocol ... | all | sv | E
Configure usable SSL protocol flavors
SSLProxyCACertificateFile file-path |  | sv | E
File of concatenated PEM-encoded CA Certificates for Remote Server Auth
SSLProxyCACertificatePath directory-path |  | sv | E
Directory of PEM-encoded CA Certificates for Remote Server Auth
SSLProxyCARevocationFile file-path |  | sv | E
File of concatenated PEM-encoded CA CRLs for Remote Server Auth
SSLProxyCARevocationPath directory-path |  | sv | E
Directory of PEM-encoded CA CRLs for Remote Server Auth
SSLProxyCipherSuite cipher-spec | ALL:!ADH:RC4+RSA:+H + | svdh | E
Cipher Suite available for negotiation in SSL proxy handshake
SSLProxyEngine on|off | off | sv | E
SSL Proxy Engine Operation Switch
SSLProxyMachineCertificateFile filename |  | s | E
File of concatenated PEM-encoded client certificates and keys to be used by the proxy
SSLProxyMachineCertificatePath directory |  | s | E
Directory of PEM-encoded client certificates and keys to be used by the proxy
SSLProxyProtocol [+|-]protocol ... | all | sv | E
Configure usable SSL protocol flavors for proxy usage
SSLProxyVerify level | none | svdh | E
Type of remote server Certificate verification
SSLProxyVerifyDepth number | 1 | svdh | E
Maximum depth of CA Certificates in Remote Server Certificate verification
SSLRandomSeed context source [bytes] |  | s | E
Pseudo Random Number Generator (PRNG) seeding source
SSLRequire expression |  | dh | E
Allow access only when an arbitrarily complex boolean expression is true
SSLRequireSSL |  | dh | E
Deny access when SSL is not used for the HTTP request
SSLSessionCache type | none | s | E
Type of the global/inter-process SSL Session Cache
SSLSessionCacheTimeout seconds | 300 | sv | E
Number of seconds before an SSL session expires in the Session Cache
SSLUserName varname |  | sdh | E
Variable name to determine user name
SSLVerifyClient level | none | svdh | E
Type of Client Certificate verification
SSLVerifyDepth number | 1 | svdh | E
Maximum depth of CA Certificates in Client Certificate verification
StartServers number |  | s | M
Number of child server processes created at startup
StartThreads number |  | s | M
Number of threads created on startup
SuexecUserGroup User Group |  | sv | E
CGI 프로그램이 사용할 사용자와 그룹 권한
ThreadLimit number |  | s | M
Sets the upper limit on the configurable number of threads per child process
ThreadsPerChild number |  | s | M
Number of threads created by each child process
ThreadStackSize number | 65536 | s | M
Determine the stack size for each thread
TimeOut seconds | 300 | s | C
Amount of time the server will wait for certain events before failing a request
TraceEnable [on|off|extended] | on | s | C
Determines the behaviour on TRACE requests
TransferLog file|pipe |  | sv | B
로그파일 위치를 설정한다
TypesConfig file-path | conf/mime.types | s | B
The location of the mime.types file
UnsetEnv env-variable [env-variable] ... |  | svdh | B
환경변수를 제거한다
UseCanonicalName On|Off|DNS | On | svd | C
Configures how the server determines its own name and port
User unix-userid | #-1 | s | M
The userid under which the server will answer requests
UserDir directory-filename | public_html | sv | B
사용자별 디렉토리 위치
VirtualDocumentRoot interpolated-directory|none | none | sv | E
Dynamically configure the location of the document root for a given virtual host
VirtualDocumentRootIP interpolated-directory|none | none | sv | E
Dynamically configure the location of the document root for a given virtual host
<VirtualHost addr[:port] [addr[:port]] ...> ... </VirtualHost> |  | s | C
Contains directives that apply only to a specific hostname or IP address
VirtualScriptAlias interpolated-directory|none | none | sv | E
Dynamically configure the location of the CGI directory for a given virtual host
VirtualScriptAliasIP interpolated-directory|none | none | sv | E
Dynamically configure the location of the cgi directory for a given virtual host
Win32DisableAcceptEx |  | s | M
Use accept() rather than AcceptEx() to accept network connections
XBitHack on|off|full | off | svdh | B
Parse SSI directives in files with the execute bit set


사이트맵 - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0

사이트맵

이 문서는 최신판 번역이 아닙니다. 최근에 변경된 내용은 영어 문서를 참고하세요.

이 페이지는 현재 Apache HTTP Server Version 2.0 문서 목록을 보여준다.

발표문

  • 1.3에서 2.0으로 업그레이드
  • 아파치 2.0의 새로운 기능
  • 아파치 라이선스

아파치 웹서버 사용하기

  • 아파치 컴파일과 설치
  • 아파치 시작
  • 서버 중단과 재시작
  • 설정파일
  • 어떻게 Directory, Location, Files 섹션이 동작하나
  • 서버 전역 설정
  • 로그파일
  • URL을 파일시스템에 대응
  • 보안 팁
  • 동적공유객체 (DSO) 지원
  • 내용협상 (content negotiation)
  • 사용자정의 오류 응답
  • 아파치가 사용할 주소와 포트 지정
  • 다중처리모듈 (MPM)
  • 아파치의 환경변수
  • 아파치에서 핸들러 사용
  • 필터
  • suEXEC 지원
  • 성능향상 힌트
  • URL 재작성(rewriting) 지침서

아파치 가상호스트 문서

  • 개요
  • 이름기반 가상호스트
  • IP기반 가상호스트 지원
  • 대량의 가상호스트를 동적으로 설정하기
  • 가상호스트 예
  • 가상호스트 찾기에 대한 자세한 설명
  • 파일기술자(file descriptor) 한계
  • DNS와 아파치와 관련된 사항

아파치 서버에 대해 자주 물어보는 질문

  • 개요
  • 지원
  • 오류문

아파치 SSL/TLS 암호화

  • 소개
  • SSL/TLS 암호화: 소개
  • SSL/TLS 암호화: 호환성
  • SSL/TLS 암호화: How-To
  • SSL/TLS 암호화: FAQ

지침서, 투토리얼, HowTo

  • 개요
  • 인증
  • CGI로 페이지 내용
  • Server Side Includes 소개
  • .htaccess 파일
  • 사용자별 웹디렉토리
  • 아파치 투토리얼

플래폼별 설명

  • 개요
  • Microsoft Windows에서 아파치 사용하기
  • Microsoft Windows에서 아파치 컴파일하기
  • Novell NetWare에서 아파치 사용하기
  • HPUX에서 고성능 웹서버 실행하기
  • 아파치 EBCDIC 포팅

아파치 웹서버와 지원 프로그램

  • 개요
  • Manpage: httpd
  • Manpage: ab
  • Manpage: apachectl
  • Manpage: apxs
  • Manpage: configure
  • Manpage: dbmmanage
  • Manpage: htdigest
  • Manpage: htpasswd
  • Manpage: logresolve
  • Manpage: rotatelogs
  • Manpage: suexec
  • 다른 프로그램들

기타 아파치 문서

  • 개요
  • 다국어 사용자정의 서버 오류문
  • FIN_WAIT_2 상태 연결과 아파치
  • 클라이언트의 이미 알려진 문제점
  • 파일기술자와 아파치
  • 관련된 표준들

아파치 모듈

  • 아파치 모듈을 설명하는데 사용한 용어정의
  • 아파치 지시어를 설명하는데 사용한 용어정의
  • 아파치 핵심 기능
  • 아파치 MPM 공통 지시어
  • 아파치 MPM beos
  • 아파치 MPM leader
  • 아파치 MPM netware
  • 아파치 MPM os2
  • 아파치 MPM perchild
  • 아파치 MPM prefork
  • 아파치 MPM threadpool
  • 아파치 MPM winnt
  • 아파치 MPM worker
  • 아파치 모듈 mod_access
  • 아파치 모듈 mod_actions
  • 아파치 모듈 mod_alias
  • 아파치 모듈 mod_asis
  • 아파치 모듈 mod_auth
  • 아파치 모듈 mod_auth_anon
  • 아파치 모듈 mod_auth_dbm
  • 아파치 모듈 mod_auth_digest
  • 아파치 모듈 mod_auth_ldap
  • 아파치 모듈 mod_autoindex
  • 아파치 모듈 mod_cache
  • 아파치 모듈 mod_cern_meta
  • 아파치 모듈 mod_cgi
  • 아파치 모듈 mod_cgid
  • 아파치 모듈 mod_charset_lite
  • 아파치 모듈 mod_dav
  • 아파치 모듈 mod_dav_fs
  • 아파치 모듈 mod_deflate
  • 아파치 모듈 mod_dir
  • 아파치 모듈 mod_disk_cache
  • 아파치 모듈 mod_dumpio
  • 아파치 모듈 mod_echo
  • 아파치 모듈 mod_env
  • 아파치 모듈 mod_example
  • 아파치 모듈 mod_expires
  • 아파치 모듈 mod_ext_filter
  • 아파치 모듈 mod_file_cache
  • 아파치 모듈 mod_headers
  • 아파치 모듈 mod_imap
  • 아파치 모듈 mod_include
  • 아파치 모듈 mod_info
  • 아파치 모듈 mod_isapi
  • 아파치 모듈 mod_ldap
  • 아파치 모듈 mod_log_config
  • 아파치 모듈 mod_log_forensic
  • 아파치 모듈 mod_logio
  • 아파치 모듈 mod_mem_cache
  • 아파치 모듈 mod_mime
  • 아파치 모듈 mod_mime_magic
  • 아파치 모듈 mod_negotiation
  • 아파치 모듈 mod_nw_ssl
  • 아파치 모듈 mod_proxy
  • 아파치 모듈 mod_proxy_connect
  • 아파치 모듈 mod_proxy_ftp
  • 아파치 모듈 mod_proxy_http
  • 아파치 모듈 mod_rewrite
  • 아파치 모듈 mod_setenvif
  • 아파치 모듈 mod_so
  • 아파치 모듈 mod_speling
  • 아파치 모듈 mod_ssl
  • 아파치 모듈 mod_status
  • 아파치 모듈 mod_suexec
  • 아파치 모듈 mod_unique_id
  • 아파치 모듈 mod_userdir
  • 아파치 모듈 mod_usertrack
  • 아파치 모듈 mod_vhost_alias

개발자 문서

  • 개요
  • Apache API 설명
  • APR의 메모리할당 디버깅
  • Apache 2.0 문서화
  • Apache 2.0 훅(hook) 함수
  • Apache 1.3에서 Apache 2.0으로 모듈을 수정하기
  • Apache 2.0의 요청처리
  • Apache 2.0의 필터 동작법

용어와 색인

  • 용어
  • 모듈 목록
  • 지시어 목록
  • 지시어 빠른참조


Apache 2.0 Thread Safety Issues - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > Developer Documentation

Apache 2.0 Thread Safety Issues

When using any of the threaded mpms in Apache 2.0 it is important that every function called from Apache be thread safe. When linking in 3rd party extensions it can be difficult to determine whether the resulting server will be thread safe. Casual testing generally won't tell you this either as thread safety problems can lead to subtle race conditons that may only show up in certain conditions under heavy load.

Global and static variables

When writing your module or when trying to determine if a module or 3rd party library is thread safe there are some common things to keep in mind.

First, you need to recognize that in a threaded model each individual thread has its own program counter, stack and registers. Local variables live on the stack, so those are fine. You need to watch out for any static or global variables. This doesn't mean that you are absolutely not allowed to use static or global variables. There are times when you actually want something to affect all threads, but generally you need to avoid using them if you want your code to be thread safe.

In the case where you have a global variable that needs to be global and accessed by all threads, be very careful when you update it. If, for example, it is an incrementing counter, you need to atomically increment it to avoid race conditions with other threads. You do this using a mutex (mutual exclusion). Lock the mutex, read the current value, increment it and write it back and then unlock the mutex. Any other thread that wants to modify the value has to first check the mutex and block until it is cleared.

If you are using APR, have a look at the apr_atomic_* functions and the apr_thread_mutex_* functions.

errno

This is a common global variable that holds the error number of the last error that occurred. If one thread calls a low-level function that sets errno and then another thread checks it, we are bleeding error numbers from one thread into another. To solve this, make sure your module or library defines _REENTRANT or is compiled with -D_REENTRANT. This will make errno a per-thread variable and should hopefully be transparent to the code. It does this by doing something like this:

#define errno (*(__errno_location()))

which means that accessing errno will call __errno_location() which is provided by the libc. Setting _REENTRANT also forces redefinition of some other functions to their *_r equivalents and sometimes changes the common getc/putc macros into safer function calls. Check your libc documentation for specifics. Instead of, or in addition to _REENTRANT the symbols that may affect this are _POSIX_C_SOURCE, _THREAD_SAFE, _SVID_SOURCE, and _BSD_SOURCE.

Common standard troublesome functions

Not only do things have to be thread safe, but they also have to be reentrant. strtok() is an obvious one. You call it the first time with your delimiter which it then remembers and on each subsequent call it returns the next token. Obviously if multiple threads are calling it you will have a problem. Most systems have a reentrant version of of the function called strtok_r() where you pass in an extra argument which contains an allocated char * which the function will use instead of its own static storage for maintaining the tokenizing state. If you are using APR you can use apr_strtok().

crypt() is another function that tends to not be reentrant, so if you run across calls to that function in a library, watch out. On some systems it is reentrant though, so it is not always a problem. If your system has crypt_r() chances are you should be using that, or if possible simply avoid the whole mess by using md5 instead.

Common 3rd Party Libraries

The following is a list of common libraries that are used by 3rd party Apache modules. You can check to see if your module is using a potentially unsafe library by using tools such as ldd(1) and nm(1). For PHP, for example, try this:

% ldd libphp4.so
libsablot.so.0 => /usr/local/lib/libsablot.so.0 (0x401f6000)
libexpat.so.0 => /usr/lib/libexpat.so.0 (0x402da000)
libsnmp.so.0 => /usr/lib/libsnmp.so.0 (0x402f9000)
libpdf.so.1 => /usr/local/lib/libpdf.so.1 (0x40353000)
libz.so.1 => /usr/lib/libz.so.1 (0x403e2000)
libpng.so.2 => /usr/lib/libpng.so.2 (0x403f0000)
libmysqlclient.so.11 => /usr/lib/libmysqlclient.so.11 (0x40411000)
libming.so => /usr/lib/libming.so (0x40449000)
libm.so.6 => /lib/libm.so.6 (0x40487000)
libfreetype.so.6 => /usr/lib/libfreetype.so.6 (0x404a8000)
libjpeg.so.62 => /usr/lib/libjpeg.so.62 (0x404e7000)
libcrypt.so.1 => /lib/libcrypt.so.1 (0x40505000)
libssl.so.2 => /lib/libssl.so.2 (0x40532000)
libcrypto.so.2 => /lib/libcrypto.so.2 (0x40560000)
libresolv.so.2 => /lib/libresolv.so.2 (0x40624000)
libdl.so.2 => /lib/libdl.so.2 (0x40634000)
libnsl.so.1 => /lib/libnsl.so.1 (0x40637000)
libc.so.6 => /lib/libc.so.6 (0x4064b000)
/lib/ld-linux.so.2 => /lib/ld-linux.so.2 (0x80000000)

In addition to these libraries you will need to have a look at any libraries linked statically into the module. You can use nm(1) to look for individual symbols in the module.

Library List

Please drop a note to dev@httpd.apache.org if you have additions or corrections to this list.

Library | Version | Thread Safe? | Notes
ASpell/PSpell |  | ? |
Berkeley DB | 3.x, 4.x | Yes | Be careful about sharing a connection across threads.
bzip2 |  | Yes | Both low-level and high-level APIs are thread-safe. However, high-level API requires thread-safe access to errno.
cdb |  | ? |
C-Client |  | Perhaps | c-client uses strtok() and gethostbyname() which are not thread-safe on most C library implementations. c-client's static data is meant to be shared across threads. If strtok() and gethostbyname() are thread-safe on your OS, c-client may be thread-safe.
cpdflib |  | ? |
libcrypt |  | ? |
Expat |  | Yes | Need a separate parser instance per thread
FreeTDS |  | ? |
FreeType |  | ? |
GD 1.8.x |  | ? |
GD 2.0.x |  | ? |
gdbm |  | No | Errors returned via a static gdbm_error variable
ImageMagick | 5.2.2 | Yes | ImageMagick docs claim it is thread safe since version 5.2.2 (see Change log).
Imlib2 |  | ? |
libjpeg | v6b | ? |
libmysqlclient |  | Yes | Use mysqlclient_r library variant to ensure thread-safety. For more information, please read http://www.mysql.com/doc/en/Threaded_clients.html.
Ming | 0.2a | ? |
Net-SNMP | 5.0.x | ? |
OpenLDAP | 2.1.x | Yes | Use ldap_r library variant to ensure thread-safety.
OpenSSL | 0.9.6g | Yes | Requires proper usage of CRYPTO_num_locks, CRYPTO_set_locking_callback, CRYPTO_set_id_callback
liboci8 (Oracle 8+) | 8.x,9.x | ? |
pdflib | 5.0.x | Yes | PDFLib docs claim it is thread safe; changes.txt indicates it has been partially thread-safe since V1.91: http://www.pdflib.com/products/pdflib/index.html.
libpng | 1.0.x | ? |
libpng | 1.2.x | ? |
libpq (PostgreSQL) | 7.x | Yes | Don't share connections across threads and watch out for crypt() calls
Sablotron | 0.95 | ? |
zlib | 1.1.4 | Yes | Relies upon thread-safe zalloc and zfree functions Default is to use libc's calloc/free which are thread-safe.


자주 물어보는 질문 (FAQ) - Apache HTTP Server

Apache > HTTP Server > Documentation > Version 2.0 > FAQ

자주 물어보는 질문 (FAQ)

FAQ 최신판은 아파치 웹사이트 <http://httpd.apache.org/docs-2.0/faq/>에서 볼 수 있다.

아파치 2.0이 나온지 얼마 안되서 우리는 아직 자주 물어보는 질문 (FAQ)이 무엇인지 모른다. 내용이 채워질 때까지 여기에 해답이 없다면 아파치 1.3 FAQ도 참고하라.

주제

지원
문제가 생기면 어떻게 해결하나?
오류문
이 오류문이 무슨 뜻인가?

지원

  • "왜 ... 안되나? 왜 ... 동작하지 않는가?" 문제가 생기면 할일
  • 도움을 얻으려면 누구에게 연락하나?

"왜 ... 안되나? 왜 ... 동작하지 않는가?" 문제가 생기면 할일

아파치 서버 소프트웨어에 문제가 생기면 다음과 같은 단계를 따른다:

오류 로그(errorlog)를 확인하라!
아파치 서버는 문제가 생기면 도움을 주려고 노력한다. 많은 경우 서버 오류 로그에 자세한 내용을 기록한다. 이것만으로도 직접 (파일권한 등) 문제를 발견하고 고칠 수 있는 경우가 많다. 오류 로그의 기본 위치는 /usr/local/apache2/logs/error_log이지만, 정확한 위치는 설정파일의 ErrorLog 지시어를 참고하라.
FAQ를 확인하라!
아파치 웹사이트에서 항상 아파치 FAQ 최신판을 볼 수 있다.
아파치 버그 데이터베이스를 확인하라
아파치그룹(The Apache Group)에 보고된 대부분의 문제는 버그 데이터베이스에 기록된다. 새로 버그를 추가하기 전에, 이미 알려졌거나(open) 해결된(closed) 버그가 있는지 확인하길 바란다. 이미 문제가 보고되었다면 "나도 이런 문제가 있다고" 보고하지 않길 바란다. 아직 해결되지 않았다면 주기적으로 상황을 확인하길 바란다. 또, 데이터베이스에 기록되지 않고 이메일 교환으로 진행된 사항이 있을 수 있으니 처음 문제를 보고한 사람에게 연락해볼 수도 있다.
사용자 지원 공간에 문의한다

아파치에 대한 지식을 공유하길 원하는 활발한 사용자 공동체들이 있다. 일반적으로 이런 공동체에 참여하는 것이 문제의 답을 얻는 가장 좋고 빠른 방법이다.

사용자 메일링리스트

USENET 뉴스그룹:

  • comp.infosystems.www.servers.unix [news] [google]
  • comp.infosystems.www.servers.ms-windows [news] [google]
  • comp.infosystems.www.authoring.cgi [news] [google]
위의 방법이 모두 실패하면 버그 데이터베이스에 문제를 보고한다

위의 단계를 모두 시도하고도 해결책이 없다면, 버그를 보고하여 웹서버 개발자들에게 문제를 알리길 바란다.

core dump를 만들며 서버가 죽는 경우라면 (가능하면) backtrace(역주; 문제가 실행파일의 정확히 어떤 지점에서 발생하였고, 프로그램이 그 지점까지 어떤 경로로 실행되었는지를 알려주는 정보)를 포함하길 바란다. 예를 들어,

# cd ServerRoot
# dbx httpd core
(dbx) where

(ServerRoot, httpd, core 파일의 실제 위치를 대신 사용하라. dbx 대신 gdb를 사용해야 할 수도 있다.)

도움을 얻으려면 누구에게 연락하나?

40명 가량의 자발적으로 참여한 개발자만으로는 수백만의 사용자에게 아파치에 대해 일일이 지원할 수 없다. 무료 지원을 얻으려면 사용자 공간에 참여하길 권한다.

아파치에 대한 직업적인 유료 지원은 여러 회사에서 제공한다.

오류문

  • Invalid argument: core_output_filter: writing data to the network
  • AcceptEx failed
  • Premature end of script headers

Invalid argument: core_output_filter: writing data to the network

플래폼이 sendfile 시스템호출을 지원한다면, 아파치는 응답의 속도를 빠르게하기위해 이 시스템호출을 사용한다. 불행히도 어떤 시스템에서 아파치는 컴파일할때 sendfile이 정상적으로 작동하지 않는데도 정상적으로 작동한다고 오판한다. 이 문제는 네트웍 파일시스템이나 비표준 파일시스템을 사용할때 자주 발생한다.

이 문제의 증상은 오류 로그(error log)에 위의 문구를 기록하거나 크기가 0이 아닌 파일에 대해 크기가 0인 응답을 하는 경우이다. 동적으로 내용을 생성할때는 sendfile을 사용하지 않기때문에 일반적으로 정적인 파일을 요청할때만 문제가 발생한다.

문제를 해결하려면 서버가 sendfile을 사용하지 않도록 EnableSendfile 지시어를 사용한다. 또, 이와 유사한 문제에 대해 EnableMMAP을 참고하라.

AcceptEx Failed

win32에서 AcceptEx 시스템호출에 대한 오류문을 나오면, Win32DisableAcceptEx 지시어를 참고하라.

Premature end of script headers

보통 CGI 스크립트에 문제가 있으면 브라우저에게 Internal Server Error를 보내고 오류로그에 이 문구를 기록한다. 이런 문제를 디버깅할때 CGI 투토리얼이 도움이 될 수 있다.