SW 개발

Linux / 설정 / iptables , netfilter 개념 사용법 예제 정리

. . . 2011. 5. 12. 11:11
반응형

iptables에 관련한 내용은 모두 뒤죽박죽 설명이 되어있어서 모두 한자리에 정리하였습니다. 출처가 된 사이트 들은 모두 다음과 같습니다.

IPTABLES 일반사항

netfilter?

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

iptables 는?

기본적으로 Iptables에는 세가지 chain이 있고 모든 패킷은 이 세가지 chain중 하나를 통과하게 된다. 이 세가지 chain은 INPUT, OUTPUT, FORWARD chain인데 우선 여러분의 컴퓨터로 들어가는 모든 패킷은 INPUT chain을 통과한다. 그리고 여러분의 컴퓨터에서 나가는 모든 패킷은 OUTPUT chain을 통과한다. 그리고 하나의 네트워크에서 다른 곳으로 보내는 모든 패킷은 FORWARD chain을 통과한다.

Iptables가 작동하는 방식은 이들 각각의 INPUT, OUTPUT, FORWARD chain에 당신이 어떠한 rule을 세우는 지에 따라 달라진다. 예를 들어 당신이 HTML 페이지를 요청하기 위해http://www.yahoo.com/에 패킷을 보낸다면 이 패킷은 우선 당신 컴퓨터의 OUTPUT chain을 통과하게 된다. 그러면 kernel에서 OUTPUT chain의 rule을 확인하고 rule과 match가 되는지 확인을 하게된다. rule중에서 최초로 match되는 것에 의해 당신이 보낸 패킷의 운명이 결정되는 것이다.

만약 어떤 rule과도 match되지 않는다면 전체 chain의 정책이 ACCEPT냐 DROP이냐에 따라 패킷의 운명이 결정될 것이다. 그러고 나서 Yahoo! 에서 응답하는 패킷은 당신의 INPUT chain을 통과하게 될 것이다.

iptables로 할수 있는 일에는 몇가지 다른것이 있다. 첫번째 작동은 전체 체인을 조절한다. 처음 시작은 세개의 미리 만들어진 체인으로 시작하는 데 이것은 제거될 수 없다.

iptables는 모듈로 되어있을 것이다. 이것은 iptable_filter.o 이다. 이것은 처음으로 iptables를 실행할때 자동으로 로드될 것이다. 이것은 커널에 영구히 포함될 수도 있다.

iptables 명령이 실행되기 전에는 기본적으로 만들어져있는 체인(입력, 포워딩, 출력)에는 아무른 규칙도 없다. (주의 : 어떤 배포판에는 초기화 스크깁트에 iptables를 실행하는 것이 들어있을 수 있다.) 입력과 출력 체인의 정책은 ACCEPT이고 포워딩 체인의 정책은 DROP이다. (iptable_filter 모듈에 'forward=1' 옵션을 선택하여 이것을 고칠 수 있다.)

iptables 명령어 실행시 시스템에 적용되는 시기

  • iptables 명령어를 실행하면 재부팅하지 않더라도 즉시 시스템에 적용된다.
  • iptables -A INPUT -s 0/0 -j DROP를 하면 그 즉시 모든 접속이 차단된다.
  • iptables -D INPUT -s 0/0 -j DROP를 하면 그 즉시 접속 차단 명령이 삭제된다.
  • iptables -L로 명령어가 시스템에 적용중인지 확인 가능

Rule 의 순서

Iptables의 chain에서는 먼저 등록 된 rule이 효력을 발생하기때문에 등록을 하는 순서가 중요하다. 모든 것을 거부하는 설정이 먼저오게 되면 그 이후에 포트를 열어주는 설정이 와도 효과가 없다. 그러므로 허용하는 정책이 먼저오고 나서 거부하는 정책이 와야한다.

-A 옵션을 줌으로써 우리는 새로운 규칙을 chain의 맨 아래에 추가하게 된다. 즉 chain상의 상위 rule이 먼저 작동하기 때문에, 만일 새로 추가하는 rule을 먼저 작동시키기 위해서는 -I 옵션을 줌으로써 새로운 rule을 원하는 위치에 놓을 수 있다. 예를 들어 INPUT chain의 가장 위에 어떤 rule을 놓고 싶다면 “-I INPUT 1” 이라 명령하면 된다. 그리고 다른 위치로 놓고 싶다면 1을 다른 숫자로 바꿔주면 된다.

이미 위치된 rule을 다른 위치로 바꾸고 싶다면 -R 옵션을 주면 된다. -I 옵션을 주는 것과 마찬가지로 사용할 수 있는데 다만 -I옵션을 사용해서 1의 위치에 놓으면 다른 rule들이 밑으로 한칸씩 내려가는 반면 -R옵션을 사용해서 1의 위치에 놓으면 그 위치의 rule은 삭제된다.

rule을 삭제하고 싶다면 -D옵션과 숫자를 사용하면 되고, -L 옵션을 사용하면 작성된 모든 rule의 목록을 보여주고, -F 옵션을 주면 해당 chain의 모든 rule을 삭제한다. 그리고 만약 chain을 명시하지 않았다면 모든 것을 flush할 것이다.

IPTABLES 의 세팅관리

  • 세팅 저장하기
    • iptables-save > /root/firewall.txt
  • 세팅 복구하기
    • iptables-restore < /root/firewall.txt

기본 Chain

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가 아닌 패킷이 통과하게 되는 체인이다.

Chain 의 실행순서 및 사용자 Chain 의 관계

ipchains 로 부터 상속되는 iptables의 강력한 기능중의 하나는 능력되는 사용 자가 기존의 세개의 체인(입력, 출력, 포워드)외에 새로운 체인을 생성할 수 있다는 것이다.

타겟이 사용자 지정의 체인인 규칙에 패킷이 맞으면 패킷은 사용자 지정의 체인을 따라 움직이게 된다. 그 체인이 패킷의 운명을 결정하지 못하면 그리고 그 체인에 따른 이송이 끝나면, 패킷은 현제 체인의 다음 규칙으로 돌아온다.

