[Dnsmasq-discuss] dnsmasq & fingerbank.org

Denton Gentry denny at geekhold.com
Sun Apr 9 19:22:53 BST 2017


https://fingerbank.org/about.html is a database of OS signatures based
on the DHCP options populated and the order in which they appear. So
for example, an Android device will typically send
'1,33,3,6,15,26,28,51,58,59' while iOS sends '1,3,6,15,119,252'.

We modified dnsmasq to export DHCP OS signatures to a
DNSMASQ_REQUESTED_OPTIONS environment variable when it forks the
dhcp-script. The environment variable is formatted to match
fingerbank. The dhcp-script we run writes the signature to a separate
file, though of course this behavior is outside of dnsmasq itself.

Is OS fingerprinting support something which could be more widely useful?
Should I rebase the patch to the current tree and start discussion?
-------------- next part --------------
Allows fingerprinting of DHCP clients in the external
dhcp-script.
---
 src/dhcp-protocol.h |  3 ++-
 src/dnsmasq.h       |  1 +
 src/helper.c        | 19 +++++++++++++++++++
 src/lease.c         |  1 +
 src/rfc2131.c       | 11 +++++++++++
 5 files changed, 34 insertions(+), 1 deletion(-)
diff --git a/src/dhcp-protocol.h b/src/dhcp-protocol.h
index a2750de..7e3c845 100644
--- a/src/dhcp-protocol.h
+++ b/src/dhcp-protocol.h
@@ -85,6 +85,7 @@
 #define BRDBAND_FORUM_IANA       3561 /* Broadband forum IANA enterprise */
 
 #define DHCP_CHADDR_MAX 16
+#define DHCP_OPT_MAX    312
 
 struct dhcp_packet {
   u8 op, htype, hlen, hops;
@@ -92,5 +93,5 @@ struct dhcp_packet {
   u16 secs, flags;
   struct in_addr ciaddr, yiaddr, siaddr, giaddr;
   u8 chaddr[DHCP_CHADDR_MAX], sname[64], file[128];
-  u8 options[312];
+  u8 options[DHCP_OPT_MAX];
 };
diff --git a/src/dnsmasq.h b/src/dnsmasq.h
index 4d368c5..3beaba7 100644
--- a/src/dnsmasq.h
+++ b/src/dnsmasq.h
@@ -563,6 +563,7 @@ struct dhcp_lease {
   } *slaac_address;
   int vendorclass_count;
 #endif
+  unsigned char req_options[DHCP_OPT_MAX];
   struct dhcp_lease *next;
 };
 
diff --git a/src/helper.c b/src/helper.c
index 24c2afd..95aa657 100644
--- a/src/helper.c
+++ b/src/helper.c
@@ -72,6 +72,7 @@ struct script_data
 #endif
   unsigned char hwaddr[DHCP_CHADDR_MAX];
   char interface[IF_NAMESIZE];
+  unsigned char req_options[DHCP_OPT_MAX];
 };
 
 static struct script_data *buf = NULL;
@@ -499,6 +500,23 @@ int create_helper(int event_fd, int err_fd, uid_t uid, gid_t gid, long max_fd)
 	  
 	  my_setenv("DNSMASQ_DOMAIN", domain, &err);
 	  
+	  {
+	    unsigned char *p;
+	    char strbuf[4096] = {0};
+	    for (p = data.req_options; *p != OPTION_END; p++)
+	      {
+	        char d[16];
+	        if (p != data.req_options) strcat(strbuf, ",");
+	        snprintf(d, sizeof(d), "%u", *p);
+	        if ((strlen(strbuf) + strlen(d) + 3) > sizeof(strbuf)) {
+	          break;
+	        }
+	        strcat(strbuf, d);
+	      }
+
+	    my_setenv("DNSMASQ_REQUESTED_OPTIONS", strbuf, &err);
+	  }
+
 	  end = extradata + data.ed_len;
 	  buf = extradata;
 	  
@@ -698,6 +716,7 @@ void queue_script(int action, struct dhcp_lease *lease, char *hostname, time_t n
   memcpy(buf->hwaddr, lease->hwaddr, DHCP_CHADDR_MAX);
   if (!indextoname(fd, lease->last_interface, buf->interface))
     buf->interface[0] = 0;
+  memcpy(buf->req_options, lease->req_options, sizeof(buf->req_options));
   
 #ifdef HAVE_BROKEN_RTC 
   buf->length = lease->length;
diff --git a/src/lease.c b/src/lease.c
index 4b4d10a..e0329da 100644
--- a/src/lease.c
+++ b/src/lease.c
@@ -703,6 +703,7 @@ static struct dhcp_lease *lease_allocate(void)
   lease->length = 0xffffffff; /* illegal value */
 #endif
   lease->hwaddr_len = 256; /* illegal value */
+  lease->req_options[0] = OPTION_END;
   lease->next = leases;
   leases = lease;
   
diff --git a/src/rfc2131.c b/src/rfc2131.c
index a49e076..4a35356 100644
--- a/src/rfc2131.c
+++ b/src/rfc2131.c
@@ -1255,6 +1255,16 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
 		  if (mess->giaddr.s_addr)
 		    lease->giaddr = mess->giaddr;
 		  
+		  if ((opt = option_find(mess, sz, OPTION_REQUESTED_OPTIONS, 0)))
+		    {
+		      int len = sizeof(lease->req_options);
+		      if (option_len(opt) < len) {
+		        len = option_len(opt);
+		      }
+		      memcpy(lease->req_options, option_ptr(opt, 0), len);
+		      lease->req_options[len] = OPTION_END;
+		    }
+
 		  free(lease->extradata);
 		  lease->extradata = NULL;
 		  lease->extradata_size = lease->extradata_len = 0;
@@ -1302,6 +1312,7 @@ size_t dhcp_reply(struct dhcp_context *context, char *iface_name, int int_index,
 			ucp++, len--;
 		      lease_add_extradata(lease, ucp, len, 0);
 		    }
+		  
 		}
 #endif
 	    }
-- 
1.9.0.rc1.175.g0b1dcb5


More information about the Dnsmasq-discuss mailing list