4. 어플리케이션 계층 공격과 방어

 * iptables를 이용한 애플리케이션 계층 문자열 매칭

 모든 IDS가 가지는 가장 중요한 기능 중 하나는 애플리케이션 계층 데이터에서 악의적인 바이트를 암시라는 바이트 나열을 검색하는 것이다. 그러나 일반적으로 애플리케이션의 구조는 네트워크나 전송 계층 프로토콜보다 훨씬 덜 엄격하게 정의되기 때문에 침입 탐지 시스템은 애플리케이션 계층 데이터를 조사할 때 융통성을 가져야 한다.

 네트워크 트래픽에서 애플리케이션 부분 전체에 대해 문자열 매칭을 수행하는 것은 좋은 출발점이며, iptables 의 문자열 매칭 확장이 이를 제공한다.

 – 문자열 매칭 확장의 동작
 다음의 규칙은 TCP 포트 5001에서 대기 중인 Netcat 서버로 문자열 “tester”가 전송될 때 syslog 메시지를 생성하기 위해 iptables LOG 타겟을 사용한다

 #iptables -I INPUT 1 -p tcp –dport 5001 -m string –string “tester” –algo bm -m state –state ESTABLISHED -j LOG –log-prefix “tester”

 # iptables -I INPUT 2 -p tcp –dport 5001 -j ACCEPT

  명령어의 –algo bm 인자에 주목하자. 문자열 매칭 확장은 리눅스 커널의 텍스트 검색 기능 위에서 구현된다. 리눅스 커널의 텍스트 검색 기능은 보이어-무어 문자열 검색 알고리즘(위의 bm)과 크누스-모리스-프랫 문자열 검색 알고리즘(kmp) 등과 같이 다양한 알고리즘을 지원한다.

 * 애플리케이션 계층 공격 정의
 
 애플리케이션 계층 공격은 애플리케이션, 애플리케이션 사용자, 애플리케이션이 관리하는 데이터를 애플리케이션 소유자나 관리자가 허용하는 것 이외의 목적으로 전복하려는 시도로 정의한다.

 애플리케이션 계층 공격은 다음의 세 가지로 분류할 수 있다.

 — 프로그래밍 버그에 대한 공격 : 애플리케이션 개발은 복잡한 과정이며 프로그래밍 오류는 반드시 존재한다. 어떤 경우에는 이런 버그가 네트워크를 통해 원격으로 접근 가능한 심각한 취약점을 유발할 수 있다. 좋은 예로 안전하지 않은 C 라이브러리 함수의 사용으로부터 야기되는 버퍼 오버플로우 취약점, 부적절한 질의를 제대로 제거하지 않고 후단 데이터베이스로 넘기거나(SQL 인젝션 공격으로 이어질 수 있다), 사용자가 입력한 필터링되지 않은 내용을 사이트에 세재하는(크로스 사이트 스크립팅이나 XSS 공격을 야기할 수 있다) 웹서버와 같이 웹 중심 취약점이 있다.

 — 신뢰 관계에 대한 공격 : 어떤 공격은 애플리케이션 프로그래밍 버그 대신 신뢰 관계를 공격한다. 이러한 공격은 애플리케이션 그 자체와의 연동만 고려하면 완전하게 정당한 것처럼 보인다. 하지만 공격은 해당 애플리케이션의 사용자들이 가지는 신뢰를 대상으로 삼는다. 피싱 공격이 대표적이다. 피싱의 목표는 웹 애플리케이션이나 메일 서버가 아니라 피싱 웹사이트나 메일 메시지를 해석하는 사람이다.

 — 자원 소진 : 네트워크나 전송 계층 DoS 공격과 같이 애플리케이션도 때때로 다량의 데이터 입력을 받을 수 있다. 이러한 공격은 모든 사용자가 애플리케이션을 사용할 수 없게 한다.

 * 애플리케이션 계층 악용

 일반적인 네트워크와 전송 계층 프로토콜의 구현이 RFC에 정의된 사항을 거의 따르는 반면 특정 CGI 애플리케이션이 웹서버를 통해 사용자 입력을 처리하는 방법을 제어하거나 애플리케이션이 자동 경계 검사나 메모리 관리를 수행하지 않는 프로그래밍 언어(C 등)로 작성됐는지 제어하는 표준은 없다.

 – 스노트 서명
 애플리케이션 계층 공격을 이해하는 가장 좋은 방법의 하나는 스노트 서명 집합을 살펴보는 것이다. 최근의 스노트 서명은 스노트 소스 코드와 함께 배포되지 않지만 블리딩 스노트(Bleeding Snort) 프로젝트에서 최신 공격에 대한 서명을 스노트 형식으로 생성하고 있다(http://www.bleedingsnort.com 참조)

 – 버퍼 오버플로우 공격
 버퍼 오버플로우 공격은 애플리케이션 소스 코드에서 버퍼에 복사되는 데이터의 양을 충당하기에 버퍼의 크기가 충분하지 않은 부분에서 발생하는 프로그래밍 오류를 이용하는 공격이다. 그러므로 오버플로우라는 용어는 인접한 메모리 위치가 덮어쓰일 때 사용된다. 스택 기반 버퍼 오버플로우의 경우 성공적인 공격은 함수의 복귀 주소(스택에 존재)가 공격자의 코드를 가리키게 덮어 쓴다. 이를 통해 공격자는 그때부터 쭉 프로세스의 실행을 제어할 수 있다. 또 다른 분류의 버퍼 오버플로우 공격은 힙으로부터 동적으로 할당되는 메모리 영역에 적용된다.

 – SQL 인젝션 공격
 SQL 인젝션 공격은 사용자 입력이 데이터베이스 질의에 포함되기 전에 이것이 올바른지 확인하거나 필터링하지 않는 애플리케이션을 공격한다. 영악한 공격자는 새로운 질의를 생성해서 잠재적으로 데이터베이스의 정보를 수정하거나 추출하기 위해 SQL 언어의 충첩(nesting) 기능을 사용할 수 있다. SQL 인젝션 공격의 일반적인 목표는 웹서버를 통해 실행되며, 후단 데이터베이스로의 인터페이스를 제공하는 CGI 애플리케이션이다.

 – 그레이 매터 해킹(Gray Metter Hacking)
 오늘날 인터넷에서 가장 문제가 되는 공격의 일부는 직접 사람들이 사용하는 애플리케이션을 통해서 사람들을 목표로 하는 공격이다. 강력한 시스템, 애플리케이션, 암호화 기법의 취약점을 찾는 것보다 사람을 공격하는 것이 때로는 쉽다.

 — 피싱(Phishing)
 피싱(Phishing)은 사용자가 은행과 같은 온라인 계좌에 대한 인증 정보를 신뢰할 수 없는 곳에 제공하게 속이는 공격이다. 이 공격은 주로 공식적인 것처럼 보이는 메일을 사용자게 전송해서 이뤄지는데, 메일의 내용은 사용자가 온라인 계좌에 접속해서 보안상 “긴급한” 작업(예를 들어 암호 변경)을 수행해야 한다는 것이다. 정상적인 것처럼 보이는 웹 링크가 제공되지만 이는 원래의 웹사이트를 비슷하게 흉내낸 공격자 제어하의 웹사이트로 사용자를 유도하는 교묘한 링크다. 일단 피싱 공격을 당하는 사용자가 사이트에 방문해서 자신의 계정 정보를 입력하는 공격자는 재빨리 계정 정보를 가로챈다.

 — 백도어와 키보드 입력 로깅
 백도어(backdoor)란 공격자는 사용할 수 있지만 정당한 사용자는 사용할 수 없는 기능을 포함하는 실행 파일이다.  예를 들어 Sdbot 트로이목마는 공격자의 명령어 전송을 기자리는 IRC 채널로 연결하기 위해 특정 IRC 클라이언트를 사용해서 백도어를 연다. 하지만 백도어는 어떤 동작도 취하기 전에 공격자가 유효한 암호를 입력하게 만든 프로그램이다. 이는 백도어 통신의 인증 수준을 높여주며, 시스템에 성공적으로 침투한 공격자만이 그 시스템을 제어할 수 있게 해준다.

 * 암호호와 애플리케이션 인코딩

 애플리케이션 계층 공격을 탐지하기 어렵게 만드는 요소로 암호화와 애플리케이션 인코딩 기법의 두 가지를 곱을 수 있다. 암호화는 암호 키가 없는 한 암호를 평문화하는 것이 현실적으로 불가능하게 설계되며, 보통의 IDS, IPS 방화벽 장치는 이러한 키에 접근할 수 없기 때문에 특히 문제가 된다.

 그러나 일부 애플리케이션 계층 공격의 경우에는 성공을 위해 암호화가 필요가 없다. 예를 들어 SSH 서버에 대한 특정 공격을 탐지하는 스노트 서명(“평문 상태”에서 동작해야 함)이 있다. 이러한 서명이 사용되면 스노트는 SSH 암호화 키에 접근하지 않고 페이로드 데이터를 검색한다. 이러한 서명의 존재는 암호화만으로는 완벽한 방어를 할 수 없다는 것을 의미하며, 때때로 공격자는 통상적으로 요구되는 암호화 계층이 어떤 차이도 만들어내지 못하는 애플리케이션 취약점을 공격할 수 있다. 즉, 암호화되지 않은 수단을 통해 접근 가능한 함수 내부에 취약점이 존재할 수도 있다.

 인코딩 기술 역시 IDS가 다루기 어려울 수 있다. 예를 들어 보통 느린 네트워크로 압축하지 않은 데이터를 전송하는 것보다 빠른 CPU로 데이터를 압축하거나 압축 해제하는 것이 빠르기 때문에 많은 웹 브라우저가 네트워크를 통해 전송되는 데이터의 크기를 줄이기 위해 gzip 인코딩을 지원한다. 공격자가 약간의 무작위 데이터를 섞은 후 gzip으로 압축하면 IDS는 공격을 탐지하기 위해 이 데이터가 네트워크로 전송될 때 해당 데이터의 압축을 해제해야 한다. 무작위 데이터는 압축된 공격이 매번 달라 보이게 한다. 이러한 무작위화를 거치지 않으면 IDS는 공격을 식별하기 위해 압축 문자열 자체를 검색할 수 있다. 분주한 네트워크에는 악의적이지 않은 대용량 압축 파일을 다운로드 하는 웹 세션이 매우 많기 때문에 모든 웹 세션을 시시간으로 압축 해제하는 것은 계산상 비현실적이다.

 – IDS가 모든 애플리케이션 인코딩을 디코딩할 수 없는 것은 아니다. 예를 들어 웹 세션에서 URL 인코딩된 데이터는 스노트 서명 언어의 uricontent 키워드를 이용해서 스노트 HTTP 전처리기에 의해 실시간으로 디코딩된다. 이는 URL 인코딩이 16진수 코드와 % 기호를 사용하는 단순한 치환 연산을 통해 수행되기 때문에 가능하다. 예를 들어 A는 %41이 되며, 이는 동일한 방식으로 쉽게 복원할 수 있다. 이러한 인코딩 기법은 많은 계산을 필요로 하지 않는다.

 * 애플리케이션 계층 응답

 기술적으로 애플리케이션 계층 공격에 대한 순수한 애플리케이션 계층 응답은 애플리케이션 계층에 존재하는 구성소만을 포함해야 한다. 예를 들어 사용자가 애플리케이션을 악용하고 있다면 단순히 해당 계정을 비활성해야 되며, 공격자가 웹서버에서 실행되는 CGI 애플리케이션을 통해 SQL 인젝션을 시도한다면 질의를 무시하고 클라이언트로 HTTP 오류 코드를 반환해야 한다. 이러한 응답은 애플리케이션 계층 아래에 존재하는 패킷 헤더 정보의 변경을 필요로 하지 않는다.

 그러나 엄격한 애플리케이션 계층 응답은 방화벽과 네트워크 침입 방지 시스템에 적합하지 않다. 이는 방화벽과 네트워크 침입 방지 시스템이 보통 애플리케이션 자체와 긴밀히 통합돼 있지 않기 때문이다. 더욱이(양방향 통신을 필요로 하는) TCP 세션상에서 특정 IP 주소로부터 매우 악의적인 공격이 발견됐다면 그때부터는 공격자 IP 주소로부터의 모든 통신을 차단하는 것이 좀 더 유용할 수 있다. 이는 애플리케이션 계층 공격에 대한 네트워크 계층 응답이다.

3. 전송 계층 공격과 방어

 TCP는 연결형 프로토콜이다. 이는 클라이언트와 서버가 실제 데이터 교환 이던에 데이터 전송 방법을 정의하는 매개변수들을 협의하며 연결의 시작과 끝에 명확한 구분이 있다는 뜻이다. TCP 는 두 노드 사이에서 신뢰할 수 있고 순서를 유지하는 방식으로 데이터를 전송하므로 애플리케이션 계층 프로토콜은 이런 기능을 자체적으로 내장할 필요가 없다.

 반면 UDP 는 비연결형 프로토콜이다. 그러므로 데이터가 의도된 목적지에 도달하리라는 보장도 없고 전송을 보장하는 데이터 형태에 대한 보장도 없다(심지어 UDP 헤더에서는 TCP와 달리 체크섬 계산초자 옵션이다). UDP 소켓을 통해 데이터를 전송하는 애플리케이션은 데이터를 신뢰할 수 있게 전송하기 위한 추가적인 기법을 구현할 수 있지만 이러한 기능은 UDP 소켓이 사용될 때 애플리케이션 계층에 내장되야 한다.

  * iptables 를 이용한 전송 계층 헤더의 기록

 iptables LOG 타겟은 TCP와 UDP 헤더 기록을 위한 광범위한 장치를 가지고 있다. TCP 헤더는 UDP 헤더보다 훨씬 더 복잡하며, TCP 헤더 항목의 일부는 iptables 정책에 LOG 규칙이 추가될 때 iptables 에 특정 명령 행 인자가 주어질 경우에만 기록된다.

 – TCP 헤더의 기록
 TCP 헤더는 RFC 793에 정의돼 있으며 TCP 세그먼트(패킷)의 헤더 길이는 포함된 옵션의 수에 따라 다양하다. 옵션(유일한 가변 길이 항목)을 제외한 헤더의 길이는 항상 20바이트다.

 INPUT, OUTPUT, FORWARD 체인의 LOG 규칙은 모두 –log-tcp-options 인자를 포함한다. 그러므로 로그 메시지는 TCP 세그먼트가 옵션을 포함할 때마다 알아볼 수 없는 16진수 코드를 포함한다.

 iptables 가 TCP 순서번호와 승인 값도 포함하게 하려면 –log-tcp-sequence 인자를 사용하면 된다.

 – UDP 헤더의 기록
 UDP 헤더는 RFC 768에 정의돼 있다. 길이가 8바이트밖에 되지 않으며 가변 길이 항목은 없다.

 LOG 타겟이 UDP 헤더를 나타내는 방법에 영향을 줄 수 있는 특수 명령 행 인자는 없기 때문에 iptables는 UDP 헤더를 항상 동일한 방식으로 기록한다.

 앞서 작성한 iptables 정책의 기본 LOG 규칙은 –log-tcp-options 인자를 사용하지만 iptables 는 UDP 패킷이 이런 규칙 중 하나와 일치하는 경우에도 제대로 동작하며, 실제 패킷에 들어있는 정보만을 기록한다. 즉, 존재하지도 않는 TCP 헤더의 옵션 부분을 기록하려고 하지 않는다. UDP 체크섬은 기록되지 않지만 나머지 세 항목(SPT, DPT, LEN)은 모두 포함한다.

 * 전송 계층 공격 정의

 네트워크 계층 공격의 정의와 마찬가지로 전송 계층 공격은 말단 호스트의 전송 스택 구현에 존재하는 취약점이나 오류 조건(error condition)을 공격하기 위해 전송 계층 헤더의 항목을 악용하는 패킷이나 패킷들로 정의된다.

 전송 계층 공격은 다음과 같이 세 분류로 나뉜다.

 — 연결 자원 소진 : 목표 호스트나 호스트 집합에서 새로운 연결을 서비스하는 데 사용할 수 있는 자원을 모두 포화시키기 위해 설계된 패킷. 대표적인 예로 SYN 플러딩 형태의 DDoS 공격이 있다.

 — 헤더 악용 : 악의적으로 구성됐거나 깨진, 또는 변조된 전송 계층 헤더를 포함하는 패킷. 대표적인 예로는 TCP 연결을 파괴하기 위해 설계된 가짜 RST 패킷이 있다. 스캔 자체가 악의적인 것은 아니지만 포트 스캔도 이 범주에 포함된다.

 — 전송 스택 공격 : 말단 스택에 존재하는 취약점에 대한 전송 계층 소택 공격을 포함하는 패킷. 즉, 전송 계층 정보를 처리하는 커널 코드 자체가 공격 목표다. 대표적인 예로는 넷필터 TCP 옵션 처리 코드에 존재하는 취약점에 대해 2004년에 발표된 공격이 있다. 이 공격은 TCP 패킷 자체를 공격하지는 않지만 넷필터 프레임워크를 통해 스택으로 직접 후킹되는 코드를 공격한다.

 * 전송 계층 악용

 어떤 면에서 전송 계층은 네트워킹된 애플리케이션과 스택 위로 통신하기 전에 나오는 마지막 게이트웨이기 때문에 공격자에게 매력적인 공격 목표다. 전송 계층 정보를 포함하는 수상한 활동의 다수는 노골적인 공격이 아니라 정탐이다.

 – 포트 스캔
 포트 스캔은 특정 IP 주소에서 어떤 TCP나 UDP 서비스가 접근 가능한지 알아보기 위해 호스트의 정보를 얻어내는 기술이다. 공격자는 시스템 스캔을 통해 접근이나 공격할 서비스의 정보를 얻기 때문에 이는 성공적인 침투의 중요한 단계일 수 있다.

 반면 포트 스캔은 단지 어떤 서비스가 이용 가능한지 알아보는 데에도 중요한 단계일 수 있다. 포트 스캔 자체에는 본질적으로 악의적인 어떤 것도 없다. 포트 스캔은 집의 모든 문을 두드려보는 사람에 비유할 수 있다. 그러나 누군가가 집의 모든 문을 두드린다면 이는 그가 집에 침입할 가장 좋은 방법에 대한 정보를 모으고 있을 수도 있다는 의미기 때문에 이를 알아채는 것은 중요한 일이다.

 마찬가지로(긍정 오류를 줄이기 위한 튜닝 연습을 한다는 가정하에) 포트 스캔을 탐지하는 것은 좋은 생각이며, 대부분의 네트워크 침입 탐지 시스템은 스캔될 때 알림을 전송할 수 있는 기능을 제공한다.

 — 취약한 서비스로 포트 스캔 일치 시키기
 포트 스캔을 위해 목표 시스템의 가능한 모든 포트에 대해 전체 시험을 수행할 필요는 없다. 예를 들어 OpenSSH 3.3과 BIND 4.9 서버의 침투에 능숙한 공격자라면 나머지 65,533 개의 포트도 모두 바인딩된 서버를 가진다는 사실을 알아내는 것은 별 소용이 없다. 더욱이 시스템의 모든 포트를 시험하기 위해 생성한 떠들썩한 스캔은 보통의 포트 스캔 임계치를 넘을 가능성이 매우 높기 때문에 IDS 의 경고를 유발하기 십상이다. 공격자 입장에서는 불필요한 주목을 받지 않는 것이 좋다. 공격자는 IDS가 스캔의 실제 출발지를 결정하기 더 어렵게 하기 위해 Nmap의 미끼 (-D) 옵션을 사용할 수 있다. 이 옵션은 포트 스캔을 여러 개의 스푸핑된 출발지 주소로 중복되게 함으로써 목표 시스템이 동시에 여러 개의 독립적인 출발지에 의해 스캔되고 있는 것처럼 보이게 한다. 목적은 IDS 알림을 본 보안 관리자가 실제 스캔 출발지를 알아내기 힘들게 하는 것이다.

 — TCP 포트 스캔 기술
 TCP 포트의 포트 스캔에는 엄청나게 많은 기술을 사용할 수 있다. 여기서는 Nmap을 사용하여 포트 스캔 기술을 다룰 것이다.
 TCP connect() 스캔 – (Nmap -sT)
 TCP SYN 또는 반개방(half-open) 스캔 – (Nmap -sS)
 TCP FIN, XMAS, NULL 스캔 – (Nmap -sF, -sX, -sN)
 TCP ACK 스캔 – (Nmap -sA)
 TCP 유휴 스캔(idle) 스캔 – (Nmap -sI)
 UDP 스캔 – (Nmap -sU)

 또 스캔에서는 Nmap이 스캔을 전송하기 전에 해당 방화벽 시스템의 동작 여부를 알아보지 않게(즉, 호스트의 발견을 생략하게) 강제하기 위해 Nmap -P0 명령 행 옵션을 사용한다. Nmap의 관점에서 볼 때 스캔된 포트는 다음의 세 상태 중 하나에 속한다.

 열림 : 포트에 바인딩된 서버가 있으며 접근 가능하다.
 닫힘 : 포트에 바인딩된 서버가 없다.
 필터링됨 : 포트에 바인딩된 서버가 있을 수 있지만 이와 통신하기 위한 시도는 차단되며 Nmap은 포트가 열려있는지 또는 닫혀있는지 알 수 없다.

 — TCP connect() 스캔
 통상적인 클라이언트 애플리케이션이 네트워크를 통해 TCP 포트와 바인딩된 서버와 통신하고자 할 때는 로컬 TCP 스택이 클라이언트 입장에서 원격 스택과 연동한다. 두 스택은 애플리케이션 계층 데이터가 전송되기 전에 클라이언트와 서버 사이에 있을 통신을 관리하는 매개변수를 협상해야 한다. 이 협상을 표준 TCP 쓰리웨이 핸드셰이킹(three-way handshake) 이라고 한다.

 TCP connect() 스캔의 문맥에서 스캐너는 스캔되는 각 포트에 SYN과 마지막 ACK 패킷을 전송한다. 일반 사용자는 Nmap을 사용해서 이런 방식으로 원격 시스템을 스캔할 수 있다. 어떤 특수 권한도 필요치 않다

 — TCP SYN이나 반개방 스캔
 SYN 이나 반개방 스캔은 목표 포트가 열렸는지 아니면 닫혔는지를 알려주는 SYN/ACK 이나 RST/ACK 응답을 모으기 위해 스캐너가 각 TCP 포트로 SYN 패킷을 전송한다는 점에서 connect() 스캔과 유사하다. 그러나 이 경우 스캔 시스템은 고의적으로 SYN/ACK 로 응답하는 열린 포트로 ACK 패킷을 반환하지 못하게 하기 때문에 쓰리웨이 핸드쉐이크는 완료되지 않는다. 그러므로 SYN 스캔은 핸드쉐이크가 정상적으로 완료될 수 없다는 점에서 반개방 스캔이라고도 한다.

 connect() 시스템 호출은 목표로부터 수신한 SYN/ACK 에 대해 ACK으로 응답하는 바닐라 TCP 스택 코드를 호출하기 때문에 SYN 스캔에는 사용할 수 없다. 그러므로 SYN 스캔에서 전송되는 모든 SYN 패킷은 TCP 스택 전체를 우회하는 기법을 이용해서 생성해야 한다. 이 작업에는 보통 OS 커널의 전송 시 SYN 패킷을 모방하는 데이터 구조를 만들기 위해 원시 소켓을 사용한다.

 — 원시 소켓과 원하지 않은 SYN/ACK
 원격 시스템에 대한 TCP SYN 패킷을 생성하기 위해 connect() 시스템 호출 대신 원시 소켓을 사용하는 것은 흥미로운 쟁점을 유발한다. 원격 호스트가 SYN/ACK 로 응답하면 스캔 시스템상의 로컬 TCP 스택은 SYN/ACK 를 수신하지만 아웃바운드 SYN 패킷은 로컬 스택으로부터 온 것이 아니다(원시 소켓을 통해 SYN을 생성했기 때문). 그러므로 SYN/ACK 는 스택이 관련되는 한 정당한 TCP 핸드쉐이크의 일부가 아니다. 그러므로 스캐너의 로컬 스택은 SYN/ACK 패킷을 원하지 않은 패킷으로 보고 목표 시스템에 RST을 전송한다. 이러한 스캔 시스템의 동작은 명령어로 스캔을 시작하기 전에 다음과 같은 iptables 규칙을 OUTPUT 체인에 추가해서 막을 수 있다.

 # iptables -I OUTPUT 1 -d target -p tcp –tcp-flags RST RST -j DROP

 Nmap은 SYN 스캔 모드(-sS, 특수 권한을 가진 사용자를 위한 기본 스캔 모드)에 사용되는 TCP SYN 패킷을 직접 만들기 위해 원시 소켓을 사용한다. 이러한 패킷의 특징은 (로컬 TCP 스택을 사용하지 않고) Nmap 에 의해 직접 결정되기 때문에 스택이 일반적으로 생성하는 TCP SYN 패킷과는 상당히 다르다.

 실제 TCP 스택이 생성하는 SYN 패킷과 달리 Nmap은 실제 TCP 세션의 협상을 신경쓰지 않는다. Nmap의 유일한 관심사는 원격 호스트의 포트가 열렸는지 (Nmap은 SYN/ACK를 수신함), 닫혀있는지(Nmap은 RST/ACK을 수신함), 아니면 필터링됐는지(Nmap은 아무것도 수신하지 않음)다. 그러므로 Nmap이 전송하는 TCP SYN 패킷은 원격 TCP 스택이 SYN/ACK, RST/ACK으로 응답하거나 응답하지 않게(포트가 필터링된 경우) SYN 플래그를 설정한 TCP 패킷으로서 원격 호스트에 적합하기만 하면 된다.

 — TCP FIN, XMAS, NULL 스캔
 FIN, XMAS, NULL 스캔은 (RFC를 따르는) 모든 TCP 스택이 포트에서 SYN, ACK, RST 제어 비트를 설정하지 않은 뜻밖의 TCP 패킷을 수신한 경우 특정한 방법으로 응답해야 한다는 사실에 기반해서 동작한다. 포트가 닫혀있다면 TCP는 RST/ACK으로 응답하지만 포트가 열려있다면 TCP는 어떤 패킷으로도 응답하지 않는다.

 — TCP ACK 스캔
 TCP ACK 스캔 (Nmap -sA)은 스캔되는 각 패킷에 TCP ACK 패킷을 전송하고 열린 포트와 닫힌 포트로부터 RST 패킷(RST/ACK 패킷이 아님)을 기다린다. 목표 포트에서 RST 패킷이 반환되지 않으면 Nmap은 해당 포트가 필터링된 것으로 추정한다.

 ACK 스캔의 목적은 포트가 열려있거나 닫혀있는지를 결정하는 것이 아니라 포트가 상태유지형 방화벼에 의해 필터링되는지 여부를 결정하는 것이다. 넷필터 연결추적 하위시스템(상태 매칭을 통해)사용될 때마다 iptables 방화벽은 상태유지형이기 때문에 뜻밖의 ACK 패킷은 방화벽 시스템의 TCP 스택에 도달할 수 없다. 그러므로 RST 패킷이 스캐너로 반환되지 않는다.

 — TCP 유휴 스캔
 TCP 유휴(Idle) 스캔은 세 개의 시스템(스캔을 시작하는 시스템, 스캔 목표, 이용률이 작은[여기서 이 스캔 이름의 “유휴” 부분이 나왔다] TCP 서버를 실행 중인 좀비 호스트)을 필요로 하는 고급 스캔 방식이다.

 유휴 스캔은 IP가 IP 스캑을 통해 전송되는 모든 패킷에 대해 IP ID 값을 1씩 증가시킨다는 사실을 이용해서 공격할 수 있다. 유휴 스캔은 이 사실과 함께 TCP 스캔이 열린 포트로의 SYN 패킷에 대한 응답으로 SYN/ACK 패킷을 전송하거나 닫힌 포트로의 SYN 패킷에 대한 응답으로 RST/ACK 패킷을 전송해야 한다는  요구사항도 이용한다. 또 모든 TCP 스택은 원하지 않은 RST/ACK 패킷을 무시해야 한다. 스캐너는 이러한 사실을 이용해서 좀비 호스트가 스캐너에서 좀비 호스트로 유지되는 TCP 세션동안 IP ID 값을 어떻게 증가되는지 지켜본다. 이와 동시에 스캐너는 목표 시스템에서 좀비 호스트의 IP 주소로 SYN 패킷을 스푸핑한다. 결과적으로 스캐너는 좀비 시스템으로부터 전송되는 패킷의 IP 헤더에 있는 IP ID 값을 감시할 수 있으며, 이 정보를 이용해서 목표 시스템의 포트가 열려있는지 아니면 닫혀있는지를 예측할 수 있다.

 스캐너가 좀비의 IP 주소로 스푸핑된 출발지 IP 주소를 가지는 SYN 패킷을 목표 시스템의 열린 포트로 전송하면 목표는 SYN/ACK 으로 (좀비 시스템에) 응답한다. 좀비가 수신한 SYN 패킷은 실제로 원하지 않은 것이기 때문에(스캐너가 스푸핑한 것) 좀비는 RST로 응답하며, 이때 IP Id 카운터를 1만큼 증가시킨다. 스캐너가 닫힌 포트로 SYN 패킷을 전송하면(역시 출발지 IP 주소는 스푸핑됨) 목표 시스템은 RST/ACK 로 좀비에 응답하며, 좀비는 원하지 않은 패킷을 무시한다. 이 경우 좀비로부터 어떤 패킷도 전송되지 않으므로 IP ID 값은 증가되지 않는다.

 스캐너는 IP ID 값이 어떻게 증가되는지를 감시해서(목표 시스템의 열린 포트에 대해서는 1만큼 증가되며 닫힌 포트에 대해서는 증가되지 않음) 목표의 어느 포트가 열려있는지 유후할 수 있다. 그러나 idel 스캔의 성공에 가장 중요한 요소는 좀비에서 이용할 수 있는 서비스의 이용률이다. 널리 쓰이는 웹서버는 좀비로 적합하지 않다. 이 경우 모든 TCP 연결이 IP ID 값을 증가시키기 때문에 대부분의 경우 스캐너가 제어할 수 없는 속도로 IP ID 값이 증가되며, 결국 IP ID 값의 변화를 스캔된 포트에 적용할 수 없게 된다.

 유휴 스캔의 목표가 되는 시스템은 좀비 호스트로부터 전송된 스푸핑된 SYN 패킷만을 보기 때문에 스캔의 실제 출발지를 알 수 없다. 목표 시스템의 iptables 로그는 정상적인 SYN 스캔처럼 보인다.

 — 좀비 호스트에서 기본 버리기 방화벽이 실행 중이라면 유휴 스캔이 동작할 수 있는 유일한 방법은 스캐너가 출발지 포트를 좀비의 열린 TCP 포트로 하드 코딩하는 것이다. 좀비 TCP 스택은 필터링된 SYN/ACK 을 볼 수 없으므로 RST를 전송하지 않을 것이며, IP ID도 증가되지 않기 때문이다. 방화벽이 설치된 경우에는 이용률이 낮은 서비스가 유일하게 이용 가능한 포트일 수도 있다.

 – UDP 스캔
 UDP는 연결을 수립하기 위한 제어 메시지를 구현하지 않기 때문에 UDP 서비스에 대한 공격은 간단하며, UDP 포트로 데이터를 전송한 후 적당한 시간 내에 응답이 오는지 알아보는 방식으로 수행된다. 서버가 대기하고 있지 않는 필터링되지 않은 포트로 UDP 패킷을 전송하면 ICMP 포트 도달 불가 메시지를 받기 때문에 스캐너는 UDP 포트가 닫혔는지 여부를 쉽게 알 수 있다.

 반면 열린 포트로 UDP 패킷을 전송하면 이 패킷이 필터링되지 않았다 하더라도 응답을 전혀 받지 못할 수도 있다. 이는 UDP 서버가 응답해야 할 의무를 가지지 않기 때문이다. 서버가 응답하는지 여부는 전적으로 포트에 바인딩된 특정 서버 애플리케이션의 결정에 달려있다.

 방화벽이 특정 포트에 대한 UDP 패킷을 스캐너로부터 차단하면 스캐너 입장에서는 아무 응답도 받지 못하므로 포트에 바인딩된 UDP 애플리케이션이 응답을 하지 않는 것처럼 보인다(이는 필터링 되는 포트가 Nmap에 의해 open|filtered 로 보고되기 때문이다).

 – 포트 스윕
 포트 스윕(sweep)은 포트 스캔과 유사한 정탐 방법이다. 그러나 포트 스윕은 단일 호스트에서 접근 가능한 서비스를 알아보는 것이 아니라 여러 호스트에 대해 단일 서비스의 이용 가능성을 확인하는 것이다. 보안 관점에서 보면 포트 스윕은 한 시스템이 웜에 의해 침투당해서 새로 감염시킬 목표를 찾고 있는 경우가 많기 때문에 포트 스캔보다 더 심각한 것이다. 네트워크에 다수의 윈도우 시스템(보통 웜의 주요 목표)이 실행 중이면 포트 스윕을 탐지하는 것은 포트 스캔을 탐지하는 것보다 더 중요하다. 그러나 웜에 직면했을 때는 수분 만에 전 세계 수천 대의 시스템을 감염시킨 SQL 슬래머(Slammer) 때처럼 빠른 탐지조차 큰 의미를 지니지 못할 수도 있다. 웜이 탐지된 시점에는 조치를 취하기엔 너무 늦은 경우가 대부분이기 때문이다.

 Nmap의 기능을 이용하면 특정 서비스에 대해 네트워크 전체를 쉽게 스윕할 수 있다. 예를 들어 공격자가 SSH 데몬을 공격한다면 Nmap은 다음과 같이 10.0.0.8/8 서브넷 전체에서 SSH 서비스를 이용할 수 있는 모드 개체를 찾을 수 있다.

 # nmap -P0 -p 22 -sS 10.0.0.0/8

 – TCP 순서 번호 예측 공격
 수립된 TCP 연결에 데이터를 삽입하기 위해서 공격자는 데이터 전달을 추적하기 위해 사용되는 현재의 순서 번호를 알아야 한다(또는 추측해야 한다). 순서 번호는 데이터를 전송하기 전에 연결 양측이 각기 선택한 초기 순서 번호에 따라 달라진다. 초기 순서 번호가 무작위로 선택되게 보장하기 위해 일부 TCP 스택에서는 상당한 작업이 수행되며 순서 번호 항목의 크기 역시 공격자가 TCP 연결을 스니핑하지 못할 때 순서 번호의 예측을 어렵게 한다.

 네트워크 게이트웨이가 iptables를 실행 중일 때 내부 네트워크의 누군가가 외부 TCP 세션에 대한 순서 번호 예측 공격을 하지 못하게 막는 가장 좋은 방법 중 하나는 내부 네트워크에서 시작된 스푸핑된 패킷을 버리는 규칙을 만드는 것이다.

 – SYN 플러딩
 SYN 플러딩(flooding)은 스푸핑된 출발지 주소로부터 엄청난 양의 TCP SYN 패킷을 생성한 후 이를 특정 TCP 서버로 전달한다. SYN 플러딩의 목적은 목표 TCP 스택이 SYN/ACK 패킷을 전송하는 데 자신의 자원을 모두 소비하고 절대 받을 수 없는 ACK 패킷을 기다리게 만들어서 서버가 본래 작업을 하지 못하게 하는 것이다. SYN 플러딩은 서비스 거부 공격이다. iptables 는 limit 매치를 통해 어느 정도 SYN 플러딩 공격을 막을 수 있다.

 # iptables -I FORWARD 1 -p tcp –syn -m limit –limit 1/s -j ACCEPT

 * 전송 계층 응답

 – TCP 응답
 TCP 문맥에서 전송 계층은 통신을 종료하기 위한 고유의 응답 메커니즘을 가지며, TCP RST(재설정)나 RST/ACK(재설정/승인) 패킷의 형태로 구현된다. 이 패킷은 더 이상 데이터를 전송할 수 없으며 현재 상태와 무관하게 연결이 종료될 거라고 수신 TCP 스택에게 알린다. RST 플래그는 TCP 헤더에서 6비트 단위의 제어 비트 항목의 한 요소다. 이 패킷은 TCP 클라이언트나 서버가 더 이상 지속할 수 없는 상황에 봉착했을 때마다 쓰이며 연결의 양쪽 모두 RST를 전송할 수 있다.

 — RST와 RST/ACK
 RFC 793에 따르면 TCP 스택이 RST/ACK 패킷을 생성해야 하는 경우는 세 가지 뿐이다. 나머지 경우 ACK 비트를 설정하지 않은 RST 패킷이 전송된다. 더욱이 TCP 세션에서 마지막에 전송된 패킷의 ACK 플래그와 연결을 종료하기 위해 사용되는 RST 패킷 사이에는 반대 관계가 존재한다. 즉, 마지막 패킷이 ACK 플래그를 가지고 있다면 RST 패킷은 ACK 플래그를 포함할 수 없다. 반대로 마지막 패킷이 ACK 플래그를 포함하고 있지 않았다면 RST 패킷은 ACK 플래그를 포함해야 한다.

 — 침입 탐지 시스템과 RST 생성
 RFC 793은 RST 패킷이 승인 값과 이에 대응되는 ACK 제어 비트를 포함하는 상황을 매우 명확히 명시히고 있지만 많은 침입 탐지 시스템이 TCP 연결을 종료시키기 위해 RST를 생성할 때 RFC를 따르지 않는다.

 — SYN 쿠키
 SYN 플러딩 공격 하에서 TCP 스택이 잘 동작하게 할 수 있는 흥미로운 방법은 SYN 쿠기를 활성화하는 것이다. 수동형 IDS가 공격에 대한 응답으로 SYN 쿠키를 구현할 수는 없지만 커널이 CONFIG_SYN_COOKIES 지원을 활성화하고 컴파일된 리눅스에서는 다음과 같은 명령어를 이용해서 /proc 파일시스템을 통해 SYN 쿠키를 쉽게 활성화할 수 있다.

 # echo 1 > /proc/sys/net/ipv4/tcp_syncookies

 – UDP 응답
 UDP 스택은 기본적인 응답 매커니즘으로 ICMP를 활용한다. UDP서버가 대기 중이지 않은 포트로 UDP 패킷이 전송되면 보통 응답으로 ICMP 포트 도달 불가(ICMP Port Unreachable) 메시지가 전송된다.

 침입 탐지 시스템과 방화벽은 UDP 트래픽에 대한 응답으로도 ICMP 포트 도달 불가 메시지를 생성할 수 있다. iptables REJECT 타겟은 –reject-with icmp-port-unreachable 명령 행 인자를 통해 이러한 응답을 지원한다.

 — 방화벽 규칙과 라우터 ACL(Access Control List)
 RST로 의심스러운 TCP 연결을 종료시키거나 UDP 트래픽에서 공격을 탐지한 후 ICMP 포트 도달 불가 메시지를 전송하는 것과 같은 전송 계층 응답은 많은 경우에 유용하다. 그러나 이러한 응답은 개별적인 TCP 연결이나 UDP 패킷에만 적용된다. 공격자가 새로운 공격을 시도하지 못하게 막는 영속적인 방어 기술은 없다.

 다행히 TCP RST나 ICMP 포트 도달 불가 메시지를 전송하는 것은 방화벽 정책의 차단 규칙이나 공격자 IP와 공격을 받고 있는 서비스에 대한 라우터 ACL과 동적으로 결합될 수 있다.

 그러나 일단 공격자에 대한 차단 규칙이 시작되면 이 규칙은 설정 가능한 시간 후에 이를 제거할 수 있는 별도의 코드를 이용해서 관리해야 한다.

2. 네트워크 계층 공격과 방어

  * iptables 를 이용한 네트워크 계층 헤더의 기록

 iptables 로 만든 방화벽은 iptables 의 LOG 타겟을 이용해서 IPv4 헤더의 거의 모든 항목에 대한 로그 데이터를 syslog 에 작성할 수 있다.

 – IP 옵션의 기록
 IP 옵션은 IP 통신에 다양한 제어 기능을 제공하는데, 이러한 기능에는 타임스탬프(timestamp), 보안 기능, 특수 라우팅 기능을 위한 규정등이 있다. IP 옵션은 가변 길이를 가지며 인터넷에서 상대적으로 드물게 사용된다. IP 옵션이 없으면 IP 패킷 헤더는 언제나 정확히 20바이트이다. iptables 가 IP 헤더의 옵션을 기록하게 하려면 다음의 명령어를 사용한다.

 # iptables -A INPUT -j LOG –log-ip-options

 – ICMP의 기록
 iptables LOG 타겟은 ICMP를 기록하기 위한 코드를 가지며, ICMP 는 네트워크 계층에 존재한다. ICMP(RFC 792 에서 정의)는 32비트에 불과한 단순한 헤더를 가진다. 이 헤더는 유형(8비트), 코드(8비트), 체크섬(16비트) 의 세 가지 항목으로 구성된다. 나머지 항목은 ICMP 패킷의 데이터 부분에 속한다.

 데이터 부분의 특정 항목은 ICMP유형과 코드 값에 따라 달라진다. 예를 들어 ICMP 에코 요청(유형8, 코드0)과 관련된 항목에는 ID 와 순서 번호(sequence) 값이 포함된다.

 IP 헤더와 마찬가지로 LOG 타겟은 항상 ICMP 유형과 코드 항목을 기록하며 ICMP 체크섬 항목은 절대 기록하지 않는다. iptables에는 LOG 타겟이 ICMP 패킷의 데이터 부분에 속한 항목을 출력하게 할 수 있는 명령 행 인자가 없다.

  * 네트워크 계층 공격 정의

 네트워크 계층 공격은 말단 호스트의 네트워크 스택 구현에 존재하는 취약점을 공격하거나 네트워크 계층 자원을 소비하거나 상위 계층에 대한 공격 전달을 숨기기 위해 네트워크 계층의 헤더 항목을 악용하는 패킷들로 정의된다.

 네트워크 공격은 아래와 같이 세 종류로 나뉜다.

 – 헤더 악용 : 악의적으로 구성됐거나 깨진, 또는 변조된 네트워크 계층 헤더를 포함하는 패킷. 예를 들어 스푸핑된 출발지 주소를 가지는 IP 패킷과 비현실적 인 단편화 오프셋(fragment offset) 값을 포함하는 패킷이 있다.

 – 네트워크 스택 공격 : 말단 호스트의 네트워크 스택 구현에 존재하는 취약점을 공격하게 설계된 특수 컴포넌트를 포함하는 패킷. 즉, 네트워크 계층 정보를 처리하는 코드 자체가 공격 목표다. 대표적인 예로는 리눅스 커널(버전 2.6.9와 그 이전 버전)에서 발견된 인터넷 그룹 관리 프로토콜(IGMP, Internet Group Management Protocol) 서비스 거부(DoS, Denial of Service) 취약점이 있다

 – 대역 폭포화 : 목표 네트워크에서 사용 가능한 모든 대역폭을 포화시키게 설계된 패킷. ICMP 를 통해 전송되는 분산 서비스 거부(DDoS, Distributed Denial of Service) 공격이 대표적인 예이다.

  * 네트워크 계층 악용

 네트워크 계층은 전 세계 어디서든지 출발지에서 목적지까지 패킷을 라우팅할 수 있으며, 이를 이용하면 전 세계의 모든 목표를 공격할 수 있다. IPv4는 어떤 인증 기법도 제공하지 않기 때문에(인증은 IPSec 프로콜이나 상위 계층 매커니즘의 역할로 남겨두었다) 공격자는 쉽게 조작된 헤더나 데이터를 가지는 IP 패킷을 만들어내고 이를 네트워크로 퍼뜨릴 수 있다. 이런 패킷은 의도된 목표에 도달하기 전에 방화벽이나 접근 제어 목록(ACL: Access Control List)을 사용하는 라우터와 같은 인라인 필터링 장치에 의해 필터링될 수 있지만 그렇지 않은 경우도 많다.

 – Nmap ICMP Ping
 동인한 서브넷이 있지 않는 시스템을 스캔하기 위해 Nmap이 사용되면 목표 호스트의 포트 80에 ICMP 에코 요청과 TCP ACK를 전송하는 방법으로 호스트 발견을 수행한다(호스트 발견은 Nmap -P0 명령 행 인자를 사용해서 비활성화할 수 있지만 기본적으로는 활성화돼있다). Nmap 에코 요청은 ICMP 헤더 외에는 어떤 데이터도 포함하지 않는다는 점에서 Nmap이 생성하는 ICMP 에코 요청은 ping 프로그램이 생성하는 에코 요청과 다르다. 그러므로 이런 패킷이 iptables에 기록되면 IP 길이 항목은 반드시 28이 된다.

 – IP 스푸핑
 IP 를 통한 통신의 경우 패킷의 출발지 주소에는 제한이 전혀 없다. 원시 소켓(특정 기준에 따라 패킷을 생성하는 저수준 프로그래밍 API)을 사용하면 임의의 출발지 주소를 가지는 IP 패킷을 전송할 수 있다. 출발지 주소가 로컬 네트워크 문맥에서 봤을 때 말이 안 되는 경우 해당 패킷은 스푸핑됐다고 한다. 관리자는 내부 네트워크의 범위에 속하지 않는 출발지 주소를 가진 패킷은 포워딩하지 않게 라우터와 방화벽을 설정할 수 있지만 많은 네트워크가 이런 식의 제어를 하지 않는다.

 보안 관점에서 스푸핑된 패킷(과 보통 IP 패킷)에 대해 알아야 할 가장 중요한 것은 출발지 주소를 믿을 수 없다는 것이다. 사실 완전한 공격이 단 하나의 스푸핑된 패킷을 통해 전달될 수도 있다.

 많은 보안 소프트웨어(공격과 방어 모두 포함)가 출발지 IP 주소를 스푸핑할 수 있다. 분산 서비스 거부(DDos)도구는 일반적으로 IP 스푸핑을 필수적인 것으로 간주하며, hping이나 Nmap과 같이 잘 알려진 도구 역시 출발지 주소를 스푸핑할 수 있다.

 – IP 단편화
 IP 패킷을 좀 더 작은 패킷으로 쪼개는 것은 IP의 주요 기능 중 하나다. IP 패킷을 쪼개는 과정을 단편화(fragmentation)라고 하며, 단편화는 데이터 링크 MTU 크기가 너무 작아 패킷을 처리할 수 없는 네트워크로 IP 패킷이 라우팅될 때마다 필요하다. 한 데이터 링크 계층에서 다른 데이터 링크 계층으로 전송되는 IP 패킷이 MTU를 초과하지 않게 MTU 크기가 서로 다른 두 데이터 링크 계층을 연결하는 것은 라우터의 역할이다. 목적지 호스트의 IP 스택은 패킷 내부에 캡슐화된 프로토콜이 다음 계층의 스택으로 전달될 때 본래의 패킷을 생성하기 위해 IP 단편을 재조립한다.

 공격자는 공격을 구성한 후 이를 다수의 IP 단편으로 정교하게 쪼개는 방법으로 IP 단편화를 IDS 회피 매커니즘으로 이용할 수 있다. 완전히 구현된 IP 스택은 모두 단편화된 트래픽을 재조립할 수 있지만 공격을 탐지하기 위해 IDS가 목적지 IP 스택이 사용하는 것과 동일한 알고리즘을 사용해서 트래픽을 재조립할 수도 있다. IP 스택의 재조립 알고리즘 구현이 약간씩 다르기 때문에(예를 들어 중복된 단편화에 대해 시스코 IOS IP 스택은 마지막 단편화 정책에 따라 트래픽을 재조립하는 반면 윈도우 XP의 스택은 첫 번째 단편화 정책에 따라 재조립한다) IDS가 동일한 알고리즘을 사용하는 것은 힘든 일이다. 단편화된 트래픽을 생성하는 최고의 표준은 덕 속으이 fragroute 도구다.(http://www.monkey.org 참조)

 – 작은 TTL 값
 모든 라우터는 IP 패킷이 다른 시스템으로 포워딩될 때마다 IP 헤더의 TTL 값을 1씩 감소시켜야 한다. 로컬 서브넷 내에 TTL 값이 1인 패킷이 나타나면 누군가 로컬 서브넷이나 로컬 서브넷을 통해 라우팅되는 서브넷에 존재하는 IP 주소에 대해 traceroute 프로그램(또는 tcptracerouote 와 같은 변형)을 사용하고 있을 가능성이 높다. 이는 보통 네트워크 연결 문제를 해결하려는 사람인 경우가 많지만 잠재적 공격 목표로의 홉(hop)을 알아내기 위해 네트워크를 정탐하고 있는 사람일 수도 있다.

 – 스머프 공격
 스머프(Smurf) 공격은 공격자가 ICMP 에코 요청을 네트워크 브로드캐스트 주소로 스푸핑하는 기술로 오래됐지만 뛰어난 것이다. 스푸핑된 주소는 의도된 목표이며, 이 공격의 목적은 브로드캐스트 주소를 통한 에코 요청에 응답하는 시스템으로부터 목표에 가능한 많은 ICMP 에코 요청 패킷이 전송되게 하는 것이다. 네트워크가 브로드캐스트 주소에 대한 ICMP 에코 요청을 적절히 제어(예를 들어 시스코 라우터에서 no ip directed-broadcast 명령어를 사용)하지 않은 채 동작한다면 에코 요청을 수신하는 모든 호스트는 스푸핑된 출발지 주소로 응답할 것이다. 공격자는 대규모 네트워크의 브로드캐스트 주소를 사용해서 목표를 향해 생성되는 패킷의 수를 증가시킬 수 있다.
 
 스머프 공격은 전용 제어 채널을 사용하며 대응할 수 있는 쉬운 라우터 설정이 없는 DDoS 공격을 수행하는 도구에 비하면 구식이다. 그러나 스머프 공격은 수행하기 매우 쉬우며, 최초의 소스 코드(http://www.phreak.org)를 쉽게 구할 수 있기 때문에 언급할만한 가치는 있다.

 – DDoS 공격
 네트워크 계층의 DDoS 공격은 동시에 목표 IP 주소로 패킷을 플러딩(flooding)하기 위해 많은 수의 시스템(잠재적으로 수천 개)을 사용한다. 이 공격의 목적은 정당한 통신을 막기 위히ㅐ 목표 네트워크의 대역폭을 쓰레기 데이터로 최대한 잠식시키는 것이다. 너무나 많은 시스템이 광대역을 통해 인터넷에 연결돼 있기 때문에 DDoS 공격은 좀 더 대처하기 어려운 네트워크 계층 공격 중 하나다. 공격자가 빠른 인터넷 연결을 가진 일부 시스템에 성공적으로 침투하면 대부분의 사이트에 손해를 끼치는 DDoS 공격을 수행할 수 있다.

 DDoS 에이전트가 생성하는 각 패킷을 스푸핑할 수 있기 때문에 패킷이 공격 목표에 도달한 시점에 이런 패킷의 출발지 IP 주소에 어떤 값을 할당하는 것은 일반적으로 무의미한다.

 일반적으로 DDoS 에이전트와 관련된 제어 통신을 탐지하는 것이 플러딩 패킷 자체를 탐지하는 것보다 더 효과적이다. 예를 들어 불분명한 포트 번호를 통해 제어 노드에서 좀비 노드로 전송되는 명령어를 탐지하는 것은 좋은 전략이다.(스노트 규칙집합의 여러 서명이 이런 유형의 통신을 찾는다) 이런 전략은 제어 통신을 통해 감염된

1. iptables가 제공하는 보호

 *iptables

 iptables 방화벽은 넷필터 프로젝트(Netfilter Project, http://www.netfilter.org)에서 개발됐으며, 2001년 1월의 리눅스 2.4 커널 배포 시점부터 리눅스의 일부분으로 제공됐다.

 iptables와 넷필터라는 단어 간의 차이는 리눅스 커뮤니티에서 다소 혼란의 원인이었다. 리눅스가 제공하는 모든 종류의 패킷 필터링과 맹글링(mangling) 도구의 공식적인 프로젝트명이 넷필터다. 하지만 이 단어는 네트워킹 스택으로 함수를 후킹(hooking)하는 데 사용할 수 있는 리눅스 커널 내부의 프레임워크를 말하기도 한다. 한편 iptables는 패킷에 대한 연산(필터링 등)을 수행하게 설계된 함수를 네트워킹 스택으로 후킹하기 위해 넷필터 프레임워크를 사용한다. 넷필터는 iptables가 방화벽 기능을 구현할 수 있게 프레임워크를 제공한다고 생각할 수 있다.

 넷필터가 트래픽 자체를 필터링하지는 않는다. 넷필터는 커널 내부의 적절한 부분에 후킹되게 트래픽을 필터링할 수 있는 기능을 가능케 해줄 뿐이다. 넷필터 프로젝트는 연결 추적이나 기록(logging)과 같은 커널 인프라스트럭처의 일부를 제공하기도 한다. 모든 iptables 정책은 특화된 패킷 처리를 수행하기 위해 이런 넷필터의 기능을 사용할 수 있다.

  * iptables를 이용한 패킷 필터링

 사용자는 iptables 방화벽을 이용해서 리눅스 시스템과 연동하는 IP 패킷에 대해 강력한 제어 기능을 갖출 수 있다. 이러한 제어는 리눅스 커널 내부에 구현된다.

 iptables 정책은 정렬된 규칙집합으로부터 생성된다. 규칙은 특정 분류의 패킷에 대해 취해야 할 조치를 커널에게 알려준다. 하나의 iptables 규칙은 테이블 내에 있는 하나의 체인에 적용된다. iptables 체인은 순서대로 공통적인 특징(예를 들어 리눅스 시스템으로 라우팅되거나 리눅스 시스템에서 외부로 나가는 것)을 공유하는 패킷들과 비교되는 규칙 모음이다.

 – 테이블
 테이블(table)은 패킷 필터링이나 네트워크 주소 변환(NAT, Network Address Translation)과 같은 기능의 광범위한 범주를 기술하는 iptables 구성소다. filter, nat, magle, raw 와 같은 4개의 테이블이 있다. 필터링 규칙은 filter 테이블에 적용된다. NAT 규칙은 nat 테이블에 적용되며, 패킷 데이터를 변경하는 특수 규칙은 mangle 테이블에 적용된다. 끝으로 텟필터의 연결추적 하위시스템과 독립적으로 기능해야 하는 규칙은 raw 테이블에 적용된다.

 – 체인
 각 테이블은 자신만의 고유(build-in) 체인(chain) 집합을 가지지만 사용자는 INPUT_ESTABLISHED 나 DMZ_NETWORK 와 같은 공통 태그와 관련된 규칙집합을 만들기 위해 사용자 정의 체인을 생성할 수 있다. 패킷 필터링에서 가장 중요한 고유 체인은 filter 테이블의 INPUT, OUTPUT, FORWARD 체인이다.

 — INPUT 체인은 커널 내부에서 라우팅 계산을 마친 후 로컬 리눅스 시스템이 목적지인 패킷(즉, 로컬 소켓이 목적지인 패킷)에 적용된다.

 — OUTPUT 체인은 리눅스 시스템 자체가 생성하는 패킷을 위해 예약된 것이다.

 — FORWARD 체인은 리눅스 시스템을 통과하는 패킷을 관리한다.(즉, 한 네트워크를 다른 네트워크와 연결하기 위해 iptables 방화벽을 사용해서 두 네트워크 간의 패킷이 방화벽을 통과해야 하는 경우)

 좀 더 견고한 iptables 설치를 위해 필요한 두 개의 추가 체인으로 nat 테이블의 PREROUTING과 POSTROUTING 체인이 있다. 이 체인은 커널 내부에서 IP 라우팅 계산을 수행하기 전과 휴에 패킷 헤더를 수정하기 위해 사용한다.

User image

iptables 패킷 흐름

 – 매치
 모든 iptables 규틱은 타겟(target)과 함께 규칙을 따르는 패킷을 어떻게 처리할지 iptables에게 알려주는 매치(Match)들을 가진다. iptables 매치는 iptables가 규칙 타겟에 의해 명시되는 동작에 따라 패킷을 처리하기 위해서 패킷이 만족해야 하는 조건이다. 예를 들어 규칙을 TCP 패킷에만 적용하고자 한다면 –protocol 매치를 사용하면 된다.

 각 매치는 iptables 명령 행에서 명시된다.

 –source (-s) : 출발지 IP 주소나 네트워크와의 매칭
 –destination (-d) : 목적지 IP 주소나 네트워크와의 매칭
 –protocol (-p) : 특정 프로토콜 값과의 매칭
 –in-interface (-i) : 입력 인터페이스(예를 들어 eth0)
 –out-interface (-o) : 출력 인터페이스
 –state : 연경 살태와의 매칭
 –string : 애플리케이션 계층 데이터 바이트 순서와의 매칭
 –comment : 커널 메모리 내의 규칙가 연계되는 최대 256 바이트의 주석

 – 타겟
 iptables 는 패킷이 규칙과 일치할 때 동작을 취하는 타겟(Target)을 지원한다.
 ACCEPT : 패킷이 본래 라우팅대로 진행된다.
 DROP : 패킷을 버린다. 더 이상 어떤 처리도 수행되지 않으며 수신 스택이 관련된 데에 한해서는 패킷이 전송된 적도 없는 것과 같다.
 LOG : 패킷을 syslog에 기록한다.
 REJECT : 패킷을 버리고 이와 동시에 적절한 응답 패킷(예를 들어 TCP 연결의 경우 TCP 재설정[Reset] 패킷, UDP 패킷의 경우 ICMP 포트 도달 불가[Port Unreachable] 메시지)을 전송한다.
 RETRUN : 호출 체인 내에서 패킷 처리를 계속한다.

 * 기본 iptables 정책

 – 정책 요구사항
 몇 개의 클라이언트와 두 개의 서버로 구성된 네트워크를 위한 효과적인 방화벽 설정에 필요한 요구사항을 정의해보자. 서버(웹서버와 DNS서버)는 외부 네트워크에서 접근할 수 있어야 한다. 내부 네트워크에 있는 시스템은 방화벽을 통해 외부 서버로 다음과 같은 유형의 트래픽을 시작할 수 있어야 한다.

 — 도메인 네임 시스템(DNS, Domain Name System) 질의

 — 파일 전송 프로토콜(FTP, File Transfer Protocol) 전송

 — 네트워크 시간 프로토콜(NTP, Network Time Protocol) 질의

 — 시큐어 쉘(SSH, Secure SHell) 세션

 — 단순 메일 전송 프로토콜(SMTP, Simple Mail Transfer Protocol) 세션

 — whois 질의

 위에 나열한 서비스 외에는 어떤 트래픽도 허용하지 않아야 한다. 내부 네트워크나 방화벽에서 바로 시작된 세션은 iptables가 상태유지형으로 추적해야 한다(유효한 상태를 따르지 않는 패킷은 기록한 후 최대한 빨리 버려야 한다). 또 NAT 서비스도 제공해야 한다.

 이와 더불어 방화벽은 외부 IP 주소로 포워딩되는 내부 네트워크로부터의 스푸팅된 패킷에 대한 제어를 구현해야 한다.

 — 방화벽 자체는 네트워크로부터 SSH를 통해 접속할 수 있어야 한다. 그러나 인증을 위해 fwknop를 실행하고 있지 않는 한 그 밖에 어떤 곳에서도 접속할 수 없어야 한다.

 — 방화벽은 내부와 외부 네트워크 모두로부터 ICMP 에코 요청(Echo Request)을 수용해야 한다. 그러나 에코 요청을 제외하면 어떤 출발지 IP 주소로부터의 원하지 않은(unsolicited) ICMP 패킷도 모두 버려야 한다.

 — 끝으로 잘못 전달된 패킷, 포트 스캔, 명시적으로 혀용된 것이 아닌 기타 연결 시도를 모두 기록하고 버리기 위해 방화벽은 기볼 기록 후 버리기 전략(log and drop stance)으로 설정해야 한다.

 – iptables.sh 스크립트 프리앰블(Preamble)

 iptables.sh 스크립트를 시작하기 위해 IPTABLES와 MODPROBE(iptables 와 modprobe 바이너리의 경로), INT_NET(내부 서브넷 주소와 마스크)과 같이 세 개의 변수를 정의하면 좋다. 이 변수들은 스크립트 전반에 걸쳐 사용된다.

 먼저 기존의 iptables 규칙이 실행 중인 커널에서 제거되고 INPUT, OUTPUT, FORWARD 에 대한 필터링 정책이 DROP 으로 설정된다. 또 modprobe 명령어를 사용해서 연결추적 모듈을 로딩한다.

User image

 – ip_conntrack : iptables에서 현재 테이블에 등록된 IP의 연결을 추적하기 위한 모듈
 – ip_conntrack_ftp, ip_nat_ftp : iptables 에서 ftp 사용을 가능하게 하는 모듈. NAT 설정을 사용하지 않는다면 ip_nat_ftp 모듈을 적재하지 않아도 된다.
 -> FTP의 경우 서버와 클라이언트 모두가 방화벽 안에 있으면 접속은 되지만, 파일 목록이나 내용 전송.. 등등이 안되는 현상이 벌어진다. 위의 적재된 모듈들은 이것을 피하기 위한 모듈이다.

 – INPUT 체인
 INPUT 체인은 로컬 시스템을 목적으로 하는 (즉, 커널의 라우팅 계산 결과 패킷이 로컬 IP 주소를 목적지로 한다는 것을 안 후) 패킷이 로컬 소켓과 통신할 수 있는지 여부를 결정하는 iptables 구성소다. INPUT 체인의 첫 번째 규칙이 iptables로 하여금 모든 패킷을 버리게 하는 것이라면(또는 INPUT 체인의 정책 설정이 DROP으로 설정돼 있다면) 시스템과 IP 통신(TCP, UDP, ICMP 등)을 통해 직접 통신하려는 모든 시도는 실패하게 된다. 주소 결정 프로토콜(ARP, Address Resolution Protocol) 역시 이더넷 네트워크상 어디에나 존재하는 중요한 트래픽이다. 그러나 ARP는 네트워크 계층이 아니라 데이터 링크 계층에서 동작하며, iptables는 IP 트래픽과 상위 프로토콜만 필터링하기 때문에 ARP 트래픽은 필터링할 수 없다.

 그러므로 ARP 요청과 응답은 iptables 정책과 무관하게 전송되고 수신된다(arptables를 이용해서 ARP 트래픽을 필터링할 수도 있다).

 – iptables 는 커널이 MAC 주소 확장을 활성화한 상태로 컴파일된 경우에만 데이터 링크 계층의 MAC 주소에 기반해서 IP 패킷을 필터링할 수 있다. 2.4 커널 시리즈에서는 사용자가 직접 MAC 주소 확장을 활성화해야 하지만 2.6 커널 시리즈에서는 기본적으로 활성화돼 있다.

 프리앰블을 완성한 후 iptables 쉘 스크립트 개발을 계속하기 위해 다음의 명령어를 사용해 INPUT 체인을 설정한다.

##### INPUT 체인 #####
echo “[+] Setting up INPUT chain…”

### 상태 추적 규칙
$IPTABLES -A INPUT -m state –state INVALID -j LOG –log-prefix “DROP INVALID ” –log-ip-options –log-tcp-options
$IPTABLES -A INPUT -m state –state INVALID -j DROP
$IPTABLES -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

### 안티 스푸핑 규칙
$IPTABLES -A INPUT -i eth2 -s ! $INT_NET -j LOG –log-prefix “SPOOFED PKT “
$IPTABLES -A INPUT -i eth2 -s ! $INT_NET -j DROP
### ACCEPT 규칙
#ftp
$IPTABLES -A INPUT -p tcp –dport 20 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A INPUT -p tcp –dport 21 –syn -m state –state NEW -j ACCEPT
#ssh
$IPTABLES -A INPUT -p tcp –dport 22 –syn -m state –state NEW -j ACCEPT
#whois
$IPTABLES -A INPUT -p tcp –dport 43 –syn -m state –state NEW -j ACCEPT
#domain
$IPTABLES -A INPUT -p tcp –dport 53 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A INPUT -p udp –dport 53 -m state –state NEW -j ACCEPT
#http
$IPTABLES -A INPUT -p tcp –dport 80 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A INPUT -p udp –dport 80 -m state –state NEW -j ACCEPT
#https
$IPTABLES -A INPUT -p tcp –dport 443 –syn -m state –state NEW -j ACCEPT
#rsync
$IPTABLES -A INPUT -p tcp –dport 873 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A INPUT -p udp –dport 873 -m state –state NEW -j ACCEPT
#icmp
$IPTABLES -A INPUT -p icmp –icmp-type echo-request -j ACCEPT

### 기본 INPUT LOG 규칙
$IPTABLES -A INPUT -i ! lo -j LOG –log-prefix “DROP ” –log-ip-options –log-tcp-options

 앞서 정의한 방화벽 정책 요구사항에 따르면 iptables 는 연결을 상태유지형으로 추적해야 한다. 즉, 유효한 상태와 일치하지 않는 패킷은 조기에 기록하고 버려야 한다. 이는 “### 상태 추적 규칙 주석” 밑의 3개의 iptables 명령어가 수행한다. OUTPUT과 FORWARD 체인에 대해서도 이와 유사한 세 개의 명령어를 볼 수 있다. 이런 각 규칙은 INVALID, ESTABLISHED, RELATED 기준과 함께 상태 매칭을 이용한다.

 INVALID 상태는 현존하는 어떤 연결에도 속했다고 식별할 수 없는 패킷에 적용된다. 예를 들어 느닷없이 도착한 TCP FIN 패킷(즉, 어떤 TCP 세션의 일부도 아닌 TCP FIN  패킷)은 INVALID 상태와 일치된다. ESTABLISHED 상태는 넷필터 연결 추적 하위시스템이 양방향 모두에서 패킷(예를 들어 데이터가 교환되는 TCP 연결의 승인[acknowledgement] 패킷)을 본 후에만 패킷에 대해 활성화된다. RELATED 상태는 넷필터 연결추적 하위시스템에서 새로운 연결을 시작하고 있는(그러나 이 연결이 이미 존재하는 연결과 연결돼 있는) 패킷(예를 들어 어떤 서버도 바인딩되지 않은 UDP 소켓에 패킷이 전소오딘 후 반환된 ICMP 포트 도달 불가 메시지)을 기술한다.

 다음으로 안티스푸핑 규칙을 추가했으므로 내부 네트워크에서 시작된 패킷은 반드시 192.168.1.0/24 서브넷에 속하는 출발지 주소를 가진다.

 또한 “### ACCEPT 규칙” 에는 서비스를 제공 하는 일련의 포트번호의 ACCEPT 규칙이 나와 있다. SSH 연결을 수용하는 규칙은 iptables의 –syn 명령 행 인자와 함께 NEW 상태가 일치될 때(연결추적 하위 시스템이 관련된 데 한해서 패킷이 새로운 연결을 시작하고 있음을 의미한다)만 이 규칙이 일치된다.

 끝에는 기본 LOG 규칙이 나와 있다. 스크립트 프리앰블에서 봤듯이 INPUT 체인 내의 규칙에 의해 혀용되지 않는 패킷은 이 체인에 할당된 DROP 정책에 의해 버려진다는 사실을 상기하자. 이는 OUTPUT 과 FORWARD 체인에 할당된 DROP 정책에도 적용된다. 위에서 알 수 있듯이 INPUT 체인의 설정은 특정 포트로의 접속만 수용하고 원치 않는 패킷은 기록하고 버리면 되기 때문에 매우 쉽다.

 – iptables.sh 스크립트에 대해 한 가지 주의해야 할 것은 모든 LOG 규칙이 –log-ip-options 와 –log-tcp-options 를 명령행 인자로 사용한다는 점이다. 이 인자를 통해 iptables syslog 메시지는 LOG 규칙과 일치하는 패킷이 IP 와 TCP 헤더에 IP 와 TCP 옵션을 포함하는 경우 이를 포함하게 된다. 이 기능은 psad 가 수행하는 공격 탐지와 수동적 OS 핑거프린팅의 동작 모두에 중요하다.

 – OUTPUT 체인
 OUTPUT 체인은 iptables가 로컬 시스템에 의해 생성되 네트워크 패킷에 커널 수준의 제어를 할 수 있게 해준다. 예를 들어 로컬 사용자가 외부 시스템으로 SSH 세션을 초기화하면 OUTPUT 체인을 이용해서 아웃 바운드 SYN 패킷을 허용하거나 거부할 수 있다.

 iptables.sh 에서 OUTPUT 체인 규칙 집합을 구성하는 명령어는 아래와 같다.

###### OUTPUT 체인 ######
echo “[+] Setting up OUTPUT chain…”

### 상태 추적 규칙
$IPTABLES -A OUTPUT -m state –state INVALID -j LOG –log-prefix “DROP INVALID ” –log-ip-options –log-tcp-options –log-tcp-sequence
$IPTABLES -A OUTPUT -m state –state INVALID -j DROP
$IPTABLES -A OUTPUT -m state –state ESTABLISHED,RELATED -j ACCEPT

### 외부로 나가는 연결을 허용하기 위한 ACCEPT 규칙
#ftp
$IPTABLES -A OUTPUT -p tcp –dport 20 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p tcp –dport 21 –syn -m state –state NEW -j ACCEPT
#ssh
$IPTABLES -A OUTPUT -p tcp –dport 22 –syn -m state –state NEW -j ACCEPT
#whois
$IPTABLES -A OUTPUT -p tcp –dport 43 –syn -m state –state NEW -j ACCEPT
#domain
$IPTABLES -A OUTPUT -p tcp –dport 53 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp –dport 53 -m state –state NEW -j ACCEPT
#http
$IPTABLES -A OUTPUT -p tcp –dport 80 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp –dport 80 -m state –state NEW -j ACCEPT
#https
$IPTABLES -A OUTPUT -p tcp –dport 443 –syn -m state –state NEW -j ACCEPT
#rsync
$IPTABLES -A OUTPUT -p tcp –dport 873 –syn -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p udp –dport 873 -m state –state NEW -j ACCEPT
$IPTABLES -A OUTPUT -p icmp –icmp-type echo-request -j ACCEPT

### 기본 OUTPUT LOG 규칙
$IPTABLES -A OUTPUT -o ! lo -j LOG –log-prefix “DROP ” –log-ip-options –log-tcp-options –log-tcp-sequence

 – FORWARD 체인
 FORWARD 체인은 시스템을 통해 라우팅을 시도하는 패킷과 관련된 iptables 규칙을 담당한다. filter 테이블의 iptables FORWARD 체인은 방화벽 인터페이스를 통해 포워딩되는 패킷에 대한 접근 제어 기능을 제공한다.

##### FORWARD 체인 #####
echo “[+] Setting up FORWARD chain…”

### 상태 추적 규칙
$IPTABLES -A FORWARD -m state –state INVALID -j LOG –log-prefix “DROP IINVALID ” –log-ip-options –log-tcp-options
$IPTABLES -A FORWARD -m state –state INVALID -j DROP
$IPTABLES -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT

### 안티 스푸핑 규칙
$IPTABLES -A FORWARD -i eth2 -s ! $INT_NET -j LOG –log-prefix “SPOOFED PKT “
$IPTABLES -A FORWARD -i eth2 -s ! $INT_NET -j DROP

### ACCEPT 규칙
# 기본적으로 FORWARD 에 한해서는 모든 포트에 ACCEPT를 적용한다.

### 기본 LOG 규칙
$IPTABLES -A FORWARD -i ! lo -j LOG –log-prefix “DROP ” –log-ip-options –log-tcp-options

 – 네트워크 주소 변환 (NAT, Network Address Translation)
 iptables 정책을 구성하는 마지막 단계는 라우팅 불가능 내부 주소 192.168.1.0/24 를 라우팅 가능한 외부 210.125.X.X 주소로 변환할 수 있게 하는 것이다. 이는 외부 클라이언트에서 시작된 웹서버나 DNS서버로의 인바운드 연결과 내부 네트워크의 시스템에서 시작된 아웃바운드 연결 모두에 적용된다. 내부 시스템에서 시작한 연결의 경우에는 출발지 NAT(SNAT, Source NAT) 타겟을 사용하며 외부 시스템에서 시작한 연결의 경우에는 목적지 NAT(DNAT, Destination NAT) 타겟을 사용한다.

 iptables nat 테이블을 모든 종류의 NAT 규칙을 위한 것으로 PREROUTING 과 POSTROUTING 이라는 두 체인을 포함한다. PREROUTING 체인은 패킷이 어느 인터페이스를 통해 전송될지 경정하기 위해 아직 커널의 라우팅 알고리즘을 통과하지 않은 패킷에 nat 테이블의 규칙을 적용하는 데 사용한다. 이 체인에서 처리되는 패킷은 아직 filter 테이블의 INPUT 이나 OUTPUT 체인과도 비교되지 않은 것이다.

 POSTROUTING 체인은 패킷이 커널의 라우팅 알고리즘을 통과한 후 계산된 물리적 인터페이스를 통해 전송되려는 시점에서 패킷 처리를 담당한다. 이 체인이 처리하는 패킷은 filter 테이블의 OUTPUT 이나 FORWARD 체인의 요구사항(mangle 테이블과 같이 등록됐을 수 있는 다른 테이블이 강제하는 요구사항도 포함)을 통과한 것이다.

##### NAT 규칙 #####
echo “[+] Setting up NAT rules…”
$IPTABLES -t nat -A POSTROUTING -s $INT_NET -o eth3 -j MASQUERADE

 POSTROUTING 규칙은 내부의 라우팅 불가능 네트워크에서 시작되며, 외부 인터넷을 목적지로 하는 연결이 IP 주소 210.125.

 iptables 정책을 작성하는 최종 단계는 리눅스 커널의 IP 포워딩을 활성화하는 것이다.

##### 포워딩 #####
echo “[+] Enabling IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward

 – 정책 활성화
 iptables의 최고 장점 중 하나는 iptables 명령어 실행을 통해 커널 내부에서 정책을 활성화하기가 매우 쉽다는 것이다. 무거운 사용자 인터페이스나 바이너리 파일 형식 또는 비대한 관리 프로토콜은 전혀 없다.

 – iptables-save 와 iptables-restore
 iptables.sh 스크립트의 모든 iptables 명령어는 새로운 규칙을 시작하거나 체인의 기본 정책을 설정하거나 이전 규칙을 제거하기 위해 한 번에 하나씩 실행된다. 각 명령어는 iptables 정책을 생성하기 위해 매번 별도의 iptables 사용자 바이너리 실행을 필요로 한다. 그러므로 이는 시스템 부팅 시에 정책을 빠르게 적용하는 최적의 방법은 아니다. 특히 iptables 규칙의 수가 수백 개에 이르면 이런 식으로 정책을 적용하는 것은 좋지 않다. iptables 프로그램과 동일한 디렉토리에 설치되는 iptables-save 와 iptables-restore 명령어에서 훨씬 더 빠른 방법을 제공한다. iptables-save 명령어는 실행 중인 정책의 모든 iptables 규칙을 사람이 읽을 수 있는 형태로 저장하는 파일을 생성한다. 이 형식은 iptables-restore 프로그램으로 해석(interpret)할 수 있다. iptables-restore 프로그램은 ipt.save 파일에 나열된 규칙을 실행 중인 커널 내부에서 활성화한다. iptable-restore 프로그램을 한 번만 실행하면 전체 iptables 정책을 커널에 재생성할 수 있으며, iptables 프로그램을 여러 번 실행하는 것은 필요치 않다. 그러므로 iptables-save 와 iptables-restore 명령어는 iptables 규칙집합을 빠르게 적용하는 데 이상적이며, 다음과 같은 두 명령어로 나타낼 수 있다.

root@extreme:~# iptables-save > ipt.save
root@extreme:~# cat ipt.save > iptables-restore

 ipt.save 파일의 내용은 iptables 테이블에 의해 구성되며, 각 테이블을 위한 부분은 다시 iptables 체인에 의해 구성된다. 별표(*)와 테이블명(예를 들어 filter)으로 시작하는 행은 ipt.save 파일에서 특정 테이블을 위한 부분의 시작을 나타낸다. 이런 행 다음에는 해당 테이블에 속한 체인을 위한 패킷과 바이트 수를 추적하는 행이 나온다.

 ipt.save 파일의 다음 부분에는 체인에 의해 구성된 모든 iptables 규칙의 완전한 기술이 나온다. iptables-restore 는 이 부분을 이용해서 실제 iptables 규칙집합을 재생성한다(iptables-save 에 -c 옵션을 사용한 경우 규칙에 대한 패킷과 바이트 수 까지 포함해서 재생성한다).

 끝으로 COMMIT을 이용해서 ipt.save 파일의 iptables 테이블 기술 부분을 끝낸다. 이 행은 해당 테이블과 관련된 모든 정보에 대한 종료 표시자다.

 다음은 ipt.save 파일의 일부분이다.

# Generated by iptables-save v1.4.1.1 on Sat Sep 26 13:17:35 2009
*filter
:INPUT DROP [226586:80181793]
:FORWARD ACCEPT [0:0]
:OUTPUT DROP [9881:717618]
:FWSNORT_FORWARD – [0:0]
:FWSNORT_FORWARD_ESTAB – [0:0]
:FWSNORT_INPUT – [0:0]
:FWSNORT_INPUT_ESTAB – [0:0]
:FWSNORT_OUTPUT – [0:0]
:FWSNORT_OUTPUT_ESTAB – [0:0]
-A INPUT -i ! lo -j FWSNORT_INPUT
-A INPUT -p udp -m udp –dport 80 -m string –string “/etc/shadow” –algo bm –to 65535 -j LOG –log-prefix “ETC_SHADOW “
-A INPUT -p tcp -m tcp –dport 80 -m state –state ESTABLISHED -m string –string “/etc/shadow” –algo bm –to 65535 -j LOG –log-prefix “ETC_SHADOW “
-A INPUT -m state –state INVALID -j LOG –log-prefix “DROP INVALID ” –log-tcp-options –log-ip-options
-A INPUT -m state –state INVALID -j DROP
-A INPUT -m state –state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp –dport 20 –tcp-flags FIN,SYN,RST,ACK SYN -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp –dport 21 –tcp-flags FIN,SYN,RST,ACK SYN -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp –dport 22 –tcp-flags FIN,SYN,RST,ACK SYN -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp –dport 43 –tcp-flags FIN,SYN,RST,ACK SYN -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp –dport 53 –tcp-flags FIN,SYN,RST,ACK SYN -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p udp -m udp –dport 53 -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp –dport 80 –tcp-flags FIN,SYN,RST,ACK SYN -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p udp -m udp –dport 80 -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp –dport 443 –tcp-flags FIN,SYN,RST,ACK SYN -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp –dport 873 –tcp-flags FIN,SYN,RST,ACK SYN -m state –state NEW -j ACCEPT
-A INPUT -i eth0 -p udp -m udp –dport 873 -m state –state NEW -j ACCEPT
-A INPUT -p icmp -m icmp –icmp-type 8 -j ACCEPT
-A INPUT -i ! lo -j LOG –log-prefix “DROP ” –log-tcp-options –log-ip-options
-A FORWARD -i ! lo -j FWSNORT_FORWARD