|
|
Question : firewall using libpcap and raw socket
|
|
hi xperts,
I am trying to write a simple firewall that will perform packet filtering on the basis of source/dest ips and ports.
Following is general logic:
1. Fork off a process for each n/w interface. 2. listen and capture packets(using libpcap) 3. get source/dest ips and ports using respective headers. 4. filter packets by comparing above parameters with those stored in a file. 5. send only required packets.
filtering rules are kept in a file named "rules". contains entries like Sourceaddr destaddr sourceport destport
Problem im having is only with the resending part. The program enters some loop and keeps on sending the same packet continuously. For eg if the filter receives 3 packets destined to say a.b.c.d then it will send many many packets to a.b.c.d
Pls Help Thanx in advance swapsthegreat
src code -------------------------------------------------------------------------------- #include #include #include #include #include #includeh> #include #includeh> #include #include #include #include #include #include #include
void capture_packet(char *); void tcp_read(int,char *,pcap_t *); char* next_packet(int *,pcap_t *); void tcp_check(char *,int); int scan_packet(char *,char *,u_int16_t,u_int16_t); void send_packet(char *,int,char[16],u_int16_t);
struct filtering_rules { char s_addr[16]; char d_addr[16]; u_int16_t s_port; u_int16_t d_port; int decision; };
typedef struct filtering_rules file_record;
FILE *fp;
int main(void) { char device[2][5]={"eth0","eth1"}; int i; fp = fopen("rules","r"); for(i=0;i<2;i++) { if (fork() == 0) capture_packet(device[i]); // Fork processes for each device } fclose(fp); return(0); }
void capture_packet(char *device) { char errbuf[PCAP_ERRBUF_SIZE]; pcap_t *pd; /* packet capture struct pointer */ int snaplen = 1500; /* amount of data to capture */ int promisc = 0; /* disable promiscous mode */ int to_ms=1500; /* timeout in ms */ int datalink; /* Type of datalink SLIP/PPP/Ethernet */ char *ptr; /*Pointer to header */
printf("Device = %s\n",device);
if((pd = pcap_open_live(device, snaplen, promisc, to_ms, errbuf)) == NULL) { /* Open device */ printf("Error opening device: %s", errbuf); }
if((datalink = pcap_datalink(pd)) < 0 ) /* returns type of datalink */ { printf("Datalink error : %s", pcap_geterr(pd)); } printf("Datalink = %d\n", datalink);
tcp_read(datalink,ptr,pd);
}
void tcp_read(int datalink,char *ptr,pcap_t *pd) { struct ether_header *eptr; int len; while(1) {
ptr = next_packet(&len,pd); /* get next packet */ switch(datalink) /* check for link type */ { case DLT_NULL: tcp_check(ptr + 4 , len - 4); /* Loopback header = 4 bytes */ break;
case DLT_EN10MB: eptr = (struct ether_header *) ptr; /* Ethernet header = 14 bytes */ /* if(ntohs(eptr->ether_type) != ETHERTYPE_IP) { printf("Ethernet type not IP"); printf("Type = %x",ntohs(eptr->ether_type)); }*/ tcp_check(ptr + 14 , len - 14); break;
case DLT_SLIP: tcp_check(ptr + 24 , len - 24); break; /* SLIP or PPP header = 24 bytes */ case DLT_PPP: tcp_check(ptr + 24 , len - 24); break;
default : printf("Unsupported datalink"); break; }
}
}
char *next_packet(int *len,pcap_t *pd) { char *ptr; struct pcap_pkthdr hdr;
while((ptr = (char *) pcap_next(pd, &hdr)) == NULL); /* keep looping until packet ready */ *len = hdr.caplen; /* captured length */ return(ptr); }
void tcp_check(char *ptr, int len) { int hlen; struct ip *iphdr; struct tcphdr *tcph; char *src, *dest; char *start; char *tempPtr; u_int16_t sport,dport; int size; iphdr = (struct ip*) ptr; /* Get IP header */
size = ntohs(iphdr->ip_len); start = (char *)malloc(size); memcpy(start,ptr,size);
hlen = IP_HL(iphdr) * 4; if(iphdr->ip_p == IPPROTO_TCP) { tempPtr = inet_ntoa(iphdr->ip_src); src = (char *)malloc(strlen(tempPtr) + 1); strncpy(src, tempPtr, strlen(tempPtr) + 1);
tempPtr = inet_ntoa(iphdr->ip_dst); dest = (char *)malloc(strlen(tempPtr) + 1); strncpy(dest, tempPtr, strlen(tempPtr) + 1);
ptr += hlen;
tcph = (struct tcphdr *)ptr; /* Get source and dest port */ sport = ntohs(tcph->th_sport); dport = ntohs(tcph->th_dport); ptr += sizeof(struct tcphdr);
printf("SIZE :%d\n",size); printf(" sport = %d\n dport = %d\n ",sport,dport); puts(src); puts(dest); if(scan_packet(src,dest,sport,dport) == 1) { send_packet(start,size,dest,dport); } free(src); free(dest); }
}
void send_packet(char *start,int size,char *d_addr,u_int16_t d_port) { struct sockaddr_in address; int sockfd; int on = 1; if((sockfd = socket(PF_INET,SOCK_RAW,IPPROTO_RAW)) < 0) { perror("Socket creation"); }
if((setsockopt(sockfd,IPPROTO_IP,IP_HDRINCL,&on,sizeof(int))) < 0) { perror("setsockopt"); }
memset(&address,'\0',sizeof(address));
address.sin_family = PF_INET; address.sin_port = htons(d_port); address.sin_addr.s_addr = inet_addr(d_addr);
if(sendto(sockfd,start,size,0,(struct sockaddr *)&address,sizeof(struct sockaddr))<0) { perror("send"); } else printf("packet sent\n"); free(start); close(sockfd);
}
int scan_packet(char *src,char *dest,u_int16_t sport,u_int16_t dport) { file_record frecord; rewind(fp);
while(!feof(fp)) { fscanf(fp,"%s %s %d %d %d",frecord.s_addr,frecord.d_addr,&frecord.s_port,&frecord.d_port,&frecord.decision);
if(strcmp(frecord.s_addr,src) == 0) { if(strcmp(frecord.d_addr,dest) == 0) { if(frecord.s_port == sport) { if(frecord.d_port == dport) { printf("DEc: %d",frecord.decision); return(frecord.decision); } } } }
} return(0);
}
-----------------------------------------------------------------------------------
|
Answer : firewall using libpcap and raw socket
|
|
Your interface could be in promiscuous mode or C could be sending the packets back. You need to look at the source and destination MAC address in the packets that B receives to understand what's going on.
In any case, I note that your program does not check before forwarding a packet if the packet was in fact sent to B. Because of the possibility of promiscuous mode (which means your program receives copies of packets intended for every host on the network) you need to check the MAC address and ignore any packet that wasn't sent to B.
|
|
|
|
|