728x90

일반적으로 Web 서비스를 구성할때는 Load balancing 역활을 수행하는 L4 Switch 이하로 n대의 WEB 서버를 구성하여 부하분산과 이중화를 통해 서비스 가용성을 높인다.

 

만약 다량의 Web Server Node를 동시에 점검해야할 사항이 발생한다면, Client Hosts 파일에 서비스 도메인에 대하여 IP를 수동 정의하여 웹브라우저를 통해 Server Node별 체크를 수행하거나 각 웹서버별 Access 로그나 Error 로그를 기준으로 체크하게 된다.

 

만약 이런 일련의 과정이 여의치 못하거나 간단히 각 Web Server Node들의 상태체크만을 원한다면 아래와 같이 Shell Script를 통해 간단히 점검이 가능하다.

 

이하 Shell Script는 curl 명령을 통해 Web Server에서 응답된 상태 Code를 기준으로 상태를 판별하며, HTTP 응답코드는 아래와 같이 분류된다.

 

 

발췌 - 위키백과사전 HTTP 상태코드 (http://ko.wikipedia.org/wiki/HTTP_%EC%83%81%ED%83%9C_%EC%BD%94%EB%93%9C)

 

2xx (성공)
 
이 클래스의 상태 코드는 클라이언트가 요청한 동작을 수신하여 이해했고 승낙했으며 성공적으로 처리했음을 가리킨다.
 200(성공): 서버가 요청을 제대로 처리했다는 뜻이다. 이는 주로 서버가 요청한 페이지를 제공했다는 의미로 쓰인다.
 201(작성됨): 성공적으로 요청되었으며 서버가 새 리소스를 작성했다.
 202(허용됨): 서버가 요청을 접수했지만 아직 처리하지 않았다.
 203(신뢰할 수 없는 정보): 서버가 요청을 성공적으로 처리했지만 다른 소스에서 수신된 정보를 제공하고 있다.
 204(콘텐츠 없음): 서버가 요청을 성공적으로 처리했지만 콘텐츠를 제공하지 않는다.
 205(콘텐츠 재설정): 서버가 요청을 성공적으로 처리했지만 콘텐츠를 표시하지 않는다. 204 응답과 달리 이 응답은 요청자가 문서 보기를 재설정할 것을 요구한다(예: 새 입력을 위한 양식 비우기).
 206(일부 콘텐츠): 서버가 GET 요청의 일부만 성공적으로 처리했다.
 207(다중 상태, RFC 4918)
 208(이미 보고됨, RFC 5842)
 226 IM Used (RFC 3229)
 
3xx (리다이렉션 완료)
 
클라이언트는 요청을 마치기 위해 추가 동작을 취해야 한다.[1]
 300(여러 선택항목): 서버가 요청에 따라 여러 조치를 선택할 수 있다. 서버가 사용자 에이전트에 따라 수행할 작업을 선택하거나, 요청자가 선택할 수 있는 작업 목록을 제공한다.
 301(영구 이동): 요청한 페이지를 새 위치로 영구적으로 이동했다. GET 또는 HEAD 요청에 대한 응답으로 이 응답을 표시하면 요청자가 자동으로 새 위치로 전달된다.
 302(임시 이동): 현재 서버가 다른 위치의 페이지로 요청에 응답하고 있지만 요청자는 향후 요청 시 원래 위치를 계속 사용해야 한다.
 303(기타 위치 보기): 요청자가 다른 위치에 별도의 GET 요청을 하여 응답을 검색할 경우 서버는 이 코드를 표시한다. HEAD 요청 이외의 모든 요청을 다른 위치로 자동으로 전달한다.
 304(수정되지 않음): 마지막 요청 이후 요청한 페이지는 수정되지 않았다. 서버가 이 응답을 표시하면 페이지의 콘텐츠를 표시하지 않는다. 요청자가 마지막으로 페이지를 요청한 후 페이지가 변경되지 않으면 이 응답(If-Modified-Since HTTP 헤더라고 함)을 표시하도록 서버를 구성해야 한다.
 305(프록시 사용): 요청자는 프록시를 사용하여 요청한 페이지만 액세스할 수 있다. 서버가 이 응답을 표시하면 요청자가 사용할 프록시를 가리키는 것이기도 하다.
 307(임시 리다이렉션): 현재 서버가 다른 위치의 페이지로 요청에 응답하고 있지만 요청자는 향후 요청 시 원래 위치를 계속 사용해야 한다.
 308(영구 리다이렉션, RFC에서 실험적으로 승인됨)
 
4xx (요청 오류)
 
4xx 클래스의 상태 코드는 클라이언트에 오류가 있음을 나타낸다.
 400(잘못된 요청): 서버가 요청의 구문을 인식하지 못했다.
 401(권한 없음): 이 요청은 인증이 필요한다. 서버는 로그인이 필요한 페이지에 대해 이 요청을 제공할 수 있다.
 403(금지됨): 서버가 요청을 거부하고 있다.
 404(찾을 수 없음): 서버가 요청한 페이지를 찾을 수 없다. 예를 들어 서버에 존재하지 않는 페이지에 대한 요청이 있을 경우 서버는 이 코드를 제공한다.
 405(허용되지 않는 방법): 요청에 지정된 방법을 사용할 수 없다.
 406(허용되지 않음): 요청한 페이지가 요청한 콘텐츠 특성으로 응답할 수 없다.
 407(프록시 인증 필요): 이 상태 코드는 401(권한 없음)과 비슷하지만 요청자가 프록시를 사용하여 인증해야 한다. 서버가 이 응답을 표시하면 요청자가 사용할 프록시를 가리키는 것이기도 한다.
 408(요청 시간초과): 서버의 요청 대기가 시간을 초과하였다.
 409(충돌): 서버가 요청을 수행하는 중에 충돌이 발생했다. 서버는 응답할 때 충돌에 대한 정보를 포함해야 한다. 서버는 PUT 요청과 충돌하는 PUT 요청에 대한 응답으로 이 코드를 요청 간 차이점 목록과 함께 표시해야 한다.
 410(사라짐): 서버는 요청한 리소스가 영구적으로 삭제되었을 때 이 응답을 표시한다. 404(찾을 수 없음) 코드와 비슷하며 이전에 있었지만 더 이상 존재하지 않는 리소스에 대해 404 대신 사용하기도 한다. 리소스가 영구적으로 이동된 경우 301을 사용하여 리소스의 새 위치를 지정해야 한다.
 411(길이 필요): 서버는 유효한 콘텐츠 길이 헤더 입력란 없이는 요청을 수락하지 않는다.
 412(사전조건 실패): 서버가 요청자가 요청 시 부과한 사전조건을 만족하지 않는다.
 413(요청 속성이 너무 큼): 요청이 너무 커서 서버가 처리할 수 없다.
 414(요청 URI가 너무 긺): 요청 URI(일반적으로 URL)가 너무 길어 서버가 처리할 수 없다.
 415(지원되지 않는 미디어 유형): 요청이 요청한 페이지에서 지원하지 않는 형식으로 되어 있다.
 416(처리할 수 없는 요청범위): 요청이 페이지에서 처리할 수 없는 범위에 해당되는 경우 서버는 이 상태 코드를 표시한다.
 417(예상 실패): 서버는 Expect 요청 헤더 입력란의 요구사항을 만족할 수 없다.
 418(I'm a teapot, RFC 2324)
 420(Enhance Your Calm, 트위터)
 422(처리할 수 없는 엔티티, WebDAV; RFC 4918)
 423(잠김,WebDAV; RFC 4918)
 424(실패된 의존성, WebDAV; RFC 4918)
 424(메쏘드 실패, WebDAV)
 425(정렬되지 않은 컬렉션, 인터넷 초안)
 426(업그레이드 필요, RFC 2817)
 428(전제조건 필요, RFC 6585)
 429(너무 많은 요청, RFC 6585)
 431(요청 헤더 필드가 너무 큼, RFC 6585)
 444(응답 없음, Nginx)
 449(다시 시도, 마이크로소프트)
 450(윈도 자녀 보호에 의해 차단됨, 마이크로소프트)
 451(법적인 이유로 이용 불가, 인터넷 초안)
 451(리다이렉션, 마이크로소프트)
 494(요청 헤더가 너무 큼, Nginx)
 495(Cert 오류, Nginx)
 496(Cert 없음, Nginx)
 497(HTTP to HTTPS, Nginx)
 499(클라이언트가 요청을 닫음, Nginx)
 
5xx (서버 오류)
 
서버가 유효한 요청을 명백하게 수행하지 못했음을 나타낸다.[1]
 500(내부 서버 오류): 서버에 오류가 발생하여 요청을 수행할 수 없다.
 501(구현되지 않음): 서버에 요청을 수행할 수 있는 기능이 없다. 예를 들어 서버가 요청 메소드를 인식하지 못할 때 이 코드를 표시한다.
 502(불량 게이트웨이): 서버가 게이트웨이나 프록시 역할을 하고 있거나 또는 업스트림 서버에서 잘못된 응답을 받았다.
 503(서비스를 사용할 수 없음): 서버가 오버로드되었거나 유지관리를 위해 다운되었기 때문에 현재 서버를 사용할 수 없다. 이는 대개 일시적인 상태이다.
 504(게이트웨이 시간초과): 서버가 게이트웨이나 프록시 역할을 하고 있거나 또는 업스트림 서버에서 제때 요청을 받지 못했다.
 505(HTTP 버전이 지원되지 않음): 서버가 요청에 사용된 HTTP 프로토콜 버전을 지원하지 않는다.
 506(Variant Also Negotiates, RFC 2295)
 507(용량 부족, WebDAV; RFC 4918)
 508(루프 감지됨, WebDAV; RFC 5842)
 509(대역폭 제한 초과, Apache bw/limited extension)
 510(확장되지 않음, RFC 2774)
 511(네트워크 인증 필요, RFC 6585)
 598(네트워크 읽기 시간초과 오류, 알 수 없음)
 599(네트워크 연결 시간초과 오류, 알 수 없음)

 

 

 

1. Check 대상 Web Server Node의 IP 또는 Domain을 기준으로 리스트 파일 작성

 

[root@TEST-01 shell]# 
[root@TEST-01 shell]# vi list
127.0.0.1
168.126.63.1
168.126.63.2
1.2.3.4
yahoo.com
google.com
naver.com
helperchoi.com
helperchoi.com/notfound.html
[root@TEST-01 shell]# 

 

 

2. Shell Script 의 실행 예시

 

[root@TEST-01 shell]# 

[root@TEST-01 shell]# 
[root@TEST-01 shell]# ./check_web.sh

 

Usage1 - ./check_web.sh [List File]
ex1) - ./check_web.sh list

 

[root@TEST-01 shell]# 
[root@TEST-01 shell]# ./check_web.sh 111

 

Usage1 - ./check_web.sh [List File]
ex1) - ./check_web.sh list

 

