본문 바로가기

리눅스 커널/네트워크

Raw socket outgoing packet capture

앞서 작성한 글에서는 raw socket을 이용해서 incoming packet을 스니핑하는 방법에 대해 다루어보았다.

그러나 테스트 시 한가지 문제가 있음을 볼 수 있다.

outgoing packet에 대해서는 제대로 스니핑 되지 않는 것이다.

 

그래서 이번에는 raw socket 사용 시 outgoing packet을 스니핑 하는 방법에 대해서 살펴보겠다.

 

#include <stdio.h>
#include <sys/socket.h>
#include <linux/if_packet.h>
#include <net/ethernet.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include "pktfilter.c"

int main(void)
{
	int sock;
	unsigned char buf[65536];	
	struct sockaddr_ll sll;

	sock = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (sock < 0)
	{
		perror("socket error");
		return -1;
	}

	memset(&sll, 0, sizeof(sll));
	sll.sll_family = PF_PACKET;
	sll.sll_ifindex = 2; //interface index
	sll.sll_protocol = htons(ETH_P_ALL);

	if (bind(sock, (struct sockaddr *)&sll, sizeof(sll)) < 0)
	{
		perror("bind error");
		return -1;
	}

	while (1)
	{
		int type;
		int rcv_bytes = recvfrom(sock, buf, sizeof(buf), 0, NULL, NULL);
	
		if (rcv_bytes < 0)
			break;
		
		eth_handle((struct ethhdr *)buf);
	}

	close(sock);
	return 0;
}

man packet을 통해 더 많은 정보를 알 수 있다. 여기서는 sockaddr_ll 구조체에 대해 정리해보겠다.

struct sockaddr_ll {
	unsigned short	sll_family; //항상 PF_PACKET.
	__be16		sll_protocol; //물리계층 프로토콜.
	int		sll_ifindex; //인터페이스 인덱스.
	unsigned short	sll_hatype; //ARP 하드웨어 타입
	unsigned char	sll_pkttype; //패킷의  타입
	unsigned char	sll_halen; //주소의 길이
	unsigned char	sll_addr[8]; //물리 계층 주소
};

sll_protocol 은 big endian으로 network byte order로 초기화 되어야 하며, ETH_P_ 로 시작하는 매크로 값을 전달해야 한다. 위 코드에서는 ETH_P_ALL을 이용하였는데, 다른 프로토콜에서는 ougoing packet들이 캡쳐되지 않았다.

 

sll_ifindex 은 if_nametoindex("~~~"); 로 넘겨도 된다. 

 

sll_hatype 은 linux/if_arp.h 을 참조하면 되며, ARPHRD_ 로 시작하는 매크로 값을 말하는 것 같다.

 

sll_pkttype 은 다음과 같은 매크로값으로 초기화 하면 되는데 정확히 무엇을 의미하는지는 모르겠다.

#define PACKET_HOST		0		/* To us		*/
#define PACKET_BROADCAST	1		/* To all		*/
#define PACKET_MULTICAST	2		/* To group		*/
#define PACKET_OTHERHOST	3		/* To someone else 	*/
#define PACKET_OUTGOING		4		/* Outgoing of any type */
#define PACKET_LOOPBACK		5		/* MC/BRD frame looped back */
#define PACKET_USER		6		/* To user space	*/
#define PACKET_KERNEL		7		/* To kernel space	*/



'리눅스 커널 > 네트워크' 카테고리의 다른 글

Kernel handler packet capture  (0) 2021.10.24
Kernel hooking packet capture  (0) 2021.10.24
Raw socket incoming packet capture  (0) 2021.10.24
Ethernet & ARP Header  (0) 2021.10.24
IP & ICMP Header  (0) 2021.10.24