Redirection (Gateway)

Home Forums Discussions Support Redirection (Gateway)

Viewing 6 posts - 1 through 6 (of 6 total)
  • Author
    Posts
  • #4993
    ed101
    Participant

      Hi,
      if I use a Windows computer as an internet-gateway (Internet Connection Sharing), is it possible to redirect some users (with a specific IP) to another Website than the requested?
      Is it possible in Visual Basic ?
      Please add some relevant source-code.
      Thanks a lot in advance.
      Ed

      #5965
      Vadim Smirnov
      Keymaster

        Yes, this is possible to implement in Visual basic using WinpkFilter library, however I can’t provide you with ready to use code in VB (as I’m not a VB coder). If you can use the C code I think I can provide some.

        Also you can use port/protocol mapping avalable in NeT Firewall (set up redirector rules on the internal LAN interface).

        #5966
        ed101
        Participant

          Hi Serpent,
          first of all, thanks for the information.
          But I have a few further questions:

          The WinpkFilter library you mentioned, is it free or do I have to purchase it? Is it the free downloadable ndisapi.dll ?

          Can you provide some code samples for the redirection in C or another programming language?

          Thanks in advance.
          Ed

          #5967
          Vadim Smirnov
          Keymaster

            The WinpkFilter library you mentioned, is it free or do I have to purchase it? Is it the free downloadable ndisapi.dll ?

            WinpkFilter is free for non-commercial use and available for download from here (http://www.ntkernel.com/w&p.php?id=7). Package includes drivers(ndisrd.sys/ndisrd.vxd), API DLL (ndisapi.dll) and several simple samples.

            If you register WinpkFilter (any type of subscription starting from 95$) you also get access to the Internet Gateway source code (http://www.ntkernel.com/w&p.php?id=31) which implements NAT and gives a good clue to how to redirect packets.

            Some code samples can be also found by looking through this forum. I can also C&P a redirect relative portion of code from NeT Firewall source, but it may appear a bit difficult to understand.

            #5968
            kkkerem
            Participant

              @SerpentFly wrote:

              Yes, this is possible to implement in Visual basic using WinpkFilter library, however I can’t provide you with ready to use code in VB (as I’m not a VB coder). If you can use the C code I think I can provide some.

              Also you can use port/protocol mapping avalable in NeT Firewall (set up redirector rules on the internal LAN interface).

              Can you provide some C code for this purpose ?

              #5969
              Vadim Smirnov
              Keymaster

                Can you provide some C code for this purpose ?

                The routine below is taken from the Internet Gateway source and implements NAT processing:

                unsigned __stdcall CsnatDlg::StartNAT ( void* pArguments )
                {
                CsnatDlg* pDlg = (CsnatDlg*)pArguments;
                HANDLE hEvents[ADAPTER_LIST_SIZE + 1];
                CNetworkInterface* hAdapters [ADAPTER_LIST_SIZE + 1];
                CNetworkInterface *pNetCard, *pProviderCard;
                unsigned dwActiveAdaptersCount = 1;
                ADAPTER_MODE Mode;
                ETH_REQUEST Request;
                INTERMEDIATE_BUFFER PacketBuffer;
                DWORD dwWait, dwIndex;
                ether_header* pEthHeader;
                iphdr* pIpHeader;
                tcphdr* pTcpHeader;
                udphdr* pUdpHeader;

                Mode.dwFlags = MSTCP_FLAG_SENT_TUNNEL|MSTCP_FLAG_RECV_TUNNEL;

                hEvents[0] = pDlg->m_hNATTerminateEvent;

                // Walk adapters list and initialize provider and clients interfaces
                POSITION pos = pDlg->m_NetCardsList.GetHeadPosition();

                for (unsigned i = 0; i < pDlg->m_dwAdapterCount; ++i)
                {
                pNetCard = (CNetworkInterface*)pDlg->m_NetCardsList.GetNext(pos);

                if ((pNetCard->m_NATState == CLIENT) || (pNetCard->m_NATState == PROVIDER))
                {
                hAdapters[dwActiveAdaptersCount] = pNetCard;
                hEvents[dwActiveAdaptersCount] = ::CreateEvent(NULL, TRUE, FALSE, NULL);
                pDlg->m_NdisApi.SetPacketEvent(pNetCard->m_hAdapter, hEvents[dwActiveAdaptersCount]);
                Mode.hAdapterHandle = pNetCard->m_hAdapter;
                pDlg->m_NdisApi.SetAdapterMode(&Mode);
                dwActiveAdaptersCount++;

                if(pNetCard->m_NATState == PROVIDER)
                pProviderCard = pNetCard;
                }
                }

                // Initialize Request
                ZeroMemory ( &Request, sizeof(ETH_REQUEST) );
                ZeroMemory ( &PacketBuffer, sizeof(INTERMEDIATE_BUFFER) );
                Request.EthPacket.Buffer = &PacketBuffer;

                do
                {
                dwWait = ::WaitForMultipleObjects(
                dwActiveAdaptersCount,
                hEvents,
                FALSE,
                INFINITE
                );

                dwIndex = dwWait - WAIT_OBJECT_0;

                if (!dwIndex)
                continue;

                ::ResetEvent(hEvents[dwIndex]);

                Request.hAdapterHandle = hAdapters[dwIndex]->m_hAdapter;

                // Read all queued packets from the specified interface
                while(pDlg->m_NdisApi.ReadPacket(&Request))
                {
                pEthHeader = (ether_header*)PacketBuffer.m_IBuffer;
                if ( ntohs(pEthHeader->h_proto) == ETH_P_IP )
                {
                pIpHeader = (iphdr*)(PacketBuffer.m_IBuffer + ETHER_HEADER_LENGTH);

                // Check if connection is established from local system (we don't do NAT processing
                // for local system)
                BOOL bIsLocalAddress = hAdapters[dwIndex]->IsLocalAddress(&pIpHeader->ip_src);

                if (bIsLocalAddress && (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND))
                {
                // Place packet on the network interface
                pDlg->m_NdisApi.SendPacketToAdapter(&Request);

                continue;
                }

                // TCP packet processing
                if (pIpHeader->ip_p == IPPROTO_TCP)
                {
                // This is TCP packet, get TCP header pointer
                pTcpHeader = (tcphdr*)(((PUCHAR)pIpHeader) + sizeof(DWORD)*pIpHeader->ip_hl);

                // Outgoing TCP packets processing
                if ((hAdapters[dwIndex]->m_NATState == PROVIDER)&&
                (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND))
                {
                CPortNATEntry* pTcpNE = NULL;

                if (pTcpHeader->th_flags == TH_SYN)
                {
                // New TCP connnection established, allocate dynamic NAT entry
                pTcpNE = pDlg->m_TcpNatTable.Allocate(pIpHeader->ip_src, pTcpHeader->th_sport, pIpHeader->ip_dst, pTcpHeader->th_dport);

                if(pTcpNE)
                {
                pTcpNE->m_IpNAT = hAdapters[dwIndex]->m_NATIp;
                }
                }
                else
                {
                // Try to locate xisting NAT entry
                pTcpNE = pDlg->m_TcpNatTable.Find(pIpHeader->ip_src, pTcpHeader->th_sport, pIpHeader->ip_dst, pTcpHeader->th_dport);
                }

                if (pTcpNE)
                {
                // If NAT entry is found perform NAT processing
                pIpHeader->ip_src.S_un.S_addr = htonl(pTcpNE->m_IpNAT.S_un.S_addr);
                pTcpHeader->th_sport = htons(pTcpNE->m_usNATPort);
                // Recalculate checksums
                RecalculateTCPChecksum (&PacketBuffer);
                RecalculateIPChecksum(pIpHeader);
                }
                }

                // Incoming TCP packets processing
                if ((hAdapters[dwIndex]->m_NATState == PROVIDER)&&
                (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_RECEIVE))
                {
                // Map connection to the NAT entry if the one exists
                CPortNATEntry* pTcpNE = pDlg->m_TcpNatTable.Map(pTcpHeader->th_dport);
                if (pTcpNE)
                {
                // NAT entry exists, make NAT processing
                if (htonl(pTcpNE->m_IpDst.S_un.S_addr) == pIpHeader->ip_src.S_un.S_addr)
                {
                pIpHeader->ip_dst.S_un.S_addr = htonl(pTcpNE->m_IpSrc.S_un.S_addr);
                pTcpHeader->th_dport = htons(pTcpNE->m_usSrcPort);
                RecalculateTCPChecksum (&PacketBuffer);
                RecalculateIPChecksum(pIpHeader);
                }
                }

                }
                }
                // UDP packets processing
                if (pIpHeader->ip_p == IPPROTO_UDP)
                {
                // This is UDP packet, get UDP header pointer
                pUdpHeader = (udphdr*)(((PUCHAR)pIpHeader) + sizeof(DWORD)*pIpHeader->ip_hl);

                // DNS hook
                // If we receive DNS packet on the NAT client adapter then we redirect it
                // to this system configured DNS server
                if ((hAdapters[dwIndex]->m_NATState == CLIENT)&&
                (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_RECEIVE))
                {
                if (ntohs(pUdpHeader->th_dport) == 53/*DNS port*/)
                {
                // Save the DNS IP used by the NAT client system
                hAdapters[dwIndex]->m_LocalDNS.S_un.S_addr = ntohl(pIpHeader->ip_dst.S_un.S_addr);
                pIpHeader->ip_dst.S_un.S_addr = pDlg->m_DNSIp.S_un.S_addr;
                RecalculateIPChecksum(pIpHeader);
                }
                }
                // DNS reply came, substitute source IP back to the original DNS address
                if ((hAdapters[dwIndex]->m_NATState == CLIENT)&&
                (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND))
                {
                if (ntohs(pUdpHeader->th_sport) == 53/*DNS port*/)
                {
                pIpHeader->ip_src.S_un.S_addr = htonl(hAdapters[dwIndex]->m_LocalDNS.S_un.S_addr);
                RecalculateIPChecksum(pIpHeader);
                }
                }
                // Outgoing UDP NAT processing
                if ((hAdapters[dwIndex]->m_NATState == PROVIDER)&&
                (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND))
                {
                CPortNATEntry* pUdpNE = NULL;
                // Try to find existing entry
                pUdpNE = pDlg->m_UdpNatTable.Find(pIpHeader->ip_src, pUdpHeader->th_sport, pIpHeader->ip_dst, pUdpHeader->th_dport);
                // If not found -> allocate a new one
                if (!pUdpNE)
                {
                pUdpNE = pDlg->m_UdpNatTable.Allocate(pIpHeader->ip_src, pUdpHeader->th_sport, pIpHeader->ip_dst, pUdpHeader->th_dport);

                if(pUdpNE)
                {
                pUdpNE->m_IpNAT = hAdapters[dwIndex]->m_NATIp;
                }
                }
                // NAT processing
                if (pUdpNE)
                {
                pIpHeader->ip_src.S_un.S_addr = htonl(pUdpNE->m_IpNAT.S_un.S_addr);
                pUdpHeader->th_sport = htons(pUdpNE->m_usNATPort);
                RecalculateUDPChecksum (&PacketBuffer);
                RecalculateIPChecksum(pIpHeader);
                }
                }
                // Incoming UDP packets processing
                if ((hAdapters[dwIndex]->m_NATState == PROVIDER)&&
                (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_RECEIVE))
                {
                CPortNATEntry* pUdpNE = pDlg->m_UdpNatTable.Map(pUdpHeader->th_dport);
                if (pUdpNE)
                {
                if (htonl(pUdpNE->m_IpDst.S_un.S_addr) == pIpHeader->ip_src.S_un.S_addr)
                {
                pIpHeader->ip_dst.S_un.S_addr = htonl(pUdpNE->m_IpSrc.S_un.S_addr);
                pUdpHeader->th_dport = htons(pUdpNE->m_usSrcPort);
                RecalculateUDPChecksum (&PacketBuffer);
                RecalculateIPChecksum(pIpHeader);
                }
                }

                }
                }

                }

                // Reinject packet into the stack
                if (PacketBuffer.m_dwDeviceFlags == PACKET_FLAG_ON_SEND)
                {
                // Place packet on the network interface
                pDlg->m_NdisApi.SendPacketToAdapter(&Request);
                }
                else
                {
                // Indicate packet to MSTCP
                pDlg->m_NdisApi.SendPacketToMstcp(&Request);
                }
                }

                }while (dwIndex);

                // Free all NAT entries
                pDlg->m_TcpNatTable.RemoveAll();
                pDlg->m_UdpNatTable.RemoveAll();

                for (unsigned i = 1; i < dwActiveAdaptersCount; ++i)
                {
                Mode.dwFlags = 0;
                Mode.hAdapterHandle = hAdapters->m_hAdapter;

                // Set NULL event to release previously set event object
                pDlg->m_NdisApi.SetPacketEvent(hAdapters
                ->m_hAdapter, NULL);

                // Close Event
                if (hEvents
                )
                CloseHandle ( hEvents
                );

                // Set default adapter mode
                pDlg->m_NdisApi.SetAdapterMode(&Mode);

                // Empty adapter packets queue
                pDlg->m_NdisApi.FlushAdapterPacketQueue (hAdapters
                ->m_hAdapter);
                }

                _endthreadex( 0 );
                return 0;
                }

                Complete source code for the Internet Gateway is available to registered WinpkFilter customers.

              Viewing 6 posts - 1 through 6 (of 6 total)
              • You must be logged in to reply to this topic.