RSS구독하기:SUBSCRIBE TO RSS FEED
즐겨찾기추가:ADD FAVORITE
글쓰기:POST
관리자:ADMINISTRATOR
'Web_developing'에 해당되는 글 102
출처 블로그 > 슈퍼유저도전
원본 http://blog.naver.com/ilove7rose/110006516800
KISA에서 나온  'ModSecurity를 이용한 아파치 웹서버 보안'문서를 요약

설치법에는  DSO 방식과 소스 설치가 있는뎅,  소스 설치에 대한 내용은 다음과 같다.

* 설치는 당사의 아파치 설치에 따라  문서와는 조금 다른 점이 있음.

1. 작업 공간으로 이동
  cd /usr/local/src
 
2. 다운로드
  http://www.modsecurity.org/download/modsecurity-apache-1.9.2.tar.gz

3. 압축 해제
  tar xvzf modsecurity-apache-1.9.2.tar.gz

4. 아파치 STOP
  /usr/local/apache/bin/apachectl stop

5. 아파치 재컴파일
  cd /usr/local/src/apache_1.3.26/

  cp /usr/local/src/modsecurity-apache-1.9.2/apache1/mod_security.c ./src/modules/extra

  ./configure --prefix=/usr/local/apache --activate-module=src/modules/php4/libphp4.a --enable-rule=SHARED_CORE --enable-module=so --enable-shared=max --add-module=src/modules/extra/mod_throttle.c --activate-module=src/modules/extra/mod_security --enable-module=security
 
  make

  make install

6. /usr/local/apache/conf 안에 mod_security.conf 복사
 

7. 실행권한 조정
  chmod 700 mod_security.conf

8. 아파치 conf에 mod_security.conf  include 시킴
  Include conf/mod_security.conf

9. 아파치 재시작


 mod_security.conf은  웹서버 및 서비스 환경에 따라 수정해야 함.
2006/09/11 10:08 2006/09/11 10:08
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > [完's Life~!]
원본 http://blog.naver.com/bbulkim2/80023987982
한국정보보호진흥원에서 권고중인 웹방화벽
웹서버의 재설치 없이 DSO방식으로 설치한다
/usr/local/apache2/bin/apxs -cia /usr/local/modsecurity-apache-1.9.2/apache2/mod_security.c

설치후 /usr/local/modules 디렉토리에 mod_security.o 가 생성되며
/usr/local/conf/httpd.conf에 LoadModule 에 mod_security.o 가 삽입된다.


httpd.conf안에 다음을 추가한다.

<IfModule mod_security.c>
첨부한 정책내용
</IfModule>

* 정책은 KrCERT에서 제작한 APM용 기본정책
2006/09/11 10:07 2006/09/11 10:07
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 나만의 세계
원본 http://blog.naver.com/didorito/60012087196

웹 어플리케이션 시큐리티, 과연 올해 시장이 있을까?  아니면 내년?

웹 방화벽의 시장성에 대해서는 약간 의문이 생긴다.


이러한 제품을 구매할 능력이 있는 회사가 얼마나 될까?

또한 웹의 보안문제로 인한 피해 규모 및 이로인한 파급효과가 얼마나 될지?

자료의 유출이나, 웹 사이트 해킹에 대한 피해액이 과연 이러한 제품을 구매할 만한 가치가 있게 만드는 것일까?


당장 머리속에 떠오르는 의문들이다. 사실 이런걸 예측한다면 만드는 것마다 성공하겠지만 어쨌든 이러한 관점에 대해서는 계속 고민을 해 봐야 할만한 문제라고 생각한다.


기술적인 관점에서는 아직 깊이 서베이를 해보지 않아서 단편적인 지식만 있는 상태이다.

하지만 대강 (항상 그렇지만) 파악한 바로는

- learning based approach

- rule-based approach

이렇게 두 가지가 있는 것으로 알고 있다.

약간 다른 관점에서 vulnerability scanner가 있지만 성향이 약간 달라 현재 고려대상에서 제외하는게 좋을 것 같다고 판단했다.


learning 방식에 대해서는 구체적으로 파악하지는 못 했지만,

정상적인 HTTP request/reponse 에서 규칙을 추출하는게 아닌가 한다. 어떤 dynamic page에 대한 request의 parameter의 전달 형태와, response의 형태를 규칙을 자동으로 생성하고 적용시에 이와 위배되는 request와 reponse가 발견되면 차단하는 걸로 파악이 된다.

반변 rule-based approach는 학습 방법과는 달리, 잘 알려진 attack이나 페이지의 변조, 데이터의 유출 등에 대한 rule-set을 미리 정의하여 이 규칙에 위배되는 request를 차단하는 방식으로 파악하고 있다.


현재 나의 관심 대상인

mod_security는 후자의 방식을 채택한 것으로 아파치의 module로 사용되며, mod_proxy와 같이 이용시에 웹 서버와 무관하게 적용할 수 있을 것으로 보인다.


현재 쓸만한 오픈소스의 조사가 더 필요하긴 하지만 mod_security와 같이 범용적으로 사용할 수 있는 오픈소스는 그다지 많지 않으리라고 파악하고 있다. 뭐, 더 있다면 좋겠지만...


아파치+mod_proxy+mod_security의 조합은 범용적으로 쓸 수 있기에는 좋은 조합이지만 언제나 그렇듯이 performance에 치명적인 단점이 있으리라고 생각한다. 이 부분에 대해서는 좀더 효율적인 구조로 변경을 통한다면 좀더 상용제품에 가까운 웹 방화벽을 만들 수 있지 않을까 한다.


시간이 되면 효용성에 대한 분석과 더불어 소스코드에 대한 좀더 심화된 분석이 필요하다. 사실 잠깐 코드를 들여다 보았는데, 스윽 본거라 뭐라고 적을만한 내용은 아직까지는 없다. 하지만 기능과 rule-set 측면에서 적용가능한 보안 정책에 대해서는 이제부터라도 조사를 시작해야 할 것 같다....


< 자료 >


- 아파치 + mod_proxy + mod_security 의 조합에 대한 overview성격의 자료

  http://www.securityfocus.com/infocus/1739

- mod_security 에 대한 자세한 정보는

  www.mod_security.org

- 웹 어플리케이션 시큐리티에 대한 정보는

  www.owasp.org

2006/09/11 10:06 2006/09/11 10:06
이 글에는 트랙백을 보낼 수 없습니다
출처 카페 > 컴퓨터, 너 누구니? / 쵸코바샘
원본 http://cafe.naver.com/whoiscomputer/24

서비스 업체

기본 DNS 1

DNS 2

DNS 3

보조 DNS

KT 한국통신

211.216.63.1

211.229.63.1

168.126.63.1

끝숫자를 2로...

하나로통신

210.94.0.7

210.180.98.74


131.107.1.7

두루넷

210.117.65.1



210.117.65.2

신비로 샤크

202.30.143.11



203.240.193.11

드림라인

210.181.1.24




데이콤 보라홈넷

211.106.67.221



164.124.101.2

SK 싱크로드

211.188.128.2




HiTEL

203.245.15.2




단지넷

210.181.1.24



164.124.101.2

2006/09/11 08:57 2006/09/11 08:57
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > 20대의 끝을 잡고
원본 http://blog.naver.com/javancoffee/40003093131

링크 : http://phpschool.com/bbs2/inc_view.html?id=10453&code=tnt2&start=0&mode=search&field=title&search_name=&operator=and&period=last6month&category_id=&s_que=%BD%BA%B8%B6%C6%BC


스마티(Smarty) 템플릿 사용하기

김영진(cogolda@hanmail.net)
이 튜토리얼은 http://www.zend.com/zend/tut/tutorial-cezar.php에 있는
내용은 제가 번역, 추가, 생략했습니다.
소스 코드가 많아서 번역할 내용은 많지 않네요.
질문이나, 의견은 메일이나 코멘트 이용해 주시고,
관심있으신 자료 있으시면, 정리해서 올리겠습니다.
이 자료는 제가 스마티 쓸 때 도움이 되었던 문서이기도 합니다.

대상 독자

이 기사는 PHP templating같은 새로운 웹 개발기술을 적용하고 싶은 PHP 프로그래머와 HTML 디자이너를
위해 작성되었습니다.

Smarty 개요

이론적인 웹 개발 과정은 다음과 같다.
처음에는 디자이너가 유저 인터페이스를 만들고, 그것을 프로그래머를 위해 HTML 조각으로 쪼갠 다음
프로그래머가 HTML안에 PHP 비즈니스 로직을 구현하는 것이다.

그것은 이론적으로는 좋다. 그러나 실질적으로, 내 경험을 빌리자면, 클라이언트는 디자인이나 비즈니스 로직을 변경을 자주 요구한다. 그런 일이 일어날 때, HTML은 변경되고 프로그래머는 HTML 소스 코드를 수정한다.

이런 상황에서 문제는 프로그래머는 디자이너가 레이아웃과 HTML 파일을 완성할떄까지 기다려야 한다는 것이다. 다른 문제는 만약 메인 디자인이 바뀌면, 프로그래머는 새로운 페이지에 적합하기 위해 변경할 것이다. 이것이 바로 내가 스마티(Smarty)를 추천하는 이유이다. 스마티는 PHP를 위한 템플릿 엔진이다.

여러분은 http://smarty.php.net/ 에서 스마티 템플릿을 다운로드 할수 있다. 설치 과정은 매우 단순하다. 문서를 읽고 지시에 따라라.

그래서 스마티가 무엇인가? 스마티는 PHP 스크립트로 템플릿을 컴파일하는 PHP 클래스의 집합이다. 스마티는 템플릿 언어이고 디자이너와 프로그래머에게 매우 유용한 툴이다.
(한국에서 디자이너에게 스마티를 가르치는 것이 가능할까요?)

디자이너를 위한 스마티

디자이너 HTML 파일로 작업한다. 스마티와 작업하기 위해, 여러분은 템플릿 파일로 작업한다. 이런 파일들은 정적인 컨텐츠로 완성했으나, 스마티는 마크업 태그와 함께 결합된다.
(여기서 정적인 컨텐츠라는건 php 코드가 없는 html파일을 애기하는 것입니다.
마크업 태그는 페이지 기술 언어 다시말해 html, sgml, xml이런 걸 애기하는 것입니다.)
모든 템플릿 파일은 확장자가 .tpl이다. 스마티 템플릿 태그는 { and } 구획문자로 감싸진다.

웹 페이지의 기본적인 구조를 생각해 보자. 헤더가 있고, 중간 부분이 있고, 꼬리말(footer)이 있다. 헤더와 꼬리말을 포함하는 파일템플릿 파일 다음과 같다.

{include file="header.tpl"}
<form name="form1">
   Label1 <input type="text" name="text1">
   <input type="submit" value="submit">
</form>
{include file="footer.tpl"}

모든 템플릿은 한 템플릿 디렉토리안에 있어야 한다. 처음에 템플릿을 호출하고 나서, 컴파일된 템플릿은 template_c에 있을 것이다.

스마티 언어는 매우 강력하다. PHP에 모든 변수는 {$Variable_Name}으로 스마티에서 식별된다. 주의할 점은 $ 표시가 앞에 와야 한다. 만약 우리가 PHP에서 $MyName로 호출되는 변수가 있으면, 그 다음에 스마티에서 그것을 출력하기 위해, 우리는 다음과 같이 작성해야 한다.

<html>
   <body>
       Welcome, {$MyName} <br>
   </body>
</html>

스마티의 힘은 유연성에도 있다. 여러분은 템플릿에 IF와 LOOP 삽입할수 있다. IF 문법은 다음과 같다.

{if <condition> }
       html code
{else}
       html code
{/if}

여러분이 링크가 있는 동적인 메뉴를 가지고 있다고 보자. 여러분이 링크를 클릭하면, 여러분은 특정 페이지에 간다. 그래서 여러분은 PHP에서 정수 변수 $Menu가 있다면, 템플릿은 다음과 같다.

{if ($Menu == 1) }
       Option 1
{else}
       <a href=”option1.php”>Option 1</a>
{/if}
{if ($Menu == 2 ) }
       Option 2
{else}
       <a href=”option2.php”>Option 2</a>
{/if}

반복문을 작성하기 위해, 여러분이 PHP에서 다음과 같은 배열을 얻기를 제안한다.
(여기서 얻는다(get)는 표현은 확장자가 php인 파일에 있는 변수나 배열을
템플릿 파일이 가져와야 하기 때문에 이렇게 표현한 것입니다.)

<table>
<tr  
{section name=user loop=$userID}
{if $smarty.section.user.iteration is odd}
       bgcolor=#efefef
{else}
       bgcolor=#ffffff        
{/if}  
>
   <td>    ID = {$userID[user]}  </td>
   <td> Name = {$name[user]}     </td>
   <td> Address = {$address[user]} </td>
</tr>
   {sectionelse}
<tr>
   <td>
       There is no user.
   </td>
</tr>
</section>
</table>

반복자는 스마티를 위한 내부 카운터이다. 그것은 우리에게 섹션의 현제 반복을 알게 해준다. 필자는 만약 현제 반복 변수가 남는지 아닌지 확인으로 인해 테이블에서 다른 열 색깔을 만들기 위해 내부 변수를 사용한다.(뭔 소리를 하는 건지)

LOOPS에 대안은 단일 연관 배열을 반복하기 위해 사용되는 FOREACH이다.

<foreach from=$users item=current_user>
       Name = {$current_user}
<foreachelse}
       No user available.
</foreach>

SECTION과 FOREACH의 중요한 차이는 SECTION은 특정 변수에서 시작할 수 있고, 반복을 위해 스텝을 설정할수 있다. 그에 반해 FOREACH는 모든 변수에 대해 반복할 수 있다.
(뒤에 예제 나오니까 그거 보시면 이해하실수 있을 것입니다.)

프로그래머를 위한 스마티

프로그래머를 위한 장점은 그들은 HTML과 PHP 코드를 분리할 수 있다는 것이다. 좀더 자세히 말하자면, 만약 디자이너가 페이지의 레이아웃을 바꾸면, 프로그래머는 기능적으로 바뀌지 않았다면, 새로운 레이아웃에 적합하게 하기 위해 코드를 바꿀 필요가 없다. 여러분은 여러분의 파일에서 작업하고 화면에 출력되는 모든 변수를 템플릿에 할당하고, 맥주 마시러 나간다.. 디자이너는 레이아웃을 바꾸고 내부적인 에러를 해결하기 위해, 여러분에게 전화 걸고 싶지 않을 것이다.
(쉽게 설명 하자면, 디자이너가 화면 디자인을 살짝 바꾼다음에 프로그래머에게 좀 고쳐달라고 말하지 않아도 됩니다. 여러분이 하는 일은 비즈니스 로직 구현이니까요)

PHP 파일에서 여러분은 스마티 클래스 require ‘Smarty.class.php’를 포함해야 한다.
그리고 $smarty = new Smarty로 인스턴스를 만들어야 합니다.

템플릿에 변수를 할당하기 위해, 여러분은 다음과 같이 해야 한다.
$smarty->assign(‘UserName’, ‘John Doe’).
모두 끝난 다음 여러분은 템플릿 $smarty->display(‘index.tpl)을 보여주기 위해 메소드를 호출한다.

다음과 같은 소스 코드를 보자 (index.php)


<?php
require 'Smarty.class.php';
$smarty = new Smarty;

$smarty->assign('Username', 'John Doe');
$smarty->display('index.tpl');
?>

이런 템플릿(index.tpl)을 보자.


<html>
<body>
       Welcome {$Username}
</body>
</html>

여러분은 역시 PHP에서 템플릿에 그것을 통과하는 배열을 만들수 있다.


$tmp = array ( 'UID'=> '10',  &'Name' => 'John Doe', 'Address'=>'Home address');
$smarty->assign('info', $tmp);

샘플 스크립트 ( 위의 내용은 추상적으로 설명한거고 밑에 내용이 중요합니다.)

이 스크립트는 로컬 데이터베이스에 접속하고 ‘Products’ 테이블에서 모든 제품을 선택(select)한다. 그 때 템플릿에 모든 변수를 통과한다. 그것은 스크린에 그것을 출력한다.


INDEX.PHP

<?php
// 스마티 클래스 파일 포함
require 'Smarty.class.php';
// 스마티 인스턴스 생성
$smarty = new Smarty;
// 디비 설정, 이부분은 각자에 맞게 고치십시오
$hostname = "localhost";
$dbUser = "sqluser";
$dbPass = "sqlpass";
$dbName = "sqldb";
// 데이터베이스에 접속
$conn = mysql_connect($hostname, $dbUser, $dbPass) or die("Cannot connect to the database");
// 디비 선택
mysql_select_db($dbName);
// 질의문 저장
$sql = "SELECT prodID, info FROM products ORDER BY prodID ASC";
// 테이블에서 모든 제품을 선택하라.
$res = mysql_query($sql);
// results를 배열 변수로 선언
$results = array();
$i=0;
while ($r=mysql_fetch_array($res)) {
           $tmp = array(
               'prodID' => $r['prodID'],
               'info'=> $r['info']
           );
           $results[$i++] = $tmp;
}
// 결과를 템플릿에 넘긴다
$smarty->assign('results', $results);
// 템플릿 파일을 로딩load 한다
$smarty->display('index.tpl');
?>


INDEX.TPL

<html>
<body>
Here's a table with the results: <br>
<table cellpadding=1 cellspacing=0 border=0 width=100%>
{section name=nr loop=$results}
   <tr {if $smarty.section.nr.iteration is odd} bgcolor="#efefef"{/if}>
       <td class=fb width=15%>
           <nobr><a href=&#8221;show-product.php?id={$results[nr].prodID}">Press here</a>

       <td class=fb width=29%><a href="show.php?id={$results[nr].prodID}"
       {popup inarray=$smarty.section.nr.iteration}
       >{$results[nr].info}</a></td>
   </tr>

{sectionelse}
<tr><td align="center"><br><b>no product </b> <br> </td></tr>
{/section}
   
</table>

<br>

