static PF_FORWARD_ACTION filter_cb(unsigned char *header, unsigned char *packet, unsigned int len, unsigned int recvindex, unsigned int sendindex, IPAddr nextrecvhop, IPAddr nextsendhop) { PBNOTIFICATION pbn= {0}; const IP_HEADER *iph=(IP_HEADER*)header; const PBIPRANGE *range=NULL; const ULONG src=NTOHL(iph->ipSource); const ULONG dest=NTOHL(iph->ipDestination); USHORT srcport=0; USHORT destport=0; int opening=1; int http = 0; // TCP = 6 (http://www.iana.org/assignments/protocol-numbers/) if(iph->ipProtocol == IPPROTO_TCP) { const TCP_HEADER *tcp=(TCP_HEADER*)packet; srcport=NTOHS(tcp->sourcePort); destport=NTOHS(tcp->destinationPort); opening = (tcp->ack==0); // XP needs this as the port which comes back is the same // as the port going out and therefore it will be blocked if (DestinationPortAllowed(destport) || DestinationPortAllowed(srcport) || SourcePortAllowed(destport) || SourcePortAllowed(srcport) ) { http = 1; } } if(!http) { KIRQL irq; KeAcquireSpinLock(&g_internal->rangeslock, &irq); //TODO: test allowed ranges. if(g_internal->allowedcount) { range = inranges(g_internal->allowedranges, g_internal->allowedcount, src); if(!range) range = inranges(g_internal->allowedranges, g_internal->allowedcount, dest); if(range) { pbn.label = range->label; pbn.labelsid = g_internal->allowedlabelsid; pbn.action = 1; } } if(!range && g_internal->blockedcount) { range=inranges(g_internal->blockedranges, g_internal->blockedcount, src); if(!range) range=inranges(g_internal->blockedranges, g_internal->blockedcount, dest); if(range) { pbn.label = range->label; pbn.labelsid = g_internal->blockedlabelsid; pbn.action = 0; } } KeReleaseSpinLock(&g_internal->rangeslock, irq); } if(!range) { pbn.action = 2; } if(range || opening) { pbn.protocol=iph->ipProtocol; pbn.source.addr4.sin_family = AF_INET; pbn.source.addr4.sin_addr.s_addr = iph->ipSource; pbn.source.addr4.sin_port = HTONS(srcport); pbn.dest.addr4.sin_family = AF_INET; pbn.dest.addr4.sin_addr.s_addr = iph->ipDestination; pbn.dest.addr4.sin_port = HTONS(destport); Notification_Send(&g_internal->queue, &pbn); return pbn.action ? PF_FORWARD : PF_DROP; } return PF_FORWARD; }
static PF_FORWARD_ACTION filter_cb(unsigned char *header, unsigned char *packet, unsigned int len, unsigned int recvindex, unsigned int sendindex, IPAddr nextrecvhop, IPAddr nextsendhop) { PGNOTIFICATION pgn={0}; const IP_HEADER *iph=(IP_HEADER*)header; const PGIPRANGE *range=NULL; const ULONG src=NTOHL(iph->ipSource); const ULONG dest=NTOHL(iph->ipDestination); USHORT srcport=0; USHORT destport=0; int opening=1; int http = 0; int forced_log = 0; //if the protocol is TCP or UDP if(iph->ipProtocol==6 || iph->ipProtocol==17) { const TCP_HEADER *tcp=(TCP_HEADER*)packet; srcport=NTOHS(tcp->sourcePort); destport=NTOHS(tcp->destinationPort); if(iph->ipProtocol==6) { opening=(tcp->ack==0); if(!g_internal->blockhttp && (srcport==80 || srcport==443 || destport==80 || destport==443)) { http = 1; } } } if(!http) { KIRQL irq; KeAcquireSpinLock(&g_internal->rangeslock, &irq); //TODO: test allowed ranges. // -> beez : this is not working if(g_internal->allowedcount) { range = inranges(g_internal->allowedranges, g_internal->allowedcount, src); if(!range) range = inranges(g_internal->allowedranges, g_internal->allowedcount, dest); if(range) { pgn.label = range->label; pgn.labelsid = g_internal->allowedlabelsid; pgn.action = 1; } } if(!range && g_internal->blockedcount) { range=inranges(g_internal->blockedranges, g_internal->blockedcount, src); if(!range) range=inranges(g_internal->blockedranges, g_internal->blockedcount, dest); if(range) { pgn.label = range->label; pgn.labelsid = g_internal->blockedlabelsid; pgn.action = 0; } } KeReleaseSpinLock(&g_internal->rangeslock, irq); } //seems like connection is oppening up. This means no special action if(!range) { pgn.action = 2; } //we filter only incomming and not already processed trafic for ports and connections if( sendindex == INVALID_PF_IF_INDEX && range == NULL && http == 0 ) { unsigned int i; for(i=0;i<g_internal->perma_allow_list_length;i++) if( src == g_internal->perma_allow_list[ i ] ) break; if( i == g_internal->perma_allow_list_length ) { //he is sending us a TCP or UDP packet and we test if our port is open. //If not he does not know about our open ports then we can ban him since he is scanning us if( destport != 0 && g_internal->f_port_open_ports[ destport ] == 0 && g_internal->disable_port_scan_detector == 0) { #ifdef USE_FIXED_LIST CheckInsertedAndAddIPForBan( src ); #else Addbanned( src ); #endif forced_log = 1; pgn.action = 20; } //a new tcp connection. See if he is spamming connections else if( opening && g_internal->disable_connection_flood_detector == 0 ) { //check if we are already banning this IP #ifdef USE_FIXED_LIST int i; for(i=0;i<TEMP_BLOCK_LIST;i++) if( g_internal->temp_connection_flood_banns[ i ] == src ) { forced_log = 1; pgn.action = 30; break; } #else if( checkbanned( src ) != 0 ) { forced_log = 1; pgn.action = 30; } #endif //not yet in banlist then check if we should add it if( forced_log == 0 ) { if( src == g_internal->f_cons_last_received_IP ) { g_internal->f_cons_last_received_IP_count++; if( g_internal->f_cons_last_received_IP_count >= g_internal->f_cons_last_received_IP_count_limit ) { //yes he is a flooder #ifdef USE_FIXED_LIST g_internal->temp_connection_flood_banns[ g_internal->temp_block_count ] = src; g_internal->temp_block_count = (g_internal->temp_block_count + 1) & TEMP_BLOCK_LIST_MASK; #else Addbanned( src ); #endif forced_log = 1; pgn.action = 30; } } else { //memorize new IP to see how many times it will consecutively connect g_internal->f_cons_last_received_IP = src; g_internal->f_cons_last_received_IP_count = 0; } } } } } if( range || opening || ( forced_log == 1 && IsListEmpty( &g_internal->queue.irp_list ) && g_internal->blockhttp == 0 ) //this is required or on DDOS CPU usage will go to 100%.. ) { pgn.protocol=iph->ipProtocol; pgn.source.addr4.sin_family = AF_INET; pgn.source.addr4.sin_addr.s_addr = iph->ipSource; pgn.source.addr4.sin_port = HTONS(srcport); pgn.dest.addr4.sin_family = AF_INET; pgn.dest.addr4.sin_addr.s_addr = iph->ipDestination; pgn.dest.addr4.sin_port = HTONS(destport); Notification_Send(&g_internal->queue, &pgn); if( pgn.action != 1 && pgn.action != 2 ) return PF_DROP; } return PF_FORWARD; }