[완료] raw socket에서 packet capture에 대한 몇가지 질문 올리옵니다...
내용 : TCP, UDP, ICMP에 대한 패킷을 전송받아 각각 Ethernet, IP, TCP, UDP, ICMP 헤더와 데이터를
출력하는 프로그램을 작성해 보았는데 몇가지 궁금증이 생겼습니다.
1. 어떤 형태로 패킷이 들어와도 모니터링하려니
sock[0] = socket(PF_INET, SOCK_RAW, IPPROTO_TCP);
sock[1] = socket(PF_INET, SOCK_RAW, IPPROTO_UDP);
sock[2] = socket(PF_INET, SOCK_RAW, IPPROTO_ICMP);
제가 방법을 아직 잘 몰라서..소켓 3개를 생성하여 각각 프로토콜에 대한 캡쳐를 진행하였습니다.
그래서..궁금한 것은..하나의 소켓으로 모든 프로토콜에 대한 캡쳐를 할 수 있는 방법이 있는지 궁금합니다.
2. 예를들어 TCP 패킷 캡쳐하여 그 데이터를 모니터링하려고 합니다.
이때 recvfrom 함수를 사용하여 패킷 데이터를 수신받게 되는데,
...
pack_buf_len = 65535;
...
recvlen = recvfrom(sock[0], pack_buf, pack_buf_len, 0, (struct sockaddr*)&addr, &addr_len);
모든 패킷 수신한다고 하였을 때, 한번에 받을 수 있는 패킷의 크기를 64kbyte로 하는 것이 맞는것인가요?
아니면 미리 수신 되는 크기(Header+Data)를 알 수 있는건가요?
3. 번외 질문이긴 한데요.. 커널에서 사용되는 송수신 패킷 버퍼의 크기가 얼마나 되나요..?
기반지식이 미흡하여 검색하는데도 키워드 선출에 문제가 많아서 창피한 질문이지만 여쭈어봅니다..
pcap library를 쓰시기를 권해드립니다.
pcap library 쓰시기를 권해드립니다.
Just do it!
pcap library를 사용하지않고.. 간략하게 구현해보고있습니다..
동작도 잘되고 하는데 위의 사항들이 의문이 들어서 질문하였습니다.
(지금도 계속 찾고있습니다..ㅠㅠ)
1. IPPROTO_RAW로 하면 되지
1. IPPROTO_RAW로 하면 되지 않을까요?
2. getsockopt 으로 얻어오는 프로토콜 버퍼와 소켓에서 사용하는 버퍼가 동일 한 것인지
모르겠지만...
3.
실제로 패킷이 네트워크 장치를 통해서 나갈때는 전송 계층, 네트워크 계층을 커널에서 모두 거친 다음에 데이타 링크 계층의
패킷이 나갈 것 입니다. 만약, 데이타 링크 계층이 이더넷이라면 1536 Bytes 단위가 되겠네요. 상위 프로토콜의 패킷 크기가
이것보다 크다면 여러번 전송하겠지요.
수신시에도 마찬가지로 데이타 링크 계층의 MTU(Maximum Transmission Unit) 단위로 수신하여, 같은 상위 프로토콜의 패킷
이면 합치거나 할 것입니다. 이때, 다수의 데이타 링크 계층의 패킷이 동일한 네트워크 계층의 패킷이면 연속된 공간에 위치
하도록 조작을 해야 합니다.
참고로, 리눅스 커널은 네트워크 패킷을 struct sk_buff 자료구조로 관리 합니다. ('소켓 버퍼'라고 부릅니다.)
ps. 좀 더 명확한 답변을 드리고 싶은데, 요즘은 네트워크와 관련된 것을 하고 있지 않아서 잘 모르겠네요. 네트워크 관련
책도 다 어디로 갔는지 안보이고...
Just do it!
감사합니다
제공해주신 정보를 가지고 다시금 테스트 해보도록 하겠습니다. 감사합니다.
태훈님은 요즘 넷트웍과 좀 멀리 계시다 하시고 저는
태훈님은 요즘 넷트웍과 좀 멀리 계시다 하시고 저는 게임 중독자이기 때문에 그냥 막 던집니다.
막던지는 속에서 읽는 사람은 전혀 다른 키워드를 조합할 수도 있거든요...사람의 뇌는 다 다른것이라.
1
소켓함수에서 세번째 인자를 정수 0 로 정의된 매크로를 사용하면 ipv4 상위 프로토콜 전체 의미가 아니던가요?
2.3
음...제가 다른 답변에서 DMA 에 도착한 데이타가 포인터된다 했는데 이는 오류입니다.익명이라 수정불가...
DMA 버퍼의 정적 주소데이타는 커널 영역으로 복사되어 동적주소로 바뀌고 그 공간자체는 skb 이며 구조체 sk_buff 가 그곳을 포인터하고 있습니다.
이 과정이 참이면 DMA 프리가 일어나고 커널백로그가 -1 되겠지요....
커널소스나 문서 여러곳에서 언급되는 변수나 함수 이름에서
수신 = 디바이스드라이버가 할당한 DMA 버퍼 에서 커널 skb 블락으로 복사할 때 사용하는 표현으로 WMEM 또는 RCV 접두사가 붙는 경향이 있다.
송신 = 사용자 영역에서 커널영역으로 받을 때 커널안에 할당할 skb 블락으로 복사할 때 사용하는 표현으로 RMEM 또는 SND 접두사가 붙는 경향이 있음...
즉 언뜻 생각하는 방식에 따라 송수신이 뒤바뀔 수도 있는데 커널은
사용자 > 커널내 skb > 장치드라이버
방향을 송신이라 하고 반대로 하위계층에서 상위계층으로를 수신이라 표현.
즉 사용자가 sockopt(이것 역시 소켓옵션 관련 비슷한유형의 접두접미사로 이해하셔요 제가 지금 모바일이라 단어나 함ㅅ 변수를 정확히 하긴 힘듭니다.)로 설정하여 커널로부터 승인받는 버퍼는 송신버퍼이다.
proc 안 적절한 위치에 찾으면 wmem 이나 snd 접두사가 쓰인 설정치가 있을텐데 이게 그 값입니다.아마도 실제 데이타 + 구조체 그니깐 skb + sk_buff 크기일텐데 확인필요요.
세개가 있는데 최소,기본,최대 값이고 이 값을 맘대로 늘리는 것은 신중해야 하지요...
수신시 :
DMA 안의 데이타 각 크기는 PCI 유형 및 관련 드라이버 동작에 따라 한 조각 크기가 정해져 있음 랜카드는 1500 좀 넘게 이하거나 점보프레임의경우 약 9KB 이하가 한조각.
따라서 매 조각마다 skb 로 복사하고 구조체 생성하는데 이미 알려진 수치이므로 이는 커널수치가 최적화가 아닐까...합니다.
이 때
커널 내부로직인 ICMP 나 사용자 설치커널 모듈인 ethertype 호출이 아닌 경우 관련 상위 구조체인 sock 가 있어야 하고 이는 사용자가 생성한 소켓 포트로 연결됨.
만약 DOS 공격같은 경우 DMA 가 계속 차고 커널은 매 조각마다 skb 관련 자료를 셋팅하는데 공격 패킷헤더의 포트를 리슨하는 sock 이 없는 시스템의 경우 커널내에서 즉시즉시 드랍이 이루어지는데 역으로
sock 이 있다면 이는 그 socket 을 셋팅할 때 설정한 버퍼 크기 및 시스템 전체 skb 및 백로그 수치에 따라 사용자 영역으로 덤프될 때까지 시스템 에서 드랍하지 않고 리소스 소모...맥스까지 간 후 원격제어 불가...도스공격성공..
이케 되므로 전송백로그및 소켓버퍼수치를 크게하면 문제가 됩니다.
인터넷에 많이 있는 커널인자 늘리기와 버퍼늘리기는 관리자 스스로 먹통을 만드는 길일 수도 있습니다...
쓸데없는 얘기고...
소켓 버퍼는 proc 안의 값으로 바꿀수 있는데 시스템에 소켓은 많을 수 있다는걸 고려하면 하나의 소켓이 커널 전체 맥스값을 점령할 수도 있는 사태는 피해야 합니다.악의적이거나 실수나 오류로 이런 경우 생기면 루트라도 원격텔넷 접속이 안되겄죠.
DMA 안의 각 조각은 도착순서대로 목적지가 다를 수 있고 쓰레기값도 있을거고 공격도 있을겁니다.
매 조각마다 skb 관련 셋팅을 하고 sock 을 찾는데 이는 응용이 커널에 요청한 소켓바인드 및 리슨관련함수에 의해 추적될 수 있고 버퍼가 큰데 뭔가 오류가 있거나 바쁘다면 skb 는 해제되지 않고 계속 쌓입니다.
예를들어
400개의 1500B패킷이 들어왔는데
텔넷을 향한것 50개 웹을 향한것 50개는 처리되고 300개가 개인응용을 향한 것인데 문제가 있을 때 버퍼가 매우 크고 전송 백로그 128맥스를 멋대로 풀면 1.5 B 300개가 버퍼에 정체되고 이는 커널백로그 맥스로 랜카드는 블락됩니다.
즉 전혀 바쁘지 않아도 사소한 오류가 키보드제어 말고는 제어불가에 다다를 수 있게 되는거죠.
송신시 :
응용에서 커널로 덤프받을 버퍼를 커널내부에 설정하는데 이는 더욱 신중해야겠죠.
장치에서 올라오는 조각과 달리 응용에서 내려오는 것은 크기를 알 수 없고 유형도 알 수 없기 때문에.
socket 생성시 설정된 버퍼로 응용을 받고 이것의 전송헤더 처리후 sk_buff 와 연결 넷트웍 헤더 생성추가 후 장치로 덤프...대충 이렇게 되는데 시스템의 여러 응용이 다투어 맥스를 달라고 하는것을 허용해버리면 커널은 버퍼 풀 구조체생성 풀에 도달할 경우도 생기죠.
커널 내부에 많은 신중한 고려와 실험이 종합된 루틴이 있는데 이걸 풀면 요즘 10기가 이더넷같은 경우 악의적이거나 오류시 넷트웍 블락됩니다.
이는 리눅스 잘못이 아니라 관리자 잘못이죠.
확인했는데도 또 문제가 있네요 WMEM, SND
확인했는데도 또 문제가 있네요
WMEM, SND = 송신시 사용하는 접두사
RMEM, RCV = 수신시
위에는 이게 잘못되어 있음
감사합니다
아직 이해하기엔 제가 많이 부족하지만 몇몇 도움이 되었습니다^^ 정말 감사합니다
댓글 달기