Here's a select with the results: <br>
<select name="mys">
   {section name=nr loop=$results}
       <option value="{$results[nr].prodID}">{$results[nr].info}</option>
   {/section}
</select>

</body>
</html>


요약

스마티는 디자이너와 개발자 둘 다 에게 멋진 툴이다. 스마티를 사용하면서, 여러분은 사이트 개발과 관리 시간을 줄일 수 있다. 만약 여러분이 개발자라면, 여러분은 더 이상 HTML 코드로 뒤섞인 PHP code가 필요하지 않다. 비즈니스 로직에만 집중하고 디자이너에게 HTML을 떠나라.

번역자에 관하여..
집에서 놀고 있는 백수..

2006/09/08 23:33 2006/09/08 23:33
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > ▶ IT 강국 코리아
원본 http://blog.naver.com/leeyb74/130002720990

where    a.code NOT IN (select     deptno from tab2 where gcode = b.code)

위와 같이 NOT IN 의 연산자가 올 경우, SUB QUERY의 조건을 사용하여 NOT IN 대신 NOT EXISTS를 사용하여 개선할 수 있습니다.

where   a.code IS NOT NULL

and       a.code NOT IN ( select    /*+ MERGE_AJ */

                                                    deptno from tab2 where gcode = b.code

                                       and       deptno IS NOT NULL)

위와 같이 NOT IN 을 사용하는 경우 힌트를 사용하여 성능을 더욱 개선할 수 있습니다. 다음과 같이  /*+ MERGE_AJ*/ 나 혹은 /*+ HASH_AJ */ 와 같은 해당 조인시에서 양쪽 집합만을 추출하는 것에 대해 최적인 실행 계획을 수립, 실행하라는 힌트를 쓸 수 있습니다. 이 때 양쪽 집합의 조건에 NOT NULL을 주는 것은 필수 조건으로 오라클의 버그를 피하기 위한 방법입니다.

2006/09/08 19:54 2006/09/08 19:54
이 글에는 트랙백을 보낼 수 없습니다
출처 블로그 > What you see is what you get
http://blog.naver.com/etwas0227/60021345880

패턴 문법

패턴 문법 -- PCRE 정규표현식 문법 설명

설명

PCRE 라이브러리는 아주 약간의 차이(아래를 참고)를 제외하고, 펄 5와 동일한 구문과 의미를 사용하여 정규표현식 패턴 매칭을 수행하는 함수의 집합입니다. 현재 수행은 펄 5.005에 대응합니다.

펄과의 차이

여기에서 설명한 차이는 펄 5.005 기준입니다.

  1. PCRE는 다른 문자 집합으로 컴파일할 수 있지만, 기본적으로 공백 문자는 C 라이브러리 함수 isspace()가 인식하는 모든 문자입니다. 보통 isspace()는 스페이스, 폼피드, 줄바꿈, 캐리지 리턴, 수평 탭, 수직 탭을 인식합니다. 펄 5는 공백 문자에 수직 탭을 포함하지 않습니다. 오랜 기간동안 펄 문서의 \v 이스케이프는 사실상 인정되지 않았습니다. 그러나 문자 자체는 적어도 5.002까지 공백으로 취급되었으며, 5.004와 5.005는 \s에서 인식하지 않습니다.

  2. PCRE는 lookahead 단정에서 반복 횟수를 허용하지 않습니다. 펄은 허용하지만, 생각하는 그대로의 의미를 갖지 않습니다. 예를 들어, (?!a){3}는 다음 세 문자가 "a"가 아닌 것을 의미하지 않습니다. 단지, 다음 문자가 "a"가 아니라는 것을 세번 확인할 뿐입니다.

  3. 부정 lookahead 단정 안에서 일어나는 서브패턴 검출을 카운트를 하지만, 시작 위치 벡터에 그 엔트리를 설정하지는 않습니다. 펄은 부정 lookahead 단정이 단 하나의 브랜치를 가지고 있을 경우에 한하여, 그 단정이 매치에 실패(결과적으로 성공)하기 전에 매치한 어떠한 패턴에 대해서만 그에 대한 숫자 변수를 설정합니다.

  4. 바이너리 제로 문자는 목표 문자열에서는 지원하지만, 패턴 문자열에서는 허용하지 않습니다. 패턴은 제로로 종료하는 보통의 C 문자열로 처리하기 때문입니다. 패턴에서 바이너리 제로를 표현하기 위해서는 이스케이프 시퀀스 "\\x00"로 사용할 수 있습니다.

  5. 다음의 펄 이스케이프 시퀀스는 지원하지 않습니다: \l, \u, \L, \U, \E, \Q. 사실, 이들은 펄의 일반 문자열 핸들링이며, 패턴 매칭 엔진의 부분이 아닙니다.

  6. 펄의 \G는 싱글 패턴 매치에 적절하지 않기 때문에 지원하지 않습니다.

  7. 당연하게도, PCRE는 (?{code}) 구조를 지원하지 않습니다.

  8. 패턴의 일부가 반복될 때, 잡아낸 문자열의 설정에 관해서, 펄 5.005_02에서 일부 이상한 동작이 존재합니다. 예를 들어, "aba"에 대해서 패턴 /^(a(b)?)+$/를 매칭하면 $2를 "b" 값으로 설정하지만, "aabbaa"에 대해서 /^(aa(bb)?)+$/를 매칭하면 $2를 설정하지 않습니다. 하지만 패턴을 /^(aa(b(b))?)+$/로 변경하면 $2(와 $3)를 설정합니다. 펄 5.004에서는 $2를 두 경우 모두 설정했으며, PCRE에서도 TRUE입니다. 앞으로 펄이 이 차이를 일관성 있게 변경한다면, PCRE는 그 변경에 따를 것입니다.

  9. 또다른 해결되지 않은 모순점은 펄 5.005_02가 패턴 /^(a)?(?(1)a|b)+$/를 문자열 "a"에 매치하지만, PCRE는 하지 않습니다. 그러나 펄과 PCRE 모두 /^(a)?a/를 "a"에 매치하고 $1을 설정하지 않습니다.

  10. PCRE는 펄 정규표현식 기능의 몇가지 확장을 지원합니다:

    1. lookbehind 단정은 고정 길이 문자열에만 매치해야하지만, 양자 택일의 lookbehind 단정에서는 다른 길이의 문자열을 매치할 수 있습니다. 펄 5.005에서는 모두 같은 길이를 가질 것을 요구합니다.

    2. PCRE_DOLLAR_ENDONLY를 설정하고 PCRE_MULTILINE를 설정하지 않으면 $ 메타 문자는 문자열의 가장 마지막에만 매치합니다.

    3. PCRE_EXTRA를 설정하면, 백슬래쉬 뒤에 특별한 의미를 가지지 않는 문자의 사용은 실패하게 됩니다.

    4. PCRE_UNGREEDY를 설정하면, 반복 수량어의 greediness가 뒤집어져서, 기본값으로 greedy하지 않게 됩니다. 하지만 뒤에 물음표가 붙으면 greedy하게 됩니다.

정규표현식 상세

소개

아래 설명은 PCRE가 지원하는 정규표현식의 문법과 의미입니다. 정규표현식은 펄 문서 및 많은 책들에 설명이 있으며, 그 중 일부에는 풍부한 예제를 가지고 있습니다. O'Reilly에서 출판한 Jeffrey Friedl의 "Mastering Regular Expressions"(ISBN 1-56592-257-3)는 예제들을 매우 자세하게 다루고 있습니다. 여기의 설명은 레퍼런스 문서에 따릅니다.

정규표현식은 주어진 문자열에 대하여 왼쪽에서 오른쪽으로 매치하는 패턴입니다. 문자열은 패턴으로 준비하고, 목표에서 대응하는 문자열에 매치합니다. 간단한 예로, 패턴 The quick brown fox는 목표 문자열의 동일한 부분에 매치합니다.

메타 문자

정규표현식이 강력한 이유는 패턴에 선택과 반복을 포함할 수 있다는 점입니다. 이는 특별한 방법으로 해석하는 메타 문자를 사용하여 패턴에 넣습니다.

메타 문자는 두가지 종류가 존재합니다: 대괄호 안을 제외하고 패턴의 어디에서라도 작동하는 종류와, 대괄호 안에서만 작동하는 종류입니다. 다음은 대괄호 밖에서 사용하는 메타 문자들입니다.

\

여러가지로 사용하는 일반적인 이스케이프 문자

^

목표의 처음 (멀티라인 모드에서는 줄의 처음)

$

목표의 마지막 (멀티라인 모드에서는 줄의 끝)

.

(기본값으로) 줄바꿈을 제외한 아무 문자

[

클래스 정의 시작 문자

]

클래스 정의 끝 문자

|

선택 브랜치 시작

(

서브패턴 시작

)

서브패턴 끝

?

( 의미 확장, 또는 0회나 1회, 또는 수량어 minimizer

*

0회 이상의 횟수

+

1회 이상의 횟수

{

최소/최대 횟수 시작

}

최소/최대 횟수 끝

대괄호 안쪽의 패턴은 "문자 클래스"라고 부릅니다. 다음은 문자 클래스에서 사용하는 메타 문자들입니다:
\

일반적인 이스케이프 문자

^

처음 문자로 올 때, 부정 클래스로 설정

-

문자 범위 지정

]

문자 클래스 종료

다음 섹션은 각 메타 문자의 사용을 설명합니다.

백슬래쉬

백슬래쉬 문자는 여러가지 사용법을 가집니다. 먼저, 뒤에 영숫자가 아닌 문자가 붙는다면, 그 문자가 가지고 있는 특별한 의미가 사라집니다. 이러한 이스케이프 문자로 백슬래쉬를 사용하는 것은 문자 클래스 안과 밖 양쪽에 모두 적용됩니다.

예를 들어, "*" 문자를 매치하길 원한다면, 패턴에는 "\*"로 써야합니다. 이는 따라오는 문자가 메타 문자이던 아니던간에 관계 없이 적용하기 떄문에, 영숫자가 아닌 문자에 그 자체를 사용하기 위해 "\"를 붙이는 것이 항상 안전합니다. 특히, 백슬래쉬를 매치하고자 한다면, "\\"로 써야합니다.

패턴에 PCRE_EXTENDED 옵션을 사용하면, 패턴에 존재하는 (문자 클래스 안이 아닌) 공백, 그리고 문자 클래스 밖의 "#"사이의 문자와 바로 뒤의 줄바꿈 문자를 무시합니다. 이스케이프하는 백슬래쉬를 공백이나 "#"문자를 패턴에 넣기 위해 사용할 수 있습니다.

백슬래쉬의 두번째 사용법은 패턴에서 출력할 수 없는 문자를 보여지게 인코딩하는 방법을 제공합니다. 바이너리 제로가 패턴 종료를 의미하는걸 제외하면, 출력할 수 없는 문자가 나타나는 제한은 존재하지 않습니다. 그러나 패턴을 텍스트 편집으로 준비할 때는, 다음의 이스케이프 시퀀스를 사용하는 편이 바이너리 문자를 직접 표현하는 것보다 간편합니다:

\a

알람, BEL 문자(hex 07)

\cx

"control-x", x는 임의의 문자

\e

이스케이프 (hex 1B)

\f

폼피드 (hex 0C)

\n

줄바꿈 (hex 0A)

\r

캐리지 리턴 (hex 0D)

\t

탭 (hex 09)

\xhh

16진 코드 hh 문자

\ddd

8진 코드 ddd 문자, 혹은 역참조

"\cx"의 효과는 다음과 같이 계산합니다: "x"가 소문자라면, 대문자로 변환합니다. 그 후, 문자의 6번째 비트(hex 40)가 뒤집어집니다. 즉 "\cz"은 hex 1A가 되고, "\c{"은 hex 3B, 그리고 "\c;"은 hex 7B가 됩니다.

"\x" 뒤에, 두개의 16진 숫자를 읽습니다. (대소문자는 구별하지 않습니다)

"\0"은 다음의 두자리의 8진수를 읽습니다. 양쪽 모두, 두자리가 되지 않을 경우, 그 표현을 그대로 사용합니다. 즉 "\0\x\07" 시퀀스는 두개의 바이너리 제로에 이어지는 BEL 문자를 정의합니다. 바로 뒤에 8진수로 인식되는 문자가 이어질 경우에는 처음의 제로 뒤에 두자리 수를 써야한다는 것을 잊지 마십시오.

백슬래쉬 뒤에 0이 아닌 수가 올 경우에 혼동할 수 있습니다. 문자 클래스 밖에서, PCRE는 그것과 따라오는 수를 10진수로 읽습니다. 수가 10보다 작거나, 표현식에서 수 이상의 묶음을 잡아냈다면, 이 시퀀스는 역참조가 됩니다. 이 작동에 관해서는 아래에, 묶음 서브패턴에 설명이 있습니다.

문자 클래스 안이나, 10진수 9 이상이 없고 서브패턴이 그만큼 존재하지 않을 경우, PCRE는 백슬래쉬 뒤의 세자리 8진수로 다시 읽어들여, 해당하는 8비트 값으로 하나의 바이트를 생성합니다. 어떠한 수라도 사용할 수 있습니다. 예를 들면:

\040

스페이스의 다른 표현 방법

\40

40개 미만의 서브 패턴을 검출하였을때, 동일한 의미

\7

항상 역참조

\11

역참조, 혹은 탭의 다른 표현 방법

\011

항상 탭

\0113

문자 "3"이 따라오는 탭

\113

8진 코드 113 문자 (역참조는 99까지입니다)

\377

1비트만을 제외한 바이트

\81

역참조이거나 "8"과 "1"의 두 문자가 붙는 바이너리 제로

100이상의 8진 값은 앞에 제로가 붙지 않아야만 합니다. 세자리를 넘어가는 8진 값은 읽지 않습니다.

하나의 바이트값을 정의하는 모든 시퀀스는 문자 클래스 내외, 어디에서도 사용할 수 있습니다. 추가로, 문자 클래스 안에서 "\b" 시퀀스는 백스페이스 문자(hex 08)로 해석합니다. 문자 클래스 밖에서는 다른 의미를 가집니다. (아래를 참고)

백슬래쉬의 세번째 사용법은 일반적인 문자 타입의 지정입니다:

\d

임의의 10진 숫자

\D

10진 숫자가 아닌 임의의 문자

\s

임의의 공백 문자

\S

공백이 아닌 임의의 문자

\w

임의의 "word" 문자

\W

임의의 "non-word" 문자

각 이스케이프 시퀀스 조합은 완전한 문자 세트를 두개의 개별 세트로 분리합니다. 주어진 문자는 각 조합의 한쪽에만 매치합니다.

"word" 문자는 어떠한 문자나 숫자, 혹은 언더스코어(_)입니다. 즉, 펄의 "word"에 해당하는 어떠한 문자입니다. 문자와 숫자의 정의는 PCRE의 문자 테이블이 제어하고, 로케일 특정 매칭이 존재할 경우에는 다양할 수 있습니다. (위쪽의 "로케일 지원" 참고) 예를 들어, "fr"(프랑스어) 로케일에서는, 128 이상의 몇몇 코드를 엑센트 문자를 나타내는데 사용하며, 이들은 \w에 매치합니다.

문자형 시퀀스는 문자 클래스 안과 밖에서 모두 사용할 수 있습니다. 각각 해당하는 형의 한 문자에 매치합니다. 현재 매칭 위치가 목표 문자열의 마지막이라면, 전부 실패하고, 어떠한 문자도 매치하지 않습니다.

백슬래쉬의 네번째 사용법은 간단한 단정입니다. 단정은 조건이 목표 문자열에서 다른 부분에 매치하지 않고, 특정한 위치에만 매치하도록 지정합니다. 복잡한 단정을 위한 서브패턴의 사용법은 아래에 설명이 있습니다. 백슬래쉬 단정은 다음과 같습니다.

\b

word 경계

\B

word 경계가 아님

\A

목표의 처음 (멀티라인 모드와 무관)

\Z

목표의 마지막이나 마지막에서 줄바꿈 (멀티라인 모드와 무관)

\z

목표의 마지막 (멀티라인 모드와 무관)

단정은 문자 클래스 안에서 사용할 수 없습니다. ("\b"가 문자 클래스 안에서는 백스페이스 문자를 나타내는 점에 주의하십시오)

word 경계는 현재 문자와 이전 문자가 둘 다 \w에 매치하지 않거나 둘 다 \W에 매치하지 않는 (즉, 하나는 \w에 매치하고 다른 하나는 \W에 매치) 목표 문자열의 위치이거나, 처음이나 마지막 문자가 \w에 매치할 경우는 문자열의 처음이나 마지막입니다.

\A, \Z, \z 단정은 전통적인 circumflex와 달러와는 달리 옵션과 관계 없이 목표 문자열의 가장 처음이나 가장 마지막에만 매치합니다. 이들은 PCRE_MULTILINE이나 PCRE_DOLLAR_ENDONLU 옵션에 영향을 받지 않습니다. \Z\z의 차이는, \Z가 문자열의 마지막뿐만 아니라 문자열 마지막 문자가 줄바꿈일 경우에는 바로 앞에도 매치하지만, \z는 마지막에만 매치합니다.





출처: http://www.php.net/manual/kr/pcre.pattern.syntax.php



-------------------------------------------------------------------------------






array preg_grep ( string pattern, array input [, int flags])

preg_grep()은 주어진 pattern에 매치되는 input 배열의 요소를 포함하는 배열을 반환합니다.


EXAMPLE:
$food = array('apple', 'banana', 'squid', 'pear');
$fruits = preg_grep("/squid/", $food, PREG_GREP_INVERT);
echo "Food  "; print_r($food);
echo "Fruit "; print_r($fruits);

RESULTS IN:
Food  Array
(
  [0] => apple
  [1] => banana
  [2] => squid
  [3] => pear
)
Fruit Array
(
  [0] => apple
  [1] => banana
  [3] => pear
)

출처: http://www.php.net/manual/kr/function.preg-grep.php



-------------------------------------------------------------------




preg_match -- 정규표현식 매치를 수행합니다.


