//==============================================================================
//SSL 설정 START
//==============================================================================
//==============================================================================
//일자 : 2007.09.18//
//소속 : (주)수퍼유저코리아 이재석
//SSL 페이지적용을 간단하게 하기위한 스크립트
//
// 사용법
//// function ssl_page(); 수정으로 다른 페이지 추가 가능
//
// switch 구문에 아래의 구문 추가로 ssl 적용페이지 확장
// case '파일명'
// $check = '1';
// break;
//
// 주의 회원가입 같이 연관 페이지가 많을 경우 연관페이지도 ssl적용을 안할경우 자바스크립트 에러 발생 가능
//
//==============================================================================
function ssl_page(){
$tmp = explode("/",$_SERVER["SCRIPT_FILENAME"]);
$tmp_count = count($tmp);
$tmp_count--;
$str = $tmp[$tmp_count];
switch($str){
case 'register.php'://실명인증(인터페이스)
$check = '1';
break;
case 'register_form.php'://회원 가입폼 및 수정폼(인터페이스)
$check = '1';
break;
case 'register_form_update.php'://회원정보 수정 및 입력 (프로세스)
$check = '1';
break;
case 'register_result.php'://회원 가입폼완료 (인터페이스)
$check = '1';
break;
case 'member_confirm.php': //회원 정보수정시 패스워드 입력(인터페이스)
$check = '1';
break;
case 'zip.php': //우편번호 찾기
$check = '1';
break;
case 'member_id_check.php': //아이디 중복 체크
$check = '1';
break;
case 'login_check.php': //로그인 처리
$check = '1';
break;
default :
$check ='2';
}
return $check;
}
function ssl_http($check){
$port = $_SERVER[SERVER_PORT];
if($check == "1"){
if($port != "443") header("Location: https://".$_SERVER["HTTP_HOST"].$_SERVER["PHP_SELF"]."?".$_SERVER["QUERY_STRING"]);
}
if($check == "2"){
if($port != "80") header("Location: http://".$_SERVER["HTTP_HOST"].$_SERVER["PHP_SELF"]."?".$_SERVER["QUERY_STRING"]);
}
}
$check = ssl_page();
ssl_http($check);
//SSL 설정 END
?>
2008. 6. 2.
TCP SYN_Flooding 공격의 원인과 해결책
TCP SYN_Flooding 공격의 원인과 해결책
오늘과 내일 넷센터 홍석범(antihong@tt.co.kr)
최근 자신이 운영하는 서버에 특별히 부하가 걸리거나 이상이 있는 것도 아니고
또 데몬도 정상적으로 떠 있는데, 정작 서비스가 작동하지 않는 경우가 종종 있다.
이러한 경우에는 해당 데몬을 완전히 멈추었다가 살리면 다시 작동하는데,
잠시 후에 확인해 보면 똑같은 현상이 다시 나타나곤 한다.
혹시 프로그램을 잘못 설치했나 싶어 지우고 다시 설치해도 마찬가지이다.
만약 최근 들어 이러한 경험이 있다면 이는 최근 유행하는 DoS(서비스 거부 공격)의 일종인
TCP SYN Flooding 공격을 당했을 가능성이 크다.
SYN Flooding 공격의 개념이 소개된지는 꽤 되었지만 최근 들어 리눅스가 확산되고, 간단하게 실행할 수 있는 공격 소스가 광범위하게 배포되면서 이 공격이 자주 확인되고 있고, 이로 인해 그 피해가 급속히 확산되고 있다. 실제로 현재 가장 많이 사용되고 있는 배포판인 레드햇 6.X 계열에 이 공격을 실행하기만 하면 단 몇 초만에 서비스가 정지해 버리게 된다.
따라서 피해가 확산되고 있는 이 공격의 원리와 대처방법에 대해 알아보도록 하자.
“TCP 의 약점을 이용한 공격원리”
SYN Flooding 공격은 TCP 의 취약점을 이용한 공격의 형태이므로 먼저 TCP 에 대해
알아야 한다. TCP 는 Transmition Control Protocol 의 약자로 UDP와는 달리 신뢰성 있는 연결을 담당한다. 따라서 서버와 클라이언트간에 본격적인 통신이 이루어지기 전에는
다음 그림과 같이 소위 "3 Way handshaking" 이라는 정해진 규칙이 사전에 선행되어야 한다.
1단계. A 클라이언트는 B 서버에 접속을 요청하는 SYN 패킷을 보낸다.
2단계. B 서버는 요청을 받고 A 클라이언트에게 요청을 수락한다는 SYN 패킷과
ACK 패킷을 발송한다.
3단계. A 클라이언트는 B 서버에게 ACK 를 보내고 이후로부터 연결이 이루어지고
본격적으로 데이터가 교환된다.
이것이 TCP 의 기본적인 Flow 이다.
그런데, 이 그림에서 악의적인 공격자가 1단계만 요청(SYN)하고 B서버로부터 응답을 받은 후(SYN+ACK) 3단계, 즉 클라이언트에게 ACK를 보내지 않는다면 어떻게 될까?
SYN+ACK 패킷을 받은 B 호스트는 A 로부터 응답이 올 것을 기대하고 반쯤 열린
이 른바 “Half Open” 상태가 되어 대기 상태에 머무른 후 일정 시간(75초) 후에 다음 요청이 오지 않으면 해당 연결을 초기화 하게 되는데, 초기화하기 전까지 이 연결은 메모리 공간인 백로그큐(Backlog Queue)에 계속 쌓이게 된다.
그런데, 이 위조된 연결 시도를 초기화하기 전에 위조된 새로운 요구가 계속 들어오게 된다면 또한 위조된 새로운 요구가 연결을 초기화하는 속도보다 더 빨리 이루어진다면 어떻게 될까? 이러한 경우 SYN 패킷이 어느 정도 백로그큐에 저장이 되다 결국 꽉차게 되어 더 이상의 연결을 받아들일 수 없는 상태, 즉 서비스 거부 상태로 들어가게 되는 것이다. 이처럼 백로그큐가 가득 찼을 경우에 공격을 당한 해당 포트로만 접속이 이루어지지 않을 뿐 다른 포트에는 영향을 주지 않고, 또한 서버에 별다른 부하도 유발하지 않으므로 관리자가 잘 모르는 경우가 많다. 또한 다른 DoS 공격과는 달리 많은 트래픽을 유발하는 공격이 아니므로 쉽게 파악이 되지 않는 공격 형태이다.
그렇다면 이 공격을 당하고 있는지 여부는 어떻게 알 수 있을까?
시스템에 로긴후 "netstat" 이라는 명령으로 확인 가능하다.
“그럼, 어떻게 파악하는가?”
netstat 은 시스템의 각종 네트워크 정보를 알려주는 명령어로 네트워크 연결, 라우팅 현황, 인터페이스 통계등의 정보를 확인할 수 있게 해 준다. 여기서 잠깐 netstat 으로 나오는 연결 상태에 대해 알아보자.
netstat -na 로 확인해 보면 Local Address, Foreign Address, State 등의 정보가 출력되는데,
이 중 State 부분에 보이는 메시지를 주목하면 된다.
### 참고 : State 부분에 가능한 연결상태 ###################################
LISTEN : 서버의 데몬이 떠서 접속 요청을 기다리는 상태
SYS-SENT : 로컬의 클라이언트 어플리케이션이 원격 호스트에 연결을 요청한 상태
SYN_RECEIVED : 서버가 원격 클라이언트로부터 접속 요구를 받아 클라이언트에게
응답을 하였지만 아직 클라이언트에게 확인 메시지는 받지 않은 상태
ESTABLISHED : 3 Way-Handshaking 이 완료된 후 서로 연결된 상태
FIN-WAIT1 , CLOSE-WAIT , FIN-WAIT2 :
서버에서 연결을 종료하기 위해 클라이언트에게 종결을 요청하고
회신을 받아 종료하는 과정의 상태
CLOSING : 흔하지 않지만 주로 확인 메시지가 전송도중 분실된 상태
TIME-WAIT : 연결은 종료되었지만 분실되었을지 모를 느린 세그먼트를 위해
당분간 소켓을 열어놓은 상태
CLOSED : 완전히 종료
################################################################################
각각의 연결 상태는 통신 상황에 따라 매우 복잡하게 순간적으로 변화하는데,
이 중 주로 주목하여야 할 상태는 SYN_RECEIVED 이다. 설명에 나온 대로 이 상태는
클라이언트의 확인 메시지를 기다리는 상태이지만 특별히 전용 회선에 장애가 없는 한 이 과정은 순간적으로 일어나므로 실제 netstat 으로 확인되는 경우는 거의 없다.
따라서 netstat -na|grep SYN_RECV 로 확인해 보아 많은 메시지가 보인다면
Syn Flooding 공격을 당하고 있는 것으로 판단하면 된다.
“실제 테스트 공격으로 직접 확인해 보자!!”
실제 자신의 시스템이 얼마나 취약한지 자신의 시스템에 테스트해 보도록 하자.
노파심에 이야기하는 것이지만 이 공격은 반드시 자신의 시스템에서만 테스트 용도로 실행해 보기 바란다. 이 공격 소스는 인터넷상에서 쉽게 찾을 수 있다.
http://packetstorm.securify.com/ 나 http://rootshell.com/ 에 접속후 syn 으로 검색해 보면 많은 소스와 문서가 있는데, 이중 관련 파일을 다운로드받아 설치해 보면 된다.
소스에 따라 실행 방법이 다르지만 다운로드 받은 소스파일이 syn_floodinbg_dos.c 라면 gcc ?o syn_flooding_dos syn_flooding_dos.c 로 컴파일을 한다. 이후
"./syn_flooding_dos 소IP 공격지IP 공격할하위포트번호 상위포트번호" 와 같이 실행하면 되는데, 필자는 ./syn_flodding_dos 0 localhost 80 80 과 같이 테스트해 보았다.
위 명령어의 의미는 공격지 주소를 랜덤하게 무작위 IP주소로 설정(0) 하여 localhost 서버의 80 번 포트에 Syn_Flooding 공격을 한다는 내용이다.
실제 본인이 테스트한 레드햇 6.2 서버에서는 공격후 2-3초만에 웹서비스가 중지되었다.
테스트 공격 후 telnet localhost 80 으로 접속해 보기 바란다.
분명히 httpd 데몬은 떠 있는데, 접속이 되지 않을 것이다.
아래는 공격을 당한 서버에서 netstat -na|grep SYN 으로 SYN 패킷을 잡은 부분이다.
분 명히 localhost 에서 공격을 했음에도 위 그림에서처럼 80번 포트로 SYN 패킷을 요청한 IP주소는 랜덤하게 보이고 있어 도무지 어떤 IP 에서 공격하고 있는 것인지 알 수 없다. 실제로 공격지 IP 를 확인해 보면 대부분이 현재 인터넷상에 연결되지 않은 존재하지 않는 위조된 IP들이다.
실제 공격 소스 코드중 소스 IP를 생성하는 부분을 보면 아래와 같이 0부터 255까지
임의의 값을 뽑아 IP 주소로 설정하는 것을 확인할 수 있다.
{
a = getrandom(0, 255);
b = getrandom(0, 255);
c = getrandom(0, 255);
d = getrandom(0, 255);
sprintf(junk, "%i.%i.%i.%i", a, b, c, d);
me_fake = getaddr(junk);
}
SYN_Flooding 공격에 대한 대비 및 해결책
그렇다면 이 공격에 대해 어떻게 대비하여야 할까?
1. 백로그 큐를 늘려준다.
직관적으로 보았을 때 서비스 거부에 돌입하게 되는 것은 백로그큐(Backlog Queue)가 가득
차 서 다른 접속 요구를 받아들이지 못하기 때문이므로 백로그 큐의 크기를 늘려주면 될 것이다. 실제로 리눅스를 포함해서 많은 운영체제들의 백로그큐값을 조사해 보면 이 값이 필요 이상으로 작게 설정되어 있어 적절히 늘려주는 것이 좋다.
현재 시스템에 설정된 백로그큐의 크기는
[root@net /root]# sysctl -a|grep syn_backlog
net.ipv4.tcp_max_syn_backlog = 128
또는
[root@net /root]# cat /proc/sys/net/ipv4/tcp_max_syn_backlog
128
로 확인가능하며 128kb 인 것을 확인할 수 있다.
일 반적으로 시스템의 RAM 이 128M 일 경우에는 128 을 설정하고 그 이상일 경우에는 1024 정도로 설정해 주는 것이 좋다. 이 때 주의할 점은 이 값을 무작정 크게 설정한다고 좋은 것은 아니며 1024 이상으로 설정할 경우는 /usr/src/linux/include/net/tcp.h 소스에서 TCP_SYNQ_SIZE 변수를 수정 후 커널을 재컴파일하여야 한다. 이 변수를 설정시 TCP_SYNQ_HSIZE에 16을 곱한 값이 tcp_max_syn_backlog 보다는 작거나 같아야 하는데, 그렇지 않을 경우에는 시스템에 문제가 발생할 수 있으니 1024 보다 높은 값으로 설정하지 말기 바란다. 그리고 이 값을 너무 크게 설정하였을 경우에는 경험적으로 아래 설명할 syncookies 기능이 잘 적용되지 않는 현상이 가끔 확인되었다.
이와는 별개로 시스템의 부하가 많이 걸릴 경우에도 백로그큐를 늘려주면 일정 정도의 효과를 볼 수 있는 것으로 알려져 있다.
백로그큐의 값을 설정하는 방법은 다음과 같다.
[root@net /root]# sysctl -w net.ipv4.tcp_max_syn_backlog=1024
또는
[root@net /root]# echo 1024 > /proc/sys/net/ipv4/tcp_max_syn_backlog
로 해도 된다.
그러나 이 방법은 임시적인 대책일 뿐, 지속적으로 많은 TCP SYN Flooding 공격을 당할 때는 결국 백로크큐가 가득 차게 되므로 근본적인 해결 방안은 아니다.
2. syncookies 기능을 켠다.
Syncookies (“신쿠키” 라고 발음한다.) 는 "Three-way handshake" 진행 과정을 다소 변경하는 것으로 Alex Yuriev 와 Avi Freedman 에 의해 제안되었는데, TCP header 의 특정한 부분을 뽑아내어 암호화 알고리즘을 이용하는 방식으로 Three-way Handshake 가 성공적으로 이루어지지 않으면 더 이상 소스 경로를 거슬러 올라가지 않는다. 따라서 적절한 연결 요청에 대해서만 연결을 맺기 위해 리소스를 소비하게 되는 것이다.
syncookies 기능은 TCP_Syn_Flooding 공격을 차단하기 위한 가장 확실한 방법으로 이 기능을 이용하려면 일단 커널 컴파일 옵션에서 CONFIG_SYN_COOKIES이 Y 로 선택되어 있어야 한다.
자신의 커널 옵션에 이 기능이 설정되어 있는지 확인하려면
/usr/src/linux 디렉토리로 이동후 make menuconfig 후
Networking options --->
[*] IP: TCP syncookie support (disabled per default)
와 같이 확인하면 된다.
만약 설정이 되어 있지 않다면 선택 후 커널 컴파일을 다시 하여야 하지만 대부분 배포판은 기본적으로 이 옵션이 선택되어 있으므로 걱정할 필요는 없다.
그러나 위와 같이 커널 옵션에 설정되어 있다 하더라도 실제 syncookies 적용은 꺼져 있으므로 이 값을 다음과 같은 방법으로 활성화해야 한다.
[root@control src]# sysctl -a|grep syncookie
net.ipv4.tcp_syncookies = 0
0 으로 설정되어 있으므로 현재 syncookies는 적용되지 않는다.
따라서 아래와 같이 1을 설정하여 syncookies 기능을 활성화하도록 한다.
[root@control src]# sysctl -w net.ipv4.tcp_syncookies=1
syncookies는 백로그큐가 가득 찼을 경우에도 정상적인 접속 요구를 계속 받아들일 수 있도록 해 주므로 SYN_Flooding 공격에 대비한 가장 효과적인 방법중 하나이다.
만약 공격을 당해 syncookies 가 작동할 때에는 /var/log/messages 파일에 아래와 같이 SynFlooding 공격이 진행중이라는 메시지가 출력된다.
Jun 11 18:54:08 net kernel: possible SYN flooding on port 80. Sending cookies.
SYN_Flooding 공격이 지속적으로 매우 심하게 진행중일 때에는 syncookies 기능이 작동한다 하더라도 네트워크가 다운되는 현상이 가끔 확인되었다. 따라서 syncookies 기능 외에 몇 가지 설정도 함께 적용하는 것이 시스템의 안정성을 위해 권장하는 방법이다. 아울러 네트워크가 다운되었을 경우에는 /etc/rc.d/init.d/network restart 로 network 를 재설정해 보거나 reboot 를 하여야 한다.
3. 기타 시스템의 네트워크 설정을 최적화한다.
아래 설정은 비단 TCP Syn_Flooding 공격뿐만이 아니라 다른 여타 DoS 공격에도 효과적이으로 방어하므로 적절히 설정할 것을 권장한다.
sysctl -w net.ipv4.icmp_destunreach_rate=1
# 1/100초 동안 받아들일 수 있는 "dest unreach (type 3) icmp" 의 개수
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
# Broadcast 로부터 오는 ping 을 차단함. (Smurf 공격을 차단함)
sysctl -w net.ipv4.icmp_echoreply_rate=1
# 1/100초에 반응하는 ping 의 최대 숫자
sysctl -w net.ipv4.icmp_echo_ignore_all=1
#모든 ping 을 차단함
sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1
# IP 나 TCP 헤더가 깨진 bad icmp packet을 무시한다.
sysctl -w net.ipv4.icmp_paramprob_rate=1
# 1/100 초에 받아들이는 param probe packets의 수
sysctl -w net.ipv4.icmp_timeexceed_rate=1
# 1/100 초에 받아들이는 timeexceed 패킷의 수(traceroute 와 관련)
sysctl -w net.ipv4.igmp_max_memberships=1
# 1/100 초에 받아들이는 igmp "memberships" 의 수
sysctl -w net.ipv4.ip_always_defrag=0
# 항상 패킷 조각 모음을 하지 않는다.
sysctl -w net.ipv4.ip_default_ttl=64
# 매우 복잡한 사이트에서는 이 값을 늘리는 것도 가능하지만
# 64로 두는 것이 적당하며 더 늘렸을 경우에는 큰 문제가 발생할 수도 있다.
sysctl -w net.ipv4.ip_forward=0
# 게이트웨이 서버가 아닌 이상 패킷을 포워딩 할 필요는 없다.
sysctl -w net.ipv4.ipfrag_time=15
# fragmented packet이 메모리에 존재하는 시간을 15초로 설정한다.
sysctl -w net.ipv4.tcp_syn_retries=3
# 일정한 시간과 IP 별로 보내고 받는 SYN 재시도 횟수를 3회로 제한한다.
# 이 옵션은 스푸핑된(위조된) 주소로 오는 SYN 연결의 양을 줄여준다.
# 기본값은 5이며 255를 넘지 않아야 한다.
sysctl -w net.ipv4.tcp_retries1=3
# 무언가 문제가 있을 때 연결을 위해 재시도 할 횟수. 최소값과 기본값은 3이다.
sysctl -w net.ipv4.tcp_retries2=7
# TCP 연결을 끊기 전에 재시도할 횟수.
sysctl -w net.ipv4.conf.eth0.rp_filter=2
sysctl -w net.ipv4.conf.lo.rp_filter=2
susctl -w net.ipv4.conf.default.rp_filter=2
sysctl -w net.ipv4.conf.all.rp_filter=2
# 이 설정은 자신의 네트워크가 스푸핑된 공격지의 소스로 쓰이는 것을 차단한다.
# 모든 인터페이스에서 들어오는 패킷에 대해 reply를 하여 들어오는 인터페이스로 나가지
# 못하는 패킷을 거부한다.
sysctl -w net.ipv4.conf.eth0.accept_redirects=0
sysctl -w net.ipv4.conf.lo.accept_redirects=0
sysctl -w net.ipv4.conf.default.accept_redirects=0
sysctl -w net.ipv4.conf.all.accept_redirects=0
# icmp redirects 를 허용하지 않는다.
# 만약 ICMP Redirect 를 허용할 경우에는 공격자가 임의의 라우팅 테이블을 변경할 수
# 있게 되어 자신이 의도하지 않는 경로, 즉 공격자가 의도한 경로로 트래픽이 전달될 수
# 있는 위험이 있다.
sysctl -w net.ipv4.conf.eth0.accept_source_route=0
sysctl -w net.ipv4.conf.lo.accept_source_route=0
sysctl -w net.ipv4.conf.default.accept_source_route=0
sysctl -w net.ipv4.conf.all.accept_source_route=0
# 스푸핑을 막기 위해 source route 패킷을 허용하지 않는다.
# 소스 라우팅을 허용할 경우 악의적인 공격자가 IP 소스 라우팅을 사용해서 목적지의 경로# 를 지정할 수도 있고, 원래 위치로 돌아오는 경로도 지정할 수 있다.
# 이러한 소스 라우팅이 가능한 것을 이용해 공격자가 마치 신뢰받는 호스트나
# 클라이언트인것 처럼 위장할 수 있는 것이다.
sysctl -w net.ipv4.conf.eth0.bootp_relay=0
sysctl -w net.ipv4.conf.lo.bootp_relay=0
sysctl -w net.ipv4.conf.default.bootp_relay=0
sysctl -w net.ipv4.conf.all.bootp_relay=0
# bootp 패킷을 허용하지 않는다.
sysctl -w net.ipv4.conf.eth0.log_martians=1
sysctl -w net.ipv4.conf.lo.log_martians=1
sysctl -w net.ipv4.conf.default.log_martians=1
sysctl -w net.ipv4.conf.all.log_martians=1
# 스푸핑된 패킷이나 소스라우팅, Redirect 패킷에 대해 로그파일에 정보를 남긴다.
sysctl -w net.ipv4.conf.eth0.secure_redirects=0
sysctl -w net.ipv4.conf.lo.secure_redirects=0
sysctl -w net.ipv4.conf.default.secure_redirects=0
sysctl -w net.ipv4.conf.all.secure_redirects=0
# 게이트웨이로부터의 redirect 를 허용하지 않음으로써 스푸핑을 막기 위해 설정한다.
sysctl -w net.ipv4.conf.eth0.send_redirects=0
sysctl -w net.ipv4.conf.lo.send_redirects=0
sysctl -w net.ipv4.conf.default.send_redirects=0
sysctl -w net.ipv4.conf.all.send_redirects=0
# icmp redirects 를 보내지 않는다.
sysctl -w net.ipv4.conf.eth0.proxy_arp=0
sysctl -w net.ipv4.conf.lo.proxy_arp=0
sysctl -w net.ipv4.conf.default.proxy_arp=0
sysctl -w net.ipv4.conf.all.proxy_arp=0
# proxy arp 를 설정하지 않는다. 이 값이 1로 설정되었을 경우 proxy_arp 가 설정된 인터페
# 이스에 대해 arp 질의가 들어왔을 때 모든 인터페이스가 반응하게 된다.
sysctl -w net.ipv4.tcp_keepalive_time=30
# 이미 프로세스가 종료되어 불필요하게 남아 있는 연결을 끊는 시간을 줄이도록 한다.
sysctl -w net.ipv4.tcp_fin_timeout=30
# 연결을 종료시 소요되는 시간을 줄여준다. (기본 설정값 : 60)
sysctl -w net.ipv4.tcp_tw_buckets=720000
# 동시에 유지 가능한 timewait 소켓의 수이다. 만약 지정된 숫자를 초과하였을 경우에는
# timewait 소켓이 없어지며 경고 메시지가 출력된다. 이 제한은 단순한 DoS 공격을 차단하
# 기 위해 존재하는데, 임의로 이 값을 줄여서는 안 되며 메모리가 충분하다면 적절하게 늘
# 려주는 것이 좋은데, 64M 마다 180000 으로 설정하면 된다. 따라서 256M 일 경우에는
# 256/4=4 4*180000=720000 을 적용하면 된다.
sysctl -w net.ipv4.tcp_keepalive_probes=2
sysctl -w net.ipv4.tcp_max_ka_probes=100
# 간단한 DoS 공격을 막아준다.
위의 모든 설정은 재부팅 후에 원래의 값으로 다시 초기화되므로 /etc/rc.d/rc.local 에 두어 부팅시마다 실행하도록 하여야 한다. 그리고 리눅스의 버전이 낮아 sysctl 명령어가 없는 경우에는
echo 0 or 1 > /proc/sys/net/* 와 같이 직접 /proc 이하의 값을 직접 설정해 주어도 된다.
echo 명령어 역시 재부팅되면 초기화되므로 /etc/rc.d/rc.local 에 설정해 두어야 재부팅후에도 적용이 된다.
아울러 레드햇 6.2 이상일 경우에는 /etc/sysctl.conf 파일에 net.ipv4.tcp_syncookies=1 와 같이 설정한 후 network 를 restart 하는 방법도 있다.
4. 그외 SYN_Flooding 에 대한 보충 설명 몇 가지
(1) 위에서 설명한 방법 외에 추가적으로 설정할 만한 몇 가지 방법이 있다.
RFC 1918 에 의해 내부(Private) IP를 소스로 들어오는 트래픽을 차단한다.
127.0.0.0, 10.0.0.0, 172.16.0.0, 192.168.0.0 등은 Private IP 로서 내부의 가상 IP 를 사용할 때 쓰이는 주소이며 일반적으로 이러한 IP를 소스 주소로 라우팅이 될 수 없다.
따라서 아래와 같이 비정상적인 IP 주소를 소스로 해서 들어오는 트래픽을 차단한다.
iptables -A INPUT -s 10.0.0./8 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 192.168.0.0/16 -j DROP
# 사설 IP 를 차단한다.
# /8, /16 등은 CIDR 라 하며 /8 은 A Class, /16 은 B Class 를 뜻한다.
iptables -A INPUT -s 255.255.255.255/32 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP
# 일반적으로 라우팅이 되지 않는 IP 대역을 차단한다.
iptables -A INPUT -s 240.0.0.0/5 -j DROP
# IANA 에 예약된 주소를 차단한다.
iptables -A INPUT -s 211.2.3.4 -j DROP
# 아울러 자기 자신의 IP 를 소스로 하는 패킷도 필터링한다.(211.2.3.4 대신 자신의 IP입력)
# 자신의 IP 를 소스로 해서 패킷이 들어올 수는 없다.
자신의 시스템이 Kernel 2.4 이전 버전의 경우에는 iptables 대신 ipchains 를 사용하므로
ipchains -A input -s 10.0.0./8 -j DENY 와 같은 방법으로 사용하면 된다.
만 약 iptables 가 설치되어 있지 않으면 http://netfilter.kernelnotes.org/ 에 접속 후 최신 버전의 iptables.tar 를 다운로드 받아 압축해제 후 make; make install 로 설치하면 된다.
현재 리눅스 시스템의 Kernel 버전은 uname ?r 을 입력하면 확인할 수 있다.
아울러 아래는 네트워크를 통해 라우팅 될 수 없는 IP 대역이므로 필터링 하여야 할 IP 이다.
0.0.0.0/8 - Historical Broadcast
10.0.0.0/8 - RFC 1918 에 의한 내부 네트워크
127.0.0.0/8 - Loopback
169.254.0.0/16 - Link Local Networks
172.16.0.0/12 - RFC 1918 에 의한 내부 네트워크
192.0.2.0/24 - TEST-NET
192.168.0.0/16 - RFC 1918에 의한 내부 네트워크
224.0.0.0/4 - Multicast D Class
240.0.0.0/5 - 예약된 E Class
248.0.0.0/5 - 미할당
255.255.255.255/32 - 브로드캐스트
(2) 임의의 IP 가 아닌 특정한 IP를 소스 주소로 계속적으로 SYN 공격이 이루어 질 경우에는 해당 IP 를 차단하는 것도 좋은 방법이다.
만약 211.2.3.4 에서 지속적으로 공격이 들어올 때는 아래와 같이 차단할 수 있다.
iptables -A INPUT -s 211.2.3.4 -j DROP (Kernel 2.4.x 버전)
ipchains -A input -s 211.2.3.4 -j DENY (Kernel 2.4 이전 버전)
또는
route add -host 211.2.3.4 reject 로 한다.
만약 211.2.3.X 대역 전체를 차단하려면 211.2.3.0/24 와 같이 하면 된다.
(/24 는 C Class 를 뜻한다.)
그러나 위와 같이 route 보다는 iptables 나 ipchains 로 차단하는 것이 더 효과적이다.
만 약 임의의 IP로 공격지를 생성한다면 SYN_RECEIVED 로 보이는 IP 중에는 실제 네트워크에 연결되어 있는 IP 도 있을 것이고 그렇지 않은 IP 도 있을 것이다. 그러나 실제 공격을 당할 때 공격지 IP 를 검출해 보면 모두 ping 이 되지 않는 실제 네트워크에 연결되지 않은 IP 주소이다. 어째서 이런 현상이 일어날까? 이는 앞에서 설명한 TCP 의 3 Way-Handshake 원리를 잘 생각해보면 이해가 될 것이다.
즉, 무작위로 생성된 IP 를 소스로 한 SYN 패킷을 받은 서버는, 요청을 받은 모든 IP 로 SYN+ACK 패킷을 보낸다. 그런데, 정작 실제로 해당 IP 를 사용중인 호스트는 SYN 패킷을 보내지도 않았는데, 공격을 받은 서버로부터 영문도 모르는 SYN+ACK 를 받았으므로 이 패킷을 비정상적인 패킷으로 간주하고 해당 패킷을 리셋(RST)하여 초기화 시킨다.
그리고 실제 존재하지 않는 IP 에 대해서 알아보자. 공격을 당한 서버가 해당 IP로부터 SYN 패킷을 받았다고 판단(실제로는 위조된 패킷이지만) 하여 SYN+ACK 패킷을 발송 후 ACK 패킷을 계속 기다리지만 해당 IP 는 인터넷에 연결되어 있지 않으므로 SYN+ACK 패킷을 받을 수도 없을 뿐더러 이에 대한 응답으로 ACK 패킷을 발송하지 않을 것임은 불을 보듯 뻔한 것이고, 결국 공격을 받는 서버는 존재하지도 않는 IP 로부터 ACK 패킷을 받을 것만을 기다리며 백로그큐는 가득 차게 되는 것이다. 이것이 백로그큐가 가득 차게 되는 이유이며 백로그큐를 가득 채우는 IP가 모두 실제로는 존재하지 않는 IP 들인 것이다. 따라서 공격자의 입장에서는 인터넷상에서 라우팅이 되지 않는 IP 를 소스 IP 로 하여 공격하는 것이 가장 효과적일 것이다. 즉 인터넷에 연결되어 있는 IP 를 소스 주소로 하여 SYN Flooding 공격하는 것은 의미가 없다.
(3) 실제 공격지 IP를 추적하는 것은 거의 불가능하다.
대 부분의 DoS 공격이 그러하듯이 SYN_Flooding 공격도 소스IP를 속여서 들어오기 때문에 netstat 으로 보이는 IP를 실제 공격지 IP 라고 판단해서 해당 IP로 역공격을 해서는 안 된다. 공격을 당하는 리눅스 서버에서 공격지를 아는 방법은 없으며 상위 라우터와 해당 라우터가 연결되어 있는 ISP 업체와 긴밀하게 협조가 되었을 때라야 그나마 추척이 가능하다.
그 러나 사실상 협조가 이루어져도 추척하기란 매우 어려운데, 만약 라우팅 경로가 20개이상 되는 곳에서 공격한다면 20개 라우터를 관리하는 모든 관리자와 동시에 협조가 이루어져야하고 공격이 실제 이루어지고 있는 당시에 추척이 되어야 하므로 매우 어렵다고 할 수 있다. 결론적으로 공격지 IP 를 추척하는 것은 불가능하다고 할 수 있다.
그리고, 참고적으로 시스템에서 위조된 패킷을 생성하는 것은 오직 root 만이 가능하므로 공격자는 공격지 시스템의 root 소유로 SYN Flooding 공격을 하는 것이라는 사실을 참고하기 바란다.
(4) Virtul-Sever 커널 패치를 하는 방법도 있다.
이 커널 패치를 하였을 경우에는 몇 가지 DoS 공격을 차단할 수 있다. VirtualServer란 말 그대로 로드 밸랜싱등의 클러스터링 시스템을 구성할 때 필요한 커널 패치로서 패치를 한 후 sysctl -a|grep .vs. 로 확인해 보면 몇 가지 설정이 추가된 것을 확인할 수 있다.
이 방법에 대한 보다 자세한 안내는 http://www.linuxvirtualserver.org/defense.html 를 참고하기 바란다.
(5) 라우터나 방화벽에서 차단 가능하다.
라 우터등 네트워크 장비로 유명한 CISCO 에서는 TCP SYN_Flooding 공격을 차단하기 위해 TCP Intercept 라는 솔루션을 제안했다. TCP Intercept 는 두 가지 방식으로 구현가능한데 , 첫번째 방식은 “인터셉트 모드” 라 하여 말 그대로 라우터로 들어오는 SYN 패킷 요청을 그대로 서버에 넘겨주지 않고 라우터에서 일단 가로채어(Intercept 하여) 서버를 대신하여 SYN 패킷을 요청한 클라이언트와 연결을 맺고, 연결이 정상적으로 이루어지면 이번에는 클라이언트를 대신하여 서버와 연결을 맺은 다음 두 연결을 투명하게 포워딩하여 연결시켜주는 방식이다. 따라서 존재하지 않는 IP 로부터 오는 SYN 요청은 서버에 도달하지 못하게 되는 것이다. 두번째 방식은 “와치(watch) 모드” 라 하여 “인터셉트 모드”와는 달리 라우터를 통과하는 SYN패킷을 그대로 통과시키고 일정 시간동안 연결이 이루어지지 않으면 라우터가 중간에서 SYN 패킷을 차단하는 방식이다. 몇몇 방화벽에서도 위의 두 가지 방식으로 SYN Flooding 을 차단하고 있다. 실제로 tcp intercept 를 설정하여 테스트 결과 서버 레벨에는 전혀 스푸핑된 SYN 패킷이 보내지지 않아 SYN_Flooding 공격을 차단하기 위한 가장 확실한 방법이기는 했지만 아쉽게도 라우터의 CPU, Memory 부하가 너무 높아지는 단점이 있었다. 이 설정에 대해 궁금하신 분은 http://www.cisco.com/ 접속후 "tcp intercept" 로 검색해 보기 바란다. 이 설정을 했을 경우에는 모든 패킷에 대해 인터셉트를 하므로 트래픽이 많을 경우에는 라우터가 다운되는 경우도 있으니 설정시 각별히 주의하기 바란다.
(6) Windows NT/2000 계열에서는 Registry값을 수정함으로써 튜닝이 가능하다.
이 값에 대한 튜닝은 Microsoft 의 technical page 나
http://packetstorm.securify.com/groups/rhino9/synflood.doc 를 다운로드 받아 참고하기 바란다.
AIX나 Solaris등 다른 UNIX 계열에 대한 튜닝은
http://www.cymru.com/~robt/Docs/Articles/ip-stack-tuning.html 를 참고하기 바란다.
(7) CRON 을 이용해 SYN_Flooding 공격을 감지한다.
아 무리 튜닝을 잘 했다 하더라도 집중적으로 SYN Flooding 공격을 받을 때는 네트워크나 서비스 데몬이 이상 작동할 수도 있다. 그래서 이상 현상이 나타나기 전에 일정 시간마다 시스템에 로그인하여 netstat 으로 확인할 수 있겠지만 언제 공격이 들어올 줄 알고 지켜보고 있겠는가? 그래서 필자는 SYN Flooding 을 감지하기 위해 다음과 같이 간단한 스크립트를 짜서 공격이 확인되면 메일로 통보되도록 하여 사용중이다.
#!/usr/bin/perl
$TASK = `netstat -na|grep SYN_RECV`;
$HOSTNAME = `/bin/hostname`;
$TO_MAIL = 'antihong@tt.co.kr';
$SUBJECT = "$HOSTNAME SYN_FLOODING 공격 감지";
$MAIL_PROGRAM = "/usr/sbin/sendmail";
if ($TASK){
$TASK_CONFIRM = `netstat -na|grep SYN_RECV|wc -l`;
if($TASK_CONFIRM > 20){
`/etc/rc.d/init.d/httpd stop`;
`/etc/rc.d/init.d/httpd start`;
$HTTP_DONE ="httpd was Refreshed!!n";
}
open(MAIL, "|$MAIL_PROGRAM -t");
print MAIL "To: $TO_MAIL n";
print MAIL "Subject: $SUBJECT nn";
print MAIL "$HOSTNAME Server is Attacked by SYN_Flooding!!!n";
print MAIL "SYN_Flooding Process Number :$TASK_CONFIRM n";
print MAIL "$HTTP_DONEn";
print MAIL "$TASK n";
close(MAIL);
}
위 파일의 내용중 $TO_MAIL 은 공격 감지시 통보될 메일 주소이므로 자신의 e-mail 주소로 변경하고, 불완전한 SYN 패킷이 20개 이상일 경우 ($TASK_CONFIRM > 20)
`/etc/rc.d/init.d/httpd stop`; 과 `/etc/rc.d/init.d/httpd start`; 으로 웹데몬을 멈추었다가 시작하도록 설정하였는데, 이는 자신의 설정에 맞게 적절히 수정하도록 한다.
물론 SYN Flooding 공격이 특정 포트에 대해서만 가능한 것은 아니지만 거의 80번 포트에 대해 집중적으로 이루어지고 있으므로 웹데몬을 예로 설정한 것 뿐이다.
위 파일의 내용을 /etc/cron.5min/ 이라는 디렉토리에 두고 실행할 수 있도록 700 으로 설정해 둔다. 그리고 /etc/crontab 파일을 열어 아래 내용을 추가하면 5분마다 SYN_Flooding 여부를 체크하여 공격이 확인시 지정된 메일 주소로 통보해 준다..
59/5 * * * * root run-parts /etc/cron.5min/
오늘과 내일 넷센터 홍석범(antihong@tt.co.kr)
최근 자신이 운영하는 서버에 특별히 부하가 걸리거나 이상이 있는 것도 아니고
또 데몬도 정상적으로 떠 있는데, 정작 서비스가 작동하지 않는 경우가 종종 있다.
이러한 경우에는 해당 데몬을 완전히 멈추었다가 살리면 다시 작동하는데,
잠시 후에 확인해 보면 똑같은 현상이 다시 나타나곤 한다.
혹시 프로그램을 잘못 설치했나 싶어 지우고 다시 설치해도 마찬가지이다.
만약 최근 들어 이러한 경험이 있다면 이는 최근 유행하는 DoS(서비스 거부 공격)의 일종인
TCP SYN Flooding 공격을 당했을 가능성이 크다.
SYN Flooding 공격의 개념이 소개된지는 꽤 되었지만 최근 들어 리눅스가 확산되고, 간단하게 실행할 수 있는 공격 소스가 광범위하게 배포되면서 이 공격이 자주 확인되고 있고, 이로 인해 그 피해가 급속히 확산되고 있다. 실제로 현재 가장 많이 사용되고 있는 배포판인 레드햇 6.X 계열에 이 공격을 실행하기만 하면 단 몇 초만에 서비스가 정지해 버리게 된다.
따라서 피해가 확산되고 있는 이 공격의 원리와 대처방법에 대해 알아보도록 하자.
“TCP 의 약점을 이용한 공격원리”
SYN Flooding 공격은 TCP 의 취약점을 이용한 공격의 형태이므로 먼저 TCP 에 대해
알아야 한다. TCP 는 Transmition Control Protocol 의 약자로 UDP와는 달리 신뢰성 있는 연결을 담당한다. 따라서 서버와 클라이언트간에 본격적인 통신이 이루어지기 전에는
다음 그림과 같이 소위 "3 Way handshaking" 이라는 정해진 규칙이 사전에 선행되어야 한다.
1단계. A 클라이언트는 B 서버에 접속을 요청하는 SYN 패킷을 보낸다.
2단계. B 서버는 요청을 받고 A 클라이언트에게 요청을 수락한다는 SYN 패킷과
ACK 패킷을 발송한다.
3단계. A 클라이언트는 B 서버에게 ACK 를 보내고 이후로부터 연결이 이루어지고
본격적으로 데이터가 교환된다.
이것이 TCP 의 기본적인 Flow 이다.
그런데, 이 그림에서 악의적인 공격자가 1단계만 요청(SYN)하고 B서버로부터 응답을 받은 후(SYN+ACK) 3단계, 즉 클라이언트에게 ACK를 보내지 않는다면 어떻게 될까?
SYN+ACK 패킷을 받은 B 호스트는 A 로부터 응답이 올 것을 기대하고 반쯤 열린
이 른바 “Half Open” 상태가 되어 대기 상태에 머무른 후 일정 시간(75초) 후에 다음 요청이 오지 않으면 해당 연결을 초기화 하게 되는데, 초기화하기 전까지 이 연결은 메모리 공간인 백로그큐(Backlog Queue)에 계속 쌓이게 된다.
그런데, 이 위조된 연결 시도를 초기화하기 전에 위조된 새로운 요구가 계속 들어오게 된다면 또한 위조된 새로운 요구가 연결을 초기화하는 속도보다 더 빨리 이루어진다면 어떻게 될까? 이러한 경우 SYN 패킷이 어느 정도 백로그큐에 저장이 되다 결국 꽉차게 되어 더 이상의 연결을 받아들일 수 없는 상태, 즉 서비스 거부 상태로 들어가게 되는 것이다. 이처럼 백로그큐가 가득 찼을 경우에 공격을 당한 해당 포트로만 접속이 이루어지지 않을 뿐 다른 포트에는 영향을 주지 않고, 또한 서버에 별다른 부하도 유발하지 않으므로 관리자가 잘 모르는 경우가 많다. 또한 다른 DoS 공격과는 달리 많은 트래픽을 유발하는 공격이 아니므로 쉽게 파악이 되지 않는 공격 형태이다.
그렇다면 이 공격을 당하고 있는지 여부는 어떻게 알 수 있을까?
시스템에 로긴후 "netstat" 이라는 명령으로 확인 가능하다.
“그럼, 어떻게 파악하는가?”
netstat 은 시스템의 각종 네트워크 정보를 알려주는 명령어로 네트워크 연결, 라우팅 현황, 인터페이스 통계등의 정보를 확인할 수 있게 해 준다. 여기서 잠깐 netstat 으로 나오는 연결 상태에 대해 알아보자.
netstat -na 로 확인해 보면 Local Address, Foreign Address, State 등의 정보가 출력되는데,
이 중 State 부분에 보이는 메시지를 주목하면 된다.
### 참고 : State 부분에 가능한 연결상태 ###################################
LISTEN : 서버의 데몬이 떠서 접속 요청을 기다리는 상태
SYS-SENT : 로컬의 클라이언트 어플리케이션이 원격 호스트에 연결을 요청한 상태
SYN_RECEIVED : 서버가 원격 클라이언트로부터 접속 요구를 받아 클라이언트에게
응답을 하였지만 아직 클라이언트에게 확인 메시지는 받지 않은 상태
ESTABLISHED : 3 Way-Handshaking 이 완료된 후 서로 연결된 상태
FIN-WAIT1 , CLOSE-WAIT , FIN-WAIT2 :
서버에서 연결을 종료하기 위해 클라이언트에게 종결을 요청하고
회신을 받아 종료하는 과정의 상태
CLOSING : 흔하지 않지만 주로 확인 메시지가 전송도중 분실된 상태
TIME-WAIT : 연결은 종료되었지만 분실되었을지 모를 느린 세그먼트를 위해
당분간 소켓을 열어놓은 상태
CLOSED : 완전히 종료
################################################################################
각각의 연결 상태는 통신 상황에 따라 매우 복잡하게 순간적으로 변화하는데,
이 중 주로 주목하여야 할 상태는 SYN_RECEIVED 이다. 설명에 나온 대로 이 상태는
클라이언트의 확인 메시지를 기다리는 상태이지만 특별히 전용 회선에 장애가 없는 한 이 과정은 순간적으로 일어나므로 실제 netstat 으로 확인되는 경우는 거의 없다.
따라서 netstat -na|grep SYN_RECV 로 확인해 보아 많은 메시지가 보인다면
Syn Flooding 공격을 당하고 있는 것으로 판단하면 된다.
“실제 테스트 공격으로 직접 확인해 보자!!”
실제 자신의 시스템이 얼마나 취약한지 자신의 시스템에 테스트해 보도록 하자.
노파심에 이야기하는 것이지만 이 공격은 반드시 자신의 시스템에서만 테스트 용도로 실행해 보기 바란다. 이 공격 소스는 인터넷상에서 쉽게 찾을 수 있다.
http://packetstorm.securify.com/ 나 http://rootshell.com/ 에 접속후 syn 으로 검색해 보면 많은 소스와 문서가 있는데, 이중 관련 파일을 다운로드받아 설치해 보면 된다.
소스에 따라 실행 방법이 다르지만 다운로드 받은 소스파일이 syn_floodinbg_dos.c 라면 gcc ?o syn_flooding_dos syn_flooding_dos.c 로 컴파일을 한다. 이후
"./syn_flooding_dos 소IP 공격지IP 공격할하위포트번호 상위포트번호" 와 같이 실행하면 되는데, 필자는 ./syn_flodding_dos 0 localhost 80 80 과 같이 테스트해 보았다.
위 명령어의 의미는 공격지 주소를 랜덤하게 무작위 IP주소로 설정(0) 하여 localhost 서버의 80 번 포트에 Syn_Flooding 공격을 한다는 내용이다.
실제 본인이 테스트한 레드햇 6.2 서버에서는 공격후 2-3초만에 웹서비스가 중지되었다.
테스트 공격 후 telnet localhost 80 으로 접속해 보기 바란다.
분명히 httpd 데몬은 떠 있는데, 접속이 되지 않을 것이다.
아래는 공격을 당한 서버에서 netstat -na|grep SYN 으로 SYN 패킷을 잡은 부분이다.
분 명히 localhost 에서 공격을 했음에도 위 그림에서처럼 80번 포트로 SYN 패킷을 요청한 IP주소는 랜덤하게 보이고 있어 도무지 어떤 IP 에서 공격하고 있는 것인지 알 수 없다. 실제로 공격지 IP 를 확인해 보면 대부분이 현재 인터넷상에 연결되지 않은 존재하지 않는 위조된 IP들이다.
실제 공격 소스 코드중 소스 IP를 생성하는 부분을 보면 아래와 같이 0부터 255까지
임의의 값을 뽑아 IP 주소로 설정하는 것을 확인할 수 있다.
{
a = getrandom(0, 255);
b = getrandom(0, 255);
c = getrandom(0, 255);
d = getrandom(0, 255);
sprintf(junk, "%i.%i.%i.%i", a, b, c, d);
me_fake = getaddr(junk);
}
SYN_Flooding 공격에 대한 대비 및 해결책
그렇다면 이 공격에 대해 어떻게 대비하여야 할까?
1. 백로그 큐를 늘려준다.
직관적으로 보았을 때 서비스 거부에 돌입하게 되는 것은 백로그큐(Backlog Queue)가 가득
차 서 다른 접속 요구를 받아들이지 못하기 때문이므로 백로그 큐의 크기를 늘려주면 될 것이다. 실제로 리눅스를 포함해서 많은 운영체제들의 백로그큐값을 조사해 보면 이 값이 필요 이상으로 작게 설정되어 있어 적절히 늘려주는 것이 좋다.
현재 시스템에 설정된 백로그큐의 크기는
[root@net /root]# sysctl -a|grep syn_backlog
net.ipv4.tcp_max_syn_backlog = 128
또는
[root@net /root]# cat /proc/sys/net/ipv4/tcp_max_syn_backlog
128
로 확인가능하며 128kb 인 것을 확인할 수 있다.
일 반적으로 시스템의 RAM 이 128M 일 경우에는 128 을 설정하고 그 이상일 경우에는 1024 정도로 설정해 주는 것이 좋다. 이 때 주의할 점은 이 값을 무작정 크게 설정한다고 좋은 것은 아니며 1024 이상으로 설정할 경우는 /usr/src/linux/include/net/tcp.h 소스에서 TCP_SYNQ_SIZE 변수를 수정 후 커널을 재컴파일하여야 한다. 이 변수를 설정시 TCP_SYNQ_HSIZE에 16을 곱한 값이 tcp_max_syn_backlog 보다는 작거나 같아야 하는데, 그렇지 않을 경우에는 시스템에 문제가 발생할 수 있으니 1024 보다 높은 값으로 설정하지 말기 바란다. 그리고 이 값을 너무 크게 설정하였을 경우에는 경험적으로 아래 설명할 syncookies 기능이 잘 적용되지 않는 현상이 가끔 확인되었다.
이와는 별개로 시스템의 부하가 많이 걸릴 경우에도 백로그큐를 늘려주면 일정 정도의 효과를 볼 수 있는 것으로 알려져 있다.
백로그큐의 값을 설정하는 방법은 다음과 같다.
[root@net /root]# sysctl -w net.ipv4.tcp_max_syn_backlog=1024
또는
[root@net /root]# echo 1024 > /proc/sys/net/ipv4/tcp_max_syn_backlog
로 해도 된다.
그러나 이 방법은 임시적인 대책일 뿐, 지속적으로 많은 TCP SYN Flooding 공격을 당할 때는 결국 백로크큐가 가득 차게 되므로 근본적인 해결 방안은 아니다.
2. syncookies 기능을 켠다.
Syncookies (“신쿠키” 라고 발음한다.) 는 "Three-way handshake" 진행 과정을 다소 변경하는 것으로 Alex Yuriev 와 Avi Freedman 에 의해 제안되었는데, TCP header 의 특정한 부분을 뽑아내어 암호화 알고리즘을 이용하는 방식으로 Three-way Handshake 가 성공적으로 이루어지지 않으면 더 이상 소스 경로를 거슬러 올라가지 않는다. 따라서 적절한 연결 요청에 대해서만 연결을 맺기 위해 리소스를 소비하게 되는 것이다.
syncookies 기능은 TCP_Syn_Flooding 공격을 차단하기 위한 가장 확실한 방법으로 이 기능을 이용하려면 일단 커널 컴파일 옵션에서 CONFIG_SYN_COOKIES이 Y 로 선택되어 있어야 한다.
자신의 커널 옵션에 이 기능이 설정되어 있는지 확인하려면
/usr/src/linux 디렉토리로 이동후 make menuconfig 후
Networking options --->
[*] IP: TCP syncookie support (disabled per default)
와 같이 확인하면 된다.
만약 설정이 되어 있지 않다면 선택 후 커널 컴파일을 다시 하여야 하지만 대부분 배포판은 기본적으로 이 옵션이 선택되어 있으므로 걱정할 필요는 없다.
그러나 위와 같이 커널 옵션에 설정되어 있다 하더라도 실제 syncookies 적용은 꺼져 있으므로 이 값을 다음과 같은 방법으로 활성화해야 한다.
[root@control src]# sysctl -a|grep syncookie
net.ipv4.tcp_syncookies = 0
0 으로 설정되어 있으므로 현재 syncookies는 적용되지 않는다.
따라서 아래와 같이 1을 설정하여 syncookies 기능을 활성화하도록 한다.
[root@control src]# sysctl -w net.ipv4.tcp_syncookies=1
syncookies는 백로그큐가 가득 찼을 경우에도 정상적인 접속 요구를 계속 받아들일 수 있도록 해 주므로 SYN_Flooding 공격에 대비한 가장 효과적인 방법중 하나이다.
만약 공격을 당해 syncookies 가 작동할 때에는 /var/log/messages 파일에 아래와 같이 SynFlooding 공격이 진행중이라는 메시지가 출력된다.
Jun 11 18:54:08 net kernel: possible SYN flooding on port 80. Sending cookies.
SYN_Flooding 공격이 지속적으로 매우 심하게 진행중일 때에는 syncookies 기능이 작동한다 하더라도 네트워크가 다운되는 현상이 가끔 확인되었다. 따라서 syncookies 기능 외에 몇 가지 설정도 함께 적용하는 것이 시스템의 안정성을 위해 권장하는 방법이다. 아울러 네트워크가 다운되었을 경우에는 /etc/rc.d/init.d/network restart 로 network 를 재설정해 보거나 reboot 를 하여야 한다.
3. 기타 시스템의 네트워크 설정을 최적화한다.
아래 설정은 비단 TCP Syn_Flooding 공격뿐만이 아니라 다른 여타 DoS 공격에도 효과적이으로 방어하므로 적절히 설정할 것을 권장한다.
sysctl -w net.ipv4.icmp_destunreach_rate=1
# 1/100초 동안 받아들일 수 있는 "dest unreach (type 3) icmp" 의 개수
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1
# Broadcast 로부터 오는 ping 을 차단함. (Smurf 공격을 차단함)
sysctl -w net.ipv4.icmp_echoreply_rate=1
# 1/100초에 반응하는 ping 의 최대 숫자
sysctl -w net.ipv4.icmp_echo_ignore_all=1
#모든 ping 을 차단함
sysctl -w net.ipv4.icmp_ignore_bogus_error_responses=1
# IP 나 TCP 헤더가 깨진 bad icmp packet을 무시한다.
sysctl -w net.ipv4.icmp_paramprob_rate=1
# 1/100 초에 받아들이는 param probe packets의 수
sysctl -w net.ipv4.icmp_timeexceed_rate=1
# 1/100 초에 받아들이는 timeexceed 패킷의 수(traceroute 와 관련)
sysctl -w net.ipv4.igmp_max_memberships=1
# 1/100 초에 받아들이는 igmp "memberships" 의 수
sysctl -w net.ipv4.ip_always_defrag=0
# 항상 패킷 조각 모음을 하지 않는다.
sysctl -w net.ipv4.ip_default_ttl=64
# 매우 복잡한 사이트에서는 이 값을 늘리는 것도 가능하지만
# 64로 두는 것이 적당하며 더 늘렸을 경우에는 큰 문제가 발생할 수도 있다.
sysctl -w net.ipv4.ip_forward=0
# 게이트웨이 서버가 아닌 이상 패킷을 포워딩 할 필요는 없다.
sysctl -w net.ipv4.ipfrag_time=15
# fragmented packet이 메모리에 존재하는 시간을 15초로 설정한다.
sysctl -w net.ipv4.tcp_syn_retries=3
# 일정한 시간과 IP 별로 보내고 받는 SYN 재시도 횟수를 3회로 제한한다.
# 이 옵션은 스푸핑된(위조된) 주소로 오는 SYN 연결의 양을 줄여준다.
# 기본값은 5이며 255를 넘지 않아야 한다.
sysctl -w net.ipv4.tcp_retries1=3
# 무언가 문제가 있을 때 연결을 위해 재시도 할 횟수. 최소값과 기본값은 3이다.
sysctl -w net.ipv4.tcp_retries2=7
# TCP 연결을 끊기 전에 재시도할 횟수.
sysctl -w net.ipv4.conf.eth0.rp_filter=2
sysctl -w net.ipv4.conf.lo.rp_filter=2
susctl -w net.ipv4.conf.default.rp_filter=2
sysctl -w net.ipv4.conf.all.rp_filter=2
# 이 설정은 자신의 네트워크가 스푸핑된 공격지의 소스로 쓰이는 것을 차단한다.
# 모든 인터페이스에서 들어오는 패킷에 대해 reply를 하여 들어오는 인터페이스로 나가지
# 못하는 패킷을 거부한다.
sysctl -w net.ipv4.conf.eth0.accept_redirects=0
sysctl -w net.ipv4.conf.lo.accept_redirects=0
sysctl -w net.ipv4.conf.default.accept_redirects=0
sysctl -w net.ipv4.conf.all.accept_redirects=0
# icmp redirects 를 허용하지 않는다.
# 만약 ICMP Redirect 를 허용할 경우에는 공격자가 임의의 라우팅 테이블을 변경할 수
# 있게 되어 자신이 의도하지 않는 경로, 즉 공격자가 의도한 경로로 트래픽이 전달될 수
# 있는 위험이 있다.
sysctl -w net.ipv4.conf.eth0.accept_source_route=0
sysctl -w net.ipv4.conf.lo.accept_source_route=0
sysctl -w net.ipv4.conf.default.accept_source_route=0
sysctl -w net.ipv4.conf.all.accept_source_route=0
# 스푸핑을 막기 위해 source route 패킷을 허용하지 않는다.
# 소스 라우팅을 허용할 경우 악의적인 공격자가 IP 소스 라우팅을 사용해서 목적지의 경로# 를 지정할 수도 있고, 원래 위치로 돌아오는 경로도 지정할 수 있다.
# 이러한 소스 라우팅이 가능한 것을 이용해 공격자가 마치 신뢰받는 호스트나
# 클라이언트인것 처럼 위장할 수 있는 것이다.
sysctl -w net.ipv4.conf.eth0.bootp_relay=0
sysctl -w net.ipv4.conf.lo.bootp_relay=0
sysctl -w net.ipv4.conf.default.bootp_relay=0
sysctl -w net.ipv4.conf.all.bootp_relay=0
# bootp 패킷을 허용하지 않는다.
sysctl -w net.ipv4.conf.eth0.log_martians=1
sysctl -w net.ipv4.conf.lo.log_martians=1
sysctl -w net.ipv4.conf.default.log_martians=1
sysctl -w net.ipv4.conf.all.log_martians=1
# 스푸핑된 패킷이나 소스라우팅, Redirect 패킷에 대해 로그파일에 정보를 남긴다.
sysctl -w net.ipv4.conf.eth0.secure_redirects=0
sysctl -w net.ipv4.conf.lo.secure_redirects=0
sysctl -w net.ipv4.conf.default.secure_redirects=0
sysctl -w net.ipv4.conf.all.secure_redirects=0
# 게이트웨이로부터의 redirect 를 허용하지 않음으로써 스푸핑을 막기 위해 설정한다.
sysctl -w net.ipv4.conf.eth0.send_redirects=0
sysctl -w net.ipv4.conf.lo.send_redirects=0
sysctl -w net.ipv4.conf.default.send_redirects=0
sysctl -w net.ipv4.conf.all.send_redirects=0
# icmp redirects 를 보내지 않는다.
sysctl -w net.ipv4.conf.eth0.proxy_arp=0
sysctl -w net.ipv4.conf.lo.proxy_arp=0
sysctl -w net.ipv4.conf.default.proxy_arp=0
sysctl -w net.ipv4.conf.all.proxy_arp=0
# proxy arp 를 설정하지 않는다. 이 값이 1로 설정되었을 경우 proxy_arp 가 설정된 인터페
# 이스에 대해 arp 질의가 들어왔을 때 모든 인터페이스가 반응하게 된다.
sysctl -w net.ipv4.tcp_keepalive_time=30
# 이미 프로세스가 종료되어 불필요하게 남아 있는 연결을 끊는 시간을 줄이도록 한다.
sysctl -w net.ipv4.tcp_fin_timeout=30
# 연결을 종료시 소요되는 시간을 줄여준다. (기본 설정값 : 60)
sysctl -w net.ipv4.tcp_tw_buckets=720000
# 동시에 유지 가능한 timewait 소켓의 수이다. 만약 지정된 숫자를 초과하였을 경우에는
# timewait 소켓이 없어지며 경고 메시지가 출력된다. 이 제한은 단순한 DoS 공격을 차단하
# 기 위해 존재하는데, 임의로 이 값을 줄여서는 안 되며 메모리가 충분하다면 적절하게 늘
# 려주는 것이 좋은데, 64M 마다 180000 으로 설정하면 된다. 따라서 256M 일 경우에는
# 256/4=4 4*180000=720000 을 적용하면 된다.
sysctl -w net.ipv4.tcp_keepalive_probes=2
sysctl -w net.ipv4.tcp_max_ka_probes=100
# 간단한 DoS 공격을 막아준다.
위의 모든 설정은 재부팅 후에 원래의 값으로 다시 초기화되므로 /etc/rc.d/rc.local 에 두어 부팅시마다 실행하도록 하여야 한다. 그리고 리눅스의 버전이 낮아 sysctl 명령어가 없는 경우에는
echo 0 or 1 > /proc/sys/net/* 와 같이 직접 /proc 이하의 값을 직접 설정해 주어도 된다.
echo 명령어 역시 재부팅되면 초기화되므로 /etc/rc.d/rc.local 에 설정해 두어야 재부팅후에도 적용이 된다.
아울러 레드햇 6.2 이상일 경우에는 /etc/sysctl.conf 파일에 net.ipv4.tcp_syncookies=1 와 같이 설정한 후 network 를 restart 하는 방법도 있다.
4. 그외 SYN_Flooding 에 대한 보충 설명 몇 가지
(1) 위에서 설명한 방법 외에 추가적으로 설정할 만한 몇 가지 방법이 있다.
RFC 1918 에 의해 내부(Private) IP를 소스로 들어오는 트래픽을 차단한다.
127.0.0.0, 10.0.0.0, 172.16.0.0, 192.168.0.0 등은 Private IP 로서 내부의 가상 IP 를 사용할 때 쓰이는 주소이며 일반적으로 이러한 IP를 소스 주소로 라우팅이 될 수 없다.
따라서 아래와 같이 비정상적인 IP 주소를 소스로 해서 들어오는 트래픽을 차단한다.
iptables -A INPUT -s 10.0.0./8 -j DROP
iptables -A INPUT -s 172.16.0.0/12 -j DROP
iptables -A INPUT -s 192.168.0.0/16 -j DROP
# 사설 IP 를 차단한다.
# /8, /16 등은 CIDR 라 하며 /8 은 A Class, /16 은 B Class 를 뜻한다.
iptables -A INPUT -s 255.255.255.255/32 -j DROP
iptables -A INPUT -s 127.0.0.0/8 -j DROP
# 일반적으로 라우팅이 되지 않는 IP 대역을 차단한다.
iptables -A INPUT -s 240.0.0.0/5 -j DROP
# IANA 에 예약된 주소를 차단한다.
iptables -A INPUT -s 211.2.3.4 -j DROP
# 아울러 자기 자신의 IP 를 소스로 하는 패킷도 필터링한다.(211.2.3.4 대신 자신의 IP입력)
# 자신의 IP 를 소스로 해서 패킷이 들어올 수는 없다.
자신의 시스템이 Kernel 2.4 이전 버전의 경우에는 iptables 대신 ipchains 를 사용하므로
ipchains -A input -s 10.0.0./8 -j DENY 와 같은 방법으로 사용하면 된다.
만 약 iptables 가 설치되어 있지 않으면 http://netfilter.kernelnotes.org/ 에 접속 후 최신 버전의 iptables.tar 를 다운로드 받아 압축해제 후 make; make install 로 설치하면 된다.
현재 리눅스 시스템의 Kernel 버전은 uname ?r 을 입력하면 확인할 수 있다.
아울러 아래는 네트워크를 통해 라우팅 될 수 없는 IP 대역이므로 필터링 하여야 할 IP 이다.
0.0.0.0/8 - Historical Broadcast
10.0.0.0/8 - RFC 1918 에 의한 내부 네트워크
127.0.0.0/8 - Loopback
169.254.0.0/16 - Link Local Networks
172.16.0.0/12 - RFC 1918 에 의한 내부 네트워크
192.0.2.0/24 - TEST-NET
192.168.0.0/16 - RFC 1918에 의한 내부 네트워크
224.0.0.0/4 - Multicast D Class
240.0.0.0/5 - 예약된 E Class
248.0.0.0/5 - 미할당
255.255.255.255/32 - 브로드캐스트
(2) 임의의 IP 가 아닌 특정한 IP를 소스 주소로 계속적으로 SYN 공격이 이루어 질 경우에는 해당 IP 를 차단하는 것도 좋은 방법이다.
만약 211.2.3.4 에서 지속적으로 공격이 들어올 때는 아래와 같이 차단할 수 있다.
iptables -A INPUT -s 211.2.3.4 -j DROP (Kernel 2.4.x 버전)
ipchains -A input -s 211.2.3.4 -j DENY (Kernel 2.4 이전 버전)
또는
route add -host 211.2.3.4 reject 로 한다.
만약 211.2.3.X 대역 전체를 차단하려면 211.2.3.0/24 와 같이 하면 된다.
(/24 는 C Class 를 뜻한다.)
그러나 위와 같이 route 보다는 iptables 나 ipchains 로 차단하는 것이 더 효과적이다.
만 약 임의의 IP로 공격지를 생성한다면 SYN_RECEIVED 로 보이는 IP 중에는 실제 네트워크에 연결되어 있는 IP 도 있을 것이고 그렇지 않은 IP 도 있을 것이다. 그러나 실제 공격을 당할 때 공격지 IP 를 검출해 보면 모두 ping 이 되지 않는 실제 네트워크에 연결되지 않은 IP 주소이다. 어째서 이런 현상이 일어날까? 이는 앞에서 설명한 TCP 의 3 Way-Handshake 원리를 잘 생각해보면 이해가 될 것이다.
즉, 무작위로 생성된 IP 를 소스로 한 SYN 패킷을 받은 서버는, 요청을 받은 모든 IP 로 SYN+ACK 패킷을 보낸다. 그런데, 정작 실제로 해당 IP 를 사용중인 호스트는 SYN 패킷을 보내지도 않았는데, 공격을 받은 서버로부터 영문도 모르는 SYN+ACK 를 받았으므로 이 패킷을 비정상적인 패킷으로 간주하고 해당 패킷을 리셋(RST)하여 초기화 시킨다.
그리고 실제 존재하지 않는 IP 에 대해서 알아보자. 공격을 당한 서버가 해당 IP로부터 SYN 패킷을 받았다고 판단(실제로는 위조된 패킷이지만) 하여 SYN+ACK 패킷을 발송 후 ACK 패킷을 계속 기다리지만 해당 IP 는 인터넷에 연결되어 있지 않으므로 SYN+ACK 패킷을 받을 수도 없을 뿐더러 이에 대한 응답으로 ACK 패킷을 발송하지 않을 것임은 불을 보듯 뻔한 것이고, 결국 공격을 받는 서버는 존재하지도 않는 IP 로부터 ACK 패킷을 받을 것만을 기다리며 백로그큐는 가득 차게 되는 것이다. 이것이 백로그큐가 가득 차게 되는 이유이며 백로그큐를 가득 채우는 IP가 모두 실제로는 존재하지 않는 IP 들인 것이다. 따라서 공격자의 입장에서는 인터넷상에서 라우팅이 되지 않는 IP 를 소스 IP 로 하여 공격하는 것이 가장 효과적일 것이다. 즉 인터넷에 연결되어 있는 IP 를 소스 주소로 하여 SYN Flooding 공격하는 것은 의미가 없다.
(3) 실제 공격지 IP를 추적하는 것은 거의 불가능하다.
대 부분의 DoS 공격이 그러하듯이 SYN_Flooding 공격도 소스IP를 속여서 들어오기 때문에 netstat 으로 보이는 IP를 실제 공격지 IP 라고 판단해서 해당 IP로 역공격을 해서는 안 된다. 공격을 당하는 리눅스 서버에서 공격지를 아는 방법은 없으며 상위 라우터와 해당 라우터가 연결되어 있는 ISP 업체와 긴밀하게 협조가 되었을 때라야 그나마 추척이 가능하다.
그 러나 사실상 협조가 이루어져도 추척하기란 매우 어려운데, 만약 라우팅 경로가 20개이상 되는 곳에서 공격한다면 20개 라우터를 관리하는 모든 관리자와 동시에 협조가 이루어져야하고 공격이 실제 이루어지고 있는 당시에 추척이 되어야 하므로 매우 어렵다고 할 수 있다. 결론적으로 공격지 IP 를 추척하는 것은 불가능하다고 할 수 있다.
그리고, 참고적으로 시스템에서 위조된 패킷을 생성하는 것은 오직 root 만이 가능하므로 공격자는 공격지 시스템의 root 소유로 SYN Flooding 공격을 하는 것이라는 사실을 참고하기 바란다.
(4) Virtul-Sever 커널 패치를 하는 방법도 있다.
이 커널 패치를 하였을 경우에는 몇 가지 DoS 공격을 차단할 수 있다. VirtualServer란 말 그대로 로드 밸랜싱등의 클러스터링 시스템을 구성할 때 필요한 커널 패치로서 패치를 한 후 sysctl -a|grep .vs. 로 확인해 보면 몇 가지 설정이 추가된 것을 확인할 수 있다.
이 방법에 대한 보다 자세한 안내는 http://www.linuxvirtualserver.org/defense.html 를 참고하기 바란다.
(5) 라우터나 방화벽에서 차단 가능하다.
라 우터등 네트워크 장비로 유명한 CISCO 에서는 TCP SYN_Flooding 공격을 차단하기 위해 TCP Intercept 라는 솔루션을 제안했다. TCP Intercept 는 두 가지 방식으로 구현가능한데 , 첫번째 방식은 “인터셉트 모드” 라 하여 말 그대로 라우터로 들어오는 SYN 패킷 요청을 그대로 서버에 넘겨주지 않고 라우터에서 일단 가로채어(Intercept 하여) 서버를 대신하여 SYN 패킷을 요청한 클라이언트와 연결을 맺고, 연결이 정상적으로 이루어지면 이번에는 클라이언트를 대신하여 서버와 연결을 맺은 다음 두 연결을 투명하게 포워딩하여 연결시켜주는 방식이다. 따라서 존재하지 않는 IP 로부터 오는 SYN 요청은 서버에 도달하지 못하게 되는 것이다. 두번째 방식은 “와치(watch) 모드” 라 하여 “인터셉트 모드”와는 달리 라우터를 통과하는 SYN패킷을 그대로 통과시키고 일정 시간동안 연결이 이루어지지 않으면 라우터가 중간에서 SYN 패킷을 차단하는 방식이다. 몇몇 방화벽에서도 위의 두 가지 방식으로 SYN Flooding 을 차단하고 있다. 실제로 tcp intercept 를 설정하여 테스트 결과 서버 레벨에는 전혀 스푸핑된 SYN 패킷이 보내지지 않아 SYN_Flooding 공격을 차단하기 위한 가장 확실한 방법이기는 했지만 아쉽게도 라우터의 CPU, Memory 부하가 너무 높아지는 단점이 있었다. 이 설정에 대해 궁금하신 분은 http://www.cisco.com/ 접속후 "tcp intercept" 로 검색해 보기 바란다. 이 설정을 했을 경우에는 모든 패킷에 대해 인터셉트를 하므로 트래픽이 많을 경우에는 라우터가 다운되는 경우도 있으니 설정시 각별히 주의하기 바란다.
(6) Windows NT/2000 계열에서는 Registry값을 수정함으로써 튜닝이 가능하다.
이 값에 대한 튜닝은 Microsoft 의 technical page 나
http://packetstorm.securify.com/groups/rhino9/synflood.doc 를 다운로드 받아 참고하기 바란다.
AIX나 Solaris등 다른 UNIX 계열에 대한 튜닝은
http://www.cymru.com/~robt/Docs/Articles/ip-stack-tuning.html 를 참고하기 바란다.
(7) CRON 을 이용해 SYN_Flooding 공격을 감지한다.
아 무리 튜닝을 잘 했다 하더라도 집중적으로 SYN Flooding 공격을 받을 때는 네트워크나 서비스 데몬이 이상 작동할 수도 있다. 그래서 이상 현상이 나타나기 전에 일정 시간마다 시스템에 로그인하여 netstat 으로 확인할 수 있겠지만 언제 공격이 들어올 줄 알고 지켜보고 있겠는가? 그래서 필자는 SYN Flooding 을 감지하기 위해 다음과 같이 간단한 스크립트를 짜서 공격이 확인되면 메일로 통보되도록 하여 사용중이다.
#!/usr/bin/perl
$TASK = `netstat -na|grep SYN_RECV`;
$HOSTNAME = `/bin/hostname`;
$TO_MAIL = 'antihong@tt.co.kr';
$SUBJECT = "$HOSTNAME SYN_FLOODING 공격 감지";
$MAIL_PROGRAM = "/usr/sbin/sendmail";
if ($TASK){
$TASK_CONFIRM = `netstat -na|grep SYN_RECV|wc -l`;
if($TASK_CONFIRM > 20){
`/etc/rc.d/init.d/httpd stop`;
`/etc/rc.d/init.d/httpd start`;
$HTTP_DONE ="httpd was Refreshed!!n";
}
open(MAIL, "|$MAIL_PROGRAM -t");
print MAIL "To: $TO_MAIL n";
print MAIL "Subject: $SUBJECT nn";
print MAIL "$HOSTNAME Server is Attacked by SYN_Flooding!!!n";
print MAIL "SYN_Flooding Process Number :$TASK_CONFIRM n";
print MAIL "$HTTP_DONEn";
print MAIL "$TASK n";
close(MAIL);
}
위 파일의 내용중 $TO_MAIL 은 공격 감지시 통보될 메일 주소이므로 자신의 e-mail 주소로 변경하고, 불완전한 SYN 패킷이 20개 이상일 경우 ($TASK_CONFIRM > 20)
`/etc/rc.d/init.d/httpd stop`; 과 `/etc/rc.d/init.d/httpd start`; 으로 웹데몬을 멈추었다가 시작하도록 설정하였는데, 이는 자신의 설정에 맞게 적절히 수정하도록 한다.
물론 SYN Flooding 공격이 특정 포트에 대해서만 가능한 것은 아니지만 거의 80번 포트에 대해 집중적으로 이루어지고 있으므로 웹데몬을 예로 설정한 것 뿐이다.
위 파일의 내용을 /etc/cron.5min/ 이라는 디렉토리에 두고 실행할 수 있도록 700 으로 설정해 둔다. 그리고 /etc/crontab 파일을 열어 아래 내용을 추가하면 5분마다 SYN_Flooding 여부를 체크하여 공격이 확인시 지정된 메일 주소로 통보해 준다..
59/5 * * * * root run-parts /etc/cron.5min/
실무에서 자주 사용되는 쉘 스크립트
실무에서 자주 사용되는 쉘 스크립트
<1>
(아파치 자동 재시작 스크립트)
리눅스 시스템을 관리하다 보면, 쉘 스크립트의 필요성을 절실히 느끼게 된다. 저자는 쉘프로그램관련 강좌(bash, awk, sed)를 쓰고 싶었다. bash문법, awk문법, sed사용법을 묶은 강좌를 만들고 싶었다.. 하지만, 이것은 나를 위한 정리일 뿐이다. 내가 정리하여 강좌를 쓴다면, 읽는 사람들은 필요하지도 않은 문법을 머리속에 넣어야 하고, 그 조합으로 실무에 적용시키기위해서 수 없이 많은 노력을 할 것이다. 이런 강좌는 필요하지 않다. 정리는 man 페이지를 보면 자세하게 나와 있다. 저자는 리눅스 시스템 관리에 자주 사용되는 쉘 스크립트를 경험담을 담아 강좌를 써 보려고 한다. 최대한 간단하게 만들어서 누구든 쉽게 써 보고 이해하기 쉽게 쉘스크립트를 만들고, 설명하려 할 것이다.
처음 시작할 쉘 스크립트는 '아파치 자동 재시작 스크립트'이다.
서 버를 계속해서 모니터링 해야 한다거나, 특정 수치를 초과 했을 때 조치를 해 줘야 하는 경우가 발생한다. 물론 그 문제점이 일어나지 않게 원인을 파악하여 처리하는 것이 가장 좋지만, 그럴 만한 시간이 없다면, 자동으로 실행되는 쉘 스크립트를 만들어서 띄워 두면 된다.
금번 강좌에서 아파치 프로세스가 특정 수치만큼 생성 되었을 때, 아파치를 자동 재 시작 해주는 쉘 스크립트를 만들어 보도록 하겠다.
먼저, 어떤일을 할 것인지 생각 해 보자...
1) 아파치 프로세스 수를 어떻게 알지??
기본적으로 아파치 프로세스 이름은 'httpd'이다 물론 다른 이름을 수 있다. 이 프로세스가 얼마나 떠 있는지 조사하려면?
ps
명령어가 떠 오를 것이다.
그리고 httpd 프로세스만 잡아서 갯수를 세려면?
grep 명령어와 wc 명령어가 필요하다.
이런 3명령어를 조합해서 결과를 만들어 보자.
ps -e : 현재 서버에서 실행중인 모든 프로세스들을 보여준다.
ps -e | grep -w httpd : 현재 서버에서 실행중인 프로세스 중 httpd 문자가 포함된 프로세스만 잡아 보여준다.
'-w' 옵션은 단어 단위 검색이다. httpds 이런 이름이 있어도 포함시키지 않겠다는 의미이다.
ps -e | grep -w httpd |wc -l: 위에서 잡은 결과의 줄 수를 세어 준다.
이렇게 하면 프로세스 수를 구할 수 있다.
위 명령을 단순화 시키려면,
pgrep -x httpd | wc -l : 'pgrep'은 프로세스이름에서 단어가 포함된 프로세스들의 pid를 얻기 위한 명령이다.
'-x' 옵션은 'grep'의 '-w'옵션처럼 단어 단위로 검색하기 위한 옵션이다.
2) 아파치를 재시작하는 방법?
아파치 서버를 운영한다면, 이 방법은 알고 있을 것이다.
컴파일 설치 했다면, /usr/local/apache/bin/apachectl restart
또 다른 방법은 apachectl stop, apachectl start 등의 방법이 있으며,
다른 방법은 아파치 프로세스를 모두 죽이고 시작하는 방법이 있을 것이다.
pgrep -x httpd | xargs kill -9
여기서 pgrep은 위에서 설명했고, xargs라는 명령이 뭘까?
xargs는 표준 입력으로 받은 내용을 xargs의 인자로 기술하는 명령어(kill -9)의 인자로 넣는 명령어이다.
다음 예를 보자.
pgrep -x httpd
5598
5843
실행결과가 위와 같다면, 5598과 5843은 httpd의 PID임을 알수 있다.
위 프로세스를 모두 죽이기 위해서는
kill -9 5598
kill -9 5843
이런 명령을 내려야 하며, 100개라면 100번? 물론 killall 이라는 좋은 명령어가 있지만, 잘 죽지 않을 때는 kill 명령으로 죽여야 한다.
위와 같은 일을 쉽게 해 줄 수 있는 명령이 xargs 이다.
pgrep -x httpd | xargs kill -9
이렇게 하면,
pgrep -x httpd 의 결과인 5598, 5843 이 자동 kill -9 명령어 뒤에 붙어 실행 되는 것이다.
이 명령어 하나면, 프로세스가 1000개라도 상관 없다^^
3) 자동으로 실행 시켜 주는 반복 작업 시작..
만약 문제가 있는 시스템이라면, 시스템 관리자는 '1)'의 명령을 내려 프로세스를 수를 확인하고, 생각했던 수치 보다 많으면 '2)'번 명령어를 내려서 아파치를 재 시작 할 것이다. 언제 발생할지도 모르는 것 때문에 지속적으로 보고 있을 수 없고, 자리를 비울 수 도 없다.
bash 쉘에서는 반복작업을 위해서 여러가지 제어문을 제공한다.
지금 사용할 문법은 while 문이다.
while ( 조건 ) ; do
<문장>
done
위 '조건'이 만족하는한 '<문장>'은 계속 실행된다.
while ( true ) ; do
ls
done
위와같이 입력한다면, 계속.. 'ls'명령어를 실행 시킬 것이다.
대부분의 언어에서 그렇듯 반복문에서 빠져 나올려면, 'break' 문법이 있다.
while ( true ) ; do
ls
break
done
4) 반복 실행하여 프로세스가 특정 수치 이상이면 아파치 재 시작
우리의 목적한 일을 할 수 있는 쉘 프로그램을 만들어 보자.
while ( true ) ; do
if [ "`pgrep -x httpd | wc -l`" -ge "500" ] ; then
/usr/local/apache/bin/apachectl restart
fi
done
이렇게 작성하면 끝!!!
if 문은 조건을 비교하여 조건이 맞으면 then 이하의 문장을 실행한다. 문법은 다음과 같다.
if [ 조건 ] ; then
<문장>
fi
'조건'을 비교하기 위해서 '-ge' 를 썼다. ge(greater than or equal)이다. 크거나 같다의 의미.. 그렇다면,
gt(크다), le(작거나 같다), lt(작다), eq(같다) 등이 있을 것이라 예상할 수 있다.
5) 문제점 발견!!
위 쉘 스크립트를 돌려 두니.. 너무 자주 비교해서, 쉘스크립트가 서버에 부하를 준다..
그렇다면, sleep으로 비교 시간을 늘려 준다.
while ( true ) ; do
if [ "`pgrep -x httpd | wc -l`" -ge "500" ] ; then
/usr/local/apache/bin/apachectl restart
fi
sleep 1
done
위와같이 'sleep 1'을 입력하였다면, 1초가 쉬어라는 것이다. 1초간 쉬었다가 다시 비교하게 된다.
우리는 이것으로 원하는 결과를 얻었다.!
이젠 지속적으로 프로세스를 수를 확인하여 아파치를 재 시작해야 하는 노가다는 하지 않아도 된다. 하하하!!
이것으로 ' 실무에서 자주 사용되는 쉘 스크립트 #1' 강좌를 마무리 하겠습니다.
본 강좌의 설명이 어렵거나, 잘못된 부분이 있으면 언제든지 따끔한 지적을 바랍니다.
<2>
(MySQL DB관리 유틸리티)
지난번, 강좌(apache 자동 재 시작 프로그램)에 이어 실무에서 자주 사용되는 쉘 스크립트에 대한 강좌를 써 내려 가겠다. 물론 최대한 쉽고 최소한의 라인 수로 작성 가능한 쉘 스크립트에 대한 강좌를 쓸 것이다.
금번 강좌는 MySQL을 쉽게 관리 할 수 있는 툴이다. 서버 관리를 하다 보면, mysql 접속하여 여러가지 sql문으로 서버 상태를 알아 보거나, 모니터링 해야 할 때가 있다. 이럴 때 마다 로그인을 해서, sql문을 얻어내는 것은 아주 귀찮은 일이고, 또 익숙하지 않으면 아주 오랜 시간이 소요되는 작업이다. 내가 만들고자 하는 스크립트는 이런 작업을 쉽게 해 줄 수 있는 스크립트를 만드는 것이다.
먼저, 어떤일을 할 것인지 생각 해 보자...
1) MySQL의 프로세스 리스트를 보려면?
mysql의 프로세스 리스트는 ps 등의 명령어로 쉽게 볼 수 있다. 난 그런 것을 원하는 것이 아니고, 각 프로세스들이 하는 일들을 보고 싶다. mysql은 다음과 같은 방법으로 이런 일이 가능하게 제공한다.
mysqladmin -u root -p processlist
또는
mysql 접속한 상태에서
show processlist;
나는 일괄적으로 다음과 같은 방법으로 mysql 명령을 실행 시킬 것이다.
echo "쿼리;" | mysql -u"root" -p"비밀번호"
위 명령어는 다음과 같다.
echo "쿼리; " : "쿼리;"를 출력한다.
| : 파이프, 앞 명령어의 내용을 뒷 명령어의 표준 입력으로 넣는다.
mysql -u"root" -p"비밀번호" : mysql 서버에 접속한다. "비밀번호"는 서버의 비밀번호를 넣어준다.
우리가 원하는 일은 다음과 같이 한다.
echo "show processlist;" | mysql -u"root" -p"비밀번호"
2) root로 그냥 접속만 하려면?
'1)'의 프로세스 리스트를 보는 것 보다 쉽다. 단순하게..
mysql -u"root" -p"비밀번호"
이렇게만 하면 끝난다.
3) MySQL에 존재하는 database 들을 보려면?
'1)'의 프로세스 리스트를 응용하면,
echo "show databases;" | mysql -u"root" -p"비밀번호"
이렇게만 하면 끝난다.
이정도 했으면, 원하는 쿼리들을 위와 같은 방법으로 자유롭게 추가 할 수 있을 것이다.
내가 원하는 것은 위 명령어들을 모아서 쓰기 편리한 메뉴 방식으로 만드는 것이다.
어떻게 할까???
나는 키보드로 특정 문자들을 입력받아 변수에 넣을 것이다. 그리고 그 변수에 따라 위 명령어들을 실행 시킬 것이다. 이런 작업들을 특정 문자가 입력될 때 까지 반속 할 것이다.
4) 쉘 프로그램에서 키보드 입력 받기
나는 쉘 프로그램에서 키보드로 입력을 받아서 변수에 넣을 것이다. 어떻게 해야 할까
read <변수>
no라는 변수에 입력값을 넣으려면 다음과 같이 한다.
read no
이렇게 하면, '엔터'키를 누를 때 까지 입력을 받는다.
read no
echo "$no"
위와같이 하면 간단하게 입력받은 문자를 출력해서 보여 줄 수 있다.
5) 입력된 문자에 따라서 프로그램 실행 시키기
'4)'에서 입력받은 문자에 따라서, 프로그램을 실행시키기 위해서는 case문을 사용해야 한다.
다음과 같다.
case <변수> in
"값" )
<명령어> ;;
"값" )
<명령어> ;;
esac
위와같다.
위 방법을 우리가 목표 하는 것에 적용 시키면.
먼저 메시지를 뿌려 준다.
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
'
echo -n "번호 선택 : "
read no
case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
esac
위와같이 작성하면, 위 쉘 스크립트를 실행 시키면, 리스트가 나오며 입력 대기 할 것이고, 1,2,3 중 하나의 번호를 누르면 지정 명령어가 실행 될 것이다..
그렇다면, 다른 문자를 입력하면?? 조건에 만족하는 문자가 없으면 그냥 지나간다...
6) 실행이 끝나면 다시 메뉴 보여주기
명령어를 실행 시키고 빠져 나가 버리면, 다른 메뉴를 선택하기 위해서 또 명령어를 실행시켜야 한다. 하나의 명령어 실행 시키고 다시 메뉴 리스트를 반복적으로 보여 주기 위해서는 이전 강좌에서 배웠던, while 문을 사용하여 계속 실행 시키도록 해 보자.
while ( true ) ; do
<프로그램>
done
위와같은 문법을 우리 스크립트에 적용하면,
while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
'
echo -n "번호 선택 : "
read no
case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
esac
done
이렇게 하면, 선택한 명령어 실행이 끝나면, 다시 메뉴를 보여 줄 것이다.
clear 명령어는 화면의 내용을 지우라는 명령어이다. 메뉴가 줄줄줄~~ 내러 가는 일을 방지하기 위함니다.
7) 이 반복 메뉴에서 빠져 나오려면??
한 명령어 실행이 끝나면, 메뉴가 나올 것이다. Ctrl + C 키를 눌러 빠져 나올 수 있지만, 그건 좀 아닌 것 같은데... 하나의 항목을 추가 했다. 메뉴에서 'q'키를 누르면 빠져 나오게 한다.
while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
q. 끝내기
'
echo -n "번호 선택 : "
read no
case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
"q" )
exit 0 ;;
esac
done
위 쉘스크립트에서 'q'키를 누르면 exit 명령어를 실행시켜 빠져 나오게 된다. 물론 정상 종료이기 때문에 0을 리턴한다..
8) "비밀번호"가 바뀌면 다 고쳐 줘야 하나요??
비밀번호가 바뀌면 위 스크립트에서 "비밀번호" 부분을 모두 수정해야 한다. vi 등의 에디터에 치환 기능이 있어 한번에 치환 한다면 문제가 없다. 하지만, 비밀번호가 'mysql' 이라면, 얘기는 달라진다,.. 명령어인 'mysql'이 함께 바뀌기 때문에.. 하나 하나 수작업으로 고쳐야 한다.
변수라는 개념을 써서 이 부분을 해결 해 보자.
a="변수"
echo $a
이렇게 하면 출력값은 ?
변수
위와같이 출력된다. 변수라는 개념을 우리의 쉘스크립트에 적용시키면?
mysqlpw="비밀번호"
while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
q. 끝내기
'
echo -n "번호 선택 : "
read no
case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"$mysqlpw" ;;
"2" )
mysql -u"root" -p"$mysqlpw" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"$mysqlpw" ;;
"q" )
exit 0 ;;
esac
done
위와 같이 보라색 부분을 수정했다. 이렇게 수정하면, 상단의 변수만 수정 하면 다른 부분은 수정할 필요없이 적용되는 것이다.
우리는 이것으로
쉘 스크립트의 case문과, 변수, 키보드로부터 입력받기 를 알게 되었다.
여러가지 편리한 기능들을 넣어 둔다면, 나만의 관리툴로 만들 수 있을 것이다. [뿌듯]
이것으로 ' 실무에서 자주 사용되는 쉘 스크립트 #2' 강좌를 마무리 하겠습니다.
본 강좌의 설명이 어렵거나, 잘못된 부분이 있으면 언제든지 따끔한 지적을 바랍니다.
<3>
<1>
(아파치 자동 재시작 스크립트)
리눅스 시스템을 관리하다 보면, 쉘 스크립트의 필요성을 절실히 느끼게 된다. 저자는 쉘프로그램관련 강좌(bash, awk, sed)를 쓰고 싶었다. bash문법, awk문법, sed사용법을 묶은 강좌를 만들고 싶었다.. 하지만, 이것은 나를 위한 정리일 뿐이다. 내가 정리하여 강좌를 쓴다면, 읽는 사람들은 필요하지도 않은 문법을 머리속에 넣어야 하고, 그 조합으로 실무에 적용시키기위해서 수 없이 많은 노력을 할 것이다. 이런 강좌는 필요하지 않다. 정리는 man 페이지를 보면 자세하게 나와 있다. 저자는 리눅스 시스템 관리에 자주 사용되는 쉘 스크립트를 경험담을 담아 강좌를 써 보려고 한다. 최대한 간단하게 만들어서 누구든 쉽게 써 보고 이해하기 쉽게 쉘스크립트를 만들고, 설명하려 할 것이다.
처음 시작할 쉘 스크립트는 '아파치 자동 재시작 스크립트'이다.
서 버를 계속해서 모니터링 해야 한다거나, 특정 수치를 초과 했을 때 조치를 해 줘야 하는 경우가 발생한다. 물론 그 문제점이 일어나지 않게 원인을 파악하여 처리하는 것이 가장 좋지만, 그럴 만한 시간이 없다면, 자동으로 실행되는 쉘 스크립트를 만들어서 띄워 두면 된다.
금번 강좌에서 아파치 프로세스가 특정 수치만큼 생성 되었을 때, 아파치를 자동 재 시작 해주는 쉘 스크립트를 만들어 보도록 하겠다.
먼저, 어떤일을 할 것인지 생각 해 보자...
1) 아파치 프로세스 수를 어떻게 알지??
기본적으로 아파치 프로세스 이름은 'httpd'이다 물론 다른 이름을 수 있다. 이 프로세스가 얼마나 떠 있는지 조사하려면?
ps
명령어가 떠 오를 것이다.
그리고 httpd 프로세스만 잡아서 갯수를 세려면?
grep 명령어와 wc 명령어가 필요하다.
이런 3명령어를 조합해서 결과를 만들어 보자.
ps -e : 현재 서버에서 실행중인 모든 프로세스들을 보여준다.
ps -e | grep -w httpd : 현재 서버에서 실행중인 프로세스 중 httpd 문자가 포함된 프로세스만 잡아 보여준다.
'-w' 옵션은 단어 단위 검색이다. httpds 이런 이름이 있어도 포함시키지 않겠다는 의미이다.
ps -e | grep -w httpd |wc -l: 위에서 잡은 결과의 줄 수를 세어 준다.
이렇게 하면 프로세스 수를 구할 수 있다.
위 명령을 단순화 시키려면,
pgrep -x httpd | wc -l : 'pgrep'은 프로세스이름에서 단어가 포함된 프로세스들의 pid를 얻기 위한 명령이다.
'-x' 옵션은 'grep'의 '-w'옵션처럼 단어 단위로 검색하기 위한 옵션이다.
2) 아파치를 재시작하는 방법?
아파치 서버를 운영한다면, 이 방법은 알고 있을 것이다.
컴파일 설치 했다면, /usr/local/apache/bin/apachectl restart
또 다른 방법은 apachectl stop, apachectl start 등의 방법이 있으며,
다른 방법은 아파치 프로세스를 모두 죽이고 시작하는 방법이 있을 것이다.
pgrep -x httpd | xargs kill -9
여기서 pgrep은 위에서 설명했고, xargs라는 명령이 뭘까?
xargs는 표준 입력으로 받은 내용을 xargs의 인자로 기술하는 명령어(kill -9)의 인자로 넣는 명령어이다.
다음 예를 보자.
pgrep -x httpd
5598
5843
실행결과가 위와 같다면, 5598과 5843은 httpd의 PID임을 알수 있다.
위 프로세스를 모두 죽이기 위해서는
kill -9 5598
kill -9 5843
이런 명령을 내려야 하며, 100개라면 100번? 물론 killall 이라는 좋은 명령어가 있지만, 잘 죽지 않을 때는 kill 명령으로 죽여야 한다.
위와 같은 일을 쉽게 해 줄 수 있는 명령이 xargs 이다.
pgrep -x httpd | xargs kill -9
이렇게 하면,
pgrep -x httpd 의 결과인 5598, 5843 이 자동 kill -9 명령어 뒤에 붙어 실행 되는 것이다.
이 명령어 하나면, 프로세스가 1000개라도 상관 없다^^
3) 자동으로 실행 시켜 주는 반복 작업 시작..
만약 문제가 있는 시스템이라면, 시스템 관리자는 '1)'의 명령을 내려 프로세스를 수를 확인하고, 생각했던 수치 보다 많으면 '2)'번 명령어를 내려서 아파치를 재 시작 할 것이다. 언제 발생할지도 모르는 것 때문에 지속적으로 보고 있을 수 없고, 자리를 비울 수 도 없다.
bash 쉘에서는 반복작업을 위해서 여러가지 제어문을 제공한다.
지금 사용할 문법은 while 문이다.
while ( 조건 ) ; do
<문장>
done
위 '조건'이 만족하는한 '<문장>'은 계속 실행된다.
while ( true ) ; do
ls
done
위와같이 입력한다면, 계속.. 'ls'명령어를 실행 시킬 것이다.
대부분의 언어에서 그렇듯 반복문에서 빠져 나올려면, 'break' 문법이 있다.
while ( true ) ; do
ls
break
done
4) 반복 실행하여 프로세스가 특정 수치 이상이면 아파치 재 시작
우리의 목적한 일을 할 수 있는 쉘 프로그램을 만들어 보자.
while ( true ) ; do
if [ "`pgrep -x httpd | wc -l`" -ge "500" ] ; then
/usr/local/apache/bin/apachectl restart
fi
done
이렇게 작성하면 끝!!!
if 문은 조건을 비교하여 조건이 맞으면 then 이하의 문장을 실행한다. 문법은 다음과 같다.
if [ 조건 ] ; then
<문장>
fi
'조건'을 비교하기 위해서 '-ge' 를 썼다. ge(greater than or equal)이다. 크거나 같다의 의미.. 그렇다면,
gt(크다), le(작거나 같다), lt(작다), eq(같다) 등이 있을 것이라 예상할 수 있다.
5) 문제점 발견!!
위 쉘 스크립트를 돌려 두니.. 너무 자주 비교해서, 쉘스크립트가 서버에 부하를 준다..
그렇다면, sleep으로 비교 시간을 늘려 준다.
while ( true ) ; do
if [ "`pgrep -x httpd | wc -l`" -ge "500" ] ; then
/usr/local/apache/bin/apachectl restart
fi
sleep 1
done
위와같이 'sleep 1'을 입력하였다면, 1초가 쉬어라는 것이다. 1초간 쉬었다가 다시 비교하게 된다.
우리는 이것으로 원하는 결과를 얻었다.!
이젠 지속적으로 프로세스를 수를 확인하여 아파치를 재 시작해야 하는 노가다는 하지 않아도 된다. 하하하!!
이것으로 ' 실무에서 자주 사용되는 쉘 스크립트 #1' 강좌를 마무리 하겠습니다.
본 강좌의 설명이 어렵거나, 잘못된 부분이 있으면 언제든지 따끔한 지적을 바랍니다.
<2>
(MySQL DB관리 유틸리티)
지난번, 강좌(apache 자동 재 시작 프로그램)에 이어 실무에서 자주 사용되는 쉘 스크립트에 대한 강좌를 써 내려 가겠다. 물론 최대한 쉽고 최소한의 라인 수로 작성 가능한 쉘 스크립트에 대한 강좌를 쓸 것이다.
금번 강좌는 MySQL을 쉽게 관리 할 수 있는 툴이다. 서버 관리를 하다 보면, mysql 접속하여 여러가지 sql문으로 서버 상태를 알아 보거나, 모니터링 해야 할 때가 있다. 이럴 때 마다 로그인을 해서, sql문을 얻어내는 것은 아주 귀찮은 일이고, 또 익숙하지 않으면 아주 오랜 시간이 소요되는 작업이다. 내가 만들고자 하는 스크립트는 이런 작업을 쉽게 해 줄 수 있는 스크립트를 만드는 것이다.
먼저, 어떤일을 할 것인지 생각 해 보자...
1) MySQL의 프로세스 리스트를 보려면?
mysql의 프로세스 리스트는 ps 등의 명령어로 쉽게 볼 수 있다. 난 그런 것을 원하는 것이 아니고, 각 프로세스들이 하는 일들을 보고 싶다. mysql은 다음과 같은 방법으로 이런 일이 가능하게 제공한다.
mysqladmin -u root -p processlist
또는
mysql 접속한 상태에서
show processlist;
나는 일괄적으로 다음과 같은 방법으로 mysql 명령을 실행 시킬 것이다.
echo "쿼리;" | mysql -u"root" -p"비밀번호"
위 명령어는 다음과 같다.
echo "쿼리; " : "쿼리;"를 출력한다.
| : 파이프, 앞 명령어의 내용을 뒷 명령어의 표준 입력으로 넣는다.
mysql -u"root" -p"비밀번호" : mysql 서버에 접속한다. "비밀번호"는 서버의 비밀번호를 넣어준다.
우리가 원하는 일은 다음과 같이 한다.
echo "show processlist;" | mysql -u"root" -p"비밀번호"
2) root로 그냥 접속만 하려면?
'1)'의 프로세스 리스트를 보는 것 보다 쉽다. 단순하게..
mysql -u"root" -p"비밀번호"
이렇게만 하면 끝난다.
3) MySQL에 존재하는 database 들을 보려면?
'1)'의 프로세스 리스트를 응용하면,
echo "show databases;" | mysql -u"root" -p"비밀번호"
이렇게만 하면 끝난다.
이정도 했으면, 원하는 쿼리들을 위와 같은 방법으로 자유롭게 추가 할 수 있을 것이다.
내가 원하는 것은 위 명령어들을 모아서 쓰기 편리한 메뉴 방식으로 만드는 것이다.
어떻게 할까???
나는 키보드로 특정 문자들을 입력받아 변수에 넣을 것이다. 그리고 그 변수에 따라 위 명령어들을 실행 시킬 것이다. 이런 작업들을 특정 문자가 입력될 때 까지 반속 할 것이다.
4) 쉘 프로그램에서 키보드 입력 받기
나는 쉘 프로그램에서 키보드로 입력을 받아서 변수에 넣을 것이다. 어떻게 해야 할까
read <변수>
no라는 변수에 입력값을 넣으려면 다음과 같이 한다.
read no
이렇게 하면, '엔터'키를 누를 때 까지 입력을 받는다.
read no
echo "$no"
위와같이 하면 간단하게 입력받은 문자를 출력해서 보여 줄 수 있다.
5) 입력된 문자에 따라서 프로그램 실행 시키기
'4)'에서 입력받은 문자에 따라서, 프로그램을 실행시키기 위해서는 case문을 사용해야 한다.
다음과 같다.
case <변수> in
"값" )
<명령어> ;;
"값" )
<명령어> ;;
esac
위와같다.
위 방법을 우리가 목표 하는 것에 적용 시키면.
먼저 메시지를 뿌려 준다.
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
'
echo -n "번호 선택 : "
read no
case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
esac
위와같이 작성하면, 위 쉘 스크립트를 실행 시키면, 리스트가 나오며 입력 대기 할 것이고, 1,2,3 중 하나의 번호를 누르면 지정 명령어가 실행 될 것이다..
그렇다면, 다른 문자를 입력하면?? 조건에 만족하는 문자가 없으면 그냥 지나간다...
6) 실행이 끝나면 다시 메뉴 보여주기
명령어를 실행 시키고 빠져 나가 버리면, 다른 메뉴를 선택하기 위해서 또 명령어를 실행시켜야 한다. 하나의 명령어 실행 시키고 다시 메뉴 리스트를 반복적으로 보여 주기 위해서는 이전 강좌에서 배웠던, while 문을 사용하여 계속 실행 시키도록 해 보자.
while ( true ) ; do
<프로그램>
done
위와같은 문법을 우리 스크립트에 적용하면,
while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
'
echo -n "번호 선택 : "
read no
case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
esac
done
이렇게 하면, 선택한 명령어 실행이 끝나면, 다시 메뉴를 보여 줄 것이다.
clear 명령어는 화면의 내용을 지우라는 명령어이다. 메뉴가 줄줄줄~~ 내러 가는 일을 방지하기 위함니다.
7) 이 반복 메뉴에서 빠져 나오려면??
한 명령어 실행이 끝나면, 메뉴가 나올 것이다. Ctrl + C 키를 눌러 빠져 나올 수 있지만, 그건 좀 아닌 것 같은데... 하나의 항목을 추가 했다. 메뉴에서 'q'키를 누르면 빠져 나오게 한다.
while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
q. 끝내기
'
echo -n "번호 선택 : "
read no
case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"비밀번호" ;;
"2" )
mysql -u"root" -p"비밀번호" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"비밀번호" ;;
"q" )
exit 0 ;;
esac
done
위 쉘스크립트에서 'q'키를 누르면 exit 명령어를 실행시켜 빠져 나오게 된다. 물론 정상 종료이기 때문에 0을 리턴한다..
8) "비밀번호"가 바뀌면 다 고쳐 줘야 하나요??
비밀번호가 바뀌면 위 스크립트에서 "비밀번호" 부분을 모두 수정해야 한다. vi 등의 에디터에 치환 기능이 있어 한번에 치환 한다면 문제가 없다. 하지만, 비밀번호가 'mysql' 이라면, 얘기는 달라진다,.. 명령어인 'mysql'이 함께 바뀌기 때문에.. 하나 하나 수작업으로 고쳐야 한다.
변수라는 개념을 써서 이 부분을 해결 해 보자.
a="변수"
echo $a
이렇게 하면 출력값은 ?
변수
위와같이 출력된다. 변수라는 개념을 우리의 쉘스크립트에 적용시키면?
mysqlpw="비밀번호"
while ( true ) ; do
clean
echo '
1. 프로세스 리스트 보기
2. mysql 접속
3. database 리스트 보기
q. 끝내기
'
echo -n "번호 선택 : "
read no
case $no in
"1" )
echo "show processlist;" | mysql -u"root" -p"$mysqlpw" ;;
"2" )
mysql -u"root" -p"$mysqlpw" ;;
"3" )
echo "show databases;" | mysql -u"root" -p"$mysqlpw" ;;
"q" )
exit 0 ;;
esac
done
위와 같이 보라색 부분을 수정했다. 이렇게 수정하면, 상단의 변수만 수정 하면 다른 부분은 수정할 필요없이 적용되는 것이다.
우리는 이것으로
쉘 스크립트의 case문과, 변수, 키보드로부터 입력받기 를 알게 되었다.
여러가지 편리한 기능들을 넣어 둔다면, 나만의 관리툴로 만들 수 있을 것이다. [뿌듯]
이것으로 ' 실무에서 자주 사용되는 쉘 스크립트 #2' 강좌를 마무리 하겠습니다.
본 강좌의 설명이 어렵거나, 잘못된 부분이 있으면 언제든지 따끔한 지적을 바랍니다.
<3>
2008. 6. 1.
20080530 PlatformDay 2008 행사 참여
플렛폼데이 행사 참여 후~
http://www.platformday.com/pages/introduce
제목 Keynote: 클라우드 컴퓨팅의 성공 요인
요약
키워드 클라우드 컴퓨팅, 컴퓨팅 플랫폼, Grid Computing, 분산컴퓨팅
발표시간 10:10 ~ 10:50
강사 성기준
현 NHN 기술연구센터 선행기술개발랩 랩장 (2007 ~ )
전 NHN 분산컴퓨팅팀 팀장 (2006 ~ 2007)
전 삼성 SDS 기술연구소 이머징테크팀 팀장 (2003 ~ 2006)
2003년 귀국 전 미국 실리콘밸리 여러 회사 R&D Center에서 20년의 소프트웨어 기술 개발 경력
제목 Hadoop Overview and MapReduce Programming
요약 Hadoop의 분산파일시스템인 HDFS, 분산 데이타베이스인 HBase와 분산 프로그래밍모델인 MapReduce에 대해 소개한다. 어떤 작업들에 Hadoop 분산환경에 적용하기 적합하며 어떻게 MapReduce로 구현하는지에 대해 알아본다. 이해를 돕기 위해 실제 MapReduce로 구현된 검색엔진인 Nutch등을 예제로 소개할 예정이다.
키워드 Hadoop, HDFS, HBase, MapReduce
발표자료 PDF
발표시간 11:00 ~ 11:50
강사 이준복
KAIST 전산학과 박사과정
제목 Grid Computing at Yahoo!
요약 현재 야후에서 사용하고 있는 Hadoop 그리드 컴퓨팅 환경에 대한 소개를 하고 내부 직원들이 어떠한 방법, 용도로 그리드를 사용 하는지 소개를 한다. 또한 앞으로 그리드 컴퓨팅의 지원 방향에 대한 간략한 소개도 해본다. ps. 이해를 위해 Hadoop에 대한 약간의 소개를 포함할 수 있다.
키워드 Yahoo!, Hadoop
발표자료 PDF
발표시간 11:50 ~ 12:30
강사 전희원
Yahoo! Korea Search Eng. 팀 대리
블로그 : http://www.freesearch.pe.kr
제목 Tenth: Daum의 대용량 분산 파일 시스템 소개
요약 Daum 한메일, 카페 등의 서비스는 Peta 단위 이상의 대량 데이타를 다루고 있다. 이런 대량의 데이타를 안전하고 효율적으로 관리하기 위해선, 기존의 파일 시스템이 아닌 Daum만의 저비용, 대용량, 고가용성 파일시스템이 필요하였다. Tenth 는 Daum 에서 만든 대용량 분산 파일 시스템으로, 이번 세션에서는 Tenth 를 설계하면서 고려했던 구조적인 이슈들과 Tenth 를 사용하는 서비스들을 운영하면서 얻게된 노하우에 대해서 언급하고자 한다.
키워드 저비용, 대용량, 고가용성, 파일시스템, Tenth
발표자료 PDF
발표시간 1:30 ~ 2:10
강사 김남희
다음커뮤니케이션 기반기술팀 팀장
다음커뮤니케이션 2000년 입사
제목 MR.Flow: 분산 프로그래밍 서비스와 가상화 기반 Hadoop
요약 최근 대용량 데이터 처리를 위한 분산 프로그래밍 방식으로 Google이 제안한 MapReduce가 각광받고 있다. 하지만 데이터 처리를 위해 MapReduce 프로그램을 개발하고 Hadoop 환경을 꾸며 실행하는 것은 쉽지 않은 과정이다. NexR이 개발한 MR.Flow는 MapReduce 모듈들을 간편하게 조합하여 데이터 처리 프로그램을 만들고 실행해 볼 수 있는 웹서비스를 제공한다. 또한, Xen 가상화 클러스터 시스템인 Virtual Cluster Center(VCC)를 개발하여 Hadoop의 설치와 실행, 관리를 자동화해 준다. 본 발표에서는 MR.Flow와 Virtual Cluster Center에 대해 소개하고 기술적인 구조에 대해 논의한다. 그리고 이러한 툴들을 기반으로 대학에 분산 데이터 처리 교육과정 개설을 지원해 주는 Academic Distributed Computing Initiative 구상을 소개한다.
키워드 MapReduce, Hadoop, Xen, 가상화, MR.Flow, 분산 데이터 처리 교육
발표자료 PDF
발표시간 2:20 ~ 3:00
강사 한재선
NexR 대표이사
KAIST 정보미디어 경영대학원 대우교수
블로그 : http://www.web2hub.com
제목 광우병과 대용량 데이터 처리 플랫폼
요약 여자 3명, 남자 2명을 대상으로 시작한 휴먼 지놈 프로젝트(Human Genome Project)를 시발점으로 이제는 국제적 협력 프로젝트를 통해서천명이 넘는 다양한 인종의 유전적 변이(Genetic Variation)에 대한 연구가 진행되고 있다. 이에 국내에서도 한국인 만명을 대상으로 하는 대규모 프로젝트가 수행되면서 이제까지 다루어보지 못한 대규모의 유전적 변이 데이터가 쏟아져 나오기 시작했다. 그 결과 이제까지 다루어 보지 못했던 대규모의 유전적 변이 데이터의 분석을 위한 고속의 컴퓨팅 파워와 협업에 대한 필요가 절실해 졌다. 이러한 시점에서 생물학 데이터 분석을 위해 필요한 것은 무엇이고, 이를 어떻게 대용량 데이터 처리 플랫폼에 결합시킬 수 있을지에 대한 문제를 제기한다.
키워드 광우병, 데이터 처리 플랫폼, 휴먼 지놈 프로젝트, 유전적 변이, Genetic Variation
발표자료 PDF
발표시간 3:10 ~ 3:50
강사 홍창범
국립보건연구원의 유전체센터에서 근무하고 있으며, 리눅스 기반의 클러스터를 효율적으로 대규모 분석 업무에 사용할지에 대한 고민중이며, 국내의 바이오인포매틱스 관련 오픈소스 활성화에 대해 관심을 가지고 자신의 블로그(http://socmaster.homelinux.org/~hongiiv)를 통해 다양한 시도를 하고 있다.
제목 Neptune: 대용량 분산 데이터 저장소
요약 Neptune은 Google의 Bigtable과 같이 Column Oriented Data Storage로 PetaByte 규모의 데이터를 n개의 노드에 분산 저장시킨 후 실시간 또는 배치 업무에 데이터 서비스를 제공하는 시스템이다. 이번 발표에서는 Neptune의 소개 및 Neptune을 이용한 간단한 사례에 대해 알아본다.
키워드 Neptune, Bigtable, Hadoop, HBase, Distributed Data Storage
발표자료 PDF
발표시간 4:10 ~ 4:50
강사 김형준
NHN, 분산시스템TF 수석
구글 스타일의 분산컴퓨팅 관련 연구수행
블로그 : http://www.jaso.co.kr
제목 저비용 대규모 서비스 기반 분산파일시스템 기술
요약 웹2.0의 등장으로 인터넷 서비스가 공급자 중심에서 사용자 중심으로 패러다임이 이동함에 따라 UCC와 함께 인터넷 서비스 시장이 급속도로 증가하고 있다. 이러한 추세에 따라 인터넷 서비스 업체들의 경우 매일 수십GB 이상의 데이터가 새롭게 저장되고 있으며, 이를 효과적으로 관리할 수 있는 저비용, 고효율의 스토리지 환경이 요구되고 있다. 특히, 공개소프트웨어인 Hadoop DFS의 경우 다수의 서버 노드들을 하나의 단일 이미지로 가상화한 후 대량의 분산 데이터를 처리하기 위한 구조로서 주목받고 있으나, 동영상 서비스와 같은 인터넷 환경에 적용하기에는 몇가지 문제점들을 가지고 있다. 본 발표에서는 기존 Hadoop DFS를 인터넷 서비스 환경에 적용할 때 발생하는 문제점들에 대한 기술적 분석 내용과 이를 개선하기 위해 진행한 작업에 대하여 설명하고, 아울러 자체적으로 개발한 분산파일시스템에 대한 소개 및 적용 사례를 설명한다.
키워드 HDFS, 분산파일시스템, 스토리지가상화
발표자료 PDF
발표시간 5:00 ~ 5:40
강사 진기성
전자통신연구원 저장시스템연구팀 선임연구원(2001~)
클러스터 DBMS 개발(iBASE Cluster)
OSD 기반 파일시스템 개발(OASIS)
저비용 대규모 분산파일시스템 개발(GLORY-FS)
http://www.platformday.com/pages/introduce
제목 Keynote: 클라우드 컴퓨팅의 성공 요인
요약
키워드 클라우드 컴퓨팅, 컴퓨팅 플랫폼, Grid Computing, 분산컴퓨팅
발표시간 10:10 ~ 10:50
강사 성기준
현 NHN 기술연구센터 선행기술개발랩 랩장 (2007 ~ )
전 NHN 분산컴퓨팅팀 팀장 (2006 ~ 2007)
전 삼성 SDS 기술연구소 이머징테크팀 팀장 (2003 ~ 2006)
2003년 귀국 전 미국 실리콘밸리 여러 회사 R&D Center에서 20년의 소프트웨어 기술 개발 경력
제목 Hadoop Overview and MapReduce Programming
요약 Hadoop의 분산파일시스템인 HDFS, 분산 데이타베이스인 HBase와 분산 프로그래밍모델인 MapReduce에 대해 소개한다. 어떤 작업들에 Hadoop 분산환경에 적용하기 적합하며 어떻게 MapReduce로 구현하는지에 대해 알아본다. 이해를 돕기 위해 실제 MapReduce로 구현된 검색엔진인 Nutch등을 예제로 소개할 예정이다.
키워드 Hadoop, HDFS, HBase, MapReduce
발표자료 PDF
발표시간 11:00 ~ 11:50
강사 이준복
KAIST 전산학과 박사과정
제목 Grid Computing at Yahoo!
요약 현재 야후에서 사용하고 있는 Hadoop 그리드 컴퓨팅 환경에 대한 소개를 하고 내부 직원들이 어떠한 방법, 용도로 그리드를 사용 하는지 소개를 한다. 또한 앞으로 그리드 컴퓨팅의 지원 방향에 대한 간략한 소개도 해본다. ps. 이해를 위해 Hadoop에 대한 약간의 소개를 포함할 수 있다.
키워드 Yahoo!, Hadoop
발표자료 PDF
발표시간 11:50 ~ 12:30
강사 전희원
Yahoo! Korea Search Eng. 팀 대리
블로그 : http://www.freesearch.pe.kr
제목 Tenth: Daum의 대용량 분산 파일 시스템 소개
요약 Daum 한메일, 카페 등의 서비스는 Peta 단위 이상의 대량 데이타를 다루고 있다. 이런 대량의 데이타를 안전하고 효율적으로 관리하기 위해선, 기존의 파일 시스템이 아닌 Daum만의 저비용, 대용량, 고가용성 파일시스템이 필요하였다. Tenth 는 Daum 에서 만든 대용량 분산 파일 시스템으로, 이번 세션에서는 Tenth 를 설계하면서 고려했던 구조적인 이슈들과 Tenth 를 사용하는 서비스들을 운영하면서 얻게된 노하우에 대해서 언급하고자 한다.
키워드 저비용, 대용량, 고가용성, 파일시스템, Tenth
발표자료 PDF
발표시간 1:30 ~ 2:10
강사 김남희
다음커뮤니케이션 기반기술팀 팀장
다음커뮤니케이션 2000년 입사
제목 MR.Flow: 분산 프로그래밍 서비스와 가상화 기반 Hadoop
요약 최근 대용량 데이터 처리를 위한 분산 프로그래밍 방식으로 Google이 제안한 MapReduce가 각광받고 있다. 하지만 데이터 처리를 위해 MapReduce 프로그램을 개발하고 Hadoop 환경을 꾸며 실행하는 것은 쉽지 않은 과정이다. NexR이 개발한 MR.Flow는 MapReduce 모듈들을 간편하게 조합하여 데이터 처리 프로그램을 만들고 실행해 볼 수 있는 웹서비스를 제공한다. 또한, Xen 가상화 클러스터 시스템인 Virtual Cluster Center(VCC)를 개발하여 Hadoop의 설치와 실행, 관리를 자동화해 준다. 본 발표에서는 MR.Flow와 Virtual Cluster Center에 대해 소개하고 기술적인 구조에 대해 논의한다. 그리고 이러한 툴들을 기반으로 대학에 분산 데이터 처리 교육과정 개설을 지원해 주는 Academic Distributed Computing Initiative 구상을 소개한다.
키워드 MapReduce, Hadoop, Xen, 가상화, MR.Flow, 분산 데이터 처리 교육
발표자료 PDF
발표시간 2:20 ~ 3:00
강사 한재선
NexR 대표이사
KAIST 정보미디어 경영대학원 대우교수
블로그 : http://www.web2hub.com
제목 광우병과 대용량 데이터 처리 플랫폼
요약 여자 3명, 남자 2명을 대상으로 시작한 휴먼 지놈 프로젝트(Human Genome Project)를 시발점으로 이제는 국제적 협력 프로젝트를 통해서천명이 넘는 다양한 인종의 유전적 변이(Genetic Variation)에 대한 연구가 진행되고 있다. 이에 국내에서도 한국인 만명을 대상으로 하는 대규모 프로젝트가 수행되면서 이제까지 다루어보지 못한 대규모의 유전적 변이 데이터가 쏟아져 나오기 시작했다. 그 결과 이제까지 다루어 보지 못했던 대규모의 유전적 변이 데이터의 분석을 위한 고속의 컴퓨팅 파워와 협업에 대한 필요가 절실해 졌다. 이러한 시점에서 생물학 데이터 분석을 위해 필요한 것은 무엇이고, 이를 어떻게 대용량 데이터 처리 플랫폼에 결합시킬 수 있을지에 대한 문제를 제기한다.
키워드 광우병, 데이터 처리 플랫폼, 휴먼 지놈 프로젝트, 유전적 변이, Genetic Variation
발표자료 PDF
발표시간 3:10 ~ 3:50
강사 홍창범
국립보건연구원의 유전체센터에서 근무하고 있으며, 리눅스 기반의 클러스터를 효율적으로 대규모 분석 업무에 사용할지에 대한 고민중이며, 국내의 바이오인포매틱스 관련 오픈소스 활성화에 대해 관심을 가지고 자신의 블로그(http://socmaster.homelinux.org/~hongiiv)를 통해 다양한 시도를 하고 있다.
제목 Neptune: 대용량 분산 데이터 저장소
요약 Neptune은 Google의 Bigtable과 같이 Column Oriented Data Storage로 PetaByte 규모의 데이터를 n개의 노드에 분산 저장시킨 후 실시간 또는 배치 업무에 데이터 서비스를 제공하는 시스템이다. 이번 발표에서는 Neptune의 소개 및 Neptune을 이용한 간단한 사례에 대해 알아본다.
키워드 Neptune, Bigtable, Hadoop, HBase, Distributed Data Storage
발표자료 PDF
발표시간 4:10 ~ 4:50
강사 김형준
NHN, 분산시스템TF 수석
구글 스타일의 분산컴퓨팅 관련 연구수행
블로그 : http://www.jaso.co.kr
제목 저비용 대규모 서비스 기반 분산파일시스템 기술
요약 웹2.0의 등장으로 인터넷 서비스가 공급자 중심에서 사용자 중심으로 패러다임이 이동함에 따라 UCC와 함께 인터넷 서비스 시장이 급속도로 증가하고 있다. 이러한 추세에 따라 인터넷 서비스 업체들의 경우 매일 수십GB 이상의 데이터가 새롭게 저장되고 있으며, 이를 효과적으로 관리할 수 있는 저비용, 고효율의 스토리지 환경이 요구되고 있다. 특히, 공개소프트웨어인 Hadoop DFS의 경우 다수의 서버 노드들을 하나의 단일 이미지로 가상화한 후 대량의 분산 데이터를 처리하기 위한 구조로서 주목받고 있으나, 동영상 서비스와 같은 인터넷 환경에 적용하기에는 몇가지 문제점들을 가지고 있다. 본 발표에서는 기존 Hadoop DFS를 인터넷 서비스 환경에 적용할 때 발생하는 문제점들에 대한 기술적 분석 내용과 이를 개선하기 위해 진행한 작업에 대하여 설명하고, 아울러 자체적으로 개발한 분산파일시스템에 대한 소개 및 적용 사례를 설명한다.
키워드 HDFS, 분산파일시스템, 스토리지가상화
발표자료 PDF
발표시간 5:00 ~ 5:40
강사 진기성
전자통신연구원 저장시스템연구팀 선임연구원(2001~)
클러스터 DBMS 개발(iBASE Cluster)
OSD 기반 파일시스템 개발(OASIS)
저비용 대규모 분산파일시스템 개발(GLORY-FS)
피드 구독하기:
글 (Atom)