Resolving MAC address for IP address using C++ on Linux - linux

I need to generate an Ethernet header that includes the destination MAC address, (since libnfnetlink gives only the IP header before prerouting takes place), the outgoing interface number is also known, so the lookup can be made in the correct network.
What's the library/function to resolve the MAC address from an IP address?

It's unclear why you need the MAC address, since that's usually handled for you at a lower level.
However, assuming your target is on your local Ethernet segment, you can use the arp command to look up values in the local cache. If the value is not cached... Well, that's a problem. Perhaps arping would help...
(Normally you'd send a packet to, for example, IP address 10.10.10.10, and your system would send an ARP packet out querying who-has 10.10.10.10, and a response would come back from that target system with its MAC address, and then it would be cached. (You can watch this happening with tcpdump.) Or when a system comes on line it would send out a broadcast message informing everyone else of its MAC address. Naturally, if your destination is on another Ethernet segment, you're routing to a gateway rather than directly to the destination, and no destination-MAC address is available.)
You might read further at:
http://linux.die.net/man/8/arp
http://linux.die.net/man/8/arping
http://linux.die.net/man/7/arp
http://www.kernel.org/doc/man-pages/online/pages/man7/arp.7.html

Obviously you can only find the MAC address for directly connected IP addresses, but there's no platform-independent way of doing it. On Linux, you can look in /proc/net/arp after sending something to the target to trigger the kernel to send the ARP.
Edit to add you could also use the SIOCGARP ioctl() though that just looks in the ARP cache, so it won't send an ARP if there isn't one already there.
Otherwise, you would have to craft your own ARP request packet. You could probably reuse a bunch of code from arping if you go that route.

You cannot in general get the MAC address from the IP address, and in fact as IP can run on data link protocols other than ethernet, some IP addresses have no corresponding MAC address.
The MAC address is only available and only relevant on the same ethernet segment. On that segment, it can be retrieved by an ARP request.

Related

Scapy ARP Poisoning

The Scapy documentation gives the following example of ARP Cache Poisoning:
send(Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client))
Question 1:
My understanding is that this is the broadcast of an ARP request from a client.
Shouldn't the ARP Poison be executed by the attacker responding with:
send(Ether(dst=clientMAC)/ARP(op="is-at", psrc=gateway, pdst=client))
Question 2:
In a post on stackoverflow about Scapy, the OP posted:
This sends the victim an ARP reply packet with the local machine masquerading as the router:
send(ARP(op=ARP.is_at, psrc=router_ip, hwdst=victim_mac, pdst=victim_ip))
This sends the router an ARP reply packet with the local machine masquerading as the victim:
send(ARP(op=ARP.is_at, psrc=victim_ip, hwdst=router_mac, pdst=router_ip))
In both of these packets, the hwsrc field is filled by default with the local machine's MAC address.
But the Scapy documentation doesn't mention that hwdst is required.
I'd like to know why.
Question 3:
In the Scapy documentation:
send(Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client))
But in the OP's post from Question 2, the Ether(dst-clientMAC) is not supplied.
Does that mean it's not required?
Thanks.
In computer networking, ARP spoofing, ARP cache poisoning, or ARP
poison routing, is a technique by which an attacker sends (spoofed)
Address Resolution Protocol (ARP) messages onto a local area network.
Generally, the aim is to associate the attacker's MAC address with the
IP address of another host, such as the default gateway, causing any
traffic meant for that IP address to be sent to the attacker instead.
Wiki
As it is mentioned in Scapy documentation,
ARP cache poisoning attack prevents a client from joining the gateway
by poisoning its ARP cache through a VLAN hopping attack.
What they mean by that is that the poor client will not be able to send his packets to the gateway (Access Point in this case) and will fail to communicate with external resources. Note, however, that the very same client will still be able to communicate with other hosts within the VLAN. Even with the attacker (assuming it is also connected to the same WiFi network).
Let's go through this attack step-by-step.
Before, we move further, let's check the current ARP table on the Client side (before the attack is executed). On Linux to view the ARP table you need to run the following command:
$ sudo arp -n
Address HWtype HWaddress Flags Mask Iface
192.168.1.1 ether 54:f6:15:f5:51:55 C wlan0
As you can see, the ARP table has only one record which lists the Gateway IP address (192.168.1.1) and it's MAC (54:f6:15:f5:51:55).
When the Attacker executes the following command in Scapy:
send(Ether(dst=clientMAC)/ARP(op="who-has", psrc=gateway, pdst=client))
it creates and sends the following packet:
At the Ether layer, the destination MAC address dst is set to point to the Client's (victim's) MAC. At the same time, Scapy automatically fills in other Ether layer fields, most importantly, the src field which is set to attacker's MAC address. This means that on Ether layer the packet seems to come from the Attacker. Other Ether layer fields remained unchanged and contain default values. You can see it yourself if you run the following command in Scapy:
a = Ether(dst="clientMAC")
a.show()
Now, on IP layer the attacker crafts an ARP request packet, in which he sets the psrc (source IP) field to point to the IP of the gateway node (AP in this case). Now, remember that previously, on the Ether layer Scapy filled in the src field for us and set it to point to Attacker's MAC address. This means, that the final packet which is sent to the Client (victim) will look like it came from host that has Attacker's MAC and Gateway's IP address. We will get to it later. For now, let's move on. Finally, Client's IP address is set as a destination for the packet in a pdst field.
The packet is created and sent to the Client (victim).
The Client receives this packet and checks the packet's content. It sees that the ARP request arrived from Gateway IP (let's assume it's 192.168.1.1). It checks the MAC address field psrc in the Ether layer of the packet (let's assume it's a9:2b:24:9c:fd:c7) and updates it's ARP table, which now looks as following:
$ sudo arp -n
Address HWtype HWaddress Flags Mask Iface
192.168.1.1 ether a9:2b:24:9c:fd:c7 C wlan0
As you can see the IP address remained the same, but the MAC address changed. So, now, whenever the Client sends packets to the Gateway node, it actually sends them to the Attacker's MAC. If the Attacker's goal is to prevent the Client from communicating with the Gateway, these packets will be dropped and never delivered to the desired destination.
While the Attacker keeps sending crafted ARP packets to the Client, the Client will not be able to communicate with the Gateway. Once the Attacker stops, the real ARP request from the Gateway with real IP and MAC addresses will eventually arrive to eh Client restoring the normal communication. That is why, you, as an attacker, would probably want to create a loop for sending malicious packets, like this:
sendp(Ether(dst=”CLIENT-MAC”)/ARP(op="who-has", psrc=”GATEWAY-IP”, pdst=”CLIENT-IP”), inter=0.2, loop=1)
With this never ending loop, you effectively jam the communication between the Client and Gateway.