예 1. 문자열 "php" 찾기

<?php
// 패턴 구분자 뒤의 "i"는 대소문자를 구별하지 않게 합니다.
if (preg_match("/php/i", "PHP is the web scripting language of choice."
)) {
  echo
"발견하였습니다."
;
} else {
  echo
"발견하지 못했습니다."
;
}
?>

예 2. 단어 "Web" 찾기

<?php
/* 패턴에서 \b는 단어를 지시합니다. 단어 "web"만 매치하고,
* "webbing"이나 "cobweb" 등의 부분적인 경우에는 매치하지 않습니다. */
if (preg_match("/\bweb\b/i", "PHP is the web scripting language of choice."
)) {
  echo
"발견하였습니다."
;
} else {
  echo
"발견하지 못했습니다."
;
}

if (
preg_match("/\bweb\b/i", "PHP is the website scripting language of choice."
)) {
  echo
"발견하였습니다."
;
} else {
  echo
"발견하지 못했습니다."
;
}
?>

예 3. URL에서 도메인 이름 얻기

<?php
// URL에서 호스트 이름 얻기
preg_match("/^(http:\/\/)?([^\/]+)/i"
,
 
"http://www.php.net/index.html", $matches
);
$host = $matches[2
];

// 호스트 이름에서 마지막 두 세그멘트 얻기
preg_match("/[^\.\/]+\.[^\.\/]+$/", $host, $matches
);
echo
"도메인 이름은: {$matches[0]}\n"
;
?>

이 예제의 결과:

도메인 이름은: php.net



출처: http://www.php.net/manual/kr/function.preg-match.php



------------------------------------------------------------------------






< 참고 >





-----------------------------------------------------------------------------









1. ereg(string pattern, string string, array [regs])

   해당 문자열에서 주어진 정규 표현식 패턴과의 일치 되는 문자열을 검색합니다.

2. ereg_replace(string pattern, string replacement, string string)

   해당 문자열에서 주어진 정규 표현식 패턴과의 일치 되는 문자열을 검색하고 바꿀 문자열로 대체합니다.


3. eregi(string pattern, string string, array [regs])

   ereg() 함수와 동일하나 검색을 할 때 대, 소 문자를 구분하지 않습니다.


4. eregi_replace(string pattern, string replacement, string string)

   ereg_replace()와 동일하나 검색을 할 때 대, 소 문자를 구분하지 않습니다.

                                                       
5. split(string pattern, string string, int [limit])

   지정한 패턴과 일치하는 문자열을 경계로 해당 문자열을 나누고 배열에 저장합니다.


 
정규 표현식 패턴의 종류

                                                                        

정규 표현식은 주로 게시판의 입력 사항에서 사용 되어 집니다. 가령 비밀번호나 기타 이름 등을 입력할 때

주어진 조건에 맞게 입력하게끔 하는 것입니다.

   " . " - 이 표현은 c.y처럼 표현하기도 하고 .cy로 하기도 합니다.
             즉, 전자는 c로 시작 하면서 y로 끝나는 문자를 나타냅니다.
             (cry , cay , cat) 물론 여기서 . 은 한 문자만을 가리키는 것입니다.
             후자는 문자열이 cy로 끝나는 문자열을 나타냅니다(xcy, xcy). 잘못된 표현은 전자의 경우
             csdy, cfgy , cy입니다. " . " 은 한문자 만을 나타냅니다.

   " ? " - ?앞의 문자가 있거나 없음을 나타냅니다. 즉, sc?y 는 sy , scy , scyf , frsy …와 일치합니다.               

   " + " - +는 앞의 문자를 가리키며 최소 하나 이상의 문자임을 나타냅니다.
             즉, c+ry는 cry, ccry, cccry, cryhj … 와 일치합니다.

   " * " - * 는 앞의 문자가 없거나 하나 이상의 문자임을 나타냅니다.
             즉, c*ry 는 ry, cry, cccry … 과 일치합니다. 또 cry* 는 y가 없거나 하나 이상 문자임을 나타냅니다.
             cr, cry, cry, cryyy …. 와 일치합니다.

   " $ " - $는 해당 문자열의 마지막 부분을 가리킵니다. 즉, c?ry$ 는 ry로 끝나는 문자열에서 앞의 문자가 c가
             있거나 없는 문자열을 나타냅니다.
             cry , ry , skycry …와 일치합니다. c?r+$ 는 앞의 문자 c 가 있거나 없는 문자이며 r로 적어도 하나이상
             끝나는 문자열을 나타냅니다. r , cr , crr , crrr … 와 일치합니다.
                                                                                          
   " ^ " - ^ 는 뒤 문자열로 시작되는 모든 문자열을 나타냅니다.
             즉, ^cry 는 cry is good, cry is very good, crypdf … 와 일치합니다.
             또 ^cry?df는 y가 있거나 없는 crydf , crdf로 시작하는 모든 문자열을 나타냅니다.
             crydf is good, crdfgg …와 일치합니다.


   이렇게 이 기호들은 상호 같이 사용해서 문자열을 표현합니다.

                                                                                               
   " [ ] " - [ ] 는 이 안의 문자 중에 하나의 문자를 표현합니다. 그리고 [ ] 안의 문자의 표현은
            "-" 를 사용해서 합니다.
            즉, [a-z] 는 영문의 소문자 한글자를 포함하는 모든 문자열을 나타냅니다.
            A2sdr , skycry , cry , zzzz …. 와 일치합니다.
            또 [a-zA-Z0-9] 는 영문 대,소문자 와 십진수 한자를 포함하는 모든 문자열을 나타냅니다.
            a4df, Cry44 is passw , 4ded … 등과 일치합니다. 
            [cC][yY] 는 cy , cY , Cy , CY 를 포함하는 문자열을 나타냅니다. Cycap , Cyclub … 등과 일치합니다.
            만약 해당하는 문자를 제외한 문자열과의 일치를 나타내려면 ^기호를 [] 안에 사용합니다.
            [^a-z]는 영문 소문자를 제외한 한글자를 포함하는 문자열을 나타냅니다.
            Cry44, skycryGood, 444 is passw … 와 일치합니다.
            물론 영문 자체의 입력을 하지 못하게 하려면 [^a-zA-Z]로 표현할 수 있습니다.
            [ ] 는 일정한 문자의 표현은 간단하게 표현할 수도 있습니다. 클래스화된 방법을 사용합니다.
            즉, [[:space:]]는 공백 문자를 나타냅니다 ( ) 와 일치합니다.
            [[:digit:]]는 숫자 하나를 나타냅니다. [0-9]와 일치합니다.
            [[:alpha:]]는 영문 알파벳 하나를 나타냅니다. [a-zA-Z] , [a-Z]와 일치합니다.
            [[:alnum:]]는 영문 알파벳 문자와 숫자 중 하나를 나타냅니다. [a-zA-Z0-9]와 일치합니다.

                                                                                                                                                
   " { } " - { }는 {숫자}로 표현하며 중괄호 안의 숫자는 앞의 문자의 개수를 나타냅니다.
            C{4}ry는 C가 ry 앞에 4개 존재하는 문자열을 나타냅니다.
            CCCCry를 나타냅니다. C{4,}ry는 C가 ry 앞에 적어도 4개 이상인 문자열을 나타냅니다.
            CCCCry , CCCCCry , CCCCCCry … 와 일치합니다.
            C{1,4}ry 는 C 가 ry 앞에 1 ~ 4개 존재하는 문자열을 나타냅니다.
            Cry , CCry , CCCry , CCCCry 와 일치합니다.

   " ( ) " - ( ) 는 이 안의 문자를 그룹화합니다.
            sky(cry)* 는 sky 뒤에 cry 가 하나 이상 있거나 없는 문자열을 나타냅니다.
            sky , skycry is good , skycrycrydd …. 와 일치합니다.

   " | " - | 는 OR 연산을 나타내 줍니다.
            sky|cry 는 sky 나 cry 를 나타내는 문자열을 나타냅니다. sky is good , cry is good..와 일치합니다.
            sky(cry|g)* 는 sky 뒤에 cry 나 g 가 없거나 하나 이상 존재하는 문자열을 나타냅니다.
            sky , skycry , sky is good , skygjjh … 등과 일치합니다.

                                      
   특수 기호 패턴에 비교하기 -
            특수 기호 " ^  .  [ ]  $  ( ) |  *  +  ?  { }  \ " 앞에 \를 붙여 표현합니다.
            하지만 [ ] 안에서 특수 기호를 사용할 경우 \를 붙이지 않고 그냥 표현합니다.
            \$+ 는 문자열 앞에 $ 기호가 하나 이상 포함된 문자열을 나타냅니다.
            $cry , $$$sky … 등과 일치합니다.
            [^.[]?*{}/\] 는 문자열 중에 "^" , " ." , " [" , " ]" , "? " , " * " , " { " ,
            " } " , "/ " , "\"문자가 포함된 문자열을 나타냅니다. Hi? , {cry} , … 등과 일치합니다.



출처: http://www.junjaewoo.com/kldp/ApacheMySQLPHP_Guide-KLDP-html/ApacheMySQLPHP_Guide-KLDP-8.html#ss8.1







-------------------------------------------------------------------------------








< 테스트 예제 >

위 내용들을 적용한 테스트 소스~ 문의는 http://blog.naver.com/etwas0227.do 에게루~


<?
  // ex) php 에서 해당 페이지 접속한 client ip 구하기 //
  $ip = $_SERVER['REMOTE_ADDR'];
  $fullhost = gethostbyaddr($ip);
 
  echo ("Client IP : $ip <br>");
  echo ("Fullhost  : $fullhost <br>"); 
  echo ("Server IP : $ServerIP <br><br>");
 
  
  // ex) php 에서 아이피 추출하기 //
  // preg_match 함수적용
  echo ("preg_match - Fullhost Sample : 123.10.101.102 <br>");   
 
  preg_match("/^([^\.]+)+\.([^\.]+)/i", "123.10.101.102", $matches);   //1,2 단계 아이피 추출
  echo ("1,2 단계 아이피 : $matches[0] <br>");  
 
  preg_match("/[^\.\/]+\.[^\.\/]+$/", "123.10.101.102", $matches);   //3,4 단계 아이피 추출
  echo ("3,4 단계 아이피 : $matches[0] <br>");
 
  preg_match("/^([^\.]+)+\.([^\.]+)+\.([^\.]+)/i", "123.10.101.102", $matches);  //1,2,3 단계 아이피 추출
  echo ("1,2,3 단계 아이피 : $matches[0] <br><br>");  //결과 : 123.10.101


  // preg_replace 함수적용
  echo ("preg_replace - Fullhost Sample : 123.10.101.102 <br>");
  $fullhost = "123.10.101.102";
  //$host = preg_replace("/*./", "*.*.", $fullhost);
  //$fullhost = preg_replace("/^[^\.]+\.[^\.]+/", "*", $fullhost);
  $fullhost = preg_replace("/^([^\.]+)+\.([^\.]+)/", "*.*", $fullhost);
  echo ("Fullhost 해당 패턴 변형 : $fullhost <br>");
 
?>


<br>


<?

  // 특정 아이피 접속자만 해당 페이지 보여주기
   $ip = $_SERVER['REMOTE_ADDR'];
   $client_ip = gethostbyaddr($ip);    //사용자 접속아이피
preg_match("/^([^\.]+)+\.([^\.]+)/i", $client_ip, $matches);   //두 단계 아이피를 추출
$match_ip = $matches[0]; 

if ($match_ip == "12.34.56.78") {   //추출한 아이피와 접속가능 아이피 비교
 echo ("Match IP : $matches[0] <br>");  //해당페이지 내용보여줌

else
 exit;   //해당페이지 내용보여주지 않음
?>

<br>

2006/09/08 16:23 2006/09/08 16:23
이 글에는 트랙백을 보낼 수 없습니다
Web_developing/PHP  2006/09/08 16:00
출처 카페 > 플래시,Flash,포토샵,P.. / 나만봐
원본 http://cafe.naver.com/q69/9076

II. 배열함수

소개

이 함수는 다양한 방법으로 배열에 접근하고 배열을 조작할 수 있게 해 준다. 배열은 변수들의 집합을 저장, 관리, 처리하는데 있어서 핵심적이다.

일차원 뿐만 아니라 다차원 배열이 지원되고 있고, 사용자나 다른 함수에 의해 생성될 수 있다. 데이터베이스 질의문으로부터 배열을 생성하는 전용 데이터베이스 제어 함수와 배열을 반환하는 함수를 제공한다.

PHP에서의 배열 구현과 사용법에 대한 자세한 설명은 매뉴얼의 배열 섹션을 참고.

요구 사항

이 확장 모듈을 빌드할 때 외부 라이브러리가 필요하지 않습니다.

설치

이 함수들은 설치하지 않아도 사용할 수 있습니다; PHP 코어의 일부입니다.

런타임 설정

이 확장 모듈은 php.ini 설정이 존재하지 않습니다.

리소스 종류

이 확장 모듈은 리소스형을 정의하지 않습니다.

상수 정의

아래 상수들은 PHP 코어의 일부로, 항상 사용할 수 있습니다.

CASE_LOWER (integer)

CASE_LOWERarray_change_key_case() 함수에서 배열 키를 소문자로 변환하는데 사용된다. 또한 이 상수는 array_change_key_case()의 기본값이다.

CASE_UPPER (integer)

CASE_UPPERarray_change_key_case() 함수에서 배열 키를 대문자로 변환하는데 사용된다.

정렬 순서 플래그:

SORT_ASC (integer)

SORT_ASCarray_multisort() 함수에서 오름차순 정렬에 사용된다.

SORT_DESC (integer)

SORT_DESCarray_multisort() 함수에서 내림차순 정렬에 사용된다.

정렬 형태 플래그: 여러 정렬함수에 의해 사용됨.

SORT_REGULAR (integer)

SORT_REGULAR는 아이템들을 통상적인 방법으로 비교하는데 사용됨.

SORT_NUMERIC (integer)

SORT_NUMERIC는 아이템들을 수치로서 비교하는데 사용됨.

SORT_STRING (integer)

SORT_STRING는 아이템들을 문자열로서 비교하는데 사용됨.

COUNT_NORMAL (integer)
COUNT_RECURSIVE (integer)
EXTR_OVERWRITE (integer)
EXTR_SKIP (integer)
EXTR_PREFIX_SAME (integer)
EXTR_PREFIX_ALL (integer)
EXTR_PREFIX_INVALID (integer)
EXTR_PREFIX_IF_EXISTS (integer)
EXTR_IF_EXISTS (integer)
EXTR_REFS (integer)
차례
array_change_key_case -- 모두 대문자나 소문자화된 문자열 키를 갖는 배열로 반환한다
array_chunk -- 배열을 여러 덩어리로 분산시킨다
array_combine --  키를 위한 배열과 값을 위한 배열을 각각 사용하여 배열을 생성한다
array_count_values -- 배열 값의 수를 센다
array_diff_assoc -- 인덱스 검사와 함께 배열간의 차이를 계산한다
array_diff_uassoc --  Computes the difference of arrays with additional index check which is performed by a user supplied callback function
array_diff -- 배열간의 차이를 계산한다
array_fill -- 배열을 특정값으로 채운다
array_filter --  콜백함수를 사용하여 배열의 원소를 필터한다
array_flip -- 배열안의 모든 키를 각 키의 연관값으로 바꾼다.
array_intersect_assoc -- 인덱스 검사과 함께 배열의 중복을 계산한다
array_intersect -- 배열의 중복을 계산한다
array_key_exists -- 주어진 키와 인덱스가 배열에 존재하는지 확인한다
array_keys -- 배열의 모든 키를 반환한다
array_map --  Applies the callback to the elements of the given arrays
array_merge_recursive -- 두개 이상의 배열을 재귀적으로 병합한다
array_merge -- 두개 이상의 배열을 병합한다
array_multisort -- 여러개의 배열 또는 다차원 배열을 정렬한다
array_pad --  설정된 길이만큼 특정 값으로 배열을 채운다
array_pop -- 배열 끝의 요소를 뽑아낸다
array_push --  배열의 끝에 하나 이상의 원소를 넣는다.
array_rand --  배열안에서 하나 이상의 임의 원소를 뽑아낸다
array_reduce --  콜백 함수를 사용하여 배열을 반복적으로 단일 값으로 축소시킨다
array_reverse --  배열 원소를 역순으로 반환한다
array_search --  배열에서 주어진 값을 검색하고 성공하면 해당 키를 반환한다
array_shift --  배열의 맨 앞에 있는 원소를 옆으로 이동시킨다
array_slice -- 배열의 일부를 추출한다
array_splice --  배열의 일부를 삭제하고, 그 위치에 다른 내용을 대체한다
array_sum --  배열내의 값들의 합을 계산한다
array_udiff_assoc -- Computes the difference of arrays with additional index check. The data is compared by using a callback function.
array_udiff_uassoc -- Computes the difference of arrays with additional index check. The data is compared by using a callback function. The index check is done by a callback function also
array_udiff -- Computes the difference of arrays by using a callback function for data comparison.
array_unique -- 배열에서 중복된 값을 제거한다
array_unshift --  배열의 맨 앞에 하나 이상의 원소를 첨가한다
array_values -- 배열의 모든 값들을 반환한다
array_walk_recursive --  Apply a user function recursively to every member of an array
array_walk --  배열의 개개의 원소에 대해서 특정 함수를 적용하여 수행한다
array --  배열을 생성한다
arsort --  배열을 내림차순 정렬하고 인덱스의 상관관계를 유지한다.
asort -- 배열을 정렬하고 인덱스 상관 관계를 유지한다
compact --  여러 변수들과 값을 갖는 배열을 생성한다
count -- 변수의 원소 갯수를 구한다
current -- 배열의 현재 원소를 반환한다
each --  배열에서 현재의 키와 값 쌍을 반환하고 배열 커서를 전진시킨다
end --  내부 배열 포인터를 마지막 원소를 가리키게 한다
extract --  배열의 현재 심볼 테이블로 변수들을 입력한다
in_array -- 배열에서 값이 존재하는지 점검한다
key -- 연관배열에서 키를 꺼낸다
krsort -- 역순으로 키에 의해 배열을 정렬한다
ksort -- 키에 의해 배열을 정렬한다
list --  배열처럼 변수들을 지정한다
natcasesort --  대소문자를 구별하지 않고 "natural order" 알고리즘을 사용하여 배열을 정렬한다
natsort --  "natural order" 알고리즘을 사용하여 배열을 정렬한다
next --  배열의 내부 배열 포인터를 전진시킨다
pos -- 배열에서 현재 원소를 꺼내온다
prev -- 내부 배열 포인터를 앞으로 돌린다
range --  특정 범위의 원소를 갖는 배열을 생성한다
reset --  배열의 내부 포인터가 배열의 첫번째 원소를 가리키게 한다
rsort -- 역순으로 배열을 정렬한다
shuffle -- 배열을 뒤섞는다
sizeof -- count()의 별칭
sort -- 배열을 정렬한다
uasort --  사용자-정의 비교함수로 배열을 정렬하고 인덱스 연관성을 유지한다
uksort --  사용자-정의된 비교함수를 사용하여 키에 의해 배열을 정렬한다
usort --  사용자-정의된 비교함수를 사용하여 값들에 의해 배열을 정렬한다
2006/09/08 16:00 2006/09/08 16:00
이 글에는 트랙백을 보낼 수 없습니다
myisamchk 이란?

- DB 테이블에대한 오류 검사 및 오류 복구 유틸리티 이다
- 버전 3.22.x : isamchk 유틸리티 사용
         3.23.x : myisamchk 유틸리티 사용

[ myisamchk 사용전 주의사항 ]

- mysql 데몬을 stop 시킨후 이 유틸리티를 사용해야함.
- mysql 데몬을 중지시킬수 없는 사항이라면 검사할 테이블에대한 rock을 걸고
   검사를 수행하여야만 검사도중에 발생할수있는 오류를 막을수있다.
- 모든작업을 항상 백업을 한후 작성을 수행하는것이 좋을것이다.

[ myisamchk 사용법 및 옵션 ]

- 해당 테이블이있는 디렉토리로 이동 ( 보통  /usr/local/mysql/var 밑에 위치함 )


1.일반적인 검사

# myisamchk  [table 명]
예)  
Checking MyISAM file: zz_news.MYI
Data records:       0   Deleted blocks:       0
- check file-size
- check key delete-chain
- check record delete-chain
- check index reference
- check data record references index: 1
- check data record references index: 2
- check record links
   ==>  에러메시지가 없으면 테이블에 오류가 없다는것이다.

