Folks,

Any thoughts?

On 2/4/20 22:55, Fernando Gont wrote:
Folks/Hiroki,

I've implemented the upcoming revision of RFC4941 (https://tools.ietf.org/html/draft-ietf-6man-rfc4941bis-08) for FreeBSD.

The main changes are this:

* Reduce the Valid Lifetime from 1 week to 2 days. This effectively limits the number of concurrent temporary addresses per prefix to 2

* Use different interface-ids for each temporary address, to prevent correlation of network activity among temporary addresses corresponding to different prefixes.

P.S.: The patch is also available here: <https://www.gont.com.ar/code/fgont-patch-freebsd-rfc4941bis.txt>


---- cut here ----
diff --git sys/netinet6/in6_ifattach.c sys/netinet6/in6_ifattach.c
index 91ef544d8b2..c093b53974a 100644
--- sys/netinet6/in6_ifattach.c
+++ sys/netinet6/in6_ifattach.c
@@ -87,7 +87,6 @@ VNET_DECLARE(struct inpcbinfo, ripcbinfo);
  #define    V_ripcbinfo            VNET(ripcbinfo)

  static int get_rand_ifid(struct ifnet *, struct in6_addr *);
-static int generate_tmp_ifid(u_int8_t *, const u_int8_t *, u_int8_t *);
  static int get_ifid(struct ifnet *, struct ifnet *, struct in6_addr *);
  static int in6_ifattach_linklocal(struct ifnet *, struct ifnet *);
  static int in6_ifattach_loopback(struct ifnet *);
@@ -152,84 +151,6 @@ get_rand_ifid(struct ifnet *ifp, struct in6_addr *in6)
      return 0;
  }

-static int
-generate_tmp_ifid(u_int8_t *seed0, const u_int8_t *seed1, u_int8_t *ret)
-{
-    MD5_CTX ctxt;
-    u_int8_t seed[16], digest[16], nullbuf[8];
-    u_int32_t val32;
-
-    /* If there's no history, start with a random seed. */
-    bzero(nullbuf, sizeof(nullbuf));
-    if (bcmp(nullbuf, seed0, sizeof(nullbuf)) == 0) {
-        int i;
-
-        for (i = 0; i < 2; i++) {
-            val32 = arc4random();
-            bcopy(&val32, seed + sizeof(val32) * i, sizeof(val32));
-        }
-    } else
-        bcopy(seed0, seed, 8);
-
-    /* copy the right-most 64-bits of the given address */
-    /* XXX assumption on the size of IFID */
-    bcopy(seed1, &seed[8], 8);
-
-    if (0) {        /* for debugging purposes only */
-        int i;
-
-        printf("generate_tmp_ifid: new randomized ID from: ");
-        for (i = 0; i < 16; i++)
-            printf("%02x", seed[i]);
-        printf(" ");
-    }
-
-    /* generate 16 bytes of pseudo-random value. */
-    bzero(&ctxt, sizeof(ctxt));
-    MD5Init(&ctxt);
-    MD5Update(&ctxt, seed, sizeof(seed));
-    MD5Final(digest, &ctxt);
-
-    /*
-     * RFC 3041 3.2.1. (3)
-     * Take the left-most 64-bits of the MD5 digest and set bit 6 (the
-     * left-most bit is numbered 0) to zero.
-     */
-    bcopy(digest, ret, 8);
-    ret[0] &= ~EUI64_UBIT;
-
-    /*
-     * XXX: we'd like to ensure that the generated value is not zero
-     * for simplicity.  If the caclculated digest happens to be zero,
-     * use a random non-zero value as the last resort.
-     */
-    if (bcmp(nullbuf, ret, sizeof(nullbuf)) == 0) {
-        nd6log((LOG_INFO,
-            "generate_tmp_ifid: computed MD5 value is zero.\n"));
-
-        val32 = arc4random();
-        val32 = 1 + (val32 % (0xffffffff - 1));
-    }
-
-    /*
-     * RFC 3041 3.2.1. (4)
-     * Take the rightmost 64-bits of the MD5 digest and save them in
-     * stable storage as the history value to be used in the next
-     * iteration of the algorithm.
-     */
-    bcopy(&digest[8], seed0, 8);
-
-    if (0) {        /* for debugging purposes only */
-        int i;
-
-        printf("to: ");
-        for (i = 0; i < 16; i++)
-            printf("%02x", digest[i]);
-        printf("\n");
-    }
-
-    return 0;
-}

  /*
   * Get interface identifier for the specified interface.
@@ -798,58 +719,15 @@ in6_ifdetach_destroy(struct ifnet *ifp)
      _in6_ifdetach(ifp, 0);
  }

-int
-in6_get_tmpifid(struct ifnet *ifp, u_int8_t *retbuf,
-    const u_int8_t *baseid, int generate)
-{
-    u_int8_t nullbuf[8];
-    struct nd_ifinfo *ndi = ND_IFINFO(ifp);
-
-    bzero(nullbuf, sizeof(nullbuf));
-    if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) == 0) {
-        /* we've never created a random ID.  Create a new one. */
-        generate = 1;
-    }
-
-    if (generate) {
-        bcopy(baseid, ndi->randomseed1, sizeof(ndi->randomseed1));
-
-        /* generate_tmp_ifid will update seedn and buf */
-        (void)generate_tmp_ifid(ndi->randomseed0, ndi->randomseed1,
-            ndi->randomid);
-    }
-    bcopy(ndi->randomid, retbuf, 8);
-
-    return (0);
-}
-
  void
  in6_tmpaddrtimer(void *arg)
  {
      CURVNET_SET((struct vnet *) arg);
-    struct nd_ifinfo *ndi;
-    u_int8_t nullbuf[8];
-    struct ifnet *ifp;

      callout_reset(&V_in6_tmpaddrtimer_ch,
          (V_ip6_temp_preferred_lifetime - V_ip6_desync_factor -
          V_ip6_temp_regen_advance) * hz, in6_tmpaddrtimer, curvnet);

-    bzero(nullbuf, sizeof(nullbuf));
-    CK_STAILQ_FOREACH(ifp, &V_ifnet, if_link) {
-        if (ifp->if_afdata[AF_INET6] == NULL)
-            continue;
-        ndi = ND_IFINFO(ifp);
-        if (bcmp(ndi->randomid, nullbuf, sizeof(nullbuf)) != 0) {
-            /*
-             * We've been generating a random ID on this interface.
-             * Create a new one.
-             */
-            (void)generate_tmp_ifid(ndi->randomseed0,
-                ndi->randomseed1, ndi->randomid);
-        }
-    }
-
      CURVNET_RESTORE();
  }

