카페 > 컴퓨터, 너 누구니? / 쵸코바샘님 http://cafe.naver.com/whoiscomputer/24 | |||||||||||||||||||||||||||||||||||||||||||||||||||
|
카페 > 컴퓨터, 너 누구니? / 쵸코바샘님 http://cafe.naver.com/whoiscomputer/24 | |||||||||||||||||||||||||||||||||||||||||||||||||||
|
##### 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 화일을 이미지 폴더나 파일이 들어가 있는 폴더에 넣어주면 그폴더및 하위폴더의이미지나 파일을 무단링크 할수가 없다. 지정해놓은 사이트에서만 링크가 가능하다..(닷) 앞에는 \ 를 꼭 사용해야 한다. | |
덧글 쓰기 | 엮인글 쓰기 | 이 포스트를.. | 수정 | 삭제 |
|
블로그 > 나라사랑하세 http://blog.naver.com/cain2332/40009924489 | ||
[ Home | Freetime works | FreeBSD | KFUG ] 프로그램세계 2002년 8월분웹 캐시 서버 도전하기최준호, Korea FreeBSD Users Group <cjh at kr.FreeBSD.org>이번달에는 가장 많이 사용하는 인터넷의 도구인 웹에 관련된 캐시 서버에 대해서 알아 보자. 일반적으로 웹 서버에 대한 설정이나 관련 내용은 많지만 상대적으로 캐시에 관련된 내용은 적은 편이다. 웹 캐시는 이용도에 따라 다양한 활용이 가능하므로 꼭 한번 살펴보기 바란다.
FreeBSD와 웹 캐시웹 캐시란?인터넷상의 대부분의 트래픽을 차지하는 HTTP 프로토콜은 주로 웹 페이지 또는 파일이라는 객체 단위의 전송을 지원하는 프로토콜이라 생각하면 되며, 접근할 수 있는 각 객체에는 URL이라는 유일한 이름이 붙어 있다(여기에 쿠키나 CGI 인수 등이 추가되기도 한다). 일반적으로는 사용자의 웹 브라우저에서 웹 서버까지 직접 접속하여 URL로 지정된 웹 객체를 전송해 와서 적절한 MIME 타입에 따라 사용자 화면에 표시하는 구조로 되어 있다. 사람들이 많이 몰리는 웹 사이트의 경우 접속이 빈번해지면 웹 서버는 부하를 많이 받게 된다. 웹 서버의 부하를 낮추는 방법에는 여러가지가 있지만, 가장 편리한 방법 중의 하나는 사용자의 웹 브라우저와 웹 서버 사이에 웹 캐시를 중간에 두어 지나가는 내용을 캐싱하도록 하는 것이다. 웹 캐시는 HTTP 프로토콜의 서버와 클라이언트 양방향으로 동작하여 웹 브라우저 입장에서는 웹 서버로, 웹 서버 입장에서는 웹 클라이언트의 형태로 동작하며, 브라우저와 서버 사이의 URL 객체를 조건에 따라 캐시의 저장 공간에 저장하고 이용자의 요청이 웹 서버에게 불필요한 경우 캐시가 직접 처리하도록 되어 있다. 하지만 캐시라는 것은 여러 수준에서 존재할 수 있다. 웹에 관련된 것이라면, 일차적으로 웹 브라우저가 있는 PC에서 메모리와 디스크에 각 객체를 캐싱하고(인터넷 익스플로러나 넷스케이프 네비게이터, 모질라의 경우 각각 메모리와 디스크 캐시에 대한 설정을 찾아볼 수 있다) 있으므로 직접 연결시에도 전혀 캐시가 적용되지 않는 것은 아니다. 웹 캐시의 종류웹 캐시에는 크게 두가지의 용법이 있다.
결국 캐시라는 것은 사용자 - 웹 서버 간의 구간 어디엔가에 놓여서 트래픽을 줄이기 위한 목적으로 사용되는 것이지만, HTTP 프로토콜 자체가 모두 캐시를 통해 지나가는 특성상 이를 응용하여 여러가지 일이 가능하다. 예를 들면 다음과 같다.
캐시 관련 포트웹 캐시에 관련된 포트는 대부분 www 카테고리에 존재한다. 대부분의 포트는 웹 캐시 또는 캐시에 관련된 유틸리티(통계, 캐시 브라우저 등)이다. squid (www/squid)오픈 소스로 된 웹 캐시 중 가장 유명한 것은 squid(www/squid)이다. squid는 원래 Harvest라는 프로젝트의 일부였으나 Harvest 프로젝트가 종료된 뒤에 웹 캐시 부분이 따로 계속 발전하여 현재의 형태에 이르고 있다. squid는 웹 캐시에 필요한 모든 기능을 제공하고 있는 완전한 웹 캐시 소프트웨어이다. 상용 웹 캐시에 비해 성능이 조금 떨어질지는 모르겠지만, 실제 중소규모의 네트워크에서 사용하기에는 조금도 부족함이 없는 수준이다. squid 프로젝트의 홈페이지는 아래 주소이다. Squid Web Proxy Cache: http://www.squid-cache.org현재의 안정 버전은 2.4이이다. 이 글에서는 2.4 버전을 간단히 설정하고 사용하는 방법에 대해 알아 보자. 이 글에서는 주로 프록시 캐시의 사용법에 대해서 알아보겠다. 리버스 캐시의 경우 L4 스위치 등과 같이 이용해야 하는 경우가 많으므로 이 부분에 대해서는 독자에게 맡기겠다. squid의 설치와 설정: 프록시 캐시squid의 설치에 대해서는 별다르게 말할 것이 없다. 기본적으로는 패키지를 설치하거나 www/squid24 포트에서 설치하면 되는데, 포트 설치시 많은 옵션을 줄 수 있으므로 www/squid24/Makefile을 꼭 보기 바란다. 기본적인 캐시 설정을 위해서는 추가로 해 주어야 할 것은 없으므로 잘 모르면 그대로 설치하기 바란다. 설치 후를 보면 대몬의 시작/정지 스크립트는 /usr/local/etc/rc.d/squid.sh 에 설치되어 있다는 것을 알 수 있다. 실제로는 RunCache라는 명령을 부르게 되며, RunCache는 다시 squid라는 프로그램을 대몬 형태로 실행시킨다. 설정 파일은 /usr/local/etc/squid/squid.conf를 설정하면 된다. 이 파일은 매우 크기가 크고 다양한 설정이 가능한데, 여기서는 최소한의 설정에 대해서 알아 보자. 나머지는 squid의 문서 등을 참고해서 스스로 해 보기 바란다. # 캐시 서버의 포트를 지정한다. 보통 프록시 캐시로 쓰는 경우는# 3128번이고, 리버스 캐시로 사용한다면 80번으로 쓰는 경우가 많다.http_port 3128# 캐시용 메모리 크기를 지정한다.cache_mem 8 MB# 캐싱할 수 있는 최대 객체 크기를 정한다.maximum_object_size 4096 KB# 캐시 보관용의 디스크 영역을 지정한다.# 첫번째 인수인 ufs는 디스크 관리 방법(가장 보통인 것)을 나타내며,# aufs, diskd 등의 대체 키워드를 사용할 수 있다.# 두번째 인수는 캐시의 디렉토리이다. 용량이 충분한 디렉토리를# 지정한다.# 세번째 인수는 캐시의 최대 크기를 M바이트 단위로 지정한다.# 1500의 경우 1500M(1.5G) 를 나타낸다.# 네번째 인수와 다섯번째 인수는 캐시 디렉토리의 갯수를 나타내는데,# 캐시 디렉토리 아래 네번째 인수만큼의 디렉토리를 만들고, 그 아래# 다섯번째 인수만큼의 디렉토리를 만든다. 이를 통해 빠르게 캐시# 객체를 찾아갈 수 있다.cache_dir ufs /spool/cache/spool 1500 16 256# 캐시의 접근 로그를 저장한다. webalizer같은 로그 분석 도구로# 분석할 수 있다.cache_access_log /spool/cache/logs/access.log# 캐시에 대한 행동 로그 파일을 지정한다.cache_log none# 캐시 저장에 관련된 로그를 기록한다. 보통은 필요 없다.cache_store_log none# squid는 FTP 캐시도 가능한데, 이 경우 사용자 대신 실제 FTP 서버에# 익명 로그인할 경우의 id를 지정한다. 웹 캐시는 FTP 접속을 대신하는# 경우, 알맞은 인덱스 파일을 생성해 준다.ftp_user Squid@# 접근 제어 목록을 지정한다. 캐시에 아무나 접근할 수 있다면 불필요한# 외부 접속과 트래픽을 발생할 수 있다.# acl 다음은 그룹 이름, 그 다음에 포트, IP 주소 등을 지정할 수 있다.acl all src 0.0.0.0/0.0.0.0acl manager proto cache_objectacl localhost src 127.0.0.1/255.255.255.255acl SSL_ports port 443 563acl Safe_ports port 80 # httpacl Safe_ports port 21 # ftpacl Safe_ports port 443 563 # https, snews# http_access 뒤에는 allow/deny의 동작을 지정하고 acl 에서 지정했던# 그룹을 지정한다.# 아래의 경우 manager 그룹과 localhost 그룹은 접근을 허가,# 다음 행에 의해 localhost 이외의 manager 그룹은 접근이 안되는 것을# 알 수 있다.http_access allow manager localhosthttp_access deny manager# Safe_ports 이외는 거부(!은 not의 의미를 갖는다)http_access deny !Safe_ports# SSL_ports(443, 563 포트)가 아니면 CONNECT 그룹을 허가하지 않는다.# CONNECT 그룹은 acl에서 CONNECT 메소드를 나타낸다.http_access deny CONNECT !SSL_ports# 아래 예는 자신의 네트워크를 정의하고 여기에 대해 접속을 허가하는# 경우이다. 자신의 네트워크는 여기서 192.168.1.0/24 이다.acl myhome src 192.168.1.0/255.255.255.0http_access allow myhome# 가장 끝에는 명시적으로 allow all이나 deny all을 적어주기 바란다.# 아래와 같이 적어주면 위의 allow 규칙에 해당되지 못한 요청은 이 줄에# 의해서 모두 거부된다.http_accessde deny all 대략 설정이 끝났으면 squid를 실행해 보자. 실행하기 전에 해야 할 일은 먼저 캐시 디렉토리를 만드는 일이다. 위에서 cache_dir 에서 지정한 디렉토리를 만들고, squid -z 를 이용해서 캐시 디렉토리 아래의 하부 디렉토리를 생성한다. # mkdir -p /spool/cache/spool# chown -R nobody:nogroup /spool/cache/spool# squid -z 잠시 후에 디렉토리 생성이 종료될 것이다. squid는 nobody 권한으로 실행되기 때문에 (cache_effective_user, cache_effective_group 으로 설정한다) 해당 사용자가 읽고 쓰기 가능하도록 권한을 변경해 주어야 한다. /tmp 처럼 sticky 비트를 지정하는 것도 좋은 생각일 것이다. 다 되었다면 이제 캐시를 실행해 보자. # /usr/local/etc/rc.d/squid.sh start 실행이 잘 되고 있는지는 사용자의 웹 브라우저에서 프록시를 해당 IP와 포트(기본인 경우 3128)번으로 설정하고, 다시 브라우저를 실행한 후 웹 브라우징이 잘 되는지 확인해 보면 된다. IE의 경우, "도구" - "인터넷 옵션" 탭을 선택한 후 "연결" 탭, "LAN 설정(L)..." 을 선택하면 프록시 입력 화면으로 이동할 수 있다. 여기서 "프록시 서버 사용"을 선택하고 서버 IP와 포트 이름을 적어주면 된다. 넷스케이프라면 "편집" - "설정" 메뉴의 "고급" - "프락시" - "프락시 수동 설정" 탭을 이용하면 된다.
그러면 이후의 HTTP 접속은(FTP나 Gopher도 프록시 캐시를 이용할 수 있다) 모두 지금 설정한 캐시를 통하게 된다. 정상적으로 웹 브라우징이 되는 경우라면 잘 되는지의 여부를 확인할 수 있다. 만약 이 방법으로 연결이 잘 안되거나, proxy가 어떤 오류 메시지를 내보낸다면(squid가 아예 제대로 떠 있지 않은 경우를 제외한다면 오류 메시지는 브라우저에 표시된다) 이를 보고 적절히 대처해 주면 된다. 대부분이 경우 squid.conf의 설정 변경으로 해결할 수 있다. 다음 사이트를 사용하면 캐시의 사용 여부와 캐시가 외부에서 이용 가능한지를 점검할 수 있다. 만약 외부에서 접근이 가능하다고 나오는 경우 일부러 열어둔 것이 아니라면 squid.conf의 acl 부분을 다시 보고 한정된 범위만 프록시 연결을 허가하기 바란다. 가장 아래쪽의 "Environment Variable Check"를 선택하고 "Show Proxy related Variable"을 선택하면 HTTP_VIA 헤더에 현재 사용하고 있는 캐시의 IP와 포트 번호가 나온다. 만약 자신이 사용하고 있지 않은 프록시가 출력되는 경우 대부분 ISP에서 직접 설치해 놓은 캐시인지 의심해 볼 필요가 있다. 대형 ISP의 경우 HTTP 접속을 줄이기 위해 라우터 수준에서 투명 프록시를 설치해 둔 경우가 많다. Proxy Checker: http://cache.jp.apan.net/proxy-checker/FreeBSD에서는 HTTP_PROXY와 FTP_PROXY 환경 변수를 사용해서 fetch, lynx 등의 명령이 프록시를 거치도록 할 수 있다. 방화벽 내에 있는 환경이라든가 프록시를 써야 하는 환경이라면 포트 등의 설치에서 이 변수를 지정하도록 할 수 있다. ports의 경우 많이 쓴다면 make.conf 에서 지정해 두자. FETCH_ENV= HTTP_PROXY=http://192.168.1.1:3128 squid의 관리squid는 -k 옵션을 통해 여러가지 관리 명령을 실행할 수 있으므로 대몬 관리에 조금 도움이 될 것이다. squid -k reconfigure|rotate|shutdown|interrupt|kill|debug|check|parse 특히 reconfigure, shutdown, kill 등은 웹 캐시 프로세스를 빠르게 제어할 수 있다. 설정이 변경된 경우 reconfigure를, 서버를 중지시키고 싶은 경우 shutdown이나 kill(kill이 더 강제적이다)을 사용하기 바란다. squid의 경우 프로세스가 비정상적으로 종료되어도 다시 시작하기 때문에 프로세스를 직접 kill로 정지시키는 일이 잘 안되는 경우가 많다. # squid -k reconfigure squid의 설치와 설정: 투명 캐시프록시 캐시는 설치가 간단하고 이용이 비교적 쉽다는 점이 있지만, 대상이 되는 네트워크에 많은 수의 클라이언트 PC가 있다면 일일이 환경 설정을 열어서 프록시 캐시를 지정해 주기는 어려운 점이 많다. 이러한 경우 방화벽을 사용하고 있다면 투명 캐시라는 기능을 사용하면 사이트 전체의 전역 설정으로 바꿀 수 있다. 투명 캐시는 웹 서버로 가는 패킷의 흐름을 강제적으로 캐시로 돌려주고, 캐시가 대신 웹 서버에 접속하도록 한다. 이번 경우는 다음 네트워크를 예로 들도록 하자. 지금은 ipfw를 사용하는 예를 들지만, 대부분의 패킷 필터 방화벽은 비슷한 설정을 제공한다. 점검이 끝났으면 squid를 다시 시작해 두자. 그 다음은 방화벽인데, 보통은 NAT를 사용하는 경우 다음과 같이 방화벽이 설정되어 있을 것이다. 조금 다른 주제로 오프라인 캐시에 대해서 다루어 보자. 최근의 브라우저는 오프라인 기능이 있어서 인터넷 접속이 안되는 경우에도 이미 캐시에 존재하는 페이지만으로 브라우징이 가능한 기능을 제공하지만, 이를 캐시 수준에서 할 수 있지 않을까? 하는 생각으로 만들어진 것이 wwwoffle 등의 오프라인 캐시이다. 이러한 캐시는 프록시 캐시의 형태로 동작하며, 최대한 캐싱하고 있다가 원래 사이트에 접근이 안되는 경우에도 사용자가 잘 모를 정도로 캐싱하고 있는 데이터를 전송해 준다. 이러한 캐시는 모뎀 등의 저속 환경 사용자, 빈번이 끊어지는 네트워크 환경을 이용하고 있는 사용자에게 매우 유용하다. 가정에서 인터넷 환경을 사용하는 경우라면 조금 무거운 squid보다는 이러한 캐시가 더 유용할 지도 모른다. 대신 wwwoffle는 리버스 캐시 등의 다양한 기능은 이용할 수 없다. wwwoffle는 www/wwwoffle 포트를 설치하면 된다. 설치 후에는 설정 파일을 만들기 위해 다음과 같이 템플릿에서 한부 복사해 오면 된다. wwwoffle.conf의 설정은 squid보다 더 친절하게 설명되어 있는 관계로 쉽게 설정할 수 있을 것이다. 가장 기본적인 것은 StartUp 부분이다. wwwoffle 대몬을 실행한 후(/usr/local/etc/rc.d/wwwoffle.sh), 이 대몬의 제어는 squid -k와 비슷하게 wwwoffle 프로그램을 사용하면 된다. squid에 없는 재미있는 설정은 온/오프라인 설정이다. 프록시 서버를 온라인 모드로 한다. 모든 웹사이트에 직접 접근 가능한 경우이다. 모뎀이나 ISDN 등의 사용자의 경우 필요하면 외부에 접속하지만 네트워크 연결 없이 캐시에서 바로 돌려줄 수 있다면 그렇게 한다. 외부와 접속이 끊어진 경우, 오프라인 모드로 동작한다. -online이나 -offline의 경우 모뎀 등의 ppp의 시동/종료 스크립트에 넣어두면 편리하다. 현재 캐싱된 요청을 모두 다시 읽어들인다. 그외 설정을 다시 읽으려면 -config, 캐시를 비우려면 -purge, 대몬을 정지시키려면 -kill 옵션을 사용한다. 아마 이정도로도 충분히 재미있게 사용할 수 있을 것이다. 또한 특정 URL을 지정하여 읽어들여 두는 옵션도 가능하다(-O URL). 그외 wwwoffle은 목적에 따라 HTML을 그대로가 아니라 약간 변형하여 캐시에 저장할 수 있는(animated gif를 정지 이미지로 바꾸거나 스크립트 실행을 금지시키는 등) 기능을 제공하므로 설정 파일을 읽어보고 따라해 보도록 하자. 단 이러한 대몬의 단점은 캐싱 기능에 초점을 맞춘 것이므로 조금은 오래된 데이터를 바로 돌려줄 수 있다는 것이 단점이다. 브라우저의 다시 읽기 단추를 사용하거나 항상 online 모드로 두도록 하자. 그 외 캐시 서버로 동작하는 것은 광고 제거 서버인 www/junkbuster, www/adzapper 등을 들 수 있다. 이러한 프록시는 웹 페이지 내의 광고 이미지를 빈 이미지로 돌려 주거나 아예 돌려주지 않는다. 이렇게 하면 광고가 많은 사이트의 접속을 빠르게 할 수 있다. dansguardian (www/dansguardian) 도 비슷한 역할을 할 수 있지만 이는 squid와 같이 사용한다. 이외 oops, tinyproxy 등 프록시 역할을 할 수 있는 다양한 프로그램들이 있다. 이번 기사에서 다루지 않은 내용 중 더 배워 볼 만한 주제는 다음과 같다. 이후에 웹 캐시 서버를 관리하게 된다면 꼭 한번씩 해 보자. 이번 기사에서는 웹 캐시의 다양한 활용 방법에 대해 알아보았는데, 집이나 사무실이라면 광고 제거 서버 등은 한번 사용해 보면 편할 것이다. 물론 윈도 등에 설치하는 광고 제거용 프록시(이것도 결국 프록시 캐시로 동작하는 프로그램이다)들도 많이 있지만, 사이트 전체에 적용해 보는 것도 재미있을 것이다. |
블로그 > seafig님의 블로그 http://blog.naver.com/seafig/60005184191 | |
아파치에서 전송 속도 제한하기 (모든 설명은 레드햇 6.0을 기준으로 합니다.) 1. 아파치 1.3.x용 bandwidth 모듈이 필요합니다. ftp://ftp.cohprog.com/pub/apache/module/1.3.0/mod_bandwidth.c를 받아 오시면 됩니다. 레드햇 6.0 이상을 기반으로 한 배포판에는 이 모듈이 포함되어 있습니다. /usr/lib/apache/mod_bandwidth.so가 이미 존제하는 분은 컴파일 과정을 생략하시면 됩니다. 참고: 레드햇에 포함된 버젼은 1.2 버젼입니다. 최신 버젼은 2.0 버젼이며 다음의 설명들에 1.2 버젼에는 없는 기능의 경우에는 *로 마크를 하겠습니다. 2. 아파치 모듈로의 컴파일이 필요합니다. o 아파치 소스와 같이 컴파일 하려면 아파치 소스의 src/modules/extra/ 디렉토리로 mod_bandwidth.c를 복사한 후에 ./configure시에 --add-module=mod_bandwidth.c 옵션을 주시면 됩니다. o 직접 컴파일 하려면 다음의 명령을 따라하시면 됩니다. 물론 그러기 위해서는 아파치의 개발용 헤더들이 시스템에 설치되어 있어야 합니다. 레드햇의 경우 apache-devel이라는 패키지로 존재합니다. 그 위치는 /usr/include/apache/에 있습니다. (배포판에 따라 틀릴 수 있습니다.) $ gcc -c -I/usr/include/apache -O2 -m486 -fno-strength-reduce mod_bandwidth.c -fpic -DSHARED_MODULE mod_bandwidth.c $ gcc -shared -o mod_bandwidth.so mod_bandwidth.o $는 쉘 프롬프트를 나타내며 는 줄이 이어진다는 뜻입니다. 그러니까 한 줄로 붙여 쓰시기 바랍니다. 3. 컴파일된 모듈을 아파치 모듈이 위치하는 디렉토리로 옮기시기 바랍니다. 레드햇의 경우 /usr/lib/apache/에 위치합니다. 직접 컴파일하셨다면 지정한 것에 따라 틀릴 수 있습니다. 알아서 하시기 바랍니다. :) 4. 아파치의 설정 파일을 고쳐야 할 것입니다. 그럼 하나씩 고치는 방법에 대해서 알아 보겠습니다. 1. 모듈로 컴파일 했기 때문에 모듈을 읽도록 해야 합니다. httpd.conf에서 LoadModule foobar_modules modules/mod_foobar.so 같은 내용이 있는 부분이 있습니다. 그 하단부에 다음 줄을 추가 하십시오. LoadModule bandwidth_module modules/mod_bandwidth.so 마지막은 모듈의 위치입니다. 설치한 것에 따라 설정하십시오. httpd.conf 설정에 ClearModuleList가 있다면 다음 줄이 추가되어야 합니다. AddModule mod_bandwidth.c 비슷한 내용이 있는 부분의 아래에 적으시면 될 것입니다. :) 2. 이제 전송 속도 제한 기능을 하는 모듈을 사용하겠다는 것을 지정해 주어야 합니다. 디렉토리별 설정 위에 다음 줄을 추가하시면 됩니다. BandWidthModule On 3. 이 모듈이 사용하기 위해서는 데이타를 기록할 장소가 필요합니다. 기본값으로 /tmp/apachebw 디렉토리를 사용합니다. /tmp/apachebw/link /tmp/apachebw/master 이렇게 디렉토리를 생성해 주시십시오. 퍼미션은 nobody 사용자가 쓸 수 있는 권한이 있어야 합니다. (여기서 nobody는 아파치가 사용하는 사용자입니다. 다른 사용자를 사용한다면 그 사용자의 권한으로 줘야 겠지요.) 생각하기 싫으신 분은 다음 명령을 실행하십시오. chown root.nobody /tmp/apachebw chmod -R 770 /tmp/apachebw/ 4. 이제 실제적인 전송 속도 제한의 옵션을 알아 보겠습니다. BandWidth, LargeFileLimit, MinBandWidth 이렇게 세가지의 지시자?가 있습니다. 각각에 대해서 알아 봅시다. o BandWidth 문 법: BandWidth <도메인|IP주소|all> <속도> 기본값: 없음 사용처: 전체 설정, 디렉토리별 설정, .htaccess 호스트에 따라 속도의 제한을 걸 수 있습니다. all은 모든 호스트에 대해서 제한을 거는 것입니다. 도메인이나 IP주소로 접속 호스트를 지정할 수 있습니다. 그리고 네트워크/마스크 포맷*으로 지정할 수도 있습니다. (예: 192.168.0.0/24) 속도는 Bytes/second로 나타냅니다. 0의 경우는 제한이 없는 것입니다. 디렉토리별 설정에서 사용한 예를 들겠습니다. BandWidth 192.168.1 0 BandWidth foobar.net 0 BandWidth all 1024 /home/httpd/html 디렉토리에서의 제한을 한 것입니다. 192.168.1.* IP 주소를 가진 호스트와 *.foobar.net이라는 도메인명을 사용하는 호스트에 대해서는 제한을 걸지 않으며 그 외 모든 접속에 대해서 1024Bytes/sec으로 제한을 걸었습니다. o LargeFileLimit 문 법: LargeFileLimit <파일크기> <속도> 기본값: 없음 사용처: 전체 설정, 디렉토리별 설정, .htaccess 일정 이상의 크기를 가진 파일을 누군가가 받아 가려 할 때 그 속도의 제한을 걸 수 있습니다. 파일크기는 KByte 기준이며 속도는 역시 Bytes/secound입니다. LargeFileLimit 1024 4096 LargeFileLimit 2048 2048 위 예제는 1024 ~ 2047KB 크기의 파일을 받아가려 할 때 속도를 4KB/sec으로 제한하고 2048KB 이상의 파일은 2KB/sec으로 제한을 하는 것입니다. o MinBandWidth 문 법: MinBandWidth <도메인|IP주소|all> <속도> 기본값: all, 256 사용처: 전체 설정, 디렉토리별 설정, .htaccess 데이타 전송의 최저 속도를 지정하게 됩니다. 예를 들어서 설명하는 것이 가장 좋을 것 같군요. BandWidth를 4096 (4KBytes/sec)으로 지정하고 MinBandWidth가 1024로 지정이 되어 있을 때: - 지정된 호스트에서 하나만 접속할 경우, 4096bytes/sec이 최고의 속도가 됩니다. - 지정된 호스트에서 두개가 동시에 접속할 경우, 각각의 세션에 대해 2048Bytes/sec이 최고의 속도가 됩니다. - 더 많은 동시 접속이 일어나도 세션 당 최고 속도는 1024Bytes/sec 이하로는 줄지 않습니다. (MinBandWidth 값이 1024기 때문에) MinBandWidth가 "-1"로 지정되면 모든 세션에 대해 최고 속도는 BandWidth나 LageFileLimit에서 지정한 속도가 나올 수 있게 됩니다. BandWidth를 4096으로 지정하고 MinBandWidth가 -1이라면 동시에 지정된 호스트에서 몇개의 접속을 하더라도 각 세션의 속도는 4096Bytes/sec 까지 나오게 되는 것입니다. 출처: 적수네 |
0