[root@TEST-01 shell]# 
[root@TEST-01 shell]# ./check_web.sh list

 

========================= HTTP OK =========================
HTTP Code 301 OK - yahoo.com
HTTP Code 301 OK - google.com
HTTP Code 301 OK - naver.com
HTTP Code 200 OK - helperchoi.com

======================== HTTP Fail ========================
HTTP Code 403 Fail - 127.0.0.1
HTTP Code 404 Fail - helperchoi.com/notfound.html

===================== HTTP Not Listen =====================
HTTP Not Listen - 168.126.63.1
HTTP Not Listen - 168.126.63.2
HTTP Not Listen - 1.2.3.4

 

[root@TEST-01 shell]# 

[root@TEST-01 shell]# 

 

 

3. Shell Script Code

 

[root@TEST-01 shell]# 
[root@TEST-01 shell]# vi check_web.sh
#!/bin/bash

 

declare -a ARRAY_OK
declare -a ARRAY_FAIL
declare -a ARRAY_NOT

 

[ $1 -ge 0 2>/dev/null ]

 

if [ $# -eq 1 -a -e "$1" ]
then
 LIST_FILE=`cat $1`

 

 for LIST in ${LIST_FILE}
 do
  CHECK_HTTP_CODE=`curl -I -4 -m 1 ${LIST} 2>/dev/null | grep "^HTTP" | awk '{print $2}'`
  VERIFY_CEHCK=`expr ${CHECK_HTTP_CODE} + 0 2>/dev/null`
 
  if [ "$VERIFY_CEHCK" -ge 1 ]
  then
   if [ "$CHECK_HTTP_CODE" -eq 200 -o "$CHECK_HTTP_CODE" -le 308 ]
   then
    ARRAY_OK=("${ARRAY_OK[@]}" "`echo "HTTP Code ${CHECK_HTTP_CODE} OK - ${LIST}"`")
   else
    ARRAY_FAIL=("${ARRAY_FAIL[@]}" "`echo "HTTP Code ${CHECK_HTTP_CODE} Fail - ${LIST}"`")
   fi
  else
   ARRAY_NOT=("${ARRAY_NOT[@]}" "`echo "HTTP Not Listen - ${LIST}"`")
  fi
 done
 
 echo
 echo "========================= HTTP OK ========================="
 LOOP_COUNT=0
 LOOP_LIMIT=${#ARRAY_OK[@]}
 while [ "${LOOP_COUNT}" -le "${LOOP_LIMIT}" ]
 do
  echo "${ARRAY_OK[${LOOP_COUNT}]}"
  LOOP_COUNT=`echo "${LOOP_COUNT} + 1" | bc`
 done
 
 echo "======================== HTTP Fail ========================"
 LOOP_COUNT=0
 LOOP_LIMIT=${#ARRAY_FAIL[@]}
 while [ "${LOOP_COUNT}" -le "${LOOP_LIMIT}" ]
 do
  echo "${ARRAY_FAIL[${LOOP_COUNT}]}"
  LOOP_COUNT=`echo "${LOOP_COUNT} + 1" | bc`
 done
 
 echo "===================== HTTP Not Listen ====================="
 LOOP_COUNT=0
 LOOP_LIMIT=${#ARRAY_NOT[@]}
 while [ "${LOOP_COUNT}" -le "${LOOP_LIMIT}" ]
 do
  echo "${ARRAY_NOT[${LOOP_COUNT}]}"
  LOOP_COUNT=`echo "${LOOP_COUNT} + 1" | bc`
 done

 

else 
 echo
 echo "Usage1 - $0 [List File]"
 echo "ex1) - $0 list"
 echo
 exit 0
fi

 

 

출처 : 불량펭귄 - http://blog.helperchoi.com

반응형

'UNIX & LINUX > CentOS' 카테고리의 다른 글

centOS iptables 사용법  (0) 2016.05.27
728x90

iptables은 강력한 패킷필터링 툴입니다.
기존의 iptables에 관한 자세한 문서들이 많이 나와있지만
이 문서는 리눅스 환경을 전제로 하며 iptables의 초심자들을 위해 설명을 하고자 합니다.
오타나 틀린 내용이 있으면 홈페이지에 관련부분을 기제해주기바랍니다.

작성일 2002.10.13

작성자 : 김창현 [CTCquatre] http://www.eyetolife.com

[ 패킷필터링 지식 ]

패킷필터링이란?

패킷필터링은 지나가는 패킷의 해더를 보고 그 전체 패킷의 운명을 결정하는 것을 말한다.
(iptables의 경우 많은 개발중인 기능에서 헤더에 그치지 않고 data의 내용을 검토하기도 한다. 가장 대표적인것이 string match기능이다.)

*:(일반적으로 패킷은 헤더와 데이타를 가진다. 헤더에 필터링할 정보인 출발지IP:PORT,도착지 IP:PORT, checksum,프로토콜 옵셋등을 가지며 데이터는 각각의 전송데이터가 들어간다.)

리눅스 박스의 패킷필터링의 역사

리눅스는 커널 1.1버젼 부터 패킷필터링을 포함하기 시작했다.
제 1세대는 BSD의 ipfw을 기본으로 하였고 
2.0버젼에서 ipfwadm이 사용되었으며
1998년에 2.2기반 패킷필터링툴인 ipchains를 내놓았다. 
그리고 이글에서 논의하고자 하는 제 4세대 필터링툴인 iptables이 2.4커널을 위해
만들어졌다.

netfilter?

일반 iptables사용자들이 가장간과하기 쉬운부분중 한 부분이다.
iptables이 패킷을 필터링 하는것이 아니다.
패킷필터링은 커널에 탑제된 netfilter기능으로 하며
iptables은 단지 netfilter의 룰을 세워줄 뿐이다.
즉 다시 말하자면 iptables은 룰셋구축 툴이라는 말이다.

[ 패킷필터링 ]

iptables에 대해

iptable에 기본 Chain은 아래와 같다.

INPUT chain
FORWARD chain
OUTPUT chain

위의 3가지가 기본 체인이다. 체인들의 모식도는 아래와 같다.

——>INPUT——> Linux Box ——>OUTPUT———>
———↕—————————-↕
———└——— FORWARD ———-┘

여러분의 Linux box를 도착지로 삼는 모든패킷은 INPUT Chain을 통과하게 되며 
여러분의 Linux box에서 생성되 외부로 보내지는 모든패킷은 OUTPUT Chain을 
통과하게 된다.

Forward chain은 *엄밀히 말하자면 도착지가 여러분의 Linux box가 아닌 패킷이 통과하게 되는 체인이다.

*:(다음문서에 다루게 될 Masqurading시에 패킷의 destnationIP정보는 여러분의 Linux box이지만 패킷의 최종도착지는 내부네트워크의 어떠한 컴퓨터일것이다)

지금 커맨드라인에 아래와 같이 쳐보기 바란다.

# iptables -A INPUT -j DROP

엔터키를 누르는 즉시 여러분의 Linux box로 오는 패킷은 모두 거부당할것이다. 즉 모든 통신이 끊어진다.

위의 룰을 굳이 말로 옮기자면

-A:룰을 추가한다 
INPUT: 패킷이 들어오는 체인에 
-j:패킷의 운명을 결정한다. 
DROP: 패킷을 버려라.

즉, INPUT체인으로 들어오는 패킷을 모두 버리는 룰을 추가하는 명령이다.

적용시킨 룰을 보고 싶다면 

# iptables -L 

이라는 명령을 치면된다.

-A와 같은 위치에 있는 옵션은 아래와 같다.

체인에 새로운 규칙을 추가하기 (-A) 
체인의 어떤 지점에 규칙을 삽입하기 (-I) 
체인의 어떤 지점의 규칙을 교환하기 (-R) 
체인의 어떤 지점의 규칙을 제거하기 (-D) 
체인에서 일치하는 첫번째 규칙을 제거하기 (-D) 

이제 위에서 내린 룰을 지워 통신이 되게 하자.
아래와 같이 명령을 내리면 된다.
# iptables -D INPUT 1
또는
# iptables -D INPUT -j DROP 하면 될것이다.

첫번째 방법은 index(룰의 순서)를 지정해서 지우는 방법이고, 두번째는 룰의 내용으로 지우는것이다.

-I,-R은 첫번째 방법과 유사하게 쓸수있다.

룰을 다시 세우고 목록을 보자.

# iptables -A INPUT -j DROP
# iptables -L

살펴보면 

Chanin INPUT (policy ACCEPT)

위와 같은 줄을 볼수있을것이다.
저 줄 밑에는 여러분들이 세운 룰의 정보를 볼수있을것이다.

(policy ACCEPT)를 설명하자면 여러분들이 세운룰에 해당되지 않을때
마지막으로 기본정책을 따라 패킷의 운명을 결정하게 된다. 여기서는 ACCEPT이므로
패킷은 받아드려질것이다. 아지만 이것을 DROP으로하면 패킷은 버려질것이다.

그리고 패킷필터링을 알아가면서 여러룰들을 세울것이다.
기본적으로 룰은 세워진 순서대로 패킷을 검사한다.

이제 기본정책을 바꾸어 보자.

# iptables -P INPUT DROP

위의 명령을 내리고 다시 iptables -L을 하면

Chanin INPUT (policy DROP)으로 된걸 볼수있다.

-P와 동등 위치의 옵션은 아래와 같다.

새로운 체인 만들기 (-N). 
비어있는 체인을 제거하기 (-X).
※ 이 두옵션은 직접체인을 만들었을경우와 제어할경우에 해당된다. 기본체인(INPUT,OUTPUT,FORWARD) 에는 해당되지 않는다.

미리 만들어진 체인의 정책을 바꾸기 (-P) 
어떤 체인의 규칙들을 나열하기 (-L) 
체인으로부터 규칙들을 지우기 (-F) 
체인내의 모든 규칙들의 패킷과 바이트의 카운드를 0 으로 만들기 (-Z) 

[ 패킷의 목적지또는 출처 제어 ] 

패킷출처 제어옵션 -s

# iptables -A INPUT -s 192.168.10.10 -j DROP 

위에 같은 명령을 내렸다면 192.168.10.10으로 부터 온 패킷은 모두 버려지게 된다.

-s(–source,–src와 같은 옵션이다.) : 패킷의 출처 IP 지정

목적지 제어옵션 -d

# iptables -A INPUt -d 192.168.10.12 -j DROP

위와 같은 명령을 내렸다면 192.168.10.12의 IP를 도착지로 가지고있는 패킷은 모두 버려지게된다.

-d(–destination,–dst와 같은 옵션이다.): 패킷의 도착지 IP지정

※ IP지정 이외에 몇 가지 방법이 더 존재한다.
-s www.xxxx.com : 도메인으로 제어
-s 192.168.10.0/24 : 네트워크 또는 집단으로 제어
-s 192.168.10.0/255.255.255.0 :위와 동일

※ 보통 프로그래밍 약속기호처럼 !는 역(‘not’)이라는 것을 표시한다.
ex) -s ! 192.168.10.10 이라고 하면 “출발지가 192.168.10.10이 아닌” 이라는 뜻이된다.

[ 프로토콜 제어 ]

프로토콜제어 옵션은 -p이다

-p옵션의 인자는 TCP,UDP,ICMP가 될수있다.

# iptables -A INPUT -p TCP -j ACCEPT 

라는 명령을 내렸다면 tcp프로토콜을 쓰는 모든 패킷은 ACCEPT에 의해 허락될것이다.

※ -p의 인자로 TCP,UDP,ICMP의 프로토콜번호를 알고있다면 번호를 써도 상관없다.

포트 제어

포트제어 옵션은 –sport와 –dport이다

–sport는 패킷의 출발지 포트이다.( –source-port와 같은 옵션이다.)

–dport는 패킷의 도착지 포트이다.( –destination-port와 같은 옵션이다.)

# iptables -A INPUT -p tcp –dport 80 -j DROP

위와 같은 명령은 tcp프로토콜의 80(www:웹서버포트)번 포트를 목적지로 하는 패킷을
버리는 것이다.

※ –dport나 –sport의 인자로 서비스이름을 적어도 된다.
ex) –dport www

※ 여러 포트를 지정해야 된다면 –dport 1024:65535 와 같이 지정할수있다. 
뜻은 1024 부터 65535번까지라는 뜻이다.

[ 인터페이스 지정 ]

인터페이스는 -i (input interface), -o (output interface)로 지정할수있다.

# iptables -A INPUT -i eth0 -p tcp –dport 80 -j DROP

위의 명령은 -i eth0옵션을 빼고는 port지정 예와 같다.

-i eth0는 eth0로 들오는 모든 패킷을 뜻한다.

보통 리눅스 박스처럼 인터넷과 연결된 디바이스가 1개라면 필요없는 옵션이 되겠지만
만약 eth0, eth1등 2개이상의 인터페이스가 인터넷과 연결되어있다면 위의 옵션은 유용하게 쓰일것이다.

※ INPUT 체인은 -i 옵션만 쓸수 있고, OUTPUT 체인에는 -o옵션만 쓸쑤있다.
반면에 FORWARD 체인은 -i,-o 옵션 두가지 다 쓸쑤있다. 이유는 다음문서에서 다루겠다.

총괄적인 예:

# iptables -A INPUT -i eth0 -d 192.168.10.10 -p tcp –dport 80 -j DROP

해설: INPUT 체인에 – 입력인터페이스가 eth0이고 도착지가 192.168.10.10이고
프로토콜은 tcp이며 도착 포트는 80(www)인 패킷은 DROP시켜라.

이제까지는 별 다른 지식이 없이도 이해할수있는 부분이었다.
하지만 지금부터 나오게될 내용은 tcp/ip의 기반적인 지식을 가지고있어야
이해하기 쉬울것이다.
tcp/ip지식이 필요한 옵션에 대해서는 그에따른 자세한 설명을 하겠지만
이해가 되지 않는 부분은 다른 문서나 책을 찾아보길 바란다.

[ 패킷의 행동 유형에 따른 필터링(–tcp-flags,m state –state) ]

! 주의 : 밑에 나오는 모든옵션은 TCP프로토콜옵션(-p TCP)가 먼저 
선행되어 있어야 적용되는 옵션이다.

1)
–tcp-flags 옵션은 상태에 따라 유용하게 설정할수있다.
이 옵션을 설정하는 가장 큰 예는 한방향으로만 통신이 되게끔설정하기 위해
많이 사용한다. 
tcp/ip는 3핸드쉐이크의 접속방식이다.
즉. 접속요청패킷,접속허가 패킷,확인패킷

접속 단계를 좀더 자세하게 보면

C: Client S:Server

1) C ——— syn ——-▷ S
2) C ◁——- syn ack —– S
3) C ——— ack ——-▷ S