2. 옵션
 
  # myisamchk -s,--silent [table 명]
     -> 에러만 출력
     
  # myisamchk -v,--verbose [table 명]
   ->  -s 옵션보다 많은 정보를 출력

  # myisamchk -V
  ->    myisamchk 버젼을 표시

3. 체크 옵션  
     
  # myisamchk -c,--check [table 명]
  ->  테이블의 에러를 check 함

  # myisamchk -e,--extend-check [table 명]
   테이블을 좀더 세밀하게 check 함, 일반적인 방법으로 error를 찾을수없을  경우 사용

  # myisamchk -F,--fast [table 명]
->    빠른게 테이블 check 한다.정교한 체크는 하지않느다.
 
  # myisamchk -C,--check-only-changed [table 명]
->     테이블을 check 하고,테이블을 check 이후의 상태로 변경한다.

  # myisamchk -f,--force [table 명]
->    테이블에 error에 있을경우 강재로 check 한다.

  # myisamchk -i,--information [table 명]
->    check한 결과의 정보를 통계화하여 보여준다.
    예)
   Checking MyISAM file: zz_news.MYI
   Data records:       0   Deleted blocks:       0
   - check file-size
   - check key delete-chain
   - check record delete-chain
   - check index reference
   - check data record references index: 1
   - check data record references index: 2
   - check record links
   Record blocks:           0    Delete blocks:         0
   Record data:             0    Deleted data:          0
   Lost space:              0    Linkdata:              0

   User time 0.01, System time 0.00
   Maximum resident set size 0, Integral resident set size 0
   Non-physical pagefaults 26, Physical pagefaults 186, Swaps 0
   Blocks in 0 out 0, Messages in 0 out 0, Signals 0
   Voluntary context switches 0, Involuntary context switches 0


  #myisamchk -m,--medium-check [table 명]
->  extend-check 옵션보다 check 속도가빠르며,99.9 % 의 에러을 찾을수있다.

4.Repair 옵션  
 
   #myisamchk -o -B,--backup [table 명]
  ->    MYD파일을 백업한다. 형식은 [filename-time.BAK]의 파일이 생긴다.
   
   # myisamchk -e,--extend-check [table 명]
->    세부적인 파일까지 복구를해준다.일반적으로 아주 하찮은 에러까지 찾을수
   있다.하지만 자포자기의 상태가 아니고서는 이옵션을 사용하지 않는게 좋다.
 
   # myisamchk -f,-force [table 명]
->     이전것의 temporary file을 덥어쒸운다.

   # myisamchk -l,--no-symlinks [table 명]
->     심복릭 링크를 따르지않겠다는 옵션이다. 일반적으로 myisamchk 는symlink  points를 복구한다.

   # myisamchk -r,--recover [table 명]
->     unique key를 제외한 대부분를 복구한다.

   # myisamchk -n,--sort-recover [table 명]
->     sorting하면서 테이블을 복구한다. 심지어 temporary 파일과 같은 아주 큰
    파일역시 sorting하면서 복구한다.

  # myisamchk -o,--safe-recover [table 명]
->     -r 옵션보다 느리게 복구한다.그러나 좀더 섬세한 복구를 지원한다.

   # myisamchk -q,--quick [table 명]
->     테이터 파일의 수정없이 복구한다.

5. 기타 옵션
   # myisamchk -d,--description [table 명]
->     테이블에 대한 정보를 출력한다.

   # myisamchk -S,--sort-index [table 명]
->     index 블록을 sort한다.

   # myisamchk -R[index번호],--sort-records [table 명]
->     index 번호를 기준으로 인덱스를 정렬해준다.

     
 
6.검사중 아래의 메시지가출력되면 해당테이블을 사용중이라는 의미이므로 테이블에 LOCK을 걸든가 데몬을 죽이고 나서 검사 및 복구를해야함.

    myisamchk: warning: 1 clients is using or hasn''t closed the table  
    properly

7. LOCK 걸기
     
    myisamchk 는 테이블에대한 read 만 할수있으면 되기때문데 read 를 제외한
    모든것에 lock을 걸면된다.
     
    mysql> lock tables [table 명] READ ;
    mysql> flush tables ;

    flush tables 는 mysql이 테이블의 내용을 메모리에만 보관하고 실제 테이
    블파일에 기록을하지 않았을경우 실제 테이블파일에 기록하라는 의미이다
   
8.LOCK 풀기

    mysql> unlock talbe;

9.Myisamchk 로 복구를 위한 LOCK 걸기
   
   서비스를 죽이지않고 복구를 해야할경우는 write lock를 걸어주면된다.
   복구는 write 를 해야하기때문에 write lock를 걸어줘야한다.
   
   mysql>lock tables [table명] write;
   mysql>flush tables;

10.LOCK 풀기
 
   mysql> unlock table;
