PATCH: duplicate IP detection

Marc Merlin (marc_news@merlins.org)
Wed, 13 Oct 1999 18:11:17 -0700


Short Version:
Attached is a patch to passively detect duplicate IP conflicts. I sent it to
l-k two weeks ago and got feedback from Rogier Wolff who seemed to like it.
This patch has been tested with machines with multiple interfaces, and is
now being used at VA Linux Systems, and has been included in the standard VA
kernel.

When a conflict is detected, the kernel prints the following:
Uh Oh, MAC address 00:90:27:1D:5F:40 claims to have our IP addresses (10.1.0.142) (duplicate IP conflict likely)

----------------------------------------------------------------------------

Longer Version and discussion:
After wondering why linux doesn't detect when someone steals its IP, just
like Solaris, Irix, and windows to name only a few, do, I decided to write a
kernel patch to fix this.

What does the patch do?
It looks at all the broadcast ARP requests and checks that the source IP of
the request is different from the interface's IP. This will catch a machine
that is using your IP and is trying to talk to a machine on your net for the
first time or the first time since a while.

Why only the first time?
Once the first ARP request gets an answer, the MAC address is cached and at
least some versions of linux will freshen their cache by doing a directed
ARP request (not broadcast) to ask the remote machine if it's still using
that IP. You will not see those ARP requests as they are not broadcast.

But you could put the interface in promiscuous mode
You don't want to force people to turn on promiscuous mode on all their
interfaces. It will load up machines with interrupts, and make some buggy
NICs unhappy (among other things)

Is it correct that you will also miss a machine that has your IP on let's
say eth0:0, or that just put your IP with a different MAC address in its ARP
cache and is also answering ARP queries for your IP?
Yes

Why not send ARP queries with your IP?
That's what I originally thought about doing. I wanted to send an ARP query
for my IP each time I answered such a query, and make sure no one else
answered that query.
This would have been a big mistake however because it will create an ARP
loop between two machines using the same IP and the patch that would do that
extra ARP query. Rogier also pointed out to me that he didn't like the idea
of linux sending extra ARP packets when a passive solution exists.

So what else can you do?
Well, while the patch below will actually catch most of everyday conflicts,
an added security would be to have a small daemon that does an ARP query for
your IP every so often and makes sure there is no answer.
Because this can be implemented in user space, it shouldn't be in the kernel

----------------------------------------------------------------------------

Patch:
This is against 2.2.12.
I've looked at 2.3.21 and it needs a few simple modifications to apply
properly. While I don't run 2.3.x, if you tell me you'll include it, I can
fix the patch and find some machine to boot 2.3.x on to make sure the patch
still works.

----------------------------------------------------------------------------
diff -urN linux-2.2.12/net/ipv4/arp.c linux-arp/net/ipv4/arp.c
--- linux-2.2.12/net/ipv4/arp.c Mon Aug 9 12:04:41 1999
+++ linux-arp/net/ipv4/arp.c Tue Oct 12 09:26:57 1999
@@ -65,6 +65,7 @@
* clean up the APFDDI & gen. FDDI bits.
* Alexey Kuznetsov: new arp state machine;
* now it is in net/core/neighbour.c.
+ * Marc Merlin : Added duplicate IP detection (99/10/11)
*/

/* RFC1122 Status:
@@ -119,6 +120,9 @@
#include <asm/system.h>
#include <asm/uaccess.h>

+#define HBUFFERLEN 30
+
+
/*
* Interface to generic neighbour cache.
*/
@@ -606,7 +610,7 @@
#endif
}

- /* Undertsand only these message types */
+ /* Understand only these message types */

if (arp->ar_op != __constant_htons(ARPOP_REPLY) &&
arp->ar_op != __constant_htons(ARPOP_REQUEST))
@@ -654,6 +658,42 @@
goto out;
}

+ if (arp->ar_op == __constant_htons(ARPOP_REQUEST)) {
+ struct in_device *idev=dev->ip_ptr;
+ struct in_ifaddr *adlist=idev->ifa_list;
+
+ while (adlist != NULL)
+ {
+ if (adlist->ifa_address == sip) {
+ char hbuffer[HBUFFERLEN];
+ const char hexbuf[] = "0123456789ABCDEF";
+ int j,k;
+
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ if (hatype == ARPHRD_AX25 ||
+ hatype == ARPHRD_NETROM)
+ strcpy(hbuffer,ax2asc((ax25_address *)sha));
+ else {
+#endif
+ for (k=0,j=0;k<HBUFFERLEN-3 && j<dev->addr_len;j++) {
+ hbuffer[k++]=hexbuf[(sha[j]>>4)&15 ];
+ hbuffer[k++]=hexbuf[sha[j]&15 ];
+ hbuffer[k++]=':';
+ }
+ hbuffer[--k]=0;
+
+#if defined(CONFIG_AX25) || defined(CONFIG_AX25_MODULE)
+ }
+#endif
+
+ printk (KERN_WARNING "Uh Oh, MAC address %s claims to have our IP addresses (%s) (duplicate IP conflict likely)\n", hbuffer, in_ntoa(sip));
+ break;
+ }
+ adlist=adlist->ifa_next;
+ }
+ }
+
+
if (arp->ar_op == __constant_htons(ARPOP_REQUEST) &&
ip_route_input(skb, tip, sip, 0, dev) == 0) {

@@ -950,8 +990,6 @@
* Write the contents of the ARP cache to a PROCfs file.
*/
#ifdef CONFIG_PROC_FS
-
-#define HBUFFERLEN 30

int arp_get_info(char *buffer, char **start, off_t offset, int length, int dummy)
{
diff -urN linux-2.2.12/CREDITS linux-arp/CREDITS
--- linux-2.2.12/CREDITS Wed Aug 25 17:29:45 1999
+++ linux-arp/CREDITS Wed Oct 13 15:57:22 1999
@@ -1366,6 +1366,13 @@
S: 80220-320 Curitiba - Parana
S: Brazil

+N: Marc Merlin
+E: marcsoft@merlins.org
+D: Passive duplicate IP detection through ARP packet watching
+W: http://marc.merlins.org/
+P: 1024/763BE901 A1 9F 94 B7 78 01 E5 21 21 E0 F1 2E A2 85 E2 77
+S: Mountain View, California, USA
+
N: Michael Meskes
E: meskes@debian.org
P: 1024/04B6E8F5 6C 77 33 CA CC D6 22 03 AB AB 15 A3 AE AD 39 7D
----------------------------------------------------------------------------

-- 
Microsoft is to software what McDonalds is to gourmet cooking
 
Home page: http://marc.merlins.org/ (friendly to non IE browsers)
Finger marc_f@merlins.org for PGP key and other contact information

- 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/