Ejemplo n.º 1
0
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;
}
Ejemplo n.º 2
0
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;
}