RAW sockets, odbieranie pakietów z flagą htons(ETH_P_ALL)

0

Cześć,

Mam problem z odbieraniem pakietów. Napisałem krótki kod, który otwiera RAW socket w promiscuous mode, tak aby odbierał jakiekolwiek pakiety. Gdy program ten zostanie uruchomiony i ładuje mi się jakakolwiek strona www otrzymuje pakiety tylko z dwóch IP. Co może być przyczyną wyświetlania takiego dziwnego IP? Problem w tym, że nie mogę odróżnić pakietów skąd pochodzą.

#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdarg.h>
#include <errno.h>
#include <unistd.h>
#include <linux/if_packet.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <sys/ioctl.h>
#include <linux/if_ether.h>
#include <netdb.h>

#define DEFAULT_IF "eth0"
#define PACKET_SIZE 1 << 16

int main(int argc, char **argv){
	
	int raw_socket = 0;
	struct ifreq if_index;
	bzero(&if_index,sizeof(struct ifreq));
	
	/* Obtain the device name */
	char IFACE_NAME[10];
	if (argc > 1)
		strcpy(IFACE_NAME, argv[1]);
	else
		strcpy(IFACE_NAME, DEFAULT_IF);
	printf("device/interface name: %s\n",IFACE_NAME);
	
	/* Open a raw socket */
	if ((raw_socket = socket(AF_PACKET,SOCK_RAW,htons(ETH_P_ALL))) < 0){
		perror("socket");
		return errno;
	}
	printf("opening raw socket\n");
	
	/* Set the device to use */
	strncpy(if_index.ifr_name, IFACE_NAME, IFNAMSIZ-1);
	
	/* Get the current flags that the device might have */
	if (ioctl(raw_socket,SIOCGIFINDEX, &if_index) < 0){
		perror("SIOCGIFINDEX");
		return errno;
	}
	
	/* Set the old flags plus the IFF_PROMISC flag */
	if_index.ifr_flags |= IFF_PROMISC;
	if(ioctl(raw_socket, SIOCSIFFLAGS, &if_index) < 0){
		perror("SOICSIFFLAGS");
		return errno;
	}
	printf("entering promiscuous mode\n");
	
	/* Configuring the device */
	if (ioctl(raw_socket,SIOCGIFINDEX, &if_index) < 0){
		perror("SIOCGIFINDEX");
		return errno;
	}
	
	/* Waiting for data */
	while(1){
		
		char packet[PACKET_SIZE];
		ssize_t bytes = 0;
		struct sockaddr_in address;
		socklen_t length;
		
		if ((bytes = recvfrom(raw_socket,&packet,sizeof(packet),0,(struct sockaddr *)&address,&length)) < 1){
			perror("recvfrom");
			return errno;
		}
		printf("DG received (size: %li)\nIP: %s\n",bytes,inet_ntoa(address.sin_addr));
	}
	
	return 0;
} 
0

Nie lepiej Ci skorzystać z tcpdump -w i zapisywać do pipe'a, a potem przetwarzać?

0

Moim zdaniem powinieneś parsować zawartość pakietu, a nie polegać na zwrotce struktury typu sockaddr_in.
Poza tym - o ile wiem, to tylko zadziała przy odbiorze danych, a nie przy wysyłce. Żeby analizować cały ruch użyj libpcap albo tcpdumpa, co zostało zasugerowane wyżej.

#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>

#include <arpa/inet.h>
#include <err.h>
#include <linux/if_packet.h>
#include <linux/if_ether.h>
#include <net/if.h>
#include <netdb.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#define DEFAULT_IF "eth0"
#define PACKET_SIZE 1 << 16


void
print_ip(unsigned char *data, ssize_t len)
{
	struct ethhdr *eth;
	struct ip *iphdr;

	eth = (struct ethhdr *)(data);
	iphdr = (struct ip *)(data + sizeof(*eth));
	printf("Ether: %02x:%02x:%02x:%02x:%02x:%02x -> %02x:%02x:%02x:%02x:%02x:%02x (0x%04x)\n",
	    eth->h_source[0], eth->h_source[1],
	    eth->h_source[2], eth->h_source[3],
	    eth->h_source[4], eth->h_source[5],
	    eth->h_dest[0], eth->h_dest[1],
	    eth->h_dest[2], eth->h_dest[3],
	    eth->h_dest[4], eth->h_dest[5],
	    ntohs(eth->h_proto));

	if (ntohs(eth->h_proto) == 0x0800) {
		printf("IP: %s -> %s\n", inet_ntoa(iphdr->ip_src),
		    inet_ntoa(iphdr->ip_dst));
	}
	/*
	 * XXX: inne protokoły.
	 */
}

int
main(int argc, char **argv)
{
	int raw_socket = 0;
	char IFACE_NAME[10];
	struct ifreq if_index;

	bzero(&if_index, sizeof(struct ifreq));
	/* Obtain the device name */
	if (argc > 1)
		strncpy(IFACE_NAME, argv[1], sizeof(IFACE_NAME));
	else
		strncpy(IFACE_NAME, DEFAULT_IF, sizeof(IFACE_NAME));
	printf("device/interface name: %s\n", IFACE_NAME);

	/* Open a raw socket */
	raw_socket = socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
	if (raw_socket < 0)
		err(1, "socket(2) failed");

	printf("opening raw socket\n");

	/* Set the device to use */
	strncpy(if_index.ifr_name, IFACE_NAME, IFNAMSIZ - 1);

	/* Get the current flags that the device might have */
	if (ioctl(raw_socket,SIOCGIFINDEX, &if_index) < 0)
		err(1, "ioctl(SIOCGIFINDEX) failed");


	/* Set the old flags plus the IFF_PROMISC flag */
	if_index.ifr_flags |= IFF_PROMISC;
	if (ioctl(raw_socket, SIOCSIFFLAGS, &if_index) < 0)
		err(1, "ioctl(SOICSIFFLAGS) failed");

	printf("entering promiscuous mode\n");

	/* Configuring the device */
	if (ioctl(raw_socket,SIOCGIFINDEX, &if_index) < 0)
		err(1, "ioctl(SIOCGIFINDEX) failed");

	/* Waiting for data */
	while (1) {
		unsigned char packet[PACKET_SIZE];
		ssize_t bytes = 0;
		struct sockaddr_in address;
		socklen_t length;

		bytes = recvfrom(raw_socket, &packet, sizeof(packet), 0,
		    (struct sockaddr *)&address, &length);

		if (bytes < 0)
			err(1, "recvfrom failed");

		printf("DG received (size: %li)\n", bytes);
		print_ip(packet, bytes);
	}

	return (0);
} 

1 użytkowników online, w tym zalogowanych: 0, gości: 1