2006/09/08 15:56 2006/09/08 15:56
이 글에는 트랙백을 보낼 수 없습니다
더보기" name=source_sumtext>
##### Apache Admin### 보안설정 - 디렉토리보안 (cgi-bin, documentroot),기초보안 (ServerTokens, .htaccess, CGI), Option 지시자 (심블릭 링크, 디렉토리, SSI)*** 사용자 인증 - .htaccess, 사용자 인증 설정법*** 권한부여 - Satisfy 접근통제, order 지시자### High technic - rotatelogs, URL Redirection, Reverse Proxy, ErrorDocument, 주소와 포트지정, signal*** 서버 튜닝 - Configuration 파일, 커널 설정, 자원 설정*** 접속이 안될때 - 비정상접속 (dos, include), 정상접속 (keepalive, maxclient, RLimitMEM)*** Tips - PIDFILE, Language, 무단링크 막기############################################################Apache Admin######################### 보안설정각 파일과 디렉토리 구조는 다른 접근 통제나 사용자 인증 방법을 가질 수 있고접근 통제와 사용자 인증 방법을 사용하여 각 자원에 대한 다양한 권한을 부여할수 있다.- 웹서버 데몬은 chroot에 설치하는 것이 안전하다.### 디렉토리 보안 #### chown root.root -R /usr/local/apache			::: or root.nobody# chmod 754 /usr/local/apache# chown nobody -R /usr/local/apache/htdoc# chmod 500 /usr/local/apache/bin/httpd	root 에의해 실행 가능한 명령들은 항상 보호 되어야한다.*** 불필요한 script 제거기본적으로 설치되는 cgi-bin 디렉토리의 모든 스크립트를 제거해야 하고cgi 들을 사용할 경우는 사전에 안전성을 검토한후 사용해야한다.- src 디렉토리는 불필요한 실행 파일을 컴파일 할수있는 소스코드 들이 있으니 삭제 하도록 하자*** DocumnetRoot 하의 허가권은 다음과 같다.# ls -al	drwxrwxr-x    2  webmaste  webwrite  4096 10월 10 13:23  .	drwxr-xr-x   14  root      root      4096 10월 10 11:26  ..	-rw-r--r--    1  webmaste  webwrite   450 10월 10 11:48  index.html	-rw-r--r--    1  acsecret  webwrite  1333 10월 10 13:23  test.html- DocumnetRoot 상의 모든 파일들은 nobody 권한으로 구동하는 웹서버에 의해서 읽혀질수 있어야만 한다.또한 내부의 웹 문서 작성자들은 documentroot 에 파일을 자유롭게 추가 또는 수정할 수 있어야만 한다.따라서 DocumentRoot 디렉토리와 그 하위 디렉토리들은 웹문서 작성자 소유주와 그룹에 속해야 하고모든 이가 읽을수 있어야 하고(world readable) 그룹 소속의 사용자들이 쓰기 가능해야 한다.### 기초 보안 ###*** 헤더 정보 숨김- Apache 웹서버에서는 ServerTokens 지시자를 수정함으로써 헤더에 의해 전송되는 정보를 바꿀 수 있다.	ServerTokens ProductOnly일반적으로 ServerToken은 httpd.conf 에서 명시되어 있지않는 경우 기본값인 ServerTokens Full 이 적용되어운영체제 정보, 웹서버 정보, 버전정보, 설치된 모듈 정보 등이 모두 서버의 응답 헤더에 포함되어 전송된다.최소한의 정보를 주기 위해서 ServerTokens Prod 를 설정하는 것이 바람직하다.ServerToken은 Apache 1.3 이상에서 가능하고 ProductOnly 키워드는 1.3.12 이상 버전에서 사용가능*** ".htaccess" 의 내용을 볼수 없게 할때	<Files ~ "^\.ht">		Order allow,deny		Deny from all	</Files>*** CGI 실행	ScriptAlias /cgi-bin/ "/usr/local/apache/cgi-bin/"cgi-bin 디렉토리에서만 실행 가능 하도록 할 경우CGI 프로그램의 실행은 관리자가 지정한 특정 디렉토리 에서만 가능 하도록 제한할 필요가 있다.CGI 실행은 ScriptsAlias 지시자에 의해서 실행 가능한 디렉토리를 제한할 수 있다.### Option 지시자 보안 ###	Syntax: Options [+|-]option [[+|-]option] ...디렉토리 리스팅, 심블릭 링크, SSI 등에 대한 제어를 한다.*** 심블릭 링크 - Options 지시자 FollowSymLinks 옵션 제거명몇 서버는 심블릭 링크를 이용해서 기존의 웹 문서 이외의 fs에 접근 가능하도록 하고 있다.가령 시스템 자체의 root 디렉토리를 링크 걸게 되면 웹서버 구동 사용자 권한으로 (nobody)모든 fs의 파일에 접근할 수 있게 된다.*** 디렉토리 리스팅 - Options 지시자 Indexes 옵션 제거웹 브라우저에서 사용자가 URL을 입력했을 경우, Apache 웹서버는 3가지 방법 응답한다.정상적으로 웹 내용을 보여주든지, 디렉토리 리스트를 보여주든지, 에러 메시지를 보여준다.원격의 공격자가 시스템에 대한 많은 정보를 획득 할수록 보안 허점을 발견하기가 용이해 진다.디렉토리 리스트를 보여주는 것 또한 불필요한 정보를 공격자에게 제공하여 공격에 이용될 수 있다.백업 데이터, CGI 소스코드들, 필요에 의해 만들어 놓은 심블릭 링크등 서버 관리자가실수로 지우지 않은 파일들이 공격자의 손에 들어갈 수 있다.*** SSI (Server Side Includes) - Options 지시자 IncludesNoExec 옵션 추가- SSI는 HTML 페이지 안에 위치하고 있으며 동적인 웹 페이지를 제공할 수 있도록 한다.- SSI는 시스템의 날짜와 카운터등 CGI 프로그램을 하지 않아도 HTML 문서에서 CGI의 효과를 낼수있다.- SSI코드가 들어있는 문서는 확장자가 *.shtml이다.- SSI가 포함된 파일은 execcmd 를 사용해서 어떤 CGI 스크립트나 프로그램들을 Apache가 구동하는  사용자와 그룹 권한으로 실행시킬 수 있다. (SSI 페이지가 스크립트나 프로그램을 실행 시킬수 있다)########## 사용자 인증 ###- apache 기본설정으로 .ht*로 시작하는 파일은 접근할수 없게되어 있다.- 어떤 지시어를 .htaccess 파일에 사용할 수 있는지 알려면 지시어의 사용장소를 확인하라.  주설정 파일의 AllowOverride 지시어로 .htaccess 에 어떤 지시어를 사용할 수 있는지 조절할수 있다.*** 개요사용자가 문서에 접근하려 할때 아이디와 패스워드를 확인 함으로써 사용자를 확인하는 것을 말한다.유저 인증의 방법에는 /etc/passwd 나 db를 참조하는 등 여러 방법이 있지만 구현하기가 어렵다.상업용 사이트가 아니라면 아파치의 유저인증 방법이 적절할 것이라고 본다.HTTP는 stateless 프로토콜 이므로 기본적인 사용자 인증에 의해 보호되는 자원에 접근하기 위해서는매번 사용자 이름과 패스워드와 같은 인증서를 서버에 보내야만 한다.하지만 초기 인증을 거친후 다른 페이지에 접근하기 위해서 매번 사용자 이름과 패스워드를 전송하는 것은일반적으로 클라이언트 소프트웨어나 웹 브라우져에 의해서 자동으로 이루어진다.만약 사용자 이름이 웹서버의 리스트에 있고 패스워드가 일치하면 보호된 자원에 접근을 허락받게 된다.기본적인 인증에서는 패스워드가 암호화 되어 저장되지만 클라이언트에서 서버로 전송되는 도중에는암호화되지 않아 제 3자에 의해서 도청될수 있다.### .htaccess ###	관련된 지시어:	AccessFileName		AllowOverride	- AllowOverride 지시어를 none으로 설정하면 .htaccess 파일을 완전히 사용할 수 없다.아파치는 특별한 파일을 사용하여 설정을 나눠서(분권적으로) 관리할 수 있다.이 특별한 파일을 보통 .htaccess라고 부르지만 이름은 AccessFileName 지시어로 지정할 수 있다.- .htaccess 파일에 있는 지시어는 파일이 있는 디렉토리와 모든 하위 디렉토리에 적용된다..htaccess 파일을 발견한 디렉토리와 그 디렉토리의 모든 하위 디렉토리에 .htaccess 파일에 있는설정 지시어를 발견한 순서로 적용한다. 그래서 상위 디렉토리의 .htaccess 파일을 주의해야 한다.- .htaccess 파일은 주설정 파일과 같은 문법을 따른다.- .htaccess 파일은 매요청 때마다 읽기 때문에 파일을 수정하면 즉시 효과를 볼 수 있다.*** 지시어를 /www/htdocs/example 디렉토리의 .htaccess 파일을 두는 것과 주서버 설정의<Directory /www/htdocs/example> Directory 설정에 두는 것은 완전히 같다.httpd.conf 에 두는것은 파일을 요청할 때마다 설정을 읽지않고 아파치가 시작할때한번만 설정을 읽기때문에 같은 설정을 서버설정 파일에 사용하면 성능이 더 빠르다.# vi .htaccess	AddType text/example .exm# vi httpd.conf	<Directory /www/htdocs/example>		AddType text/example .exm	</Directory>*** 특정 디렉토리에 있는 .htaccess 파일은 상위 디렉토리에 있는 .htaccess 파일의 지시어를무효로 만들수 있고 혹은 주 설정파일에 있는 지시어를 무효로 만들수 있다.	# vi /www/htdocs/ex1/.htaccess		Options +ExecCGI		("Options" 지시어를 사용하려면 "AllowOverride Options"가 필요하다)	# vi /www/htdocs/ex1/ex2/.htaccess		Options Includes두번째 .htaccess 파일의 Options Includes가 이전 설정을 완전히 무효로 만들기 때문에/www/htdocs/ex1/ex2 디렉토리는 CGI 실행을 허용하지 않는다.*** 언제 .htaccess 파일을 사용하나 (혹은 사용하지 않나)일반적으로 주서버 파일에 접근할 수 없는 경우가 아니라면 .htaccess 파일을 사용하면 안된다.예를 들어 사용자 인증이 항상 .htaccess 파일에 있어야 한다는 것은 잘못 알려진 오해다.주서버 설정에(httpd.conf) 사용자 인증 설정을 적을 수 있고 이것을 권한다.주설정파일의 <Directory> 섹션에 인증 지시어를 두는 것이 더 권장하는 방법이고서버의 주설정파일을 수정할 수 없는 경우에만 .htaccess 파일을 사용해야 한다..htaccess 파일은 컨텐츠 제공자가 디렉토리별로 서버 설정을 다르게하고 싶지만예를 들어 한 컴퓨터에 여러 사용자 사이트를 서비스하는 ISP 에서 사용자가 자신의 설정을변경하고 싶은 경우가 그러하다. 서버 시스템에 root 권한이 없는 경우에 사용한다.그러나 일반적으로 .htaccess 파일은 가급적 피해야 한다..htaccess 파일에서 허용하는 지시어는 주설정파일의 <Directory> 섹션과 같은 효과가 있다.*** 다음 두가지 큰 이유때문에 .htaccess 파일 사용을 피해야 한다.- 첫번째는 성능이다.AllowOverride가 .htaccess 파일을 사용하도록 허용하면 아파치는 디렉토리마다 .htaccess 파일을 찾는다.그래서 .htaccess 파일을 허용하면 실제로 파일을 사용하지 않는 경우에도 성능이 떨어진다.또 .htaccess 파일은 문서를 요청 할때마다 읽어들인다.또 적용해야 하는 전체 지시어를 모으기 위해 아파치는 모든 상위 디렉토리에서 .htaccess 파일을 찾는다.(어떻게 지시어를 적용하나 절을 참고.) 그래서 /www/htdocs/example 디렉토리에 있는 파일을 요청하면아파치는 다음 파일들을 찾아야 한다.	/.htaccess   /www/.htaccess   /www/htdocs/.htaccess   /www/htdocs/example/.htaccess그래서 그 디렉토리에 있는 파일을 접근할 때마다 설정파일이 전혀 없어도 fs을 4번 더 접근해야 한다.(/에서도 .htaccess 파일을 허용한 경우를 말한다. 보통은 허용하지 않는다.)- 두번째 이유는 보안이다.사용자에게 서버설정 변경 권한을 주면 당신이 감당할 수 없는 변화가 일어날 수 있다.사용자에게 이런 권한을 줄지 곰곰이 생각하라. 또 사용자가 원하는 것보다 적은 권한을 주면기술지원 요청이 들어온다. 사용자에게 가능한 권한 수준을 명확히 알려라.사용자에게 AllowOverride를 어떻게 설정하였는지 정확히 알리고 관련 문서를 제공하면 혼란을 피할 수 있다.### 사용자 인증 설정법 ###*** 기본 사용자 인증과 다음과 같은 절차를 거쳐서 설정할 수 있다.다이제스트 사용자 인증의 설정 방법도 유사하다.- 패스워드 파일 생성 (htpasswd)	# htpasswd -c pwd_filename username [pwd]- 패스워드 파일을 사용할 수 있도록 Apache 환경 설정AccessFileName 에서 지정한 파일이름 (.htaccess)이 존재하면 그 파일을 참조한다.디렉토리별로 사용자 인증을 하기 위해서 httpd.conf 파일 내의 AllowOverride 지시자 옵션을None 에서 AuthConfig 또는 All로 바꾼다. (사용자 인증만을 위해서는 AuthConfig 사용권고)	AllowOverride AuthConfig [FileInfo] [Limit]- 사용자 인증이 필요한 디렉토리에 다음의 지시자들이 포함된 .htaccess 파일을 생성한다.# vi /usr/local/www/.htaccess	<Directory "/home/www">		AuthName "Welcome acsecret's Home"		AuthType Basic		AuthUserFile /usr/local/apache/htpasswd		AuthGroupFile /dev/null		ErrorDocument 401 "당신은 인증된 사용자가 아닙니다.~"		Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec		<Limit GET POST>			require valid-user				패스워드 화일에 등록된 사용자 모두에게 인증을 적용한다.			require acsecret ccc				패스워드 파일에 등록된 acsecret와 ccc 만이 웹서버에 접속할 수 있도록 한다.		</Limit>	</Directory>*** 다이제스트 사용자 인증기본적인 인증과의 차이점은 네트워크 등 전송로 상에서 패스워드가 평문으로 전송되지 않는다.패스워드는 MD5 암호화 해쉬를 시킨후 전송하고는 있지만 데이터는 평문으로 전송되므로문제점을 가지고 있으며 모든 웹브라우져가 다이제스트 인증을 지원하지는 않는다.- DB 인증 모듈DB 인증 모듈은 사용자 이름과 패스워드를 보다 신속하게 확인할 수 있도록 한다.일반 fs 이아닌 DB를 이용할 경우 사용자 이름과 패스워드 확인 시간을 대단히 단축할 수 있다.########## 권한부여 (Authorization) ###권한부여는 특정한 자원에 접근할 사용자 퍼미션이 유효한지를 확인하는 과정이다.어떤 퍼미션에 의해 허락되고 거부될지는 그 자원과 관련된 규칙들에 따라서 다양하다.일반적으로 Firewall 이나 라우터의 접근통제 Rule은 순차적으로 비교하다가 최초로 일치하는 Rule을적용하고 그 이후는 비교하지 않지만 Apache에서는 Allow와 Deny를 모두 비교하고 둘 중에 하나라도일치할 경우 적용한다는 점에서 차이가 있다.- Allow 와 Deny 지시자는 IP 주소나 도메인에 의해서 웹서버의 데이터에 대한 접근을 통제할 수 있다.- 기본적인 설정은 DocumentRoot의 내용에 대해 누구나 접속을 허락하도록 설정되어 있다.- Allow 와 Deny 지시자를 동시에 사용할 경우 그 순서를 정하는 Order 지시자를 사용한다.*** Satisfy 접근통제	Syntax: Satisfy any | all인터넷에서 접속시에는 사용자 이름과 패스워드를 확인하고 인트라넷에서 접속시에는 요구하지 않도록설정할 수도 있다. 이는 Satisfy 지시자로 사용자 인증(Require에 의한)과 클라이언트 호스트 주소에따른 접근통제(Allow에 의한)를 동시에 사용하여 정책 설정을 할때 쓰인다.인트라넷 밖의 모든 접속시 패스워드를 요구, 인트라넷 내부의 사용자들은 패스워드 없이 접속을 허용.	AuthName "Welcome acsecret's Home"	AuthType Basic	AuthUserFile /usr/local/apache/htpasswd	AuthGroupFile /dev/null	ErrorDocument 401 "당신은 인증된 사용자가 아닙니다.~"	Options MultiViews Indexes SymLinksIfOwnerMatch IncludesNoExec	Order deny,allow	Deny from all	Allow from 172.16.5	Satisfy Any만일 인트라넷 사용자인 동시에 이 사용자들에게 패스워드를 요구하게 강화된 보안을 설정할 경우Satisfy Any 를 Satisfy All로 바꾸면 된다. 즉, Satisfy All은 두개의 지시자 (접근통제와 사용자 인증)모두 만족해야만 할 경우 사용하고 Satisfy Any 는 둘중 하나만 만족하면 된다.### order 지시자 ###- 리스트 나열은 빈공백으로 구분한다.Order Deny,Allow	Deny 지시자가 Allow 지시자 보다 먼저 검사된다. 접근은 기본적으로 허용된다.		Allow 를 평가하기 전에 먼저 Deny 를 평가하고 그 다음 Allow 에 override 한다.		그리고 여기에 매치되지 않는 나머지 호스트 모두 Allow 된다.		즉 Deny 지시자와 일치하지 않는 클라이언트의 접속은 허용한다. 즉 순서는			1. Deny 매치 우선 결정(기본 정책 결정)			2. 그 다음 Allow 매치를 override 함			3. 나머지 포함되지 않은 호스트는 모두 Allow 됨Order Allow,Deny	Allow 지시자가 Deny 지시자 보다 먼저 검사된다. 접근은 기본적으로 차단된다.		Deny 를 평가하기 전에 먼저 Allow 를 평가하고 그 다음 Deny 에 override 함.		그리고 여기에 매치되지 않은 나머지 호스트는 모두 Deny 됨.		즉 Allow 지시자에 일치하지 않는 클라이언트의 접속은 차단한다.Order Mutual-failure	Allow 리스트에 있고 Deny 리스트에 없는 호스트만 접근을 허용한다.					순서는 Allow, Deny 와 같다.*** Example기본정책은 Allow 이고 예외로 bad.com hacker.com 은 금지	Order Allow,Deny	Allow from all	Deny from bad.com hacker.com기본정책은 Deny 이고 예외로 glister.co.kr 만 접근을 허용함	Order Deny,Allow	Deny from all	Allow from glister.co.krfoo.apache.org 를 제외한 *.apache.org 만 허용하고 나머지 모든 호스트는 접근을 금지한다.(foo.apache.org 는 당연히 금지)이유는 Order 순서에 의해서 Deny 를 평가하기 전에 Allow 를 평가하고 그 다음에 Deny 매치에override 하기 때문이며 나머지 매치되지 않는 모든 호스트는 Deny 된다.	Order Allow,Deny	Allow from apache.org	Deny from foo.apache.org아래는 Allow 를 평가하기 전에 Deny 를 먼저 평가하기 때문에 평가 순서는 다음과 같아지게 된다.	Order Deny,Allow   ->   Deny from all   ->   Deny from ccc.foo.com   ->	Allow from aaa.foo.com   ->   Allow from bbb.foo.com ccc.foo.com   ->   Allow from ddd.com.com	Order Deny,Allow	Deny from all					::: 기본정책이 모두 Deny	Allow from aaa.foo.com	Allow from bbb.foo.com ccc.foo.com	Allow from ddd.com.com	Deny from ccc.foo.com			::: 이 호스트는 Allow 됨#################### High technic*** Log Rotate이용자가 접속할 때마다 기록되는 access_log 파일의 경우 한번 접속당 약 85 바이트가 증가하며접속량이 많을 경우 파일의 크기는 실제로 엄청나다. 이럴 경우 접속마다 로그 파일을 액세스 하는데상당한 시간과 부하가 걸리므로 일정 시간마다 초기화하여 항상 경량화 시켜줄 필요가 있다.아파치에서 제공하는 rotatelog를 이용 (24시간 마다 로그 화일을 갱신해 준다. 24X60X60=86400초)# vi /usr/local/apache/conf/httpd.conf	CustomLog /usr/local/logs/access_log common	ErrorLog "/usr/local/apache/logs/error_log"	CustomLog "|/usr/local/apache/bin/rotatelogs /usr/local/apache/logs/access_log 86400" common	TransferLog "|/usr/local/bin/rotatelogs /usr/local/apache/logs/access_log 86400"	TransferLog "|/usr/local/apache/bin/rotatelogs /usr/local/apache/logs/error_log 86400"	ErrorLog "|/usr/local/apache/bin/rotatelogs /usr/local/apache/logs/error_log 86400"	|			파이프(|) 를 말한다.	/usr/local/apache/logs/access_log	로그파일 저장위치	86400		시간. 초단위로 되어 있으며, 지정된 시간을 주기로 화일을 정리한다.	CustomLog 만이 맨 뒤에 common이 붙고 나머지는 붙지 않는다.*** URL Redirection	Redirect	permanent			temp보통의 지시어들은 아파치가 fs의 특정 장소에 있는 내용을 클라이언트에게 보내게 만든다.그러나 때때로 요청한 내용이 다른 URL에 있다고 클라이언트에게 알려주어 클라이언트가 새로그 URL을 요청하도록 만드는 것이 좋을 때가 있다.예를 들어, DocumentRoot 아래 /foo/ 디렉토리의 내용을 새로 /bar/ 디렉토리로 옮겼다면다음과 같이 클라이언트가 새로운 위치를 요청하도록 한다	Redirect permanent /foo/ http://www.glister.co.kr/bar/www.glister.co.kr 서버의 /foo/로 시작하는 URL-경로는 /foo/를 /bar/로 바꾼 URL로 리다이렉션된다.클라이언트를 원래 서버외에 어떤 다른 서버로도 리다이렉션할 수 있다.또 아파치는 더 복잡한 재작성 문제를 위해 RedirectMatch 지시어를 제공한다.예를 들어 다른 요청은 그대로 두고 사이트 홈페이지에 대한 요청만을 다른 사이트로 리다이렉션 하려면	RedirectMatch permanent ^/$ http://www.glister.co.kr/startpage.html임시로 사이트의 모든 페이지를 다른 사이트의 특정 페이지로 리다이렉션 하려면	RedirectMatch temp .* http://othersite.glister.co.kr/startpage.htmlRedirectMatch /(.*)$ http://www.yahoo.com/aaa/$1	주소창에 www.yahoo.com/index.html 을 입력했다고 가정했을 때	주소를 제외한 /index.html 을 /aaa/index.html 로 리다이렉트 하라는 뜻이다.*** Reverse Proxy - 역프록시	ProxyPass			서버가 적절한 문서를 가져오도록 설정	ProxyPassReverse	external.glister.co.kr 이 보내는 리다이렉션을 재작성하여					리다이렉션이 현재 서버의 적절한 디렉토리를 가리키도록 한다.아파치는 다른 서버에 있는 문서를 서버의 URL 공간으로 가져올 수 있다.이 경우 웹서버가 원격 서버에서 문서를 가져와서 클라이언트에게 전달하는 프록시 서버와 같이동작하기 때문에 이런 방법을 역프록시(reverse proxying)라고 한다.클라이언트의 입장에서 역프록시 서버가 문서를 보내주는 것처럼 보이므로 일반 프록시와는 다르다.문서 안에 있는 링크는 재작성하지 않음을 주의하라. external.glister.co.kr 에 대한 절대링크는클라이언트가 프록시서버가 아니라 external.glister.co.kr 으로 직접 요청하게 한다.아래 설정에서 클라이언트가 /foo/에 있는 문서를 요청하면, 서버는 external.glister.co.kr 의 /bar/디렉토리에서 문서를 가져와서 문서가 마치 서버에 있었던 것처럼 클라이언트에게 보낸다.	ProxyPass /foo/ http://external.glister.co.kr/bar/	ProxyPassReverse /foo/ http://external.glister.co.kr/bar/### ErrorDocument - 에러 메시지 수정 방법 ###	Syntax: ErrorDocument error - code document1xx: Informational	100 Continue						101 Switching Protocols2xx: Successful	200 OK					연결이 성공적이고 에러가 없다.	201 Created	202 Accepted						203 Non-Authoritative Information	204 No Content						205 Reset Content	206 Pa rtia l Content3xx: Redirection	300 Multiple Choices	301 Moved Permanently		요청 자원의 이 변경 되었다 URL	302 Moved Temporarily				303 See Other	304 Not Modified					305 Use Proxy4xx: Client Error	400 Bad Request	401 Unauthorized			사용자 미등록 등으로 인해 사용자 인증 실패시							클라이언트가 승인 받지 않고 데이터에 접근함.	402 Payment Required	403 Forbidden				접속이 허락되지 않은 IP에서 접속을 시도할때	404 Not Found				일반적으로 파일을 찾을 수 없다.	405 Method Not Allowed	406 Not Acceptable					407 Proxy Authentication Require	408 Request Time-out				409 Conflict	410 Gone							411 Length Required	412 Precondition Failed				413 Request Entity Too Large	414 Request-URI Too Large			415 Unsupported Media Type5xx: Server Error	500 Internal Server Error	서버 내부 오류 발생	501 Not Implemented			클라이언트가 서버에서 수행할 수 없는 행동을 요구	502 Bad Gateway			서버 과부하 상태	503 Se rvice Unava ilable	504 Gateway Time-out				505 HTTP Version not supportedErrorDocument 403 http://dci.sppo.go.kr/	접속이 허락되지 않은 IP에서 접속을 시도할 경우 대검찰청 인터넷범죄 수사센터로	리다이렉션 되도록 하였다. 이 경우 access_log에는 403 상태코드 (Forbidden) 대신	302 상태코드(Moved Temp orarily)가 기록되게 된다.		>>> 172.16.5.17--[17/Oct/2002:10:12:56+0900] "GET/HTTP/1.1" 302 290 <<<*** 에러발생시 응답을 정의할 수 있는 방법을 3가지 나타내고 있다.ErrorDocument 500 "The server made a boo boo.					::: 일반적인 텍스트	주의: 하나의 쌍따옴표 만을 사용하여 문장을 넣어야 한다.ErrorDocument 404 /missing.html								::: 지역적인 방향전환ErrorDocument 402 http://other_server.com/subscription_info.html		::: 외부 방향전환클라이언트의 요구에 의해 발생하는 아파치 서버의 에러페이지에 출력할 텍스트나 문서를 정의각 페이지는 에러 코드별로 설정할 수 있으며 외부의 URL을 지정할 수도 있다.문자열을 설정을 경우네는 " "안에 문자열을 설정하면 되고 내부 html 문서를 지정해줄 경우문서의 경로를 지정해 주면 된다. / 최상위 경로는 DocumentRoot를 의미한다.*** 아파치 에러 메시지 바꾸기# vi httpd.conf	ErrorDocument 404 /cgi-bin/missing404.pl# vi missing404.pl#!/usr/bin/perlprint<<"(END_HTML)";Content-type: text/htmlnn<head><title> 요청한 URL 이 없습니다. </title><meta http-equiv="content-type" content="text/html;charset=EUC-KR"></head><body><br><br><center><b><h2>요청하신 http://www.gwise.com$ENV{'REQUEST_URI'}이 <br> 존재 하지 않습니다.</h2></b><br><br><h4><a href="mailto:gwise@orgio.net"> 서버관리자</a>에게 문의 바랍니다.</h4><br>(END_HTML)exit;### 주소와 포트 지정 (Binding) ###기본적으로 아파치는 컴퓨터의 모든 주소에서 기다린다.아파치가 어떻게 다른 IP 주소, 호스트명, 포트에 반응할지를 결정하는 가상호스트 기능과도 관련되있다.Listen 지시어는 서버가 특정 포트나 주소와 포트 조합에서만 요청을 받게 한다.Listen 지시어에 포트 번호만 지정하면, 서버는 모든 인터페이스에서 지정한 포트를 기다린다.여러 Listen 지시어로 기다릴 여러 주소와 포트를 지정할 수도 있다.서버가 80번과 8000번 포트 모두에서 연결을 받도록 하려면	Listen 80	Listen 8000서버가 지정한 두 인터페이스와 포트에서 연결을 기다리도록 하려면	Listen 192.170.2.1:80	Listen 192.170.2.5:8000IPv6 주소는 다음과 같이 대괄호로 묶어야 한다	Listen [2001:db8::a00:20ff:fea7:ccea]:80*** IPv6에서 특별히 고려할 점IPv6를 구현한 플래폼이 늘고 있고 APR이 이들 플래폼 대부분에서 IPv6를 지원하기 때문에아파치는 IPv6 소켓을 할당하여 IPv6로 받은 요청을 처리할 수 있다.아파치 관리자에게 복잡한 부분은 IPv6 소켓이 IPv4 과 IPv6 연결을 모두 처리할 수 있느냐는 점이다.대부분의 플래폼에서는 IPv4-대응(mapped) IPv6 주소를 사용하여 IPv6 소켓에서 IPv4 연결을 받지만FreeBSD와 NetBSD와 OpenBSD은 시스템전체 정책때문에 기본적으로 허용하지 않는다.그러나 기본적으로 허용하지않는 시스템이라도 아파치를 위해 특별한 설정 파라미터로 변경할 수 있다.리눅스와 Tru64 같은 일부 플래폼에서 IPv4와 IPv6을 모두 처리하려면 대응 주소를 사용해야만 한다.아파치가 최소한의 소켓을 사용하여 IPv4 연결과 IPv6 연결을 모두 받도록하려면IPv4-대응 IPv6 주소를 사용하고 configure 옵션 --enable-v4-mapped를 지정한다.--enable-v4-mapped는 FreeBSD, NetBSD, OpenBSD를 제외한 모든 플래폼에서 기본값이다.플래폼과 APR의 지원여부와 관계없이 아파치가 IPv4 연결만을 받도록하려면다음 예제와 같이 모든 Listen 지시어에 IPv4 주소를 사용한다	Listen 0.0.0.0:80	Listen 192.170.2.1:80플래폼에서 지원하며 아파치가 서로 다른 소켓으로 IPv4 연결과 IPv6 연결을 받도록하려면(즉 IPv4-대응 주소를 사용하지 않으려면), configure 옵션 --disable-v4-mapped를 지정한다.--disable-v4-mapped는 FreeBSD, NetBSD, OpenBSD 에서 기본값이다.***  가상호스트와 어떻게 연관되나Listen은 가상호스트를 만들지 않는다. 이는 단지 주서버가 어떤 주소와 포트를 기다릴지만 알려준다.<VirtualHost> 지시어를 사용하지 않으면 서버는 받은 모든 요청을 똑같이 처리한다.그러나 <VirtualHost>로 여러 주소와 포트에 대해 다른 행동을 지정할 수 있다.가상호스트를 만들려면 먼저 서버에게 사용할 주소와 포트를 알려줘야 한다.그리고 특정 주소와 포트에 대한 가상호스트의 행동을 지정할 <VirtualHost> 섹션이 필요하다.주서버가 기다리지않는 주소와 포트를 사용하는 <VirtualHost>는 접근할 수 없음을 주의하라.### signal ###시스템에 많은 httpd가 실행되지만 PidFile에 pid가 기록된 부모외에 다른 프로세스에시그널(signal)을 보내면 안된다. 즉, 부모이외에 다른 프로세스에 시그널을 보낼 필요가 없다# tail -f /usr/local/apache/logs/error_log	httpd 에 시그널을 보낸후 진행 상황을 알수있다# kill -TERM `cat /usr/local/apache/logs/httpd.pid`	부모 process에 해당 시그널을 보낸다*** TERM		당장 중단. 즉시 모든 자식을 죽인다. (# apachectl stop)- 자식을 완전히 죽이는데는 몇 초가 걸릴 수 있다. 그후 부모가 종료한다.- 처리중인 요청은 중단되고 더 이상 요청을 받지않는다.*** HUP		당장 재시작. (# apachectl restart)- TERM 과 같이 모든 자식을 죽이지만 부모는 종료하지 않는다.  부모는 설정파일을 다시읽고 로그파일을 다시 연후 새로운 자식들을 만들고 서비스를 계속한다.- mod_status 사용자는 HUP를 보내면 서버 통계가 0이 됨을 알수있다.*** USR1		점잖은 재시작. (# apachectl graceful)- 자식 프로세스가 현재 요청을 처리한후 종료하게 한다. (아무것도 처리하지 않다면 즉시 종료)- 부모는 설정파일을 다시읽고 로그파일도 다시 연다.- 자식이 죽을 때마다 죽은 자식대신 새로운 설정에 기초한 자식을 실행하여 즉시 요청을 처리하게 한다.- 점잖은 재시작(graceful restart)으로 USR1을 사용할 수 없는 플래폼에서는 대신  다른 시그널을 사용할 수 있다. apachectl graceful은 플래폼에 알맞은 시그널을 보낸다.- 점잖은 재시작은 항상 MPM의 프로세스 조절 지시어 설정을 고려하여 재시작동안 클라이언트를서비스하는 프로세스나 쓰레드가 적당한 수를 유지하도록 설계되었다. 또한 StartServers는 일초 후최소한 StartServers 만큼 새로운 자식이 안만들어지면 자식이 StartServers 개가 되도록 새로 만든다.즉, 서버의 현재 부하에 알맞은 자식의 개수를 유지하며 StartServers 로 지정한 당신의 기대를 존중한다- mod_status 사용자는 USR1을 받을때 서버 통계가 0이 되지 않는다.서버는 새로운 요청을 (운영체제는 이들을 큐에 담아서 어떤 경우에도 잃어버리지 않는다)처리하지 못하는 시간을 최소화하고 당신의 튜닝 파라미터를 존중하도록 만들어졌다.이를 위해 세대간 모든 자식을 기록하는 scoreboard를 유지한다.status 모듈은 또한 점잖은 재시작 전에 시작하여 아직도 요청을 처리하고 있는 자식을 G로 알려준다.현재는 USR1을 사용시 로그순환 스크립트가 재시작 전에 모든 자식이 로그 작성을 마쳤는지를 알수없다.우리는 USR1 시그널을 보내고 적당한 시간이 지난후 이전 로그를 다루도록 제안한다.예를 들어 낮은 대역폭 사용자의 경우 접속 대부분이 마치는데 10분이 안걸린다면이전 로그를 다루기전에 15분 기다린다.- 설정파일에 오류가 있다면 재시작시 부모는 재시작 하지 않고 오류를 내며 종료한다.또 점잖은 재시작의 경우 종료할때 자식이 실행되도록 놔둔다.(자식들은 자신의 마지막 요청을 처리하고 종료한다)이는 서버를 재시작할때 문제가 된다. 서버는 자신이 기다릴 포트에 연결하지 못한다.########## 서버 튜닝 ###*** 컴파일 전 src/Configuration 파일 수정# cd /usr/local/apache/src# cp Configuration.tmpl Configuration# vi Configuration	CFLAGS= -O2	LFLAGS=	EXTRA_LIBS=	AUX_CFLAGS= -DLINUX컴파일러 설정은 gcc로 되어 있을 것이다.CFLAGS 등 컴파일러 옵션 설정. 모듈과 관련된 옵션들도 이곳에 적어 넣는다.우리는 리눅스에 설치를 하므로 리눅스에 해당하는 부분의 #표시를 없애도 록 한다.### 커널 설정 ###*** 커널 소프트 레벨 튜닝- ulimit -n 32768- /proc/sys/fs/file-max: 4096 -> 32768- /proc/sys/fs/inode-max: 16384 -> 65536- /proc/sys/net/ipv4/tcp_keepalive_time: 7200 -> 1200- /proc/sys/net/ipv4/tcp_fin_timeout: 180 -> 30- /proc/sys/net/ipv4/tcp_sack: 1 -> 0- /proc/sys/net/ipv4/tcp_timestamps: 1 -> 0- /proc/sys/net/ipv4/tcp_syncookies: 0 -> 1- /proc/sys/net/ipv4/tcp_retries1: 7 -> 2- /proc/sys/net/ipv4/tcp_max_syn_backlog: 128 -> 8192- /proc/sys/net/ipv4/tcp_window_scaling: 1-> 0*** 커널 하드 레벨 튜닝- /usr/src/linux/include/linux/fs.hNR_FILE 4096 -> 32768INR_OPEN 1024 -> 32767- /usr/src/linux/include/linux/tasks.hNR_TASKS 2560 -> 3192MAX_TASKS_PER_USER 2048 -> 3192- /usr/src/linux/include/linux/limits.hNR_OPEN 1024 -> 32767- /usr/src/linux/include/net/tcp.hTCP_TIMEWAIT_LEN (60*HZ) -> (15*HZ)### 자원 설정 ###웹 서버를 운영하는데 있어서는 다른 하드웨어들도 중요 하겠지만 무엇보다도 메모리가 중요다.특히 접속량이 많을경우 메모리를 더 늘려야 하는 상황에서 튜닝만 잘하면 어느 정도의 향상을 할수있다.- "MaxRequestsPerChild 는 메모리 누수현상 등이 발생하지 않는다면 가능한 높게 설정을 (0=무한대)- "StartServers 는 프로세스가 active 되어 있는 경우가 적을 경우 값을 낮게 설정하고  접속량이 아주 많을 경우는 MaxClients 에 가깝게 조절 하자- MaxSpareServers 를 MaxClients 와 같게 설정- MaxClients 는 너무 낮거나 크게 설정하지 않도록 주의*** MaxClient 값 변경소스의 HARD_SERVER_LIMIT=256으로 설정되어 있어 httpd.conf 만 변경하면 안될것이다.256 이상의 동시접속을 허용하고자 할 경우에는 아파치를 재컴파일 해야 한다.# vi src/include/httpd.h	#define HARD_SERVER_LIMIT 256클라이언트가 256 이상의 접속을 넘어서 이루어질 경우에는 다음과 같은 메시지가 로그파일에 남게 되며클라이언트는 다른 요청의 접속이 끝날 때까지 대기하거나 접속이 이루어 질수 없다는 메시지를 보게 된다.	[error] server reached MaxClients setting, consider raising the MaxClients setting########## 접속이 느려지거나 안될 때 ###가끔 접속자가 많은 서버를 운영하다 보면 갑자기 웹 접속이 되지 않거나접속이 너무 느려 데몬 개수를 확인해 보면 httpd 가 256 개나 떠 있는 경우가 있다.기본적으로 아파치의 경우 MaxClients 가 256 으로 설정되어 있어 동시에 256 개의 데몬이 뜨게 되면더이상 접속을 받아들이지 않고, 기존의 프로세스가 죽을 때까지 대기후 접속이 끊기면 받아들이게 된다.따라서 동시 접속이 많은 경우 이전의 접속이 끊길 때까지 대기를 하여야 하므로 접속 속도가 느린 것이다."netstat -na | grep ES"	ESTABLISHED 상태를 확인하여 클라이언트의 IP 가 정상 적인 연결인지 확인"netstat -na | grep ES|awk '{print $5}' | sort"	클라이언트의 IP 만 따로 Sort 하여 확인하HTTP 1.1 규약에서부터 적용 되기 시작한 KeepAlive 기능을 지정하였을 경우 한 클라이언트 IP 에서동시에 3-5 개정도의 http 프로세스를 생성하므로 프로세스 개수의 정상적인 현상일 경우도 감안해보자.### 비정상적인 접속의 경우 ###*** 서비스 거부 공격(DoS) 의 경우동시에 서비스할 수 있는 프로세스의 한계가 있다는 점을 악용한 서비스 거부 공격일 가능성이 있다.이미 한번의 실행으로 100 개나 200 개등 원하는 만큼의 동시 접속을 맺은 후 이 접속을 끊지 않고유지할 수 있는 공격 코드가 인터넷상에 공개되어 있다.이경우 공격지의 IP 를 속이기가 어려우므로 netstat 으로 확인 후 비정상적인 접속 IP 를 차단하자공격지 IP 인 211.40.4.6 으로부터의 라우팅을 차단하는 설정	# route add -host 211.40.4.6 reject	# iptables -A INPUT -s 211.40.4.6 -j DROP실제 적용되었는지 확인: route -n, iptables -L -nTCP SYN Flooding 공격의 경우 SYN 패킷만 대량으로 발송할 뿐 ESTABLISHED 상태가 되지 않는다.*** include 를 잘못하여 무한 루프가 돌 경우php 와 mysql 을 연동하여 많이 사용하고 있는데, 프로그래밍 과정에서의 실수로 php 파일에서 같은php 파일을 include 하는 경우가 있다. 또는 a.php 파일에서 b.php 파일을 include 하고 b.php 파일에서다시 a.php 파일을 include 하는 경우도 그러한 경우일 것이다.이러한 경우에는 무한 루프가 돌게 되어 데몬이 금새 Maxclients 에서 지정한 개수로 차 버리게 되는데어떤 파일에서 무한 루프가 돌고 있는지 찾기가 힘들다.임시로 아래와 같이 include 를 하지 못하도록 차단을 하는 방법이 있다.	서버내에서 include 시에는 루프백 lo를 통해 1024 이후의 port 로 통신한다는 특성을 이용	# iptables .A INPUT -p tcp -i lo -s xxx.xxx.xxx.xxx --sport 1024:65535 -j DROP각각의 http 프로세스가 어떤 파일을 참조하고 있는지 일일이 추적하는 방법도 있다.	"ps aux | grep http" 로 보이는 프로세스에서 "ls -la /proc/pid/"### 정상적인 접속의 경우 ###*** KeepAlive 옵션 변경기본값으로 설정되어 있는 KeepAlive On 을 KeepAlive Off 로 변경 후 아파치를 재시작한다.KeepAlive 는 HTTP 1.1 규약에서부터 적용된 것으로 접속 속도에 큰 영향을 준다.KeepAlive 를 Off 로 설정시 다소 접속 속도는 떨어지지만 좀더많은 동시 접속을 수용 할수 있어서동시 접속자가 많은 경우에는 Off 로 설정하는 것이 임시 적인 해결 방법이 될것이다.*** 아파치의 MaxClients 조절기본적으로는 256 으로 설정되어 있는 MaxClients 의 한계를 512 나 1024 와 같이 적절히 변경한다.이 값을 변경하기 위해서는 아파치의 소스를 수정 후 다시 컴파일 해야한다	src/include/httpd.h 파일에서 HARD_SERVER_LIMIT 값을 512 나 1024 로 변경커널 2.2.X 경우 /usr/src/linux/include/linux/tasks.h 에서 NR_TASKS 와 MAX_TASKS_PER_USER 변수를수정후 커널을 재컴파일 해야 하며 2.4.X 의 경우 커널 제한이 없어져 아파치만 재컴파일 하면 된다.*** 추가 아파치 데몬 설정만약 여러 도메인중 특정 도메인이나 어떠한 사이트내 특정 컨텐츠의 접속이 특별히 많아같은 서버에 있는다른 사이트에까지 피해를 주고 있다면 이 부분을 별도로 데몬을 띄워 서비스하는 방법도 있다.이를테면 한 사이트에서 게시판의 접속이 매우 많다면 기존의 80 번 포트외에 8080 과 같은 임의의 포트로작동하는 웹 데몬을 추가로 띄워 이 포트를 통해 접속이 많은 서비스를 담당하게 하는 것이다.이를 위해서는 기존의 httpd.conf 파일을 httpd8080.conf 와 같이 설정 파일을 복사 후httpd8080.conf 파일을 변경하면 된다. (port 8080, User www2, Group www2)그리고 /usr/local/apache/bin/httpd -f /usr/local/apache/conf/httpd8080.conf 와 같이 실행하면8080 포트로 작동하는 웹서버 데몬을 추가로 띄우게 되는 것이다.이때 www 라는 계정은 생성되어 있어야 하며 Nobody 가 아닌 www 라는 계정으로 데몬을 작동하는 이유는한 유저(nobody) 가 생성할 수 있는 프로세스의 한계가 있기 때문이다. (커널 2.4.X는 제한이 없다)*** RLimitMEM - 메모리를 무한정 소모하는 것을 차단아파치의 설정 인자 (Directive) 중에서 RLimitMEM 을 사용하여 차단할 수 있다.이 인자는 아파치 웹 서버에서 생성된 특정 프로세스가 작동시 소요 가능한 최대 메모리의 양을제한하는 것으로 메모리를 많이 소모하는 CGI 가 작동할 때 이 인자에서 지정된 메모리까지만실행이 되고 그 이상 소요시에는 더 이상 작동하지 않도록 해 준다.	RLimitMEM 20480000 21504000	<Directory /home/special/public_html/*>		RLimitMEM 51200000 52224000	</Directory>위와 같이 설정하였다면 모든 디렉토리에서는 메모리를 20 메가나 최대 21 메가까지만 사용이 가능하고/home/special/public_html/* 디렉토리 이하에 접근시에는 특별히 50 메가까지 메모리 이용이 가능하게 된다.이와 비슷한 인자로 CPU 점유율을 제한하는 RLimitCPU 와 사용자당 프로세스의 개수를 제한할 수 있는RLimitNPROC 이 있으며 이에 대해서는 http://httpd.apache.org/docs-2.0/mod/core.html 를 참고하기 바란다.########## tips ###*** restart 가 되지 않을때# ./apachectl start	./apachectl start: httpd started# ./apachectl restart	./apachectl restart: httpd not running, trying to start	./apachectl restart: httpd started# ./apachectl stop	./apachectl stop: httpd (pid ?) not runningapachectl 파일을 열어서 경로를 확인하자	PIDFILE=	HTTPD=httpd.conf 파일을 열어서 PidFile 지시자 설정값이 PIDFILE 과 설로 같은지 확인. (서로 같아야 함)*** 웹브라우져에서 언어가 깨져서 나온다- 웹브라우져 보기에서 인코딩을 강제로 일본어를 (shift_jis) 잡으면 나온다- meta 정보의 charset은 제대로 설정되어 있는가 (예: 일본어라면 "shift_JIS" 로)- 리눅스가 다국어지원이 안되는지 확인 (/usr/share/i18n/locale, charmaps)- httpd.conf 에서 "AddDefaultCharset Off" 확인meta 정보를 웹브라우져에서 수용하로록 해준다AddDefaultCharset EUC-KR 등의 언어셋이 강제 지정되어 있는지 확인하자참고: /etc/sysconfig/i18n 정보	#LANG="ko_KR.eucKR"	LANG="en_US"	#SUPPORTED="en_US.UTF-8:en_US:en:ko_KR.eucKR:ko_KR:ko"	UPPORTED="en_US.iso885915:en_US:en:ko_KR.eucKR:ko_KR:ko"	SYSFONT="lat0-sun16"	#SYSFONTACM="iso01"*** logresolve	logresolve [-s filename] [-c] < access_log > new_logHostNameLookups 가 1.3.X 대에서는 기본으로 Off 로 설정되어져 있어 로그 파일에는 도메인 네임 대신IP 로 로그가 남게 된다. 아파치 웹 서버의 성능을 위하여 이 기능은 Off로 설정하는 것이 바람직 하며로그분석시에는 logresolve 를 통하여 로그파일 안의 IP를 도메인으로 변경할 수 있다.*** 이미지 / 파일 무단링크 막기# vi .htaccess	SetEnvIf Referer "suldo\.com" link_allow		링크가능 주소를 추가하려면 주소를 바꾸어서 추가하면 된다.	Order Deny,Allow	Deny from all	Allow from env=link_allow.htaccess 화일을 이미지 폴더나 파일이 들어가 있는 폴더에 넣어주면 그폴더및 하위폴더의이미지나 파일을 무단링크 할수가 없다. 지정해놓은 사이트에서만 링크가 가능하다..(닷) 앞에는 \ 를 꼭 사용해야 한다.
태그 EDIT
덧글 쓰기 | 엮인글 쓰기 이 포스트를.. | 수정 | 삭제
아파치 웹서버 장애 대처 | 낙서장 포스트 삭제 2006/08/17 21:20
http://blog.naver.com/comefeelone/120027839581

