Net frozen after few minutes

Home Forums Discussions Support Portal Net frozen after few minutes

This topic contains 5 replies, has 2 voices, and was last updated by  aty 11 years, 2 months ago.

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #5032

    aty
    Participant

    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);

    }

    }

    }
    #6068

    aty
    Participant

    Just 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,
    aty

    #6069

    Vadim Smirnov
    Moderator

    Just 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.

    #6070

    aty
    Participant

    SerpenFly

    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,
    aty

    #6071

    Vadim Smirnov
    Moderator

    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 ?

    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

    #6072

    aty
    Participant

    Thank you very much for the information SerpentFly.

    aty

Viewing 6 posts - 1 through 6 (of 6 total)

You must be logged in to reply to this topic.