본문 바로가기

리눅스 커널/네트워크

promiscuous mode

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

int main(void)
{
        int sock;
        unsigned char buf[65536];
        struct packet_mreq pm;

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

        memset(&pm, 0, sizeof(pm));
        pm.mr_ifindex = 2; //normally, 1: lo, 2: ens33(or eth0)
        pm.mr_type = PACKET_MR_PROMISC;
        if (setsockopt(sock, SOL_PACKET, PACKET_ADD_MEMBERSHIP, &pm, sizeof(pm)) < 0)
        {
                perror("setsockopt error");
                close(sock);
                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;
}

 

기본적으로 packet socket의 옵션은 SOL_PACKET 레벨의 setsockopt() 을 통해 변경 할 수 있다. 

그리고 이 때 옵션으로 PACKET_ADD_MEMBERSHIP, PACKET_DROP_MEMBERSHIP에 사용되는 packet_mreq 구조체는 아래와 같이 정의되어 있다. 

struct packet_mreq {
	int		mr_ifindex; //interface index
	unsigned short	mr_type; //수행할 action을 명시
	unsigned short	mr_alen; //주소 길이
	unsigned char	mr_address[8]; //물리계층 주소
};

type에는 4가지가 있다.

#define PACKET_MR_MULTICAST	0
#define PACKET_MR_PROMISC	1
#define PACKET_MR_ALLMULTI	2
#define PACKET_MR_UNICAST	3

먼저 PACKET_MR_MULTICAST 는 해당 소켓을 mr_address, mr_alen으로 명시된 물리계층의 멀티캐스트 그룹의 바인드시킨다. 그래서 해당 type을 설정할 경우 이 두 변수는 적절히 초기화되어야 한다.

PACKET_MR_ALLMULTI 는 인터페이스 도착하는 모든 멀티캐스트 패킷들을 수신하도록 해준다.

 

마지막으로 PACKET_MR_PROMISC 이다.

해당 type은 해당 socket을 promiscous mode로 전환시켜, 공유 매체내 모든 패킷을 수신하도록 하게 해준다.

즉, 같은 네트워크 상에 떠돌아 다니는 모든 패킷을 볼 수 있게 해준다는 의미이다.

 

우리가 인터넷 통신을 위해 게이트웨이로만 패킷을 보낸다고 하여도

해당 패킷은 같은 네트워크 내 모든 호스트들에게 전송된다.

그러나 시스템은 받은 패킷의 2계층 주소를 보고 필터링 하기 때문에 우리는 이 패킷을 일반적으로 볼 수 없는 것이다.

 

그러나 promiscous mode를 통해 이러한 패킷도 볼 수 있는 것이다.



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

Check Sum Layer 4  (0) 2021.10.24
netlink example  (0) 2021.10.24
DHCP  (0) 2021.10.24
Kernel handler packet capture  (0) 2021.10.24
Kernel hooking packet capture  (0) 2021.10.24