From owner-freebsd-net@freebsd.org Mon Apr 6 16:38:16 2020 Return-Path: Delivered-To: freebsd-net@mailman.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.nyi.freebsd.org (Postfix) with ESMTP id F32422B49AE for ; Mon, 6 Apr 2020 16:38:16 +0000 (UTC) (envelope-from fernando@gont.com.ar) Received: from fgont.go6lab.si (fgont.go6lab.si [91.239.96.14]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 48wx6v4Qgfz4H8W for ; Mon, 6 Apr 2020 16:38:14 +0000 (UTC) (envelope-from fernando@gont.com.ar) Received: from [192.168.0.10] (unknown [181.45.84.85]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by fgont.go6lab.si (Postfix) with ESMTPSA id BAEC1805BE; Mon, 6 Apr 2020 18:38:11 +0200 (CEST) Subject: Re: [PATCH] Implement the upcoming RFC4941bis (IPv6 SLAAC temporary addresses/privacy extensions) To: FreeBSD Net References: <93726ba6-6d96-2b45-81c5-6fd8a83f95a9@gont.com.ar> From: Fernando Gont Message-ID: Date: Mon, 6 Apr 2020 13:09:19 -0300 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.9.1 MIME-Version: 1.0 In-Reply-To: <93726ba6-6d96-2b45-81c5-6fd8a83f95a9@gont.com.ar> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 8bit X-Rspamd-Queue-Id: 48wx6v4Qgfz4H8W X-Spamd-Bar: ----- Authentication-Results: mx1.freebsd.org; dkim=none; dmarc=none; spf=pass (mx1.freebsd.org: domain of fernando@gont.com.ar designates 91.239.96.14 as permitted sender) smtp.mailfrom=fernando@gont.com.ar X-Spamd-Result: default: False [-5.81 / 15.00]; ARC_NA(0.00)[]; RCVD_VIA_SMTP_AUTH(0.00)[]; NEURAL_HAM_MEDIUM(-0.99)[-0.993,0]; FROM_HAS_DN(0.00)[]; R_SPF_ALLOW(-0.20)[+a]; TO_MATCH_ENVRCPT_ALL(0.00)[]; MIME_GOOD(-0.10)[text/plain]; DMARC_NA(0.00)[gont.com.ar]; NEURAL_HAM_LONG(-1.00)[-1.000,0]; RCPT_COUNT_ONE(0.00)[1]; IP_SCORE(-3.52)[ip: (-9.31), ipnet: 91.239.96.0/23(-4.65), asn: 198644(-3.63), country: SI(0.01)]; TO_DN_ALL(0.00)[]; RCVD_IN_DNSWL_NONE(0.00)[14.96.239.91.list.dnswl.org : 127.0.10.0]; FROM_EQ_ENVFROM(0.00)[]; R_DKIM_NA(0.00)[]; MIME_TRACE(0.00)[0:+]; ASN(0.00)[asn:198644, ipnet:91.239.96.0/23, country:SI]; MID_RHS_MATCH_FROM(0.00)[]; RCVD_TLS_ALL(0.00)[]; RCVD_COUNT_TWO(0.00)[2] X-BeenThere: freebsd-net@freebsd.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Networking and TCP/IP with FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 06 Apr 2020 16:38:17 -0000 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: > > > > ---- 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 >  #include >  #include > +#include > >  #include >  #include > @@ -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 > + * , 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: fernando@gont.com.ar || fgont@si6networks.com PGP Fingerprint: 7809 84F5 322E 45C7 F1C9 3945 96EE A9EF D076 FFF1