이런식으로 접속절차가 이루어진다.

syn패킷은 접속요청 플래그(syn)가 설정된 패킷이므로 syn패킷만 막으면 상대편에서 접속을 할수 없다는 것이다.

※ Dos공격의 일종인 Syn Flooding이 서버에 위에서 말한 syn형패킷을 무수히 많이
보내는 것이다.

이제 본격적으로 –tcp-flags옵션으로 syn 접속형 패킷을 막는것을 하겠다.

# iptables -A INPUT -p TCP –tcp-flags SYN,RST,ACK SYN -j DROP

–tcp-flags에 첫번째 인자는 검사할 리스트 마스크이다. 
두번째 인자는 설정되어있어야할 플래그다.
즉 syn,rst,ack플래그중 syn이 set이 1로 되어있으면 위의 –tcp-flags설정에
해당이 되므로 패킷은 DROP된다.

위의 옵션과 같은 뜻을 가진것이 있는데 그것은 –syn이다.
–syn은 ‘–tcp-flags SYN,RST,ACK SYN’의 뜻을 가지고 있다.

2)
–tcp-flags보다 더 간단하게 설정하는 방법이 있다.
바로 tcp의 상태천이 다이아그램을 축소시켜 놓은듯한 느낌을 받는 상태에 따른 패킷분류를 iptables은 지원한다.