diff --git sys/netinet6/in6_ifattach.h sys/netinet6/in6_ifattach.h
index 1e038fa8319..b9983200447 100644
--- sys/netinet6/in6_ifattach.h
+++ sys/netinet6/in6_ifattach.h
@@ -40,7 +40,6 @@ void in6_ifattach(struct ifnet *, struct ifnet *);
  void in6_ifattach_destroy(void);
  void in6_ifdetach(struct ifnet *);
  void in6_ifdetach_destroy(struct ifnet *);
-int in6_get_tmpifid(struct ifnet *, u_int8_t *, const u_int8_t *, int);
  void in6_tmpaddrtimer(void *);
  int in6_get_hw_ifid(struct ifnet *, struct in6_addr *);
  int in6_nigroup(struct ifnet *, const char *, int, struct in6_addr *);
diff --git sys/netinet6/nd6.h sys/netinet6/nd6.h
index 857657f6e20..c88f37288a2 100644
--- sys/netinet6/nd6.h
+++ sys/netinet6/nd6.h
@@ -185,7 +185,7 @@ struct    in6_ndifreq {
  #define RETRANS_TIMER            1000    /* msec */
  #define MIN_RANDOM_FACTOR        512    /* 1024 * 0.5 */
  #define MAX_RANDOM_FACTOR        1536    /* 1024 * 1.5 */
-#define DEF_TEMP_VALID_LIFETIME        604800    /* 1 week */
+#define DEF_TEMP_VALID_LIFETIME        172800    /* 2 days */
  #define DEF_TEMP_PREFERRED_LIFETIME    86400    /* 1 day */
  #define TEMPADDR_REGEN_ADVANCE        5    /* sec */
  #define MAX_TEMP_DESYNC_FACTOR        600    /* 10 min */
diff --git sys/netinet6/nd6_rtr.c sys/netinet6/nd6_rtr.c
index d678a53233e..179238257bb 100644
--- sys/netinet6/nd6_rtr.c
+++ sys/netinet6/nd6_rtr.c
@@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$");
  #include <sys/sysctl.h>
  #include <sys/syslog.h>
  #include <sys/queue.h>
+#include <sys/random.h>

  #include <net/if.h>
  #include <net/if_var.h>
@@ -77,6 +78,7 @@ static struct nd_defrouter *defrtrlist_update(struct nd_defrouter *);
  static int prelist_update(struct nd_prefixctl *, struct nd_defrouter *,
      struct mbuf *, int);
  static int nd6_prefix_onlink(struct nd_prefix *);
+static int in6_get_tmp_ifid(struct in6_aliasreq *);

  TAILQ_HEAD(nd6_drhead, nd_defrouter);
  VNET_DEFINE_STATIC(struct nd6_drhead, nd6_defrouter);
@@ -2248,6 +2250,51 @@ nd6_prefix_offlink(struct nd_prefix *pr)
      return (error);
  }

