기타

웹서버 접근제어

시반 2009. 11. 10. 14:56

Apache 접근 제어 (Access Control)

웹서버를 운영하다보면 “외부의 접근은 허용하지 않으며, 특정 지역에서만 접근을 원하고 싶은데… 쉬운 방법은 없을까? “ 하는 고민을 하게된다. 일반적인 웹사이트야 기본 설정대로 사용하면 되겠지만 소수의 사람들만 사용하기 위한 정보 등이라면 어플리케이션 레벨의  ACL이 아니어도 서버 설정파일(httpd.conf) 이나 디렉토리별 설정파일(.htaccess) 을 통해 간단하게 설정할 수 있다..htaccess 파일을 사용하는 경우에는 이 파일에 있는 인증 지시어를 허용하도록 서버를 설정해야 한다. 이를 위해 디렉토리별 설정파일에 어떤 지시어를 사용할 수 있는지를 결정하는 AllowOverride 지시어를 사용한다.

 서버 디렉토리를 암호로 보호하기

서버의 디렉토리를 암호로 보호하기 위해서 먼저 암호파일을 만들어야 한다.

이 파일은 웹에서 접근할 수 없는 곳에 있어야 하는데 그 이유는 다른사람이 암호파일을 다운로드하지 못하게하기 위해서다.

예를 들어, 문서들이 /usr/local/apache/htdocs에 있다면 암호파일(들)은 /usr/local/apache/passwd에 둔다.

아파치에 포함된 htpasswd 도구를 사용하여 다음과 같이 암호파일을 만들 수  있다. (아파치설치디렉토리/bin/htpasswd) 

 

htpasswd -c /usr/local/apache/passwd/passwords civan htpasswd는 암호를 물어보고, 확인을 위해 암호를 다시

New password: mypassword
Re-type new password: mypassword
Adding password for user civan

 

암호를 물어보고 확인을 위해 암호를 다시 입력하라고 요청한다.

다음으로 서버가 암호를 요청하도록 설정하고, 서버에게 어떤 사용자의 접근을 허용할지 알려줘야 한다.

httpd.conf를 편집하거나 .htaccess 파일을 사용하여 설정한다.

예를 들어, /usr/local/apache/htdocs/secret 디렉토리를 보호하려면, 아래 지시어를 /usr/local/apache/htdocs/secret/.htaccess 파일이나 httpd.conf의 <Directory /usr/local/apache/htdocs/secret> 섹션에 적어야 한다.

 

AuthType Basic
AuthName "Restricted Files"

AuthUserFile /usr/local/apache/passwd/passwds

Require user civan

 

  • AuthType : 사용자 인증 방법 선택. 

기본값은 Basic (mod_auth_basic 이 구현) 을 사용하고 있지만 Basic 인증은 브라우저가 서버로 암호를 암호화하지 않고  전송하기 때문에 기밀 자료를 보호하기 위해서는 다른 방법을 선택.

예를 들면 아파치의 경우 AuthType Digest( mod_auth_digest가 구현) 인증 방법도 지원하고 있으며  매우 안전하다.

일단 클라이언트가 "Restricted Files" 영역에 인증이 성공하였다면,   클라이언트는 자동으로 같은 서버내 "Restricted  Files" 영역으로 표시된 구역에 대해서 동일한 암호를 시도한다. 

그래서 여러 제한 구역이 같은 영역을 공유하면 사용자가 여러번 암호를 입력하지 않아도 된다. 

물론 보안상 이유로 클라이언트는 서버의 호스트명이 다르면 항상 새로 암호를 물어보게 된다.

  • AuthUserFile : htpasswd로 만든 암호파일의 경로를 설정.

사용자가 많은 경우 요청마다 매번 사용자를 인증하기위해 일반 문서파일을 검색하는 것은 시간이 상당히 많이 걸릴 수 있기  때문에 AuthDBMUserFile  지시어를 이용하여 데이타베이스 파일에 사용자 정보를 저장할 수도 있다.

  • Require : 서버의 특정 영역에 접근할 수 있는 사용자를 지정하여 권한부여

그룹권한

앞에서는 디렉토리에 한사람(사용자명이 civan인)에 대한 접근 권한을 부여했다면 이번에는 다수의 사용자들을 그룹으로 묶어 부여하는 방법을 설명합니다.

먼저 그룹명과 해당 그룹에 어떤 사용자들이 있는지 알려주는 그룹파일이 필요하다.

 

#vi /usr/local/apache/passwd/groups

groupA : civan naver google

 

위의 예는 그룹명이 groupA  이며 civan, naver, google이라는 사용자가 들어있다는 그룹파일이다.

 

#htpasswd /usr/local/apache/passwd/passwords naver