이것은 확장기능이므로 -m 플래그로 설정은 한다.

사용옵선은 -m state –state 이다.

인자값으로 들어가야할 상태에따른 리스트는 아래와 같다.

NEW : 새로운 접속을 만드는 패킷 

ESTABLISHED :존재하는 접속에 속하는 패킷 (즉, 응답 패킷을 가졌던 것) 
즉 접속이 허가되고 통신하면서 발생되는 패킷이다. 

RELATED :기존의 접속의 부분은 아니지만 연관성을 가진 패킷으로 . 
ICMP 에러 나 (FTP 모듈이 삽입 되어있으면) ftp 데이터 
접속을 형성하는 패킷. 

INVALID :어떤 이유로 확인할 수 없는 패킷. 알려진 접속과 부합하지 않는 ICMP 에러와 
‘out of memory’ 등을 포함한다. 보통 이런 패킷은 DROP 된다. 

이제 이 state 옵션을 사용해보자

위의 –tcp-flags옵션에서 예제와 같은 작용을 하는 룰을 만들어보겠다.

# iptables -A INPUT -p TCP -m state –state NEW -j DROP

왜 룰이 이렇게 되는지 차근차근 읽어보았다면 쉽게 이해가 될것이다.

일반적으로 서버는

# iptables -A INPUT -p TCP –dport 특정포트 -m state –state NEW,ESTABLISHED -j ACCEPT