그림을 보자. 두개의 체인이 있고 그것이 input 과 test 라는 사용자 지정의 체인이 라고 가정하자.

         `INPUT'                         `test'
         ----------------------------    ----------------------------
         | Rule1: -p ICMP -j DROP   |    | Rule1: -s 192.168.1.1    |
         |--------------------------|    |--------------------------|
         | Rule2: -p TCP -j test    |    | Rule2: -d 192.168.1.1    |
         |--------------------------|    ----------------------------
         | Rule3: -p UDP -j DROP    |
         ----------------------------

192.168.1.1 로부터 와서 1.2.3.4 로 향하는 TCP 패킷이 있다고 가정한다. 이것은 입력 체인으로 들어온다.

  1. Rule1 을 검사한다. 맞지 않음.
  2. Rule2 맞음. 그것의 타겟 은 "test" , 고로 다음 검사할 규칙은 "test" 의 시작이다. 테스트의 Rule1 이 맞다. 그러나 이것이 타겟을 지정하지 않는다. 그러므로 다음 규칙이 검사된다.
  3. Rule 2. 맞지 않다.
  4. 그 체인의 끝에 도달했다.
  5. 다시 입력 체인으로 돌아가서 Rule3 을 검사 한다. 그것도 맞지 않다.
  6. 그러므로 Drop 시켜버림

여기서 패킷의 이동경로를 그림으로 나타냈다.

                               v    __________________________
         `INPUT'                |   /    `test'                v
        ------------------------|--/    -----------------------|----
        | Rule1                 | /|    | Rule1                |   |
        |-----------------------|/-|    |----------------------|---|
        | Rule2                 /  |    | Rule2                |   |
        |--------------------------|    -----------------------v----
        | Rule3                 /--+___________________________/
        ------------------------|---
                                v

사용자 지정의 체인에서 대를 사용자 지정의 체인으로 갈수 있다. (그러나 루프 를 돌수는 없다. 루프를 발견하게 되면 패킷은 DROP 된다.)

Chain 관련 옵션

  • 새로운 체인 만들기 (-N).
    • iptables -N test
  • 비어있는 체인을 제거하기 (-X)
    • iptables -X test
    • 체인을 제거 하는데는 몇가지 제한이 있다. 이것은 비어있어야 한다. (아래의 체인 비우기를 보라) 그리고 그것은 다른 어떤 규칙의 타겟도 아니어야 한다. 미리 만들어진 세개의 체인은 제거할 수 없다.
    • 체인의 이름을 지정하지 않으면 모든 사용자 정의의 체인은 제거된다.
  • 체인으로부터 규칙들을 지우기 (-F)
    • iptables -F forward
    • 체인을 지정하지 않으면 모든 체인의 규칙이 지워진다.
  • 어떤 체인의 규칙들을 나열하기 (-L)
    • iptables -L test
    • 체인의 이름이 생략되면 비어있는 것을 포함한 모든 체인이 나열된다.
    • 세부옵션
      • '-v' 옵션은 규칙의 자세한 정보(패킷과 바이트 카운터, TOS 비교, 인터페이서와 같은)를 나타낸다.
      • '-n' (numeric) 옵션은 iptables가 여러분이 DNS 요구를 필터링 아웃한 경우나 DNS가 적절이 설정되어 있지 않다면 오랜 시간이 걸리는, IP 주소를 찾는 것을 예방하는 아주 유용한 옵션이다. 이것 은 TCP와 UDP 포트가 이름이 아닌 숫자로 출력되도록 하기도 한다.
      • '-x' (확장 수) 지시자를 사용하면 얼마나 큰 숫자든 전 체 숫자가 나타난다. (패킷과 바이트 카운트는 'K'(1000), 'M'(1,000,000), 'G'(1,000,000,000) 와 같은 접미어와 함께 나타난다.)
  • 체인내의 모든 규칙들의 패킷과 바이트의 카운드를 0 으로 만들기 (-Z)
    • iptables -Z
    • 이것은 카운트를 리셋하는데 유용하다. 이것은 '-Z' ('--zero') 옵션으로 가능하다.
    • 이것의 문제점은 리셋하기 직전의 카운트 값을 알필요가 있을 때가 가끔 있다는 것 이다. 이러한 경우의 예로, 어떤 패킷이 '-L' 과 '-Z' 명령 사이에 지나갈 수 있다. 이런이유로 카운트를 읽는 것과 동시에 리셋하기위해서 '-L' 과 '-Z' 명령을 같이 사용할 수 있다.
  • 미리 만들어진 체인의 정책을 바꾸기 (-P)
  • 체인에 새로운 규칙을 추가하기 (-A)
  • 체인의 어떤 지점에 규칙을 삽입하기 (-I)
  • 체인의 어떤 지점의 규칙을 교환하기 (-R)
  • 체인의 어떤 지점의 규칙을 제거하기 (-D)
  • 체인의 규칙종류
    • ACCEPT : 패킷을 허용
    • DENY : 패킷을 허용하지 않는다는 메시지를 패킷을 보낸 PC에 돌려보냄
    • DROP : 패킷을 허용하지 않으며, 허용하지 않는다는 메시지 자체도 안보냄
    • REJECT : match된 경우 -------- 거절한다는 에러 메시지를 돌려보냄 : match되지 않은 경우 - DROP과 동일한 작동을 함
  • 미리 정의되어있는 체인
    • INPUT : 내가 외부의 패킷을 받을지 결정 : INPUT을 막을 경우 외부에서 나한테 패킷을 보낼 수 없음
    • OUTPUT : 내가 외부에 패킷을 보낼지 결정 : OUTPUT을 막을 경우 내가 외부에 패킷을 보낼 수 없음
    • FORWARD : 내가 받을 패킷을 어디로 RELAY할지 결정
  • reject 옵션
    • --reject-with tcp-reset : RST 패킷을 돌려보내서 연결을 해제토록 함
    • --reject-with icmp-net-unreachable : error 메시지를 돌려보냄
    • --reject-with icmp-host-unreachable : error 메시지를 돌려보냄
    • --reject-with icmp-port-unreachable : error 메시지를 돌려보냄
    • --reject-with icmp-proto-unreachable : error 메시지를 돌려보냄
    • --reject-with icmp-net-prohibitedor : error 메시지를 돌려보냄
    • --reject-with icmp-host-prohibited : error 메시지를 돌려보냄
  • nat (Network Address Translation)
    • 패킷의 목적지나 시작점을 바꿈