추가된 사용자에 대한 암호를 만듭니다. 앞에서와 동일하지만 새로 파일을 생성하는 것이 아닌 기존파일(passwords)에 사용자를 추가합니다. 새로이 암호파일을 만들고자 하는 경우에는 -c옵션을 사용합니다.
 

#vi .hthtaccess

AuthType Basic

AuthName "By Invitation Only"

AuthUserFile /usr/local/apache/passwd/passwds

AuthGroupFile /usr/local/apache/passwd/groups

Require group GroupA


이제 GroupA 그룹에 속하면서 passwords 파일에 항목이 있는 사용자가 올바른 암호를 입력하면 접근을 허용한다.

 

그룹파일을 만들지 않고도 다수의 사용자에 대한 접근제어를 할 수 있는방법이 있다.

 

Require valid-user

 

Require user civan 대신 이 지시어를 사용하면 암호파일에 있는 누구라도 올바른 암호를 입력하기만 하면 접근을 허용하게 된다. 그룹별로 다른 암호파일을 사용하여 그룹과 비슷한 효과를 얻을 수 있으며 이 경우 아파치가 파일 두개(암호파일,그룹파일)가 아닌 한개(암호파일)만을 검사하면 된다는 점이 장점이지만 여러 암호파일을 관리해야 한다는 점과 AuthUserFile 지시어에 정확한 암호파일을 지정해야 한다는 점이 단점이다.
 

문서를 요청한 호스트명 또는 호스트 주소로 접근 제어하기

사용자명과 암호를 사용한 인증뿐 아니라 특정한 접속 장소(IP 또는 도메인)에 따라 사용자의 접근권한을 ‘제어하고자 하는 경우도 있는데 이  경우 Allow 와 Deny 그리고 Order 의 3가지의 지시어를 제공한다. Deny와 Allow 지시어는 이름에서도 암시하는 거와 같이 클라이언트의 주소 또는 호스트명를 기반으로 자원으로의 접근을 거부할 것인지 또는 허용할 지의 여부를 결정하는 지시어로, 사용되어 지는 문법은 다음과 같이 간단하다.

Allow from host 또는 Deny from host

 

이 지시어에서의 host 인자로 사용할 수 있는 것은 매우 유동적이며 그 인자로는 다음과 같다.

  • All  :  모든 호스트의 접근을 허용한다. 예)  Allow from all
  • 도메인명: 호스트의 이름과 매칭되거나, 끝나는 위치의 문자열과 같은 접근을 허용  예) Allow from host.example.com
  • 전체 IP 주소 :  IP 주소의 접근을 허용한다. 예) Allow from 205.252.46.165
  • 부분적인 IP 주소 : 서브넷 제한과 같이 IP 주소의 1 에서 3 바이트까지의 접근을 의미한다. 
    예) Allow from 10 173.20 192.168.2
  • 네트워크/넷마스크 (아파치 1.3 이상에서 가능) : 네트웍 a.b.c.d 그리고 넷마스크 w.x.y.z 와 같은 식으로 구성된다.
    예) Allow from 10.1.0.0/255.255.0.0 
  • CIDR 을 이용한 표기
     넷마스크가 1비트로 구성된 것을 제외하고는 위 경우와 유사하다. 예) 10.1.0.0/16 은 10.1.0.0/255.255.0.0 과 같다. 
  • IPv6와 서브넷 명시 - 예) Allow from 2001:db8:a00:20ff:fea7:ccea/10 

<Directory /usr/local/apache/htdocs> 
            Order deny,allow 
            Deny from all 
            Allow from localhost 192.168.23.0/255.255.255.0
</Directory>

만약 Allow, Deny 가 각각 따로 쓰인다면 지시어를 함께 사용하여 자원의 접근을 통제시 충돌이 일어날 수 있다.

아파치에서는 바로 이러한 충돌을 ‘order’ 지시어를 통하여 해결하고 있다. ‘Order’ 지시어는 Allow 와 Deny 지시어가 함께 쓰여졌을 때 어느 지시어가 우선순위를 가지고 먼저 처리가 되어져야 할지를 결정하며, 다음의 두 가지 값 중에 하나가 사용되어 질 수가 있다.

  • Order deny,allow  : Deny 지시어를 먼저  처리한 후 그 다음 Allow 지시어로 이어진다
  • Order allow,deny  : Allow 지시어를 먼저 처리한 후 그 다음 Deny 지시어로 이어진다. 

둘 중에 어느 것을 사용하느냐 하는 것은 여러분이 제한하고자 하는 사람이 적거나 또는 반대로 대부분의 사람을 포함하는 등의 선택에 따라 달라진다. 예를 들어, 만약 모든 사람들의 접근을 허용하면 반면, 특정 도메인에서 불쾌한 메시지를 게시판에 올리는 사람이 있다면 아래와 같은 설정이 가능하다.

 Order Allow , Deny
 Allow from all 
 Deny from evil.victim.com

 