아파치 웹 서버 장애 해결하기


글·홍석범 오늘과내일 넷센터 (antihong@tt.co.kr)

시스템 관리자는 시스템에 대해 보수적이어야 한다는 말이 있다. “보수적”이라는 말은 특정한 정치적 성향을 뜻하는 것이 아니라 시스템에 대해 단 1%라도 문제가 될 수 있는 여지를 제거하고, 각 유저에게는 불편함을 주지 않는 한
도 내에서 가급적 사용 권한을 제한하여 혹시나 있을지 모를 시스템의 침해나 크래킹 등에 대비해야 한다는 것을 뜻한다. 아울러 시스템 관리자는 새로운 룰을 적용 또는 변경하거나 프로그램을 새로이 도입할 때에도 이 프로그램으로 인하여 다른 문제가 발생할 수 있는 여지는 없는지 여부를 신중히 검토 후 도입해야 한다.
이번 호에서는 아파치 웹 서버를 운영시 접할 수 있는 여러 가지 장애와 이에 따르는 원인과 해결 방법을 찾아보도록 하겠다.

* 접속이 느려지거나 접속이 안 될 때
가끔 접속자가 많은 서버를 운영하다 보면 갑자기 웹 접속이 되지 않거나 접속이 너무 느려 아파치 데몬 개수를 확인해 보면 httpd가 256개나 떠 있는 경우가 있다. 기본적으로 아파치 웹 서버의 경우 Max Clients가 256으로 설정되어
있어 동시에 256개의 데몬이 뜨게 되면 더 이상의 접속을 받아들이지 않고, 기존의 프로세스가 죽을 때까지 대기한 후 접속이 끊기게 되면 그제서야 접속을 받아들이게 된다.
따라서 동시 접속이 많은 경우에는 이전의 웹 접속이 끊길 때까지 대기해야 하므로 접속 속도가 느린 것처럼 느끼게 되는 것이다. 일반적으로 정상적인 접속의 경우에 256개의 프로세스가 모두 뜨는 경우는 그리 많지 않기에 현재의 상태가 비정상적인 접속인지 여부를 판단해야 한다. 이를 판단할 수 있는 방법은 netstat ?na | grep ES로 ESTA BLISHED된 연결 상태를 확인하여 클라이언트의 IP가 정상적인 연결인지 여부를 확인하면 된다.
또는 netstat -na|grep ES|awk '{print $5}'|sort로 클라이언트의 IP만 따로 소트하여 확인해 봐도 된다. 통상적으로 HTTP 1.1 규약에서부터 적용되기 시작한 KeepAlive 기능을 지정하였을 경우 한 클라이언트 IP에서 동시에 3~5개 정
도의 http 프로세스를 생성하므로 한 IP에서 3~5개 정도의 프로세스를 생성하는 것은 정상적인 현상이다. 비정상적인 접속의 경우에는 다음과 같은 이유가 있을 수 있다.

