How to redirect TCP packets from protocol layer using NDIS filter driver? - windows

I'm writing a NDIS filter driver for windows. Now I face a problem.
I'm going to redirect TCP packets to a TCP server on the current PC which the NDIS filter driver installs on. For example, the IP address of the current PC is 192.168.1.1 and there is a TCP server on it which is listening port 8000.
A user enters a URL: http://192.168.1.10/xxxx in the IE browser and my NDIS filter driver can absolutely see the TCP SYN packet. I modify the destination IP address of the packet to 192.168.1.1 and the destination port to 8000, because I'm expecting the packet can be redirected to the local TCP server.
Then I use NdisFIndicateReceiveNetBufferLists() to to inject the NBL into the receiving path instead of sending it to the underlying miniport driver.
However, it seems that the local TCP server can never get the redirected SYN packet. I don't know where the thing is going wrong. Would anyone help me or give me some advice?
Thank you very much!

In general, you can't take an NBL from one path (the transmit path) and just drop it into another path (the receive path). You'd need to clone the NBL and indicate the clone. Also, you'll have to edit the IP and TCP headers to fix the checksums.
But before you go down that route -- be advised that a WFP callout is a more appropriate type of driver for this project. WFP callouts are designed to operate at Layer 3 and Layer 4 of the network stack, while NDIS operates at Layer 2.

Related

UDP Packets not Sending Possibly Due to Client Not Found?

I have an application that is very simple. It sends out UDP packets to a client somewhere else on the network.
The host computer is 192.168.11.66 (Windows 10), the client device is 192.168.11.65 (proprietary device).
The host pc cannot see the client device, however I know that it is on and listening to traffic. When I send UDP packets from the host, I use Wireshark and I do not see the packets being sent out. Instead I see messages from ARP trying to locate the client. I assume because ARP is unsuccessful, the host cancels the sending of the packets.
If I change the destination address of the packets to a broadcast address, all of the packets get sent and I see everything on Wireshark. I need to be able to specify the IP address of the client and have Windows send the packets regardless of whether or not it thinks the client device is on the network or not. The client device looks for UDP traffic specifically addressed to itself and the client device has no way of making itself visible on the network.
Does anyone know how to work around this?
Thank you #Remy: instead to create your own ARP record manually. – Remy Lebeau
I did not realize that I could create manual entries in the ARP. I need to read more about ARP. Adding a manual entry solved my issue. I found that you could do it using ASP -s, or add neighbor using NETSH .
Thanks!

destination MAC to use when sending to remote host (is it my router)?

