PATCH: detect IP conflicts from ARP packets

Marc Merlin (marc_news@merlins.org)
Sat, 2 Oct 1999 01:32:11 -0700


On ven, oct 01, 1999 at 09:29:53 +0200, Rogier Wolff wrote:
> Peter Benie wrote:
> > Marc Merlin writes ("Re: Why no printk for duplicate IPs?"):
> > > On mer, sep 29, 1999 at 11:47:29 +0100, Alan Cox wrote:
> > > > > So, is it correct that for IPv4, linux won't report the fact that
> > > > > another machine is answering ARP requests for one of its IPs?
> > > > ARP Replies are unicast
> > >
> > > good point.
> > >
> > > However, at least Solaris, Irix and 95/NT give you a warning when
> > > someone steals your IP (at runtime, not ifconfig time). I suppose
> > > they do an ARP request on their own IP after answering an ARP request
> > > themselves, and watch for an answer.
> > >
> > > Any reason we can't do that?
> >
> > An alternative approach is to log when we receive a broadcast IP from an
> > external interface which is apparently from one of our own addresses.
>
> Yes, THAT's it.
>
> You use the ARP REQUESTS of the double to detect that it's using your
> IP. That's the "runtime" check.

I hadn't considered this initially. It does have the advantage of being
"stealth". I wrote up an initial patch for it (against 2.2.12, but I'm
guessing it should easily apply to other kernels), but I intentionally
didn't put the dots on the i yet, because I do not believe this approach is
enough.

The problems here are that:

1) If you plug your network onto an active network, if someone is already
using your IP, you won't necessarly notice.
The reason is that if host A (linux) knows the MAC address of host B, it
will send arp queries about B's mac address from time to time, but those
ARP queries aren't broadcast, they're sent directly to B's MAC address.
This means that if you plug your laptop C into the net, and if A happens
to be using your IP, you will never know because A sends its ARP packets
directly to B.

2) A host can have your IP for its eth0:0, or it can have it as a public
entry in its ARP table, but yet you will never know by just watching ARP
traffic, until you send an ARP packet yourself, ask if anyone knows what
MAC address is linked to your IP, and and make sure the MAC you get back
is indeed yours.
The way you do this is you wait for someone to ask for your MAC address,
and when you answer, you send a ARP request yourself, also asking for
your IP, and watch the answers.

Dave, Alan, do you agree with this? Would you accept a patch that sends an
ARP query when just having answered one (and I can make this a user
configurable option), or would you simply prefer a cleaned up version of the
patch below (initial version that just assumes you're sitting on ethernet
(and that therefore the MAC address is 6 bytes long))?

--- linux.orig/net/ipv4/arp.c Mon Aug 9 12:04:41 1999
+++ linux/net/ipv4/arp.c Sat Oct 2 00:54:36 1999
@@ -654,6 +654,30 @@
goto out;
}

+ if (arp->ar_op == __constant_htons(ARPOP_REQUEST))
+ {
+ struct in_device *idev=dev->ip_ptr;
+ struct in_ifaddr *adlist=idev->ifa_list;
+
+ // printk("Got arp request %.8X (%.4X%.8X) -> %.8X\n", be32_to_cpu(sip), be16_to_cpu(*hadb16), be32_to_cpu(*hade32), be32_to_cpu(tip));
+
+ while (adlist != NULL)
+ {
+ if (adlist->ifa_address == sip) {
+ u16 *hadb16;
+ u32 *hade32;
+
+ hadb16 = (u16 *)sha;
+ hade32 = (u32 *)(sha+2);
+
+ printk (KERN_WARNING "Uh Oh, MAC address %.4X%.8X claims to have our IP %.8X\n(duplicate IP conflict likely)\n", be16_to_cpu(*hadb16), be32_to_cpu(*hade32), be32_to_cpu(sip));
+ break;
+ }
+ adlist=adlist->ifa_next;
+ }
+ }
+
+
if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
ip_route_input(skb, tip, sip, 0, dev) == 0) {

> As I was the original one to suggest doing the gratuitous ARP in the
> first place, and people have convinced me that not ifconfiging the
> interface is NOT a good idea, I've done some more thinking:

Actually I suggested that the kernel do this, and you suggested that
ifconfig do this :-)

While it doesn't hurt to have ifconfig put a warning message if someone else
claims to use the IP that you're ifconfiging up, it really doesn't help for
networks where laptops come and go, and machines are turned on and off.

Several other TCP/IP stacks already actively check while they're running
that no one is using their IP, and I believe we should do the same (although
I'll make that a configurable option in the patch)

As for what you do when you see the conflict, I do not intend to do anything
more than printk KERN_WARNING, as taking the interface down would be
yielding to the person who's stealing your IP. I much prefer getting their
MAC address, have my machine try to continue communications, and track the
rogue user with a LART (aka baseball bat :-D)

Marc

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.rutgers.edu
Please read the FAQ at http://www.tux.org/lkml/