이렇게 룰을 많이 세운다.
뜻은 tcp 특정 포트에 new:접속패킷과,established:통신패킷(정확히 쉽게 설명할 
단어가 생각나지 않아 부적절하지만 통신패킷이라 부른다)을 허용하라.

그리고 클라이언트 측에서는 위의 state상태에서 NEW를 빼고 사용한다.

# iptables -A INPUT -p TCP –sport 특정포트 -m state –state ESTABLISHED -j ACCEPT

왜 NEW를 뺄까? 그 이유는 
그 이유는 클라이언트입장에서 보면 접속을 허가해달라는 패킷이 필요없다는것이다.
더 쉽게 말하자면 클라이언트는 접속허가를 요청하는 위치이지 요청받는 
위치가 아니라는 말이다.
그러므로 ESTABLISHED만 있으면 일반적으로 통신하는데 아무런 문제가 없다

그리고 주의깊게 본 사람이라면 위에 –sport가 쓰여진것을 볼수있을것이다.

왜 서버에서는 –dport로 제어를 하면서 클라이언트는 –sport로 제어를 할까?

지금 리눅스 박스라면 wget을 쓰던지 x-windows에서 브라우져를 쓰던지 아무런 웹사이트에 접속을 하고 바로 콘솔에서 ‘netstat -nat’라는 명령을 내려보자.

