1. 서문

본 문서는 여행과도 같으며, 일부분은 아주 쉽게 여행할 수 있고 또 다른 부분에서는 독자 여러분 스스로 길을 찾아야 할 것이다. 필자가 독자에게 할 수 있는 최상의 충고는 아주 큰 머그잔에 커피나 핫쵸콜릿을 가득 담아 편안한 의자에 앉아 위험스런 길을 가기 전에 본문의 내용을 넷트웍 해킹이라는 아주 위험스러운 세상에 부합시켜 깊이 생각해 보라는 것 밖에 없다.

넷필터 프레임웍의 최상위에 있는 내부구조의 사용법을 보다 잘 이해하기 위해서는, Packet Filtering HOWTO와 NAT HOWTO를 읽어보는 것이 좋을 것이다. 커널 프로그래밍에 대한 정보를 얻고자 한다면 Rusty's Unreliable Guide to Kernel Hacking과 Rusty's Unreliable Guide to Kernel Locking을 참고하기 바란다.

(C) 2000 Paul `Rusty' Russell. Licensed under the GNU GPL.

1.1. 넷필터(netfilter)란 무엇인가?

넷필터는 표준 Berkeley socket interface의 외부에 존재하는 packet mangling(패킷을 토막내는 일)에 대한 프레임웍으로, 크게 네 부분으로 구성되어 있다. 먼저 각각의 프로토콜은 "hooks"라는 것을 정의하며, 이는 패킷 프로토콜 스택의 packet's traversal에 있는 잘 정의된 포인터를 의미한다. 이러한 포인터에서, 각각의 프로토콜은 패킷과 훅넘버(hook number)를 이용하여 넷필터 프레임웍을 호출하게 된다.

두 번째로, 커널의 일부분은 각 프로토콜에 대하여 다른 hook을 감시하도록 등록할 수 있다. 따라서 패킷이 넷필터 프레임웍을 통과할 때, 누가 그 프로토콜과 훅을 등록했는지 확인하게 된다. 이러한 것이 등록되어 있다면, 등록된 순서대로 패킷을 검사하고, 패킷을 무시하거나(NF_DROP), 통과시키고(NF_ACCEPT), 또는 패킷에 대한 것을 잊어버리도록 넷필터에게 지시하거나(NF_STOLEN), 사용자 공간에 패킷을 대기시키도록(queuing) 넷필터에게 요청한다(NF_QUEUE).

세 번째 부분은 대기된 패킷을 사용자 공간으로 보내기 위해 제어하는 것으로 이러한 패킷은 비동기방식으로 처리된다.

마지막 부분은 코드와 문서에 기록된 주석문으로 구성되어 있으며, 이는 어떠한 실험적 프로젝트에 대해서도 도움이 되는 부분이다. 넷 필터의 모토는 다음과 같다.
				``그래서... KDE보다 얼만큼 좋다는 거죠?''
			

이러한 저수준 프레임웍과 더불어, 다양한 모듈이 작성되었으며, 이는 이전 버전의 커널에 대하여 유사한 기능, 확장 가능한 NAT시스템 그리고 확장 가능한 패킷 필터링 시스템을 제공한다.

1.1.1. 커널 2.0과 2.2에서의 문제점?

  1. 사용자 공간을 통과하는 패킷에 대하여 어떠한 하부구조도 만들어져 있지 않으며 그 이유는 다음과 같다.

    • 커널수준에서 코딩하는 것이 어렵다

    • 반드시 C/C++로 커널 수준의 코딩이 되어야 한다.

    • 동적 필터링 정책이 커널에 포함되어 있지 않다.

    • 커널 2.2에서는 넷링크를 거처 사용자 공간으로 패킷을 복사하는 방법을 제시하였으나, 재전송 패킷이 느리고 `sanity' check에 지배된다. 예를 들면, 재전송 패킷이 기존의 인터페이스로 들어오도록 요청하는 것이 불가능하다.

  2. 투명한 프락시 구현이 어렵다.

    • 그 주소와 연관된 소켓이 존재하는 지 알아보기 위해 모든 패킷을 살펴본다.

    • Root는 외부 주소와 연결되는 것을 허가해야 한다.

    • 로컬에서 생성된 패킷을 리다이렉트할 수 없다.

    • REDIRECT는 UDP에 대한 응답을 처리하지 못 한다. 예를 들면, UDP 패킷을 1153으로의 리다이렉트가 동작을 하지 않는 경우도 있으며, 이는 일부 클라이언트가 53번 포트가 아닌 다른 곳으로부터 들어오는 응답을 싫어하기 때문이다.

    • REDIRECT는 tcp/upd 포트 재배치에 대하여 관여하지 않는다. 즉, 사용자가 REDIRECT 룰에 의해 결정된 포트를 얻어와야 한다.

    • 커널 2.1 시리즈 개발기간 중 최소 두 번 정도 중단되었다.

    • 코드가 상당히 지저분하다. 커널 2.2.1에서 #ifdef CONFIG_IP_TRANSPARENT_PROXY의 사용 통계를 보면, 11개의 파일에 34번 나타난다. CONFIG_IP_FIREWALL과 비교해 보면, 5개의 파일에 10번만 나타난다.

  3. 인터페이스 어드레스와 별개로 패킷필터 룰을 만드는 것이 불가능하다.

    • 인터페이스를 거쳐오는 패킷이 로컬에서 생성된 것인지 로컬을 들어오는 것인지 구분하기 위해서 반드시 로컬 인터페이스의 주소를 알아야 한다.

    • 리다이렉션이나 매스커레이딩의 경우는 정보가 충분하지 않다..

    • 포워딩 체인만이 외부로 향하는 인터페이스에 대한 정보를 가지고 있다. 네트웍 구성에 대한 지식을 이용하여 어느 인터페이스로부터 패킷이 들어오는지 알고 있어야만 한다.

  4. 매스커레이딩이 필터링에 포함되어 있다:

    필터링과 매스커레이딩간의 상호작용이 방화벽 구축을 복잡하게 만든다:

    • 입력 필터링인 경우, 응답 패킷이 박스 자체를 향하는 것으로 나타난다.

    • 디매스커레이드(demasqueraded)되는 패킷이 포워드 필터링에서는 전혀 나타나지 않는다.

    • 출력 필터링에서는 패킷이 로컬 박스로부터 들어오는 것처럼 보인다.

  5. 포트 포워딩, 라우팅과 QoS에 영향을 줄 수 있는 TOS 처리, 리다이렉트, ICMP 도달불가(unreachable)과 마크(mark) 등이 패킷 필터링 코드에 포함되어 있다.

  6. ipchains 코드는 모듈화되어 있지도 않고 확장할 수도 없다. (예: MAC 어드레스 필터링, 옵션 필터링 등)

  7. 하부구조가 불충분하기 때문에 다른 기술을 낭비하게 만들었다.

    • per-protocol 모듈을 더한 매스커레이딩

    • 라우팅 코드에 의한 빠른 정적 NAT(per-protocol 처리를 포함하지 않았다).

    • 포트 포워딩, 리다이렉트, 자동 포워딩

    • The Linux NAT and Virtual Server Projects.

  8. CONFIG_NET_FASTROUTE와 패킷 필터링간의 호환성 결여:

    • 포워드 패킷은 세 개의 체인을 거쳐 전달된다.

    • 이러한 체인을 무시하고 지나간 경우 알려줄 방법이 없다.

  9. 라우팅 프로텍스로 인해 버려진 패킷을 관찰할 수 없다. (즉, Source Address Verification)

  10. 패킷 필터링 룰에 대하여 자동으로 카운터를 읽어낼 방법이 없다.

  11. CONFIG_IP_ALWAYS_DEFRAG은 컴파일할 때 주는 옵션이라서 일반적인 목적으로 원하는 커널을 배포판을 만들기가 어렵다.

1.1.2. 누구시죠?

나는 이런 짓을 하리만큼 바보스러운 사람이다. ipchains의 공동저자이고 현재 리눅스 커널 IP 방화벽의 메인터너로서, 현재의 시스템 때문에 사람들이 많은 문제를 격었다는 것 뿐만 아니라 그들이 시도하고 있는 것이 점점 더 노출되고 있다는 것을 알았다.

1.1.3. 그게 왜 폭주하죠?

이~~야!, 지난 주에 이 문서를 봤어야 하는 건데...

사실 나는 우리 모두가 되기 원하는 그런 훌륭한 프로그래머가 아니고, 시간, 장비 그리고 영감도 부족해서 시나리오 전체를 충분히 테스트 해보지 못했다. 그저 내가 해본 것이라고는 여러분들이 참여하기를 바라는 마음에서 만든 testsuite를 돌리는 것이 고작이었다.