check if device online via ping ip when ip changes

Suppose I have the following situation. I have a Linux box sitting inside a local network, and that box will periodically ping the ip addresses of other devices on the network to make sure they are up. Also assume I know the MAC addresses of these devices, which I obtained via ARP at some point in the past. Now assume that one of the devices goes down and when it comes back up it is assigned a new ip address. How can I modify my periodic ping check to ping the new ip address? Yes I know I can check the arp table on my Linux box to get the new ip address if the record exists. But what guarantee do I have that the arp able on that box has been updated properly? Is there any way to quckly force the arp table on my Linux box to update and somehow find the new ip address for the known mac address?
My initial thoughts would be to disable DHCP and set these addresses statically unless it is critical that they cycle through different addresses.

Where do the Linux kernel router code replace the MAC address

The router will replace the source MAC address of the package it received with the address of the previous hop and the destination MAC address with the address of next hop.
The linux provides a functionality to worked as a router. My question is how the kernel code implement the function for mac address update during its package forwarding process? And where is this part of code
I try to find the codes in /net/ipv4, but can not found anything...
That is not what actually happens.
IP is not dependent on ethernet, so what happens is dependent upon the underlying protocol of the lower layer.
The same thing happens if it is a locally-originated IP packet, or if it is one which has been routed for another host.
Linux's IPv4 stack is not ethernet-dependent in any way, in fact lots of other link-layer protocols are supported by the kernel. IP being a WAN protocol, you can route between different underlying protocols. Some examples are
ppp, slip (serial lines)
PPTP, GRE (for tunnels, mostly VPNs)
IP over ATM
Token ring (mostly legacy, I think)
Loopback and dummy (for local communication only)
Wifi (although this is actually mostly identical to ethernet)
So what actually happens when routing IP frames from one ethernet interface to another is that the link-layer is stripped off completely, then a new link-layer is formed after routing. If the protocol were not ethernet, an appropriate link-layer packet for that protocol would be used instead.
So nobody "changes the MAC address", but rather, the link-layer packet is just completely rebuilt.

how to determinate destination MAC address

My application is running on CentOS 5.5
I need to send raw packets using libpcap API:
pcap_inject() or pcap_sendpacket()
To the specific IP address
How can I determinate MAC address belongs to a specific target?
It looks like what you want is ioctl and SIOCGARP. That should let you query your arp cache.
I'm assuming that the host in question is on your local network or all you're going to get is your router.
You can also read from /proc/net/arp, which seems easier. You'll need to get an arp request returned first but you'll be doing that whether your tool does it or some third-party makes the request.
In general, MAC addresses don't matter for remote targets. They are not routable; a router here at my office doesn't know the MAC addresses of network cards across the Internet. That's what IP addresses are for. Do you mean local only?

First packet to be sent when starting to browse