이와 달리, 회사에서의 접속만을 허용하고 다른 외부의 접근은 모두 허용하지 않을 때는 
 

 Order Deny, Allow
 Deny from all 
 Allow from .company.com

 

HTTP 헤더 기반의 고급 접근 제어

앞서 allow 와 deny 지시어는 호스트 또는 IP 주소를 통해서만 제어가 가능했지만, mod_setenvif 의 모듈을 이용하여 클라이언트가 요청한 HTTP 요청의 헤더정보를 환경변수로 설정하여 HTTP 헤더 기반의 고급 접근 제어도 가능하다.

mod_setenvif 는 두개의 지시어를 제공하는데 , BrowserMatch(BrowserMatchNoCase) 와 SetEnvif(SetEnvifNoCase) 이다. 각 지시어의 문법은 아래와 같다 : 

  • BrowserMatch regex variable[=value] 
  • SetEnvif attribute regex variable[=value]

정규 표현식에 따라 attribute 의 값과 일치가 되면 환경변수로 variable 을 설정하게 된다. 우선, BrowserMatch 를 이용하여 브라우저의 종류에 따라 접근제어를 해 보도록 하자. 
 

BrowserMatch ^MSIE InternetExplorer
<Directory /msie_html/> 
            order deny,allow 
            deny from all 
            allow from env=InternetExplorer
</Directory>


이 예제는, 브라우저가 인터넷 익스플로러인 경우에는 ‘InternetExplorer’ 환경변수를 설정하고 deny 지시어로 모든 접근을 거부하고, allow 지시어를 통해 ‘InternetExplorer’ 로 환경 설정된 브라우저의 접속만 허용하고 있다. SetEnvif 를 이용하여 또 다른 예를 들어 보이겠다. 
 

SetEnvIf Referer ^http://www.test.com/links_page.html referral_ok _ok
<Directory /apache_users_only/> 
            order deny,allow 
            deny from all 
            allow from env=referral_ok
</Directory>


앞서 배운 내용들을 기반으로 위 예제는 “어떠한 역할을 하는 것으로 추측되어 지는가?” 잠깐 생각에 잠기어 보기 바란다.

"http://www.test.com/links_page.html" 을 통해 접근을 하게 되면 referral_ok 의 이름으로 환경변수가 설정되어 지고 “apache_users_only” 디렉토리에는 이 링크를 통한 접속만을 허용하게 된다.

이와 같이 여러분의 상상력을 동원하여 다양한 접근방법을 수행할 수 있다.

attribute 에 해당하는 HTTP 요청헤더의 환경변수는 다음을 포함하여 RFC2616(http://www.rfc-editor.org/rfc/rfc2616.txt) 에서 더 많은 정보를 확인하여 볼 수가 있다.

  • CONTENT_TYPE : 내용물의 마임타입 
  • DATE_GMT : 현재 GMT(greenwich, UK) 시간을 표시 
  • DATE_LOCAL : 현재의 시간과/날짜 
  • DOCUMENT_NAME : 요청한 문서의 이름 
  • DOCUMENT_URI : 문서의 URL 
  • LAST_MODIFIED : 문서가 마지막으로 수정된 날짜 
  • HTTP_REFERER : 클라이언트가 어디를 참조하여 들어왔는지를 나타냄 
  • REMOTE_ADDR : 클라이언트의 IP 주소 
  • REMOTE_HOST : 클라이언트의 도메인 이름 
  • REQUEST_METHOD : HTTP 요청 방법: GET 또는 POST 
  • SERVER_NAME : 서버의 호스트네임 (i.e, www.apache.kr.net) 
  • SERVER_PORT : httpd 에 의해 사용되어 지고 있는 포트번호 (일반적으로 80번) 
  • SERVER_PROTOCOL : http 의 버전 
  • SERVER_SOFTWARE : 웹 서버의 소프트웨어 정보 

“WebZip” 과 같은 많은 프로그램들이 홈페이지에 접속하여 내용을 자동으로 클라이언트의 시스템에 저장해 주는 기능을 가지고 있다. 이러한 류의 접근을 통제하기위해서는 어떠한 방법이 가능할까 ?

BrowserMatch "WebZIP" web_spider
BrowserMatch "Teleport" web_spider
BrowserMatch "Teleport Pro/1.29" web_spider
BrowserMatch "NamoWebEditor" web_spider
BrowserMatch "WebSymmetrix" web_spider
<Directory /usr/local/apache/htdocs> 
            Order allow,deny 
            Allow from all 
            Deny from env = web_spider
</Directory>