For various reasons, I'm trying to construct and send raw TCP packets to a remote host (ex. google.com) with raw sockets. I'm trying to use pcap, so the raw socket code can be ported to Windows at some point.
Looks pretty straightforward...
1. ethernet header
2. ip header
3. tcp header
4. segment (optional)
2,3,4 are straightforward. #1 is the rub because I don't know what to use for the destination MAC address of google.com. From what I can tell, ARP is useless for telling me that MAC because I have to be connected to google's router for it to work. Snag.
So that makes me ask this question:
Should I use the MAC of MY router as the destination MAC address in the ethernet header when sending to a host not in LAN? And when the packet is forwarded, does every router it hits tear out that Ethernet header and replace it with the appropriate source/destination MACs so it gets to Google.com? That is the only thing that sounds reasonable.
Side note, I think this was the motivation here, but the question never quite made it:
how to determinate destination MAC address
That's right. The source MAC address in the ethernet header should be the MAC address of the interface you're sending from, and the destination MAC address should be your router's MAC on its interface that is connected to your LAN.
It's important to remember that Link-Layer addresses are used within networks (in this case, both your MAC address and your router's internal interface are on your LAN), while Network Layer (IPv4/IPv6) addressing is used to route your packet from the source host to the destination host (this is ignoring NAT and a whole bunch of other grossness that arises in IPv4).
What will happen when you send your Ethernet frame out of your interface is the following:
Your router will end up with the frame after it travels through 0 or more switches, which know where your router's internal MAC address is from receiving traffic from it in the past. Your router knows the frame is for it because its internal MAC address is the destination MAC.
Your router will strip off the Ethernet header. Then, it will inspect the destination IP address, and determine how to forward that packet based on that address. If we're talking about your home router, it is probably also changing the source IP address (something called Network Address Translation, or NAT), but since it isn't in the scope of your question I'll leave that alone.
Before it forwards the packet to the next router on the path toward the destination IP address, the router needs to put another Link-Layer header back on the IP datagram because it stripped off the one you had put on it. So, it will create a new Link-Layer header using its outgoing interface's MAC address as the source MAC, and the MAC address of the next router's internal MAC address as the destination. In this way, the Link-Layer header is re-written "hop-by-hop".
Somedays before even I faced the same confusion. So long story short yes the destination MAC address will be the gateway router MAC address. And about how I determined is - like this -
I used the command
route -n
Then I used the command
arp -n
The output is as you can see -
goutbose#####:~$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 10.39.51.1 0.0.0.0 UG 0 0 0 enp2s0f0
goutbose####:~$ arp -n
Address HWtype HWaddress Flags Mask Iface
10.39.51.130 ether 00:1a:c5:01:12:94 C enp2s0f0
Now you can hardcode your destination MAC in your packets as I did as an easy hack or if you want you can design your own ARP resolution which is way out of my knowledge scope to help you out. My implementation to implement my own ICMP ping request using raw sockets is as follows -
https://github.com/Goutam1511/Socket-Programming-with-C/blob/master/myping.c
Although a late reply I hope it may help somebody else out because there are very little resources related to using raw socket in the link layer.

Find IP address of directly connected device

Is there a way to find out the IP address of a device that is directly connected to a specific ethernet interface? I.e. given one host, one wired ethernet connection and one second host connected to this wired connection, which layer or protocol below IP could be used to find this out.
I would also be comfortable with a Windows-only solution using some Windows-API function or callback.
(I know that the real way to do this would probably via DHCP, but this is about discovering a legacy device.)
Mmh ... there are many ways.
I answer another network discovery question, and I write a little getting started.
Some tcpip stacks reply to icmp broadcasts.
So you can try a PING to your network broadcast address.
For example, you have ip 192.168.1.1 and subnet 255.255.255.0
ping 192.168.1.255
stop the ping after 5 seconds
watch the devices replies : arp -a
Note : on step 3. you get the lists of the MAC-to-IP cached entries, so there are also the hosts in your subnet you exchange data to in the last minutes, even if they don't reply to icmp_get.
Note (2) : now I am on linux. I am not sure, but it can be windows doesn't reply to icm_get via broadcast.
Is it the only one device attached to your pc ?
Is it a router or another simple pc ?
To use DHCP, you'd have to run a DHCP server on the primary and a client on the secondary; the primary could then query the server to find out what address it handed out. Probably overkill.
I can't help you with Windows directly. On Unix, the "arp" command will tell you what IP addresses are known to be attached to the local ethernet segment. Windows will have this same information (since it's a core part of the IP/Ethernet interface) but I don't know how you get at it.
Of course, the networking stack will only know about the other host if it has previously seen traffic from it. You may have to first send a broadcast packet on the interface to elicit some sort of response and thus populate the local ARP table.
Windows 7 has the arp command within it.
arp -a should show you the static and dynamic type interfaces connected to your system.
Your Best Approach is to install Wireshark, reboot the device wait for the TCP/UDP stream , broadcasts will announce the IP address for both Ethernet ports
This is especially useful when the device connected does not have DHCP Client enabled, then you can go from there.
You can also get information from directly connected networking devices, such as network switches with LDWin, a portable and free Windows program published on github:
http://www.sysadmit.com/2016/11/windows-como-saber-la-ip-del-switch-al-que-estoy-conectado.html
LDWin supports the following methods of link discovery: CDP (Cisco Discovery Protocol) and LLDP (Link Layer Discovery Protocol).
You can obtain the model, management IP, VLAN identifier, Port identifier, firmware version, etc.