Imagine a user sitting at an Ethernet-connected PC. He has a browser open. He types "www.google.com" in the address bar and hits enter.
Now tell me what the first packet to appear on the Ethernet is.
I found this question here: Interview Questions on Socket Programming and Multi-Threading
As I'm not a networking expert, I'd like to hear the answer (I'd assume it is "It depends" ;) ).
With a tool like Wireshark, I can obviously check my own computers behaviour. I'd like to know whether the packets I see (e.g. ARP, DNS, VRRP) are the same in each ethernet configuration (is it dependent on the OS? the driver? the browser even :)?) and which are the conditions in which they appear. Being on the data-link layer, is it maybe even dependent on the physical network (connected to a hub/switch/router)?
The answers that talk about using ARP to find the DNS server are generally wrong.
In particular, IP address resolution for off-net IP addresses is never done using ARP, and it's not the router's responsibility to answer such an ARP query.
Off-net routing is done by the client machine knowing which IP addresses are on the local subnets to which it is connected. If the requested IP address is not local, then the client machine refers to its routing table to find out which gateway to send the packet to.
Hence in most circumstances the first packet sent out will be an ARP request to find the MAC address of the default gateway, if it's not already in the ARP cache.
Only then can it send the DNS query via the gateway. In this case the packet is sent with the DNS server's IP address in the IP destination field, but with the gateway's MAC address on the ethernet packet.
You can always download wireshark and take a look.
Though to spoil the fun.
Assuming, the IP address of the host is not cached, and the MAC address of the DNS server is not cached, the first thing that will be sent will be a broadcast ARP message trying to find out the MAC address of the DNS server (which the router will respond to with its own address).
Next, the host name will be resolved using DNS. Then the returned IP address will be resolved using ARP (again the router will respond with its own address), and finally, the HTTP message will actually be sent.
Actually, it depends on a variety of initial conditions you left unspecified.
Assuming the PC is running an operating system containing a local DNS caching resolver (mine does), the first thing that happens before any packets are sent is the cache is searched for an IP address. This is complicated, because "www.google.com" isn't a fully-qualified domain name, i.e. it's missing the trailing dot, so the DNS resolver will accept any records already in its cache that match its search domain list first. For example, if your search domain list is "example.com." followed by "yoyodyne.com." then cached resources matching the names "www.google.com.example.com." "www.google.com.yoyodyne.com." and finally "www.google.com." will be used if available. Also note: if the web browser is one of the more popular ones, and the PC is running a reasonably current operating system, and the host has at least one network interface with a global scope IPv6 address assigned (and the host is on a network where www.google.com has AAAA records in its DNS horizon), then the remote address of the server might be IPv6 not IPv4. This will be important later.
If the remote address of the Google web server was locally cached in DNS, and the ARP/ND6 cache contains an entry for the IPv4/IPv6 address (respectively) of a default router, then the first transmitted packet will be a TCP SYN packet sourced from the interface address attached to the router and destined for the cached remote IPv4/IPv6 address. Alternatively, the default router could be reachable over some kind of layer-2 or layer-3 tunnel, in which case, the SYN packet will be appropriately encapsulated.
If the remote address of the Google web server was not locally cached, then the host will first need to query for the A and/or AAAA records in the DNS domain search list in sequence until it gets a positive response. If the first DNS resolving server address in the resolver configuration is in one of the local IPv4 subnet ranges, or in a locally attached IPv6 prefix with the L=1 bit set in the router advertisement, and the ARP/ND6 cache already contains an entry for the address in question, then the first packet the host will send is a direct DNS query for either an A record or a AAAA record matching the first fully-qualified domain name in the domain search list. Alternatively, if the first DNS server is not addressable on-link, and a default router has an ARP/ND6 cache entry already, then the DNS query packet will be sent to the default router to forward to the DNS server.
In the event the local on-link DNS server or a default router (respectively, as the case above may be) has no entry in the ARP/ND6 cache, then the first packet the host will send is either an ARP request or an ICMP6 neighbor solicitation for the corresponding address.
Oh, but wait... it's even more horrible. There are tweaky weird edge cases where the first packet the host sends might be a LLMNR query, an IKE initiation, or... or... or... how much do you really care about all this, buckaroo?
It depends
Got that right. E.g. does the local DNS cache contain the address? If not then a DNS lookup is likely to be the first thing.
If the host name is not in DNS cache nor in hosts file, first packet will go to DNS.
Otherwise, the first packet will be HTTP GET.
Well, whatever you try to do, the first thing happening is some Ethernet protocol related data. Notably, Ethernet adapters have to decide whether the Ethernet bus is available (so there's some collision detection taking place here)
It's hard to answer your question because it depends a lot on the type of ethernet network you're using. More information on Ethernet transmission can be found here and here

Resources