* 서비스 거부 공격(DoS)이 가해졌을 때
DoS는 동시에 서비스할 수 있는 프로세스의 한계가 있다는 점을 악용한 공격이다. 한번의 실행으로 100개나 200개 등 원하는 만큼의 동시 접속을 맺은 후 이 접속을 끊지 않고 유지할 수 있는 공격 코드가 인터넷 상에 공개되어 있
다. 그러나 이러한 공격의 경우 공격지의 IP를 속이기가 매우 어려우므로 netstat으로 확인 후 비정상적인 접속으로 확인 될 경우 해당 IP를 차단하면 된다.
특정 IP의 라우팅을 차단하는 방법은 다음과 같이 route를 이용한 방법과 iptables(커널 2.4 이상)를 이용한 방법 두 가지가 있다.

* include를 잘못하여 무한 루프가 돌 경우
요즘에는 php와 mysql을 연동하여 많이 사용하고 있는데, 프로그래밍 과정에서의 실수로 php 파일에서 같은 php 파일을 include하는 경우가 있다. 또는 a.php 파일에서 b.php 파일을 include하고 b.php 파일에서 다시 a.php 파일을
include하는 경우도 그러한 경우일 것이다. 이러한 경우에는 무한 루프가 돌게 되어 결국은 아파치 데몬이 금새 Maxclients에서 지정한 개수로 차 버리게 되는데, 어떤 파일에서 무한 루프가 돌고 있는지 찾기가 힘들다.
따라서 임시로 다음과 같이 include를 하지 못하도록 차단을 하는 방법이 있다.

# iptables -A INPUT -p tcp -i lo -s xxx.xxx.xxx.xxx --sport
1024:65535 -j DROP
이는 같이 서버 내에서 include 시에는 lo(Lookback Interface)를 통해 sport 가 1024 이후의 하이 포트를 이용하여 통신한다는 특성을 이용한 것이다. 그러나 이 설정을 하였을 경우 로컬 서버에서 클라이언트 포트를 전혀 사용할 수
없게 되므로 다른 서비스에도 장애가 되기 때문에 임시로만 사용하기 바란다.
또는 ps aux | grep http로 보이는 프로세스에서 ls -la/proc /pid/로 각각의 http 프로세스가 어떤 파일을 참조하고 있는지 일일이 추적하는 방법도 있다.
(예:cwd -> /home/user1/public_html/infinite_loop/)

* 프로세스가 과도한 메모리를 사용할 경우
특별히 이상한 프로세스는 없는데, 시스템의 부하가 갑자기 올라가는 경우가 있다. 심할 경우에는 콘솔에서 키 작동이 되지 않아 제어 자체가 불가능한 경우도 있는데, 이러한 경우는 어쩔 수 없이 시스템을 재시작하는 수밖에 없다.
이는 의도적이든 아니든 유저가 cgi나 php 등의 프로그램을 잘못 짜서 과도한 메모리를 소모하는 프로세스를 실행하기 때문인 경우인데, 실제로 시스템의 메모리를 많이 소모하는 프로그램을 짜는 것은 단 몇 줄의 코드로도 가능하다.
다음과 같이 메모리를 소모하는 간단한 C 코드를 작성해 보자(참고로 스크립트 키드의 악용을 막기위해 코드 중 일부를 변경하였다).

/* memory.c */

#include <unistd.h>
#include <stdlib.h>

void html_content(void);

int main() {
char *some_memory;
int size_to_allocate = ONE_K;
int megs_obtained = 0;
int ks_obtained = 0;

html_content();
printf("Program Executed !!!<p>");

while (1) {
for (ks_obtained = 0; ks_obtained < 1024; ks_obtained++) {
some_memory = (char *)malloc(size_to_allocate);
if (some_memory == NULL) exit(EXIT_FAILURE);
sprintf(some_memory, "Hello World");
}
printf("Now allocated %d Megabytes<br>\n", megs_obtained);
}
exit(0);
}