Forward 관련 옵션

INPUT과 OUTPUT chain은 디폴트로 ACCEPT로 정해져 있고, FORWARD chain은 DENY로 정해져 있다. forward 를 enable하기위해선 -P 옵션을 사용하면 된다. 즉 FORWARD chain을 ACCEPT로 정하기 위해선 다음과 같이 명령을 내리면 된다.

iptables -P FORWARD ACCEPT 

필터링 관련 옵션

  • IP 주소의 지정 규칙
    • 출처('-s', '--source', '--src')와 목적지('-d', '--destination', '--dst') IP 주소를 지정하는데 여러가지 방법이 있다.
    • 첫번째 방법은 'www.linuxhq.com', 'localhost' 처럼 이름을 이용하는 것이다.
    • 두번째 방법은 '127.0.0.1' 처럼 IP 주소를 이용하는 것이다.
    • 세번째와 네번째 방법은 IP 주소의 그룹을 지정하는 것으로 '199.95.207.0/24' 또는 '199.95.207.0/255.255.255.0' 같은 형태이다. 이 둘은 모두 199.95.207.0 부터 199.95.207.255 사이의 모든 IP 주소를 지정한다. '/' 다음의 숫자는 IP 주소의 어떤 부분이 의미있는가를 나타낸다. '/32' 나 '/255.255.255.255' 가 기본값이다.(IP 주소의 모든부분이 일치해야 한다.) 모든 IP 주소를 지정하는데 '/0' 가 사용된다.

숫자의 의미

  • 0/0 : 모든 IP가 해당 (/뒤의 숫자는 서브넷마스크를 의미함)
  • /8 = /255.0.0.0 (/8이나 /255.0.0.0 중 어느 것을 입력해도 같음)
  • /9 = /255.128.0.0
  • /18 = /255.192.0.0
  • /24 = /255.255.255.0
  • /27 = /255.255.255.224
  • /28 = /255.255.255.240
  • /29 = /255.255.255.248
  • /30 = /255.255.255.252
  • ' / ' 다음에 숫자가 올 경우 비트가 1로 채워진 갯수를 의미하는데 /24인 경우 왼쪽에서 24개의 비트가 1이다. (11111111.11111111.11111111.00000000 = 255.255.255.0) 따라서 192.168.1.0/24 는 192.168.1.0/255.255.255.0과 같다
  • '역'의 경우 지정
    • 많은 지시자들('-s'나 '-d' 같은)은 일치하지 않는 주소를 나타내기 위하여 '!'('not'을 의미한다)로 시작하는 설정을 할 수 있다. 예로, '-s ! localhost' 는 localhost로부터오는 패킷이 아닌경우를 나타낸다.
  • 프로토콜 지정
    • 프로토콜은 '-p' 지시자로 지정할 수 있다. 프로토콜을 숫자가 될수 있고 (IP의 프로토콜 번호를 알고 있다면) 'TCP', 'UDP', 'ICMP' 같은 이름이 될 수도 있다. 그리고 'tcp'는 'TCP'와 같은 역할을 한다. 프로토콜 이름 지정에도 '!'을 이용할 수 있다. '-p ! TCP'
  • 인터페이서 지정
    • '-i'('--in-interface')와 '-o'('--out-interface')가 인터페이서를 저정 하는데 사용된다. 인터페이서는 패킷이 들어오고 나가는 물리적인 도구이다. ifconfig 명령을 사용하여 현재 활성화 되어있는 인터페이서를 알아볼수 있다.
    • 입력 체인을 지나는 패킷은 출력 인터페이서를 가지고 있지 않으므로 '-o' 설정에 일치하는 패킷이 없을 것이고 출력 체인을 지나는 패킷은 입력 인터 페이서를 가지고 있지 않으므로 '-i' 설정에 일치하는 패킷이 없을 것이다.
    • 포워딩 체인을 지나는 패킷만이 입력과 출력 인터페이서를 모두 가질것이다. 현재 존재하지 않는 인터페이서를 지정하는 것도 아무런 문제없이 될 수 있 다. 이것은 인터페이서가 활성화 되기 전까지는 규칙에 일치하는 패킷이 있을수 없을 것이다. 이것은 dial-up PPP를 사용하는 경우 특히 유용하다. 특별한 경우로, 인터페이서 이름이 '+'로 끝날수 있는데 이것은 그 이름으로 시작하는 모든 인터페이서를 모두 지정한다(그것이 현재 존재하든 존재하지 않든).
    • 예를들어, 모든 PPP 인터페이서와 일치하는 규칙을 지정하려면 -i ppp+와같이 하면 된다. 인터페이서 이름앞에 '!'도 이용할 수 있다.
  • 분절 (Fragments) 지정
    • 가끔 패킷은 한번에 다 전달되기에는 너무 큰 경우가 있다. 이런경우 패킷은 여러 분절로 나뉘어지고 다중패킷의 형태로 전달된다. 목적지에서 이 분절들 은 재 구성되어 전체 패킷이 된다. 분절에서 문제점은 내부 패킷의 부분으로 IP 헤더 다음의 위치에서 프로토콜 헤더를 찾는데, 이것은 첫번째 분절에만 있기 때문에 찾을수가 없다. 만약 여러분이 접속추적이나 NAT를 한다면 모든 분절은 필터링 코드에 도달하 기 전에 뭉쳐지므로 분절에 대한 걱정은 할 필요가 없다. 그렇지 않다면, 분절들이 필터링 규칙에서 어떻게 처리되는가를 이해하는 것 은 중요하다.
    • 우리가 가지고있지 않은 정보를 요구하는 필터링 규칙에 부합될 수가 없다. 이것은 첫번째 패킷은 다른 패킷과 같이 처리되고 두번째 이후의 분절은 전달될 수 없음을 의미한다. 그러므로 -p TCP --sport www ('www' 를 출신 포트로 지정하는 경우)와 같은 규칙에 맞는 분절은 있을 수 없다( 첫번째 분절을 제외하고). 그 반대의 규칙인 -p TCP --sport ! www도 분 절들을 처리할 수 없다. 그러나, 두번째 이상의 분절에 대하여 규칙을 지정하기위하여 '-f' ('--fragment')라는 지시자를 사용할 수 있다.
    • 두번째 이상의 분절에는 적용 되지않는 규칙을 지정하기 위하여 '-f' 앞에 '!' 를 붙이는 것도 가능하다. 일반적으로 , 첫번째 분절에 필터링이 적용되어 DROP 되면 목적지 에서 다른 분절들의 재합성이 되지 않으므로, 두번째 이상의 분절이 그냥 지나가도록하는 것도 안전한 것으로 간주 된다. 그러나 단순히 분절들을 전달하는 것만으로 호스트를 크래쉬가 생기는 버그가 알려져 있다. 여러분이 결정할 일이다. 네트워크 헤더에 대한 주의 : 잘못 구성된 패킷들은 이러한 시험을 할때 DROP 되었다. (TCP, UDP, ICMP 패킷중 길이가 너무 짧아 파이어월 코드가 포트나 ICMP 코드와 형태를 읽을 수 없는 경우). 왜냐하면 TCP 분절은 8번째 위치부터 시작되기 때문이다.