무슨말인지 알겠는가?

서비스를 한번이라도 해본적있는 사람이면 알겠지만 서버는 특정PORT를 열어놓고 접속을 기다린다.
클라이언트는 특정 서버에 접속을 하기 위해 별도로 포트를 생성하고 접속을 시도한다.
이때 클라이언트가 생성하는 포트번호는 1024이후의 랜덤값이다. 이런이유로 클라이언트입장에서는
–dport로 제어를 하지않는게 보통이다. 제어를 하더라도 상관없다. 하지만 그것은
상당한 비효율적인 룰이 될것이다.

[ftp를 위한 상태천이를 이용해 룰 설정]

ftp는 참 유별난 프로토콜이다. 특히 마스커레이드때 쓰이는 nat과 잘 맞지도 않을뿐더러.
ftp서버에서 passive모드로 운영을 할시 iptables로 제어하고 싶다면 따로 모듈이 필요하다.

passive로 1025:65535까지 임이의 데이타 전송포트를 쓸때 
상태천이로 제어를 하자면,보안상 NEW를 사용하지 않는다.
즉,새로운 접속을 허가하지 않고
RELATED로 기존접속에 관련된것만 접속을 허용한다.

즉 실제 룰을 보면 아래와 같다

# iptables -A INPUT -p tcp –dport 1024:65535 
-m state –state ESTABLISHED,RELATED -j ACCEPT

