Net frozen after few minutes

Home Forums Discussions Support Net frozen after few minutes

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
        Keymaster

          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
            Keymaster

              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.