void html_content(void)
{
printf("Content-type: text/html\n\n");
}
작성 후 gcc -o memory.cgi memory.c로 컴파일 한 후 이 파일을 http://domain.com/memory.cgi와 같이 웹에서 실행해 보도록 하자. 아무리 메모리와 CPU의 여유가 있는 시스템이라 하더라도 이 프로그램을 실행하자마자 거의 통제 불능 상태로 되어 결국 시스템 재부팅하게 될 것이다. 이렇듯이 메모리를 무한정 소모하는 것을 차단하기 위해서는 아파치의 설정 인자 (Directive) 중에서 RLimitMEM을 사용하여 차단할 수 있다. 이 인자는 아파치 웹 서버에서 생성된 특정 프로세스가 작동시 소요 가능한 최대 메모리의 양을 제한하는 것으로 메모리를 많이 소모하는 CGI가 작동할 때 이 인자에서 지정된 메모리까지만 실행이 되고 그 이상 소요시에는 더 이상 작동하지 않도록 해 준다.
예를 들어 httpd.conf에 다음과 같이 설정하였다면 모든 디렉토리에서는 메모리를 20MB나 최대 21MB까지만 사용이 가능하고 /home /special/public_html/* 디렉토리 이하에 접근 시에는 특별히 50MB까지 메모리 이용이 가능하게 된다.

RLimitMEM 20480000 21504000

<Directory /home/special/public_html/*>
RLimitMEM 51200000 52224000
</Directory>

실제로 위와 같이 설정 후 memory.cgi를 웹에서 호출하면 아래와 같이 일정량의 메모리만 사용되고 중단하는 것을 확인할 수 있다.
이와 비슷한 인자로 CPU 점유율을 제한하는 RLimitCPU와 사용자당 프로세스의 개수를 제한할 수 있는 LimitNPROC이 있다. 이에 대해서는 http://httpd.apache.org/docs-2.0/mod/core.html를 참고하기 바란다.
용량 큰 파일의 업/다운로드시 부하가 유발될 경우 누구나 업/다운로드가 가능한 자료실을 운영하고 있을 경우 사이즈가 너무 큰 파일을 업/다운로드 할 경우 부하가 많이 걸리게 되어 결국 시스템의 성능 저하를 유발하게 된다. 최근 배포되는 게시판/자료실 프로그램에서는 대부분 업로드할 수 있는 용량 등을 제한할 수 있는 기능이 있지만 그렇지 않은 프로그램도 상당수 있어 웹 서버 차원에서 이 제한을 적절히 설정할 필요가 있다.
아파치에서는 이와 관련하여 웹 서버에서 업/다운로드 할 수 있는 파일의 사이즈를 제한하는 Limit RequestBody 기능을 이용할 수 있다.
LimitRequestBody는 클라이언트가 요청시 http 프로토콜을 통해 서버가 제공 할 수 있는 메시지의 크기를 바이트 단위로 정의하는 것으로 무한대를 의미하는 0부터 2,147,483,647(2Giga)까지 설정 가능하며 이 설정으로 대용량의 파일을 업/다운로드 하는 형태의 서비스 거부 공격을 차단할 수 있다. 이를 설정하는 방법은 httpd.conf를 열어 다음과 같은 라인을 추가하면 된다.

<Directory />
LimitRequestBody 7168000
</Directory>
<Directory /home/special/>
LimitRequestBody 10240000
</Directory>

위와 같이 LimitRequestBody 인자를 설정하면 아파치 웹 서버를 이용하여 업/다운로드 하는 모든 파일의 사이즈를 7MB로 제한하고 /home/special/ 이하에 대해서는 10MB로 제한하게 된다. 위와 같이 설정시 지정된 사이즈를 초과하는 파일을 업/다운로드 시에는 다음 그림과 같은 에러 메시지가 뜨며 업/다운로드가 되지 않는다.
특정한 이름의 파일을 실행을 제한하려면 최근에는 대부분의 사이트들이 대화방(채팅)을 위해 자바로 프로그래밍된 자바 대화방을 사용하는 추세이지만 얼마 전까지만 하더라도 C나 펄로 된 CGI 대화방을 설치하여 사용하는 것이 유행이었다. 그런데 이 대화방의 경우 대화방에 참여하는 유저 중 한 명이 글을 입력할 경우 모든 유저에게 이 내용이 실시간으로 나타나야 하는 특성상 시스템의 메모리를 매우 많이 소모하는 대표적인 프로그램 중 하나였다.
따라서 채팅 CGI 프로그램을 원천적으로 사용할 수 없도록 하는 방법을 고민하게 되었는데, 해결 방법은 대부분의 채팅 프로그램이 xxxchat.cgi 또는 chatxxx.cgi라는 파일을 실행 파일 이름으로 한다는 특징을 이용하면 된다.
즉, httpd.conf를 열어 다음과 같이 설정하면 파일명에 ‘chat’이라는 단어가 포함된 CGI 파일은 작동하지 않게 되는 것이다.

<Files "*chat*.cgi">
Order allow,deny
Deny from all
</Files>
이러한 방식으로 특정한 파일에 대해 웹에서의 접근을 차단할 수 있다. 따라서 CGI 파일에 아무리 소유권과 실행 권한을 주었다 하더라도 웹 서버 자체에서 접근을 거부하였으므로 웹에서 접근하면 ‘Forbidden’에러가 나게 된다.
이러한 식으로 특정 파일 이름을 가진 파일의 실행이나 접근을 차단할 수 있다.

* 검색 로봇의 접근 차단하기
갑자기 특정한 IP 주소에서 짧은 시간에 많은 접속을 하여 시스템의 부하가 올라가 웹 접속 로그를 살펴보니 다음과 같이 이해할 수 없는 내용이 남는 경우가 있다.

211.51.63.4 - - [26/Sep/2001:22:19:42 +0900] "GET /robots.txt HTTP/1.0"
404 285
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /index.asp HTTP/1.0"
404 284
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /index.php HTTP/1.0"
404 284
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /index.php3 HTTP/1.0"
404 285
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /default.htm HTTP/1.0"
404 286
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /default.html
HTTP/1.0" 404 287
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /default.asp HTTP/1.0"
404 286
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /default.php HTTP/1.0"
404 286
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /default.php3
HTTP/1.0" 404 287
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /main.htm HTTP/1.0"
404 283
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /main.html HTTP/1.0"
404 284
211.51.63.4 - - [26/Sep/2001:22:19:43 +0900] "GET /main.asp HTTP/1.0"
404 283
211.51.63.4 - - [26/Sep/2001:22:19:44 +0900] "GET /main.php HTTP/1.0"
404 283
211.51.63.4 - - [26/Sep/2001:22:19:44 +0900] "GET /main.php3 HTTP/1.0"
404 284

무작위로 index.php, index.asp, index.php3, default.html, default.asp 등의 파일을 순서대로 요청하는 것으로 보아 검색 엔진일 가능성이 높다고 가정
할 수 있다. 특히 robots.txt 파일을 요청하는 것으로 검색 엔진이라고 장담 할 수 있을 것이다.
httpd.conf에서 Logformat를 common 대신 {User-agent} 변수를 추가하여 정의 하면 서버에 접근하는 에이전트 정보도 알 수 있는데, UA(User Agent)는 일반적인 웹브라우저 뿐만 아니라 검색 로봇이나 방랑 로봇 등 웹 서버에 접속하여 웹페이지를 가져오거나 해석하는 모든 종류의 프로그램을 뜻한다.
이는 흔히 사용하는 익스플로러나 넷스케이프 등의 브라우저 외에도 라이코스의 스파이더(spider)나 알타비스타의 스쿠터(Scooter)와 같은 검색 로봇과 텔리포트(Teleport)나 WebZIP, GetRight 등 오프라인 브라우저 모두 UA의 범위에 속한다. 검색 로봇이 어떤 사이트를 방문하여 문서를 인덱싱하거나 오프라인 브라우저가 페이지를 한꺼번에 요청하여 긁어 가는 것은 일반 사용자가 웹 브라우저로 서버에 접속하여 원하는 페이지를 보는 일반적인 경우와 그 성격이 다르다. 여러 페이지를 동시에 요청하는 정도를 벗어나 아예 한 웹사이트의 모든 페이지를 짧은 시간에 통째로 긁어가기도 하기 때문에 이러한 경우에는 서버에 매우 많은 프로세스를 생성하면서 웹 서버의 로드가 크게 올라가게 되는 것이다. 특히 DB와 연동하는 사이트의 경우에는 심할 경우 정상적인 서비스를 하지 못 할 정도이다.
모든 사이트가 검색 엔진에 등록될 필요는 없거나 또는 허용된 일부 유저만 접근이 가능한 페이지의 경우 로봇의 접근을 차단할 필요가 있으므로 이러한 경우에는 다음과 같이 설정된 robots.txt 파일을 웹 서버의 최상위 / 디렉토리
에 두면 모든 검색 로봇이 /secure 디렉토리를 인덱싱하지 않는다.

User-agent: *
Disallow: /secure

“User-agent: *”는 모든 로봇를 대상으로 한다는 것을 뜻하며 예를 들어 알타비스타 스쿠터 등 특정한 UA에 대해서만 설정하고 싶다면 다음과 같이 하면 된다.

User-agent: scooter

검색 로봇과 관련된 더 자세한 정보를 얻기 원한다면 다음의 사이트를 참고하기 바란다.

http://info.webcrawler.com/mak/projects/robots/robots.html
http://info.webcrawler.com/mak/projects/robots/norobots.html

아울러 웹 서버에서 특정한 유저 에이전트의 접근을 차단하려면 httpd.conf에 다음과 같이 BrowserMatch를 사용하여 설정해도 된다.

BrowserMatch "WebZIP" go_out
BrowserMatch "Teleport" go_out
BrowserMatch "GetRight" go_out
BrowserMatch "WebCopier" go_out
BrowserMatch "NetZip Downloader 1.0" go_out
BrowserMatch "NetZip-Downloader/1.0.62" go_out
BrowserMatch "Teleport Pro/1.29" go_out
BrowserMatch "Teleport Pro/1.24" go_out
BrowserMatch "Teleport Pro/1.26" go_out
<Directory /home/no-ua/>
Options Includes ExecCGI
AllowOverride None
Order allow,deny
Allow from all
Deny from env=go_out
</Directory>

위와 같이 설정 시에는 /home/no-ua/ 디렉토리 이하에 대해서는 go_out이라는 변수에 지정한 WebZip이나 Teleport 등 UA 프로그램의 접근을 차단하게 된다.
다른 UA도 차단하고 싶으면 위와 같이 웹 서버의 로그를 살펴보아 에이전트 정보에 남는 UA를 go_out으로 추가해 주면 된다. 같은 방식으로 만약 특정 디렉토리 이하에 대해서 MSIE 브라우저로 접근하지 못하도록 설정하려면 다음과 같이 BrowserMacth를 이용한다. 이렇게 하면 에이전트 정보에 MSIE라 설정되는 UA는 차단될 것이다.

BrowserMatch "MSIE" msie
<Directory />
Options Includes ExecCGI
AllowOverride None
Order allow,deny
Allow from all
Deny from env=msie
</Directory>
최근에는 각종 로봇이 버전을 새롭게 하며 계속적으로 나오고 있으므로 지속적으로 로그를 살펴보아 접근 통제를 하고자 하는 UA를 설정하는 것이 좋다.

* 외부의 데이터 무단 링크로 인한 부하 없애기
최근에 와레즈 사이트를 통해 게임이나 오락, 동영상 등 각종 데이터들이 공유되면서 와레즈 사이트에서 관련 없는 임의의 서버에 데이터를 업로드한 후 무단 링크하여 서비스하는 경우가 많다. 이러한 경우 데이터 전송량이 갑자기 늘어 서버의 부하가 급격히 올라감은 물론 한정된 회선의 대역폭도 소모하게 되어 서버를 관리하는 관리자들에게는 이러한 무단링크가 큰 골치 거리 중에 하나다.
대부분의 무단 링크가 대용량이기 때문에 이를 차단하기 위해 위와 같이 LimitRequestBody를 이용하여 임의의 용량 이상의 데이터에 대한 업/다운로드 용량을 제한하는 방법도 있지만 다음과 같이 BrowserMatch 대신 SetEnvIFNoCase Referer를 이용하는 방법도 있다.

SetEnvIFNoCase Referer "warez" link_deny
SetEnvIFNoCase Referer "free" link_deny
SetEnvIFNoCase Referer "home" link_deny

<FilesMatch "\.(avi|mpe?g|zip|asf|exe)$">
Order allow,deny
allow from all
deny from env=link_deny
</FilesMatch>

위와 같이 설정 시에는 Referer이 warez 또는 free나 home이 포함되었을 경우 이 사이트를 link_deny라는 변수에 할당하고, 환경변수가 link_deny일 때는 확장자가 avi나 mprg, zip, asf 등인 파일에 대한 엑세스를 제한하고 있다. 따라
서 홈페이지 주소에 warez나 free 또는 home이 포함된 주소에서 위의 데이터를 무단 링크하였을 경우에는 이를 차단할 수 있다. Nocase를 추가로 설정하였을 경우에는 대소문자를 가리지 않아 링크하는 사이트가 대소문자에 관계없이 http://my.warez.org/, http://My.Warez.Org/, http://MY. WAREZ.ORG/ 모두 적용된다.
다른 확장자를 추가하고나 설정을 변경하고자 할 경우에는 정규식(Regurar Expression)을 이용하여 설정하면 된다. 또는 이와는 반대로 아예 httpd.conf 에서 다음과 같이 설정할 수도 있다.

<VirtualHost tt.co.kr>
ServerAdmin webmaster@tt.co.kr
DocumentRoot /home/tt/public_html
ServerName tt.co.kr
ServerAlias www.tt.co.kr
SetEnvIf Referer tt\.co\.kr link_allow
SetEnvIf Referer www\.tt\.co\.kr link_allow
SetEnvIf Referer ^$ link_allow
<FilesMatch ".(mpg|asf|wmv)$")
Order Deny,Allow
Allow from env=link_allow
Deny from all
</FilesMatch>
</VirtualHost>

위와 같이 설정하였을 경우 외부에서는 mpg, asf, wmv 확장자를 갖는 파일에 대해서는 일체의 무단 자료 링크가 불가능하게 되며 오직 link_allow에서 지정한 도메인에서만 링크가 가능하게 된다. 위와 같이 설정 후 외부에서 무단 링
크를 하였을 때 error_log를 살펴보면 다음과 같이 무단으로 링크한 자료의 다운로드가 작동하지 않는 것을 확인할 수 있다.

[Tue Sep 4 15:55:44 2001] [error] [client 211.230.82.78]
client denied by server configuration: /home/tt/public_html/data/3-2.wmv

아파치 데몬은 떠 있는데, 접속이 되지 않는 경우
분명 데몬은 정상적으로 떠 있고 MaxClients에 도달하지도 않았는데, 실제로 접속이 되지 않는 경우가 있다. 이러한 경우라면 웹 서버가 TCP SYN Flooding 공격을 받고 있을 가능성이 있다. netstat -na | grep SYN으로 확인하여 많은 SYN_RECEIVED 프로세스가 보인다면 이 공격 때문이며 이러한 경우에는 첫 번째 줄의 명령을 사용하거나 두 번째 줄의 syncookies 기능을 enable하면 된다.

# sysctl ?w net.ipv4.tcp_syncookies=1
# echo 1 > /proc/sys/net/ipv4/tcp_syncookies

Syncookie 기능은 일단 커널에서 지원되어야 하므로 이 설정이 적용되지 않으면 커널에서의 설정여부를 확인해 보아야 한다. 이 공격에 대한 보다 자세한 내용은 본지 7월호에 실린 “TCP SYN Flooding 공격의 원인과 해결책”을 참고 하기 바란다.

코드레드나 님다(Nimda) 등 웜 공격으로 로그 파일의 크기가 커질 때 최근에 코드레드와 님다 등 윈도우 NT/2000 기반의 IIS를 공격하는 무차별적인 웜 공격으로 인하여 부하가 유발되고 로그 파일이 불필요한 데이터로 채워지는 경우가 있다. 로그 파일의 크기가 커지는 것은 감안하더라도 당장 계속적으로 커지는 로그 파일 때문에 서버에 부하를 유발하는 것이 더욱 큰 문제다.
서버에서 로그를 남기는 방식은 매번 클라이언트의 요청이 있을 때마다 웹 서버에서 패킷 헤더에 있는 클라이언트의 정보를 받아낸 후 로그 파일을 열도록 한 후 로그 파일을 읽어 파일의 제일 끝으로 이동하여 로그 정보를 추가한 후 파일을 닫는 것인데, 불필요한 요청이 있을 때마다 이 작업을 계속하여야 하므로 서버에 부하를 유발함은 당연한 현상이다.
따라서 아예 로그를 남기지 않도록 하거나 로그를 남긴다 하더라도 불필요한 정보를 남기지 않도록 하는 것이 미소하게나마 서버의 성능을 높이는 것이 될 것이다. 그럼 실제로 불필요한 정보는 아예 로그를 남기지 않는 방법에 대해
알아보도록 하자. 이를테면 코드레드의 경우 다음과 같이 무차별적인 로그가 남게 된다.

2001/08/01 23:39:50.765446 152.158.99.4:58781 -> 211.233.38.193:80 [AP]
GET/default.ida?
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
NNNNNNNNNNNNNNNNNNNNNNNNNNNNNN
이러한 로그를 막기 위해서는 httpd.conf 파일을 열어 Custom Log 윗줄에
SetEnvIf Request_URI “/default.ida$” cord-red와 같이 정의한 후
CustomLog/usr/local/apache/logs /access.log combined라고 설정되어 있는 부 분을
CustomLog /usr/local /apache/logs//access.log combined env=!cord-red 라고 수정을 한다.
!는 not의 의미이므로 위 설정은 환경변수 cord-red로 정의된 요청을 거부하라는 뜻이다. 위와 같이 설정 후 아파치를 재시작하면 코드레드와 관련된 로그가 남지 않게 된다. 코드레드에 이은 님다 웜의 경우도 같은 방식으로 설정하
여 로그에 남지 않도록 설정할 수 있다.
또한 같은 원리를 이용하여 iptables를 이용하여 아예 패킷 자체를 차단할 수도 있는데, 코드 레드의 경우 default.ida 문자열을 요청한다는 특징을 이용하여 다음과 같이 차단할 수 있다.

iptables ?A INPUT -i eth0 -p tcp --tcp-flags ACK ACK --dport 80
-m string --string ‘/default.ida?’ -j REJECT --reject-with tcp-reset와 같이 iptables의 ?strings를 이용하여 특정 문자열이 포함된 패킷을 차단하는 방법도 있기는 하지만 이 방법은 커널과 iptables를 다시 컴파일해야 하는 문제가 있다. 님다 웜 역시 이외 cmd.exe 와 root.exe를 포함하므로 같은 방식으 로 다음과 같이 차단할 수 있다.

iptables -A INPUT -p tcp --tcp-flags ACK ACK --dport 80 -m string --
string "cmd.exe" -j REJECT --reject-with tcp-reset
iptables -A INPUT -p tcp --tcp-flags ACK ACK --dport 80 -m string --
string "root.exe?" -j REJECT --reject-with tcp-reset

* 서버 네임(ServerName) 인자 관련 에러 대처
아파치 서버를 시작시 자주 만나는 에러와 관련된 설정 중 하나가 바로 다음과 같은 서버 네임이다.

# /usr/local/apache/bin/apachectl start
httpd: cannot determine local host name.
Use the ServerName directive to set it manually.
./apachectl startl: httpd could not be started

대부분 서버 네임은 리눅스 설치 시 입력한 호스트 이름을 자동으로 가지고와 설정되나 DNS상에 존재하지 않은 도메인명이나 설사 존재하더라도 로컬 서버가 아닌 잘못된 도메인을 정의시 이러한 현상이 나타난다. 이러한 경우에는 서버 네임을 실제 로컬 서버의 호스트 이름이나 IP 주소로 설정해 주어야 한다.
또한 서버 네임을 잘못 설정 시 나타날 수 있는 현상 중 하나가 http: //domain.com/~user와 같이 접속할 때의 문제다. 즉, 서버 내 계정 사용자의 홈페이지를 접속시 http://domain.com/ ~user/와 같이 접속하면 접속이되나 http://domain.com/~user와 같이 /를 붙이지 않으면 접속이 되지 않는 경우다.
클라이언트가 서버의 디렉토리에 접속시 끝에 /(trailing)을 하지 않은 경우 서버는 클라이언트에게 /을 붙여 다시 접속을 하라고 요청한다. 그렇지 않으면 상대 URL 경로를 인식하지 못하는 문제가 있기 때문이다. 만약 DNS가 정상
적으로 세팅되어 작동하고 있을 경우에는 문제가 없지만 그렇지 않은 경우에는 접속이 되지 않는 경우가 생긴다. 또는 위에서처럼 서버 네임에 지정된 호스트네임이 실제로 DNS 상에 리졸빙이 되지 않는 경우도 이러한 현상이 나타나므로 이러한 경우에는 httpd.conf의 서버 네임 옵션에 실제 서비스 중인 도메인명으로 입력해 주면 된다.

* 특정 파일의 접근 제한이 되지 않을 때
가끔 서버를 운영하다보면 특정한 디렉토리 이하에 대해서는 인증된 유저만 접속이 가능하게 한다거나 특정 IP 대역의 유저만 접근하도록 하고자 할 필요가 있을 때가 있다. 특정 디렉토리 이하에 대해서 접근을 제어하고자 할 때에
는 .htaccess를 사용하거나 httpd.conf에서 <Directory>를 이용하여 제어를 할 수 있지만, 만약 특정한 파일에 대해서 외부에서의 접근을 제한하고자 한다면 어떻게 하여야 할까?
이때는 Location을 사용하면 된다. httpd.conf 파일에 다음과 같이 설정시 모든 디렉토리 이하의 secret.html 파일에 대해서는 192.168.1.1에서만 접근이 가능하게 된다.

<Location /secret.html>
order deny,allow
deny from all
allow from 192.168.1.1
</Location>

만약 여러 도메인이 설치되어 있는 호스팅 서버의 경우 secret.tt. co.kr 도메인 내의 secret.html에 대해서만 접근을 제어하고자 할 경우에는 다음과 같이 버추얼 호스트 설정에서 하면 된다.

<VirtualHost secret.tt.co.kr>
ServerAdmin antihong@tt.co.kr
DocumentRoot /usr/local/apache/htdocs/secret/
ServerName secret.tt.co.kr
<Location /secret.html>
order deny,allow
deny from all
allow from 192.168.1.1
</Location>
</VirtualHost>

또는 위와 같이 IP가 아니라 특정한 ID/PW를 입력한 유저에 대해서만 특정 파일에 대하여 접근을 허용하고자 할 때가 있다. 이러한 경우에는 httpd.conf에 다음과 같이 설정하면 된다.

<VirtualHost secret.tt.co.kr>
ServerAdmin antihong@tt.co.kr
DocumentRoot /usr/local/apache/htdocs/secret/
ServerName secret.tt.co.kr
<Files secret.html>
AuthName "ID/PW 를 입력하세요."
AuthType Basic
AuthUserFile /usr/local/apache/htdocs/.htpasswd
Require valid-user
</Files>
</VirtualHost>

그리고 htpasswd ?c htpasswd id로 .htpasswd 파일에 ID/PW를 생성하여 secret.html에 접근시 ID/PW를 정확히 입력한 유저에 대해서만 접근이 가능하게 된다.

한글 도메인으로 접속이 되지 않을 때 한글.com 형식의 한글 도메인 서비스가 1년 가까이 아직 정상적인 서비스가
되고 있지는 않지만 현재는 포워딩 방식으로나마 일부 사용 가능하다. 즉, 그 자체로 한글.com으로의 사용은 불가능하며 단지 한글.com을 접속시 다른 도메인으로 포워딩 할 수 있는 것이다. 현재 http://www.gabia.com/http://www.doregi.com/ 등에서 한글 도메인을 검색해 보면 예를 들어 팬메일.net의 경우 BQ--3DJSZOSUY56A.NET와 같이 BQ- 형식의 RaceCode 문자로 되어 있는데, 실제로는 bq--3djszosuy56a.mltbd.net와 같이 mltbd.net(한글.com 일 경우에는 mltbd.com, 한글.org 일 경우에는 mltbd.org)의 2차 도메인 형식으로 서비스된다. 따라서 위와 같이 WHOIS 검색을 한 후 나온 RaceCode을 DNS 서버에서 먼저 설정하여야 하는데, DNS 서버의 named.conf에서 설정하여야 할 내용은 다음과 같다.

zone "bq--3djszosuy56a.mltbd.net" {
type master;
file "bq--3djszosuy56a.mltbd.net.zone";
};

bq--3djszosuy56a.mltbd.net.zone 파일의 형식은 일반 zone 파일 형식과 동일하게 설정하면 된다.
그리고 DNS 서버에서 지정한 해당 웹 서버에서는 다음과 같이 버추얼 호스트 설정을 하여 원래의 사이트인 http://panmail.net/으로 리다이렉트하면 된다
(현재까지는 포워딩 서비스만 제공하므로 Redirect를 이용하여야 한다).

<VirtualHost bq--3djszosuy56a.mltbd.net>
ServerAdmin webmaster@bq--3djszosuy56a.mltbd.net
DocumentRoot /usr/local/apache/htdocs/panmail
ServerName bq--3djszosuy56a.mltbd.net
ServerAlias www.bq--3djszosuy56a.mltbd.net
Redirect / http://panmail.net
</VirtualHost>

위와 같이 설정 후 아파치를 재시작하면 팬메일.net으로 접속시 http://panmail.net/으로 접속이 되는 것을 확인할 수 있을 것이다.


* 기타 시스템 장애 대처법
리눅스가 윈도우 계열과 다른 가장 큰 특징 중 하나는 로그(log)를 철저히 남긴다는 것이다. 남겨진 로그 정보를 이용하여 각종 시스템의 장애나 상태를 점검할 수가 있는데, 아파치 웹 서버 역시 마찬가지다. 문제나 장애가 발생 시에는 반드시 error_log를 남기게 하여 /usr/local /apache/logs/error_log의 메시지를 살펴보면 문제의 원인과 해결책을 어렵지 않게 찾을 수 있게 될 것이다.
문제가 발생하였다고 당황하거나 무턱대고 관련 게시판에 질문을 올리지 말고, 에러 로그의 내용을 기초로 차근차근 문제의 원인을 분석하고 해결해 나간다면 조금씩 서버 관리자에 가까워지는 자신을 발견할 수 있을 것이다.

2006/09/08 15:53 2006/09/08 15:53
이 글에는 트랙백을 보낼 수 없습니다
웅쓰:웅자의 상상플러스
웅자의 상상플러스
전체 (379)
게임 (5)
영화 (2)
기타 (23)
맛집 (5)
영어 (2)
대수학 (3)
형태소 (5)
Hacking (9)
Linux (112)
HTML (48)
Application_developing (48)
Web_developing (102)
Window (11)
«   2024/12   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 31        
  1. 2016/01 (1)
  2. 2015/12 (3)
  3. 2015/10 (3)
  4. 2015/03 (2)
  5. 2015/01 (4)