Is there an easy way to route IP packets from a user space Windows app to the network?

I am working on a project that involves a usb device, through which we will receive ip packets from a remote pc. We assign the remote pc its IP Address. I have been experimenting with sending raw ip packets via several methods:
1 - raw sockets: ping works fine, problems sending tcp
2 - tun/tap W32: I managed to get this working enough to send pings out and get pings back to the phy ethernet device, but could not read them using ReadFile(...) on the driver guid.
3 - winpcap: ping works, out going tcp shows up on wireshark(so I assume it is leaving the pc), but i never get an ack to my syn. Im also worried that if I did get an ack the windows TCP stack would send a rst.
Our goal is to be a transparent pass through from the client pc to the network.
Client <-wrapped ip packet-> [device] <-wrapped ip packet-> WinPC <- IP -> IpNetwork
Its possible that im going about this wrong, seems like this should be easier.
I realize that windows is prob not the ideal OS for this, however I have no control over the OS.
thanks in advance
Fixed my issue with TCP Syn packets not getting acked, turns out I forgot to include the pseudo-header when calculating the TCP header checksum. Now it looks like the tcp handshake completes, so im calling this problem solved. If anyone feels like recomending a better way to accomplish this, feel free to reply. For now looks like we will use the winpcap method.
Update:
For this to work without windows constantly RST'ing tcp connections, you have to enable internet connection sharing(ICS) on the adapter you are sending packets out of. Other than that this ended up working for us.

UDP and my computer?

I recently turned on Windows Firewall logging on my computer and started tracking incoming and outgoing connections. Something curious about the logfiles is that I have noticed numerous UDP packets (in fact, it constitutes basically all of my incoming traffic) that don't have my host as destination or source showing up in the logs.
I thought this might be a implementation detail for UDP (the packets are hopping over my computer in the subnet) but Wikipedia'ing UDP didn't enlighten me any more, and I don't see why my computer should be forwarding these packets in the first place.
Any ideas?
Edit 1: Here is what a log file line with the mysterious UDP packet looks like:
2008-10-11 16:04:31 ALLOW UDP 18.243.7.218 239.255.255.250 49152 3702 0 - - - - - - - RECEIVE
Is 239.255.255.250 a broadcast address? Now that you mention it, the UDP packets I'm seeing have very specific destinations, basically 224.0.0.252, 239.255.255.250, 18.243.255.255. I also get phantom ICMP pings addressed to 224.0.0.1.
The packets addressed to IPs starting with 239 and 224 are multicast packets. This is a way to address traffic to a group of computers without broadcasting it to an entire network. It is used by various legitimate protocols.
224.0.0.252 is the address used by the Link Local Name Resolution protocol.
239.255.255.250 is the address used by the Simple Service Discovery Protocol.
224.0.0.1 is the all hosts address, used by your router to see who on your network is willing to participate in multicast conversations.
The ones addressed to 18.243.255.255 look like broadcasts, again this is used by many legitimate protocols such as Bonjour.
As recommended by Luka, a good protocol analyzer like Wireshark will tell you precisely what each of these packets are and what they contain.
It depends on the type of connection you are on.
On most cable modem ISP's you are basicly on the same LAN as your neigburs, and can usualy see some of their traffic (like brodcast).
Id recomend you install packet sniffer and see what is realy going on.
Good multiplatform packet sniffer is Wireshark
Hard to say without analyzing the log data, but they could be broadcast packets on the segment, in which case you're system would listen to them. This is possible in IPv4 and IPv6.
Your system should not be forwarding them unless it's set up to route, but it can certainly be listening to packets all the time (various network protocols use UDP).

Resources