※ 만약 NEW를 사용한다면 방화벽 구실을 못할것이다.
왜그런지는 직접 생각해보라 위에서 이미 충분히 설명하였다.

ftp에서 위처럼 RELATED로 방화벽룰을 설정했다면 
ip_conntrack_ftp라는 모듈없이 연결이 제대로 되지 않을것이다.

ip_conntrack_ftp는 ftp서버의 ftp접속 추적 모듈이다.

[ 조각(Fragments) 처리하기 ]

때때로 하나의 패킷이 한 번에 한 회선을 통과하기에는 너무 큰 경우가 발생한다.
이 때는 패킷이 `조각’으로 나뉘어 여러 개의 패킷으로 전송된다.
받는 쪽에서는 이 조각을 모아 하나의 패킷으로 재구성한다.

패킷 필터링 HOWTO에서는 nat이나 접속추적을 할때에는 분절패킷이 하나의 패킷으로

재구성되어 필터링되기때문에 해당되지 않는다고 명시되어 있다.

하지만 위와 같은 상황이 아니라면 조각을 처리해야하나 안전성을 이유로 처리하지
않는 것을 권장하고 있다. 그 이유는 아래에 설명할것이다.

일반적으로 패킷이 분절(토막)될때 필터링을 할 정보인 특히 발신지 포트,
목적지 포트, ICMP 유형, ICMP 코드 또는 TCP SYN 플래그등은 첫번쩨 패킷의
헤더에 밖에 포함되지 않는다. 즉 두번째 분절패킷부터는 그 정보가 없다는 말이다.
이를 위해서 우리는 분절된 패킷을 처리하기 위해 -f 옵션을 사용한다.

하지만 -f옵션을 권장하지 않는다. 왜냐하면 첫번째 필터링정보가 담긴 헤더를 보고
필터링을 할때 그 패킷이 거부하는 룰에 적용되어 거부되면 분절된 패킷이 거부되지
않고 오더라도 그것은 하나의 패킷으로 재구성 되지 않고 버려지기 때문이다.

사용법은

# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP

처럼 사용한다.
위의 뜻은 192.168.1.1을 항해 나가는 분절된 패킷은 모두 버린다 이다.

다시 한번 말하지만 꼭 필요한경우를 제외하고 이 옵션은 권정하지 않는다.

이정도로 iptables의 기본 사용법에 대해 마치고자 한다.
이문서에서는 방화벽설정에서 자주 사용하게 되는 옵션에 대해서만 언급했다.
아니 이정도 옵션들이면 어느정도 방화벽은 구성할수 있을것이다.
나머지 옵션들은 man패이지나 패킷필터링 HOWTO에서 찾아보기 바란다

반응형

'UNIX & LINUX > CentOS' 카테고리의 다른 글

웹 서버 상태 체크하기 #웹서버  (0) 2016.07.02

+ Recent posts