[packet] 커널에서 패킷을 직접 가져오려면?

syia의 이미지

커널에서 패킷을 집적 캡쳐 하려고합니다.

이를 유저 영역의 어플리케이션에 전달하고

유저 영역의 어플리케이션이 패킷을 분석하여

커널에 룰셋을 변경해주도록 디자인을 하려 하는데요.

커널에서 패킷을 직접 캡쳐하는 방법에 어떤게 있을까요?

제가 생각해본건

1. 커널에서 특정 파일에 계속해서 패킷을 쓰는 방법과..
2. 커널에서 유저메모리영역에 카피해주면 그걸 유저 어플리케이션이 저장하는 방법과
3. Zero-copy를 이용해 소켓버퍼에서 바로 DMA로 보내버리는 방법입니다.

어떤 방법이 유효할지 궁금하고, 만약 패킷을 카피 한다면 커널 어느부분에서 하는것이 적당한지 궁금합니다.

sangwoo의 이미지

libpcap을 쓰면 되지 않을까요? 어차피 유저랜드로 카피할 거라면..

----
Let's shut up and code.

익명 사용자의 이미지

3가지 다 가능하겠습니다.

기존 구현된 것으로는 3가지 다 있는데, 이중 3번은 특정 NIC에서만 지원됩니다. 그리고, NIC의 controller가 DMA를 이용해, 메인 CPU 및 OS의 간섭없이 사용자 영역메모리로 직접 전달하는 것을 zero-copy로 알고 있습니다만.

패킷을 복사한다면, 리눅스의 경우 ebtables나 iptables의 hooking 포인트 중 하나 골라서 하시면 되겠군요.

쉽게 하려면, raw_socket를 사용하거나, ip_queue+netfilter framework 인터페이스를 쓰시면 되겠습니다.
또는, ULOG, LOG등 iptables 인터페이스를 사용하셔도 되겠습니다.
BSD의 경우에도 pflog던가? 사용자 영역으로 로깅해주는 인터페이스가 있는 것으로 알고 있습니다. pf 프레임워크를 찾아보시길...

더 쉽게 하려면, pcap라이브러리 등을 사용하시면 되겠군요.

주목적이 패시브 패킷수집이라면, 이중 아무것이나 골라서 써도 되겠습니다.

익명 사용자의 이미지

iptables 나 netfilter의 경우 이미 로깅하는 인터페이스가 구현되어 있는건가요?

음..

raw_socket을 직접 복사하려면 별도의 시스템콜이 필요한지 궁금합니다.

pcap라이브러리를 이용하면 쉽게 되겠지만 커널에 약간 무리를 주더라도 커널에서 많은 부분을 처리하고싶어서요 ^^;

공부도 할겸해서 어려운 주제를 골랐더니 엄청 헤매이게 되는군요;

익명 사용자의 이미지

샤 wrote:
iptables 나 netfilter의 경우 이미 로깅하는 인터페이스가 구현되어 있는건가요?

예.
* 그리고, BSD도 로깅인터페이스를 사용하는 것으로 알고 있습니다.

샤 wrote:

raw_socket을 직접 복사하려면 별도의 시스템콜이 필요한지 궁금합니다.

보통 소켓 프로그래밍과 아주 유사합니다. 소켓생성시 RAW_SOCKET파라메터를 세팅하면되겠습니다.

샤 wrote:

pcap라이브러리를 이용하면 쉽게 되겠지만 커널에 약간 무리를 주더라도 커널에서 많은 부분을 처리하고싶어서요 ^^;

only~ 커널에서만 프로그램을 돌릴 수도 있겠지요. 이를테면, snort같은것을 커널로 포팅한다던지..
(그러나, 별로 권하고 싶지는 않군요. 유지보수도 문제지만, scalability가 안좋을듯 보입니다)

샤 wrote:

공부도 할겸해서 어려운 주제를 골랐더니 엄청 헤매이게 되는군요;

중점이 무엇인지를 잘 설정하세요.
패킷을 많이(100%에 근접하게...) 잡는게 문제인가?
아니면 잡은 패킷의 후처리(보통 F/W, IDS, IPS등이 하듯이)가 문제인가?
둘다를 빠르게 하는것이야 공통사항일테고, 일단은 둘중 하나로 가셔야 할듯하고(가정하고 하라는 얘기지요..이를테면, 패킷은 잘~ 잡는다....그런데...모 이런식이겠지요.),
후처리의 경우는 룰(rule)이라는 부분에 대한 고려가 필수적입니다.
횡설수설...죄송....즉, 문제를 잘게 나누고 어디를 먼저 할 것인지를 잘~ 선택하시고 접근하시기를 권고합니다.
익명 사용자의 이미지

* 참고로 Netfilter Framework에 iptables라는 프로토타입 인터페이스가 있다라고 생각하시는게 옳습니다.

익명 사용자의 이미지