+/*
+ * Get a randomized interface identifier for a temporary address
+ * <draft-ietf-6man-rfc4941bis-08.txt>, Section 3.3.1.
+ */
+static int
+in6_get_tmp_ifid(struct in6_aliasreq *ifra)
+{
+    struct in6_addr *addr;
+
+    if(!is_random_seeded()){
+        return 1;
+    }
+
+    addr = &(ifra->ifra_addr.sin6_addr);
+regen:
+    ifra->ifra_addr.sin6_addr.s6_addr32[2] |=
+        (arc4random() & ~(ifra->ifra_prefixmask.sin6_addr.s6_addr32[2]));
+    ifra->ifra_addr.sin6_addr.s6_addr32[3] |=
+        (arc4random() & ~(ifra->ifra_prefixmask.sin6_addr.s6_addr32[3]));
+
+    /*
+     *  check if generated address is not inappropriate:
+     *
+     *  - Reserved IPv6 Interface Identifers
+     * (http://www.iana.org/assignments/ipv6-interface-ids/ipv6-interface-ids.xhtml)
+     */
+
+    /* Subnet-router anycast: 0000:0000:0000:0000 */
+    if (!(addr->s6_addr32[2] | addr->s6_addr32[3]))
+        goto regen;
+
+    /* IANA Ethernet block: 0200:5EFF:FE00:0000-0200:5EFF:FE00:5212
+       Proxy Mobile IPv6:   0200:5EFF:FE00:5213
+       IANA Ethernet block: 0200:5EFF:FE00:5214-0200:5EFF:FEFF:FFFF
+    */
+    if (ntohl(addr->s6_addr32[2]) == 0x02005eff && (ntohl(addr->s6_addr32[3]) & 0Xff000000) == 0xfe000000)
+        goto regen;
+
+    /* Reserved subnet anycast addresses */
+    if (ntohl(addr->s6_addr32[2]) == 0xfdffffff && ntohl(addr->s6_addr32[3]) >= 0Xffffff80)
+        goto regen;
+
+    return 0;
+}
+
  /*
   * ia0 - corresponding public address
   */
@@ -2260,7 +2307,6 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen, int delay)
      int error;
      int trylimit = 3;    /* XXX: adhoc value */
      int updateflags;
-    u_int32_t randid[2];
      time_t vltime0, pltime0;

      in6_prepare_ifra(&ifra, &ia0->ia_addr.sin6_addr,
@@ -2272,16 +2318,11 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen, int delay)
          &ifra.ifra_prefixmask.sin6_addr);

    again:
-    if (in6_get_tmpifid(ifp, (u_int8_t *)randid,
-        (const u_int8_t *)&ia0->ia_addr.sin6_addr.s6_addr[8], forcegen)) {
+    if (in6_get_tmp_ifid(&ifra) != 0) {
          nd6log((LOG_NOTICE, "%s: failed to find a good random IFID\n",
              __func__));
          return (EINVAL);
      }
-    ifra.ifra_addr.sin6_addr.s6_addr32[2] |=
-        (randid[0] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[2]));
-    ifra.ifra_addr.sin6_addr.s6_addr32[3] |=
-        (randid[1] & ~(ifra.ifra_prefixmask.sin6_addr.s6_addr32[3]));

      /*
       * in6_get_tmpifid() quite likely provided a unique interface ID.
@@ -2289,7 +2330,6 @@ in6_tmpifadd(const struct in6_ifaddr *ia0, int forcegen, int delay)       * there may be a time lag between generation of the ID and generation
       * of the address.  So, we'll do one more sanity check.
       */
-
      if (in6_localip(&ifra.ifra_addr.sin6_addr) != 0) {
          if (trylimit-- > 0) {
              forcegen = 1;
---- cut here ----


Thanks!

Cheers,


--
Fernando Gont
e-mail: ferna...@gont.com.ar || fg...@si6networks.com
PGP Fingerprint: 7809 84F5 322E 45C7 F1C9 3945 96EE A9EF D076 FFF1



_______________________________________________
freebsd-net@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscr...@freebsd.org"

Reply via email to