프로토콜과 관련한 옵션

TCP

  • TCP 확장은 '--protocol tcp' 가 지정되고 다른 적용이 지정되지 않으면 자동으로 적제된다. 이것은 다음과 같은 옵션을 제공한다.
  • --tcp-flags
    • '!' 옵션을 사용한다면 이것 뒤에 두개의 단어를 사용한다. 첫번째 것은 검사하고자 하는 지시자 리스트의 마스크이다. 두번째 단어는 지시자에게 어떤것이 설정 될 것인지를 말해준다. 예를들어, iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DENY 이것은 모든것이 검사되어야 함을 말한다.('ALL'은 `SYN,ACK,FIN,RST,URG,PSH' 와 같다.) 그러나 SYN 과 ACK 만 설정된다. 'NONE'는 지시자가 없음을 말한다.
  • --syn
    • '!' 옵션이 선행될 수 있다. 이것은 '--tcp-flags SYN,RST,ACK,SYN'의 약어이다.
  • --source-port
    • '!' 옵션이 선행될 수 있다. 이후에 하나의 TCP 포트나 포트의 범위를 지정한다. /etc/services 에 기록된 것과 같은 포트 이름이 사용될 수 도 있고 숫자로 나타낼 수도 있다. 범위는 두개르 포트 이름을 '-' 으 로 연결해서 사용하거나 (커거나 같은경우를 위해서) 하나의 포트 뒤에 '-'를 사용하거나 (작거나 같은 경우를 위해서) 하나의 포트 앞에 '-' 를 덧붙일 수 있다.
  • --sport
    • 이것은 '--source-port'와 동의어이다.
  • --destination-port 와 --dport
    • 목적지를 지정한다.
  • --tcp-option
    • '!' 나 숫자가 옵션에 선행될 수 있는데 숫자가 앞에 올경우 그 숫자 와 TCP 옵션이 같은 경우의 패킷을 검사한다. TCP 옵션을 검사하려 할 때 완전한 TCP 헤더를 갖지않는 것은 자동으로 DROP 된다.

TCP 관련 기타사항.

가끔 한쪽 방향에서의 TCP 접속만 허랑하고 다른 방향에서의 접속을 불허하 는 것이 유용하다. 예로, 여러분은 외부 WWW 서버로의 접속은 허락하며 그 서버로 부터의 접속은 불허하기를 원할 것이다. 단순하게 그 서버로부터 오는 TCP 패킷을 막으면 된다고 생각할 것이다. 그러 나, 불행히도 작동하기 위해서 TCP 접속은 양방향의 패킷을 요구한다. 해법은 접속을 요구하는 패킷만 막는 것이다. 이러한 패킷을 SYN 패킷이라한다. (물론, 기술적으로 SYN 지시자 셋을 갖는 패킷이 있다. 그리고 FIN 과 ACK 지시 자는 지워진다. 그러나 간단히 그것을 SYN 패킷이라고 한다.) 이러한 패킷만 불가능으로 만듬으로서 외부로 부터의 접속 시도를 막을 수 있다.

이러한 것을 위해서 '--syn' 지시자가 사용된다. : 이것은 프로토콜을 TCP 로 지정했을 때만 효과가 있다. 예를 들면, 192.168.1.1 로부터의 TCP 접속을 지 정하기 위하여 다음과 같이 하면 된다.

-p TCP -s 192.168.1.1 --syn

접속을 시작한 것 외의 모든 패킷을 지정하기 위하여 '!' 옵션이 선행될 수 있다.

tcp프로토콜의 접속 제어 flag

-0 SYN (SYNchronize Sequence Numbers) : 연결을 요청하는 flag(신호) -0 ACK (Acknowledgement) : 알았다는 신호 -0 RST (Reset) : 연결을 해제하는 신호 -0 FIN (Finish) : 접속을 종료하고 전송을 끝내는 신호

일반적인 커넥션 흐름

일반적인 커넥션 흐름 : HOST A > (SYN) > HOST B > (SYN ACK) > HOST A > (ACK) > HOST B

  • 1) HOST A는 HOST B에 SYN을 보내 연결을 요청
  • 2) HOST B는 HOST A에 SYS ACK를 보내 연결을 허락한다고 회신
  • 3) HOST A는 HOST B에 ACK를 보냄으로써 연결이 이루어짐

SYN,ACK,FIN,RST SYN : 앞의 네 개 FLAG인 SYN,ACK,FIN,RST를 검사하여 맨뒤의 SYN의 방향을 결정함 (위의 명령어의 경우는 앞의 ACK만 검사하여 뒤의 ACK의 방향을 결정함)

UDP 확장

이 확장은 '--protocol udp'가 지정되고 적용이 저정되지 않으면 자동으로 적재된다. 이것은 '--source-port', '--sport', '--destination-port', '-dport'를 지원하고 내용은 TCP 설명에서 자세히 나왔다.

ICMP 확장

이 확장은 '--protocol icmp'가 지정되고 그 적용이 지정되지 않으면 자동으로 적재된다. 이것은 단 하나의 새로운 옵션만 지원한다.:

  • --icmp-type
    • '!' 옵션이 선행될 수 있다. 이후에 ICMP 타입의 이름('host-unreachable') 이나 숫자형태 ('3'), 또는 숫자형태와 코드('/'로 분리 예. '3/3') 의 형 태가 사용된다. 사용할 수 있는 ICMP 형태의 이름의 리스트는 '-p icmp --help' 하면 나타난다.
  • icmp type
    • 0 : echo-reply - ping
    • 3 : destination-unreachable - Any TCP/UDP traffic
    • 5 : redirect - routing if not running routing daemon
    • 8 : echo-request - ping
    • 11 : time-exceeded - traceroute
    • echo-request : ping프로그램으로 사용자가 목적지 서버에 보내는 패킷
    • echo-reply : echo-request에 대하여 목적지시스템이 사용자에게 회신하는 패킷

그외 확장옵션

Netfilter 패키지의 다른 확장은 시험적인 확장이다. 이것은 (설치 되어있다면) '-m' 옵션으로 활성화 된다.

  • mac
    • 이 모듈은 '-m mac' 또는 '--match mac' 이라고 함으로 지정할 수 있다. 이것은 들어오는 패킷의 이더넷 주소를 검사한다. 그러므로 입력 체인에 서만 유용하다. 이것은 하나의 옵션만 제공한다.
  • --mac-source
    • '!' 옵션이 선행 될 수 있다. 이후에 콜론으로 분리된 16진수 숫자의 이더넷 주소가 온다. 예 '--mac-source 00:60:08:91:CC:B7'
  • limit
    • 이 모듈은 '-m limit' 또는 '--match limit'이라고 함으로 지정할 수 있 다. 이것은 로그 메세지를 억제할때 처럼 적용검사의 속도를 제한하는데 사용한다. 1초에 주어진 숫자만큼의 적용만 검사한다. (기본값은 한 시간 에 3번, 최고 5번이다.) 이것은 두개의 옵션을 제공한다.
  • --limit
    • 숫자가 따라온다 : 초당 평균 최대 적용 검사 수를 지정한다. 숫자뒤 에 시간단위를 지어할 수 도 있다. ('/second', '/minute', '/hour', '/day'형태이다. 예로, '5/second' 또는 '5/s'가 가능하다)
  • --limit-burst
    • 숫자가 따라온다. 위의 제한이 적용되기전의 최대 Burst(?) 를 제한 한다.
    • 이 적용은 종종 로그의 속도를 제한하기위하여 LOG 타겟과 함께 사용된다. 이것을 이해하기위하여 아래에 기본 제한설정을 하는 로그 패킷제한 을 보자.
    • iptables -A FORWARD -m limit -j LOG
    • 이 규칙에 도달될때까지 패킷은 로그될 것이다. 사실 Burst의 기본값은 5 이므로 처므ㅇ 5개의 패킷은 로그될것이다. 그 이후 얼마나 많은 패킷이 도달하든 간에 하나의 패킷이 로그되기전에 20분이 걸릴 것이다. 그리고 20분 동안 패킷 적용이 없으면 Burst 하나가 다시 생길 것이다. 패킷없이 100분 이 지나면 Burst는 완전이 원상 복구 될것이다. 처음 시작할때로 돌아가는 것 이다.
    • 재복구 시간을 59시간 이상으로는 설정하지 못한다. 그러므로 평균속도를 하 루에 1개로 설정하였다면 Burst 속도는 3 이하가 되어야 한다.
  • owner
    • 이 모듈은 지역에서 생성된 패킷의 생성자의 여러 특징을 적용하려고 한다. 이것은 출력 체인에만 사용되며 어떤 패킷들(ICMP ping 응답같은)은 소유자 가 없으므로 적용되지 않는다.
    • --uid-owner userid
      • 유효한 사용자 id (숫자)의 프로세서가 생성한 패킷에 적용한다.
    • --uid-owner groupid
      • 유효한 그룹 id (숫자)의 프로세서가 생성한 패킷에 적용한다.
    • --pid-owner processid
      • 주어진 프로세서 id 의 프로세서가 생성한 패킷에 적용한다.
    • --sid-owner processid -세션 그룹내의 프로세서가 생성한 패킷에 적용한다.
  • unclean
    • 이 시험적인 모듈은 정확히 '-m unclean' 또는 '--match unclean'으로 지정해 주어야 한다. 이것은 무작위의 여러 건전성 검사를 한다. 이것은 제대로 검사되지 않았고 안전성 도구로도 사용되지 못한다.(아마도 이것 은 무제를 더욱 힘들게 하고 버그 그 자체일 것이다.) 이것은 옵션이 없다.
  • 상태 적용
    • 가장 유용한 적용 기준은 'ip_conntrack' 모듈의 접속 추적 분석을 해석하는 'state' 확장이다. 이것을 강력히 추천한다. '-m state'를 지정함으로 '--state' 옵션을 사용할 수 있는데 이후에 콤마로 분리되는 적용할 상태들의 리스트가 온다.('!' 지시자는 사용되어지지 않는 다.) 이 상태들은 ;
      • state --state NEW : 패킷이 network 새로 연결되어 있는 상태: 새로운 접속을 만드는 패킷
      • state --state ESTABLISHED : 패킷이 network 연결되어 있는 상태 : 존재하는 접속에 속하는 패킷 (즉, 응답 패킷을 가졌던 것)
      • state --state RELATED : 패킷이 network새로 연결되어 있으나 이미 연결되어 있는 network와 연관성이 있는 상태 기존의 접속의 부분은 아니지만 연관성을 가진 패킷으로 . ICMP 에러 나 (FTP 모듈이 삽입 되어있으면) ftp 데이터 접속을 형성하는 패킷.
        • FTP 를 예로 들어보자.. FTP는 접속할때 21번 포트로 접속을 한다.. 모든 TCP 세션처리는 21번 포트에서 실행되지만 정작..데이터를 주고 받음에는 20번 포트를 사용하게 된다.. 3way hand shake 로 21번 포트로 상태추적테이블에 저장이 되었는데.. 전혀 생소한 20번 포트로 데이터가 전송이 되면 우리 컴퓨터는 당연히 INPUT에서 DROP 된다.. ESTABLISHED의 이런점을 보안하고자 RELATED가 생겨났다..
  • state --state INVALID : 패킷이 network연결되어 있는지 모르는 상태. 어떤 이유로 확인할 수 없는 패킷: 알려진 접속과 부합하지 않는 ICMP 에러와 'out of memory' 등을 포함한다. 보통 이런 패킷은 DROP 된다.

IPTABLES 예제

iptables -A INPUT -s 200.200.200.1 -j DROP
  • 200.200.200.1 이라는 source IP(-s)로부터 오는(INPUT) 모든 패킷을 막는(DROP) 규칙을 추가(A)한다. -> 이 한 줄의 명령으로 200.200.200.1로부터 오는 모든 패킷을 무시할 수 있다. 옵션의 순서는 바뀌어도 상관이 없다. 즉 -j DROP이 -s 200.200.200.1 보다 앞에 가도 상관이 없다. 만약 그 반대로 200.200.200.1로 패킷이 못가도록 하려면 INPUT 대신에 OUTPUT을, -s 대신에 -d(destination) 옵션을 주면된다.
iptables -A INPUT -p tcp --sport 25 -j ACCEPT
  • 25번이라는 source포트(--sport)에서 오는(INPUT) protocol이(-p) tcp인 모든 접속을 허락하는(ACCEPT) 규칙을 추가(A)한다.
    • source port 와 destination port를 혼동하면 안된다. 즉 클라이언트는 어떤 포트로도 작동할 수 있는 반면에 서버는 23번 포트로 작동하기 때문이다. 즉 특정 서비스를 차단하기 위해서는 -destination-port를 이용하면 되고, 그 반대는 -source-port를 이용하면 된다.
    • IP의 영역을 선택하고 싶다면 200.200.200.0/24 와 같이 설정하면 된다. 이것은 200.200.200.* 에 해당하는 모든 IP를 선택하는 것과 같다.
iptables -A INPUT -s 200.200.200.1 -p tcp --destination-port telnet -j DROP
  • 200.200.200.1 이라는 source IP(-s)로부터 오는(INPUT) protocol이(-p) tcp이고 목적지 port(--destination-port)가 telnet인 패킷의 접속을 막는(DROP) 규칙을 추가(A)한다.
iptables -A INPUT -i eth1 -s 192.168.1.0/24 -d 0/0 -j ACCEPT
  • 192.168.1.0/24라는 source IP(-s)로부터 오는(INPUT) 서버안으로 들어오는 인터페이스(-i)가 eth1이고 destination IP(-d)가 어떤 IP라도(0/0) 접속을 허락하는(ACCEPT) 규칙을 추가(A)한다. (서버자체에 대한 접속이 아니라 마스커레이딩등을 이용하여 랜카드 두 개를 장착한 경우 eth1에 연결된 내부 PC에서 외부로의 접속 허용)
iptables -A INPUT -p tcp --destination-port telnet -i ppp0 -j DROP
  • protocol이(-p) tcp이고 목적지 port(--destination-port)가 telnet이며, 서버안으로 들어오는 인터페이스(-i)가 ppp0인 패킷의 접속을 막는(DROP) 규칙을 추가(A)한다.
    • 이렇게 함으로써 우리는 LAN상의 사용자는 telnet을 사용하고 그밖에 Internet상의 사용자는 telnet 을 사용하지 못하도록 할 수 있다.
iptables -A INPUT -i ppp0 -p tcp --syn -j DROP
  • ppp0 로 들어오는 모든 tcp의 연결을 무시해버림
  • 두 컴퓨터가 TCP connection으로 패킷을 주고 받는다면 그 connection은 우선 초기화가 되어야 한다. 이것은 바로 SYN packet이 담당한다. SYN packet은 단순히 다른 컴퓨터에게 주고 받을 준비가 되었다는 것만 알려주는 초기화 기능만을 한다.이제 서비스를 요청하는 컴퓨터는 우선적으로 SYN packet을 보낸다는 것을 알게 되었다. 그러므로 들어오는 SYN packet만 막기만 하면 다른 컴퓨터가 당신 컴퓨터의 서비스를 이용하지 못하게 할 수 있고, 하지만 당신은 그들과 통신할 수 있는 것이다. 즉 이와 같이 하면 당신이 먼저 패킷을 보내서 요청이 들어오는 것이 아니면 모두 무시해 버리게 된다.
iptables -A INPUT -i ppp0 -p tcp --syn --destination-port ! 80 -j DROP 
  • 80번 포트만 제외하고 모든 SYN packet들을 막는다.
  • 만약 당신이 웹서비스를 위해 하나의 포트(예를들어 80번-HTTP)만 열어두고 싶다면 역시 한가지 방법이 있다. 바로 “!” 마크를 사용하면 되는데 많은 프로그래밍 언어에서처럼 “!”은 “not”을 의미한다. 예를들어 80번 포트만 제외하고 모든 SYN packet들을 막고싶다면 위와 같이하면된다.
iptables -A INPUT -p icmp --icmp-type echo-request -j REJECT
iptables -A INPUT -p icmp --icmp-type 8 -j REJECT
  • protocol이(-p) icmp이고 icmp 의 type이 echo-request인 패킷이 오는(INPUT) 것을 거절하는(REJECT) 규칙을 추가(A)한다. (외부에서의 ping을 거절하는 방법임 / echo-request대신에 8을 해도 됨)
iptables -A INPUT -p tcp --dport 20:30 -j DROP
  • protocol이(-p) tcp이고 목적지 port(--dport)가 20번부터 30번까지인 패킷이 오는(INPUT) 것을 막는(DROP) 규칙을 추가(A)한다.
iptables -A INPUT -m state --state INVALID -j DROP
  • network상태가(state --state)가 INVALID인 패킷이 오는(INPUT) 것을 막는(DROP) 규칙을 추가(A)한다.
    • -m : -match로 해도 됨 (match 여부로 패킷의 방향을 결정하는 옵션임)
    • state --state INVALID : 패킷이 network연결되어 있는지 모르는 상태
    • state --state ESTABLISHED : 패킷이 network 연결되어 있는 상태
    • state --state NEW : 패킷이 network 새로 연결되어 있는 상태
    • state --state RELATED : 패킷이 network새로 연결되어 있으나 이미 연결되어 있는 network와 연관성이 있는 상태
iptables -A INPUT -p tcp --tcp-flags ACK ACK --dport 80 -m string --string "/default.ida?" -j REJECT --reject-with tcp-reset
  • protocol이(-p) tcp이고 목적지가 80번 포트(--dport 80)로 오는(INPUT) 신호가 ACK이고 /default.ida?라는 문자열이 들어있는 패킷은 연결을 해제하고(tcp-reset) 거절하는(REJECT) 규칙을 추가(A)한다.
  • tcp프로토콜의 접속 제어 flag
    • SYN (SYNchronize Sequence Numbers) : 연결을 요청하는 flag(신호)
    • ACK (Acknowledgement) : 알았다는 신호
    • RST (Reset) : 연결을 해제하는 신호
    • FIN (Finish) : 접속을 종료하고 전송을 끝내는 신호
  • 일반적인 커넥션 흐름 : HOST A > (SYN) > HOST B > (SYN ACK) > HOST A > (ACK) > HOST B
    • 1) HOST A는 HOST B에 SYN을 보내 연결을 요청
    • 2) HOST B는 HOST A에 SYS ACK를 보내 연결을 허락한다고 회신
    • 3) HOST A는 HOST B에 ACK를 보냄으로써 연결이 이루어짐
    • SYN,ACK,FIN,RST SYN : 앞의 네 개 FLAG인 SYN,ACK,FIN,RST를 검사하여 맨뒤의 SYN의 방향을 결정함 (위의 명령어의 경우는 앞의 ACK만 검사하여 뒤의 ACK의 방향을 결정함)
  • reject 옵션
    • --reject-with tcp-reset : RST 패킷을 돌려보내서 연결을 해제토록 함
    • --reject-with icmp-net-unreachable : error 메시지를 돌려보냄
    • --reject-with icmp-host-unreachable : error 메시지를 돌려보냄
    • --reject-with icmp-port-unreachable : error 메시지를 돌려보냄
    • --reject-with icmp-proto-unreachable : error 메시지를 돌려보냄
    • --reject-with icmp-net-prohibitedor : error 메시지를 돌려보냄
    • --reject-with icmp-host-prohibited : error 메시지를 돌려보냄
iptables -A input -i eth0 -s 10.0.0.0/8 -d 0/0 -j DENY
iptables -A input -i eth0 -s 127.0.0.0/8 -d 0/0 -j DENY
iptables -A input -i eth0 -s 172.16.0.0/16 -d 0/0 -j DENY
iptables -A input -i eth0 -s 192.168.0.0/24 -d 0/0 -j DENY
  • 외부에서 내부 네트워크 IP자격으로 접근하여 ip spoofing하는 것 방지
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
  • IP 주소를 할당 받은후 (POSTROUTING) NAT 테이블에 (-t nat) 서버밖으로 나가는 인터페이스(-o)가 ppp0인 모든 패킷들이 마스쿼레이드 되도록 (-j MASQUERADE) 규칙을 추가(-A) 한다.
  • ppp0는 활성화된 외부 디바이스(External Interface)가 유동IP인 경우이며, 고정IP인 경우 ppp0대신에 eth0사용 (/sbin/ifconfig를 이용하여 활성화된 외부 디바이스 확인 가능)
iptables -t nat -A POSTROUTING -o ppp0 -j MASQUERADE
echo 1 > /proc/sys/net/ipv4/ip_forward 
  • 유동(또는 고정) IP 한개인 서버를 통해 IP가 없는 PC에 인터넷 연결가능하게 함
  • ip_forward 파일의 내용을 1로 바꿈으로써 ipforwarding이 가능하게 한다. vi /proc/sys/net/ipv4/ip_forward로 보면 바꾸기 전에 기본으로는 0으로 되어 있음
  • 위의 내용을 /etc/rc.d/rc.local 의 하단에 아래 두줄 추가하여 구축 가능
    • PREROUTING : 서버안으로 들어오는 패킷에 해당되며, 들어오는 인터페이서(-i)만 선택 가능
    • POSTROUTING : 서버밖으로 나가는 패킷에 해당되면, 나가는 인터페이서(-o)만 선택 가능
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to 1.2.3.4
  • 외부로 나가는 패킷의 출발지를 현재 내 PC의 IP주소인 200.200.200.200이 아닌 1.2.3.4로 변경
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 51210 -j DNAT --to 192.168.0.2
  • 목적지 NAT(Destination NAT) (DNAT) : 패킷의 목적지를 바꾸는 방법
    • (외부에서 내부로 들어오는 패킷의 목적지를 내부 서브네트워크중 하나인 192.168.0.2로 변경)
iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
  • 127.0.0.1로부터의 모든 ICMP 패킷을 DROP한다.
  • 이경우 일치되어야할 상태는 'ICMP이면서 그 출처 가 127.0.0.1' 이다. 이 경우 'target' 은 DROP 이다. 127.0.0.1 은 'loopback' 인터페이서 이고 실제적인 네트워크 접속이 전혀 없더라도 이것은 가지고 있을 것이다. 이러한 패킷은 'ping' 프로그램을 이용하여 생성할 수 있다. (이것은 단순히 ICMP type 8 (반응요구)을 보내고 모든 협조적인 호스트는 친절하게 ICMP type 0 (반응요구에 대한 응답)을 대답한다. 이것은 테스트하는데 유용 하다. 그리고, '입력' 체인에 127.0.0.1에서 오는 패킷('-s 127.0.0.1')으로 ICMP 프로토콜인것 ('-p icmp')은 DROP ('-j DROP')하라는 규칙을 추가(-A)하였다.
  • 규칙을 제거하는데는 두가지 방법이 있다. 첫째, 입력체인에는 단 하나의 규칙 만이 있다는 것을 앎으로, 몇번을 지워라는 방식으로 할 수 있다.
    • iptables -D INPUT 1
      • 입력 체인으로부터 1번 규칙을 제거한다.
    • iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
      • -A 명령을 이용한 이전의 명령에서 -A를 -D로 다꿔주면 된다. 이것은 복잡한 규칙을 가지고 있고 각 규칙이 몇번째 규칙인지를 외우고 다니기를 싫어 한다면, 아주 유용한 방법이다.
      • -D 명령은 -A 명령과 똑 같은 문법이다. (-I 나 -R 도 마찬가지이다.) 만약, 여러개의 똑 같은 규칙들이 같은 체인에 있다면, 첫번째 것만 제거 될 것이다.
iptables  -N  TELNET
iptables  -A  INPUT  -p tcp  --dport  23  -j  TELNET 
iptables  -A  TELNET  -s  192.168.x.0/24  -p tcp  --dport  23  -j  ACCEPT
iptables  -I  TELNET  -s  192.168.x.0/24  -p tcp  --dport  23  -j LOG  --log-prefix  " Telnet Access : "
  • TELNET 이란 사용자 정의 체인을 만들고, 내부망(192.168.X.0/24) 의 사용자만 접속을 할 수 있도록 RULE 셋팅을 해당 체인에 설정한다.
  • 남김 log 가 남겨질 수 있도록 방화벽을 셋팅하세요.
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT
  • 루프백 접속 허용한다.
  • 다른 곳과 네트워크가 연결되어 있지 않더라도 시스템의 기본 네트워크이며 로컬 호스트의 인터페이스인 루프백에 대해서는 접속이 이뤄질 수 있도록 해야 하므로, 다음과 같이 설정한다.

full 예제 스크립트 - 1 -

#!/bin/sh
# 우선 모든 Rule을 정리한다.
/sbin/iptables -F

#다음으로 각각에 대한 정책을 세운다.
// INPUT chain 의 policy 를 DROP으로 한다.
/sbin/iptables -P INPUT DROP 
// OUTPUT chain 의 policy 를 ACCEPT로 한다.
/sbin/iptables -P OUTPUT ACCEPT 
// FORWARD chain 의 policy 를 DROP으로 한다.
/sbin/iptables -P FORWARD DROP

#localhost에서의 traffic을 받아들인다. 
// INPUT chain 에 append 한다. lo(localhost)라는 interface를 이용한 packet들을
ACCEPT로 jump 시킨다.
/sbin/iptables -A INPUT -i lo -j ACCEPT

# 확립된 연결에 대한 Packet을 받아들인다. 
// ! --syn 는 syn bit 이 set 되어 있지 않고, ACK(ACK 랑 뭔지 모르겠음)가 set 되어 있는것
/sbin/iptables -A INPUT -i eth0 -p tcp ! --syn -j ACCEPT

# DNS 응답을 받아들인다.
/sbin/iptables -A INPUT -i eth0 -p tcp --source-port 53 -j ACCEPT 
/sbin/iptables -A INPUT -i eth0 -p udp --source-port 53 -j ACCEPT

# 인증 연결을 거부한다(그렇지 않을 경우 메일서버가 오랫동안 타임아웃
상태가 될 것이다.) 
/sbin/iptables -A INPUT -i eth0 -p tcp --destination-port 113 -j REJECT

# echo나 목적지에 도착 못하거나 시간 초과된 icmp packet들을 받아들인다.
/sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type 0 -j ACCEPT 
/sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type 3 -j ACCEPT 
/sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type 11 -j ACCEPT

이렇게 하면, 기본적으로 INPUT은 다 DROP 이기 때문에 다른 곳에서 ping 을 때려도 ping 에 대한 응답이 오지 않는다. 그리고 INPUT안에 개별적으로 만들어 놓은 rule에 의해서 몇몇의 case만이 들어오게 될 것이고, 나머지는 DROP이다.

full 예제 스크립트 - 2 -

#!/bin/sh 
# 우선 모든 Rule을 정리한다. 
/sbin/iptables -F 

# 다음으로 각각에 대한 정책을 세운다. 
/sbin/iptables -P INPUT DROP 
/sbin/iptables -P OUTPUT ACCEPT 
/sbin/iptables -P FORWARD DROP 

# localhost에서의 traffic을 받아들인다. 
/sbin/iptables -A INPUT -i lo -j ACCEPT 

# 확립된 연결에 대한 Packet을 받아들인다. 
/sbin/iptables -A INPUT -i eth0 -p tcp ! --syn -j ACCEPT 

# DNS 응답을 받아들인다. 
/sbin/iptables -A INPUT -i eth0 -p tcp --source-port 53 -j ACCEPT 
/sbin/iptables -A INPUT -i eth0 -p udp --source-port 53 -j ACCEPT 

# 인증 연결을 거부한다(그렇지 않을 경우 메일서버가 오랫동안 타임아웃 상태가 될 것이다.) 
/sbin/iptables -A INPUT -i eth0 -p tcp --destination-port 113 -j REJECT 

# echo나 목적지에 도착 못하거나 시간 초과된 icmp packet들을 받아들인다. 
/sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type 0 -j ACCEPT 
/sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type 3 -j ACCEPT 
/sbin/iptables -A INPUT -i eth0 -p icmp --icmp-type 11 -j ACCEPT 
반응형