Home › Forums › Discussions › Support › Redirection (Gateway)
- This topic has 5 replies, 3 voices, and was last updated 18 years, 8 months ago by Vadim Smirnov.
-
AuthorPosts
-
February 17, 2006 at 2:23 am #4993
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.
EdFebruary 17, 2006 at 9:22 am #5965Yes, 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).
February 17, 2006 at 9:52 am #5966Hi 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.
EdFebruary 17, 2006 at 11:44 am #5967The 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.
April 16, 2006 at 12:01 pm #5968@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 ?
April 17, 2006 at 11:22 am #5969Can 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.
-
AuthorPosts
- You must be logged in to reply to this topic.