상세한 답변 감사합니다.

꽉막혔던 머리가 좀 뚫리는듯 하네요 +_+

일단은 패킷을 잘 잡는게 목적입니다.

그런데 iptable의 인터페이스를 사용한다는건

netfilter 를 커널에 포함해야 하는거겠죠?

즉.. 패킷이 도착해서 인터럽트가 발생하고

어떤함수가 작동해서 소켓버퍼에서 커널로 복사해오고

커널에서 포인터를 넷필터로 보낼듯 한데

그 넷필터에 보내진것을 캡쳐하게 되는걸까요?

그렇다면 넷필터의 소스 일부를 수정하여

파일로 쓰든 유저메모리로 복사하든 해야겠군요..

pcap 소스도 봤는데 그건 정말 난해하던데;

익명 사용자의 이미지

샤 wrote:

일단은 패킷을 잘 잡는게 목적입니다.

그런데 iptable의 인터페이스를 사용한다는건

netfilter 를 커널에 포함해야 하는거겠죠?


음 넷필터는 프레임웍이름이고, iptables는 그 프레임웍의 대표격입니다. 이를테면, TCP/IP Protocol Suite에는 TCP, UDP, IP, ICMP,... 등등이 있는데, 대표이름인 TCP와 IP를 혼용한 그냥 TCP/IP 프로토콜 이라고도 부르듯이 말입니다.
이 프레임웍은 이미 커널에 포함되어 있습니다. 좀 됐습니다.
그러면서, 패킷이 경유하는 주요 포인트들(NIC->커널의 IP 및 TCP 등의 주요 지점)에서 패킷을 잡을 수 있는 인터페이스를 만들어 주었습니다. 이 인터페이스를 후킹 포인트라고 합니다.
각 후킹 포인트에서 3개의 테이블에 사용자는 사용자정의 쿼리(비교연산)를 달아 놓을수 있습니다. 이 쿼리의 결과가 참이면 패킷에 대해 특정 연산을 할 수 있도록 만들어져 있는것입니다.
당연하게도 이 연산을 좀 ~ 잘~ 달아놓으면 F/W은 금방이겠지요.
이러한 프로그램을 짤 수 있는 인터페이스를 제공하니 이를 프레임웍이라고 합니다. 일반 프로그램과는 틀리게 넷필터의 룰을 따라서 짜야한다는.... 소위 로마법을 따라야한다는....

샤 wrote:

즉.. 패킷이 도착해서 인터럽트가 발생하고

어떤함수가 작동해서 소켓버퍼에서 커널로 복사해오고

커널에서 포인터를 넷필터로 보낼듯 한데

그 넷필터에 보내진것을 캡쳐하게 되는걸까요?


네트워크 인터페이스에서는 인터럽트라는 말조차 안쓰시는게 좋습니다. 구한말에는 CPU를 주로 연산에 쓰기위해 폴링보다 인터럽트를 사용했지만, 한 10여년전부터는 다시 폴링을 주로 IO에 사용합니다. 그래서 디바이스 드라이버 특히, NIC관련은 디바이스 폴링으로 드라이버를 제작하는게 현재는 de facto standard입니다.

물론, 사용자가 어디서 패킷을 잡을지를 고민끝에...지정하고 새로운 함수를 만들 수 있겠으나, 그 위치마다 이미 넷필터 프레임웍이 달려있습니다.( 그사람들 고민.... 오래전부터 했겠지요...)
그래서, 저는 넷필터 프레임웍을 사용하시기를 권고합니다. 음 ...
라이센스가 문제인데, GPL(GPL2이던가?)입니다.

샤 wrote:

그렇다면 넷필터의 소스 일부를 수정하여

파일로 쓰든 유저메모리로 복사하든 해야겠군요..


먼저, iptables라는 유틸리티가 있는데 이를 조금 연습해보세요.
그리고, 이 유틸리티를 만들때 쓴 프레임웍 라이브러리인 libiptc에 대해 조사하고 예제좀 보고...
libipq에 대해 조사하고 예제보면 원하시는바가 되지 않을까 합니다.

샤 wrote:

pcap 소스도 봤는데 그건 정말 난해하던데;

pcap소스를 보면 난해할테고, 이를 이용한 프로그램을 짜보면 비교적 쉽습니다. pcap의 경우, 커널에 PF_RING이라는 것을 찾아서 다운받고, 패치를 하시고, pcap라이브러리에도 약간 패치 를 하면, 고성능의 패킷수집기를 만들 수 있습니다. 요지는 dual buffer를 ring buffer(circular queue)로 바꿔서 버퍼좀 늘려주었더니, 좋더라~ 입니다.
익명 사용자의 이미지

으음.. 길이 보이네요 -_ㅜ

자세한 답변 너무 감사합니다!!

이제 한달동안 죽어라 파 봐야겠습니다 +_+!

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.