Home › Forums › Discussions › Support › Net frozen after few minutes
- This topic has 5 replies, 2 voices, and was last updated 18 years, 6 months ago by aty.
-
AuthorPosts
-
June 14, 2006 at 12:45 pm #5032
Hi
I’m trying to implement some basic firewall based on the PassThru example. What I’m actually doing is modifying outgoing UDP packets by attaching a secret key at the end of their buffer, and vice versa – extracting the secret key from the incoming UDP packets. The pass/drop decision is based on key match. Anyway, everything works fine for the first few minutes, and then all net activity is frozen until I kill my application. It doesn’t happen with the original PassThru example. I suspeced that the internal buffer of the helper driver is getting full, but I keep calling ReadPacket in an infinite loop. All I could see is that while the net is frozen, the code is (probably) doing WaitForSingleObject (i.e. no new packet events are received).Here is the relevant code:
ZeroMemory ( &Request, sizeof(ETH_REQUEST) );
ZeroMemory ( &PacketBuffer, sizeof(INTERMEDIATE_BUFFER) );
Request.EthPacket.Buffer = &PacketBuffer; // buffer to hold Ethernet frame
Request.hAdapterHandle = (HANDLE)AdList.m_nAdapterHandle[iIndex];
api.SetAdapterMode(&Mode);
printf ("Encapsulator running, press CTRL+C to abort.n");
while (true)
{
WaitForSingleObject ( hEvent, INFINITE );
ResetEvent(hEvent);
while(api.ReadPacket(&Request))
{
// recalculate keys (only if needed, i.e. granualrity time has passed)
GetSecretKeys(auth_key,time_granularity,SecretKeys,last_calc_time);
#pragma region Packet parsing
pEthHeader = (ether_header*)PacketBuffer.m_IBuffer;
if (ntohs(pEthHeader->h_proto) != ETH_P_IP)
{
// don't handle ARP/RARP packets
continue;
}
pIPHeader = (iphdr_ptr)(PacketBuffer.m_IBuffer + sizeof(ether_header));
protocol = pIPHeader->ip_p;
int ip_header_len = sizeof(DWORD)*(pIPHeader->ip_hl);
switch (protocol)
{
case IPPROTO_IP:
break;
case IPPROTO_ICMP:
break;
case IPPROTO_IGMP:
break;
case IPPROTO_GGP:
break;
case IPPROTO_TCP:
pTCPHeader = (tcphdr_ptr)(((PUCHAR)pIPHeader) + ip_header_len);
pTCPData = (PUCHAR)(pTCPHeader + pTCPHeader->th_off * 4);
break;
case IPPROTO_PUP:
break;
case IPPROTO_UDP:
pUDPHeader = (udphdr_ptr)(((PUCHAR)pIPHeader) + ip_header_len);
pUDPData = (PUCHAR)(pUDPHeader + sizeof(udphdr));
break;
case IPPROTO_IDP:
break;
case IPPROTO_ND:
break;
case IPPROTO_RAW:
break;
default:
break;
}
#pragma endregion
// display packet information:
#ifndef _SILENT_PASSTHRU
if (!SilentOperation)
{
if (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND)
{
printf("nMSTCP --> Interface (outgoing traffic)n");
}
else
{
printf("nInterface --> MSTCP (incoming traffic)n");
}
printf ("tEthernet Packet size = %dn", PacketBuffer.m_Length);
printf (
"tSource MAC:tt%.2X%.2X%.2X%.2X%.2X%.2Xn",
pEthHeader->h_source[0],
pEthHeader->h_source[1],
pEthHeader->h_source[2],
pEthHeader->h_source[3],
pEthHeader->h_source[4],
pEthHeader->h_source[5]
);
printf (
"tDestination MAC:t%.2X%.2X%.2X%.2X%.2X%.2Xn",
pEthHeader->h_dest[0],
pEthHeader->h_dest[1],
pEthHeader->h_dest[2],
pEthHeader->h_dest[3],
pEthHeader->h_dest[4],
pEthHeader->h_dest[5]
);
char s_address[20] = "";
char d_address[20] = "";
ParseIPAddress(pIPHeader->ip_src,s_address);
ParseIPAddress(pIPHeader->ip_dst,d_address);
printf("tIP Address:tt");
printf(s_address);
printf(" --> ");
printf(d_address);
printf("n");
switch(protocol)
{
case IPPROTO_TCP:
printf("tProtocol:ttTCPn");
printf("tSource port:tt%dntDestination Port:t%dn",ntohs(pTCPHeader->th_sport),ntohs(pTCPHeader->th_dport));
break;
case IPPROTO_UDP:
printf("tProtocol:ttUDPn");
printf("tSource port:tt%dntDestination Port:t%dn",ntohs(pUDPHeader->th_sport),ntohs(pUDPHeader->th_dport));
printf("tUDP Data Length:t%dn",ntohs(pUDPHeader->length)-sizeof(udphdr));
break;
case IPPROTO_ICMP:
printf("tProtocol:ttICMPn");
break;
default:
printf("tProtocol:ttOthern");
break;
}
} // SilentOperation
#endif // _SILENT_PASSTHRU
if (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND)
{ // Packet on its way to the network
if(!InformationOnly)
{
// if UDP packet - encapsulate (add current key at end of buffer)
if (protocol == IPPROTO_UDP)
{
if (ntohs(pUDPHeader->th_dport) != FilteredPort &&
ntohs(pUDPHeader->th_dport) != -1)
{
api.SendPacketToAdapter(&Request);
continue;
}
u_short d_len = ntohs(pUDPHeader->length); // header+data length
d_len -= sizeof(udphdr); // data only (UDP header is 8 bytes)
//memcpy(key,SecretKeys,auth_key_len);
memcpy(&pUDPData[d_len],SecretKeys,auth_key_len); // get current key
// update UDP & IP packet length
d_len += auth_key_len;
d_len += sizeof(udphdr);
pUDPHeader->length = htons(d_len);
pIPHeader->ip_len = htons(ntohs(pIPHeader->ip_len) + auth_key_len);
// must update the intermediate buffer length
PacketBuffer.m_Length += auth_key_len;
// re-calculate checksums
RecalculateUDPChecksum(&PacketBuffer);
RecalculateIPChecksum(pIPHeader);
printf("Outgoing UDP packet encapsulated.n");
}
} // InformationOnly
// Place packet on the network interface
// outgoing packets are always sent (not filtered/dropped)
api.SendPacketToAdapter(&Request);
}
if (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_RECEIVE)
{ // Packet received from network
if(!InformationOnly)
{
// if UDP packet - decapsulate
if (protocol == IPPROTO_UDP)
{
if (ntohs(pUDPHeader->th_dport) != FilteredPort &&
ntohs(pUDPHeader->th_dport) != -1)
{
api.SendPacketToMstcp(&Request);
continue;
}
u_short d_len = ntohs(pUDPHeader->length); // header + data + key length
int data_len = (d_len - sizeof(udphdr) - auth_key_len);
if (data_len < 0)
{
printf("missing key! Incoming UDP packet dropped.n");
continue; // negative data - no key attached for sure (zero data allowed)
}
// update UDP & IP packet data length first
d_len -= auth_key_len; // d_len = header+data only length
pUDPHeader->length = htons(d_len); // header+data length
pIPHeader->ip_len = htons(ntohs(pIPHeader->ip_len) - auth_key_len);
// update intermediate buffer length
PacketBuffer.m_Length -= auth_key_len;
// extract auth_key from packet
d_len -= sizeof(udphdr); // d_len = data only length = key offset
memset(key,0,auth_key_len + 1); // nulls
memcpy(key,&pUDPData[d_len],auth_key_len);
// compare extracted key to any of the 3 keys (current,prev,next)
if (!CompareKeys(key,SecretKeys))
{
printf("Incoming UDP packet allowed.n");
// re-calculate checksums
RecalculateUDPChecksum(&PacketBuffer);
RecalculateIPChecksum(pIPHeader);
}
else
{
printf("key mismatch! Incoming UDP packet dropped.n");
continue; // do not pass packet to application
}
}
} //InformationOnly
// Send packet to the application
api.SendPacketToMstcp(&Request);
}
}
}
June 15, 2006 at 12:01 pm #6068Just thought to mentioned that I’m using the runtime libraries that are available at the web site (hxxp://www.ntoskrnl.com/downloads/winpkflt_rtx86.zip).
Could it be related (are those runtimes limited) ?
Many thanks,
atyJune 15, 2006 at 6:00 pm #6069Just thought to mentioned that I’m using the runtime libraries that are available at the web site (hxxp://www.ntoskrnl.com/downloads/winpkflt_rtx86.zip).
These binaries have no limitations.
Well, first of all I would start this application under debugger and check where it stops (or what is it doing) when network is frozen. Since this is a packet filtering application the network freeze can be easily caused by application hang (some dead lock or endless loop).
Also, I think it is important to mention that you should set MTU decrement if you are attaching additional data to the packets to the maximum size of the attached data. The total size of the ethernet frame should not exceeed 1514 bytes. I can’t see from your code if any length checks are implemented.
June 16, 2006 at 9:35 am #6070SerpenFly
Thank you very much for the reply. Your tip helped me find out that I simply forgot to process non-IP packets (see line 17 in the code…).
I guess that at some point, lack of ARP/RARP functionality hanged up the LAN.
Regarding MTU: As far as I know, windows default MTU for ethernet adapters is 1500. I always attach a 20 bytes key to outgoing UDP packets.
Can I conclude from this that I might have a problem only with packets whose total length is 1480 bytes or more ?Another question:
Can I catch packets that are directed either to 127.0.0.1 or to the local IP ? are those packets passed down the TCP stack or are they redirected by Windows back to the application at higher levels ?Thanks again,
atyJune 16, 2006 at 11:27 am #6071Regarding MTU: As far as I know, windows default MTU for ethernet adapters is 1500. I always attach a 20 bytes key to outgoing UDP packets.
Can I conclude from this that I might have a problem only with packets whose total length is 1480 bytes or more ?Yes, you will have problems with packets which size is equal or close (so you don’t have 20 bytes in reserve) to MTU. There is a special API in WinpkFilter SetMTUDecrement. In your case if maximum size of the attached data is 20 bytes so you should call SetMTUDecrement with 20 as a parameter, please note that this API adds a driver specific value into the registry and requires reboot to take an effect (driver reads this value from the registry during start up).
Can I catch packets that are directed either to 127.0.0.1 or to the local IP ? are those packets passed down the TCP stack or are they redirected by Windows back to the application at higher levels ?
Packets directed to 127.x.x.x or local IP never reach NDIS level and processed internally by TCP/IP. However, these data can be intercepted at the TDI level http://www.ntkernel.com/w&p.php?id=8 and http://www.ntkernel.com/w&p.php?id=24
June 16, 2006 at 12:25 pm #6072Thank you very much for the information SerpentFly.
aty
-
AuthorPosts
- You must be logged in to reply to this topic.