IPv6 Netowrk Device Numbering BP

We're working out our dual stacked IPv4-IPv6 network. One
issue that recently has arisen is how to number the management
interfaces on the network devices themselves.

I have always been kind of partial to the idea of taking advantage
IPv6 features and letting hosts set their own addresses with EUI-64
interface numbers. For the management interface on a network device,
it's more like a "normal" host. I'd just as well tell the device its
prefix, and let it build the address itself. For IPv6, my opinion is
that I'm not even going to try to remember 128-bit addresses. It's
not something reasonable to expect humans to do. I'm going to depend
on some name-to-number service (DNS or a hosts file), and as far as
a computer goes, 2001:db8::80:abff:fe45:6789 is just as easy to
remember as, 2001:db8::12:34.

The other approach is to assign addresses. To me, that's more of
a hold over from IPv4 thinking, but there are legitimate reasons
I can think of. It's nice to have the IPv6 address tied to the
configuration rather than the hardware. If you need to drop in
a replacement device, you copy the configuration and no addresses
change. But OTOH, others might consider it a feature that the IP
follows the device rather than the role. And the real reason I think
people want to do it is that they want to be able to memorize IP
addresses of "important" hosts like these.

Another option would be to do both. Assign a fixed address and also
let it chose EUI-64. However, I see that leading to confusion. Not
sure what good it would do.

Is there anything like a standard, best practice for this (yet)?
What are other people doing and their reasons? Anyone have operational
experience with what works and what does not (and the "what does
not" is probably really of more interest)?

We're working out our dual stacked IPv4-IPv6 network. One
issue that recently has arisen is how to number the management
interfaces on the network devices themselves.
[...]
Is there anything like a standard, best practice for this (yet)?

Yes and no. It's only best practice when enough people have done it, and
enough people have done *different, bad* things, for the practice to
emerge as, in general, best. I don't think enough people have done
either of those things. There are documents floating about that
purporting to describe best practice; I've never read one I really
agreed with - in particular they have a tendency to recommend
overloading address bits with non-address information.

So I think you should listen to lots of people then go about making your
own educated decisions, and thus become part of the adventure of
creating best practice. Either by being a beacon of wonderfulness to us
all, or by crashing and burning so that we can say, in hushed voices as
we pass by where you and your network used to be, "don't do that :slight_smile:

What are other people doing and their reasons? Anyone have operational
experience with what works and what does not (and the "what does
not" is probably really of more interest)?

I espouse four principles (there are others, but these are the biggies):

- don't overload address bits with non-addressing information
- keep the network as flat as reasonably possible
- avoid tying topology to geography
- avoid exceptions

The first can be completely avoided and should be an ironcast rule IMHO.
Aggregation requirements will mean the third is always broken
eventually, and Murphy's Law will break the fourth. However, by
following each rule as far as possible and delaying the point where it
must be broken, you will end up with a more flexible, future-proof,
error-proof, extensible address plan.

I too would be really interested in whatever wisdom others have
developed, even if (especially if!) it doesn't agree with mine.

Regards, K.

We're working out our dual stacked IPv4-IPv6 network. One
issue that recently has arisen is how to number the management
interfaces on the network devices themselves.

I have always been kind of partial to the idea of taking advantage
IPv6 features and letting hosts set their own addresses with EUI-64
interface numbers. For the management interface on a network device,
it's more like a "normal" host. I'd just as well tell the device its
prefix, and let it build the address itself. For IPv6, my opinion is
that I'm not even going to try to remember 128-bit addresses. It's
not something reasonable to expect humans to do. I'm going to depend
on some name-to-number service (DNS or a hosts file), and as far as
a computer goes, 2001:db8::80:abff:fe45:6789 is just as easy to
remember as, 2001:db8::12:34.

The other approach is to assign addresses. To me, that's more of
a hold over from IPv4 thinking, but there are legitimate reasons
I can think of. It's nice to have the IPv6 address tied to the
configuration rather than the hardware. If you need to drop in
a replacement device, you copy the configuration and no addresses
change. But OTOH, others might consider it a feature that the IP
follows the device rather than the role. And the real reason I think
people want to do it is that they want to be able to memorize IP
addresses of "important" hosts like these.

For simplicity and a wish to keep a mapping to our IPv4 addresses,
each device (router/server/firewall) has a static IPv6 address that
has the same last digits as the IPv4 address, only the subnet is
changed.
You can say it's a IPv4 thinking model, but it's easier to remember
that if the fileserver it's at 192.168.10.10 then it's IPv6
counterpart address would be 2001:abcd::192:168:10:10 (each subnet
being a /64)

Another option would be to do both. Assign a fixed address and also
let it chose EUI-64. However, I see that leading to confusion. Not
sure what good it would do.

Is there anything like a standard, best practice for this (yet)?
What are other people doing and their reasons? Anyone have operational
experience with what works and what does not (and the "what does
not" is probably really of more interest)?

Letting the host choose it's own IP can be very tricky and has
operational hurdles along the way as it's not that easy to copy
configurations across devices during upgrades and maintenance swap
outs.

Eugeniu Patrascu wrote:

You can say it's a IPv4 thinking model, but it's easier to remember
that if the fileserver it's at 192.168.10.10 then it's IPv6
counterpart address would be 2001:abcd::192:168:10:10 (each subnet
being a /64)

That is a clever idea except that it can not always follow
modified EUI-64 format aof rfc4291.

We should better introduce partially decimal format for
IPv6 addresses or, better, avoid IPv6 entirely.

            Masataka Ohta

Though 2001:abcd::192:168:10:10 was written in a format with both :
and . , I think would could take the concept mentioned above and
extend it either by making it
2001:abcd::C0:A8:0A:0A
or
2001:abcd::C0A8:0A0A

Doing the latter wastes less space and let's the host use the upper
32bits of the host portion for vhosts.
Ex: 2001:abcd::1:C0A8:0A0A

Should be easy enough as something like pxelinux already squishes your
v4 address down to do file searching on tftp servers.
Ex: /mybootdir/pxelinux.cfg/C000025B for 192.0.2.91

I personally have for this "use the last 32bits of the v6 address for
the v4 dual stack address" trick and was happy with it. Still fits
with the concept of "give each host a /64"

No we shouldn't. Text representations of IPv6 addresses are already a
complete pain to parse. We don't need to add to this pain by adding a new
format which gains us nothing in particular over existing schemas such as
that suggested by Eugeniu.

Nick

In article <xs4all.CALgc3C7ngGpkRNYaCgN_ACY28uPFbM=KRnACsW0Jg=YsLuQHhQ@mail.gmail.com> you write:

For simplicity and a wish to keep a mapping to our IPv4 addresses,
each device (router/server/firewall) has a static IPv6 address that
has the same last digits as the IPv4 address, only the subnet is
changed.
You can say it's a IPv4 thinking model, but it's easier to remember
that if the fileserver it's at 192.168.10.10 then it's IPv6
counterpart address would be 2001:abcd::192:168:10:10 (each subnet
being a /64)

We use a /120 subnet for servers to prevent the NDP cache exhaustion
attack. We do maintain a mapping between IPv4 and IPv6 addresses;
it's simply 2001:db8:vv:ww::xx, where xx is the hex value of the
last octet of the IPv4 address.

Mike.

I agree with you that we shouldn't introduce partially decimal format, but I
don't see why you say IPv6 addresses are difficult to parse.

1. Tokenize (on : boundaries).
2. If n(tokens) < 8, expand null token to 9-n tokens.
  (result 8 total tokens).
3. Parse tokens left to right as 16 bit hex numbers, such that accumulator a accumulates each token t
  as follows:

  a<<=16
  a |= t

The only exceptions to this parsing would be if someone handed you a textual representation of
an IPv4 mapped address (::ffff:192.0.2.50), which essentially represents the partial decimal format
Masataka is requesting.

You really shouldn't need to parse these and it's perfectly valid to reject them as invalid input.
This really is an output only format to describe an IPv4 connection being mapped to an IPv6
socket with IPV6_V6ONLY=false in the socket options. These addresses should never appear
on the wire. Internally, the software sees them as any other 128 bit integer and only the
UI presentation of these numbers for display should ever use that format.

That format is used as a convenience for user display because it allows the user to readily
identify the IPv4 address of the connection rather than having to convert the hex to decimal
to know what host is involved.

Finally, at this point, if you're feeling like you have to write your own IP address parser,
you're probably doing something wrong. PLEASE PLEASE PLEASE use the standard
libraries whenever possible. inet_pton, getaddrinfo, etc. if you are using C. In PERL,
you have these, plus Net::IP as well which provides extensive IP address parsing and
manipulation capabilities.

There are similar library functions for virtually every other language at this point as well.

Owen

Hi Owen,

You really shouldn't need to parse these and it's perfectly valid to reject them as invalid input. This really is an output only format [...]

I don't agree. I think it's actually the other way around. It's a valid representation of an IPv6 address so you be able to parse them. You don't need to be able to output them though.

Finally, at this point, if you're feeling like you have to write your own IP address parser, you're probably doing something wrong. PLEASE PLEASE PLEASE use the standard
libraries whenever possible.

Definitely +1 here!
Sander

The active advice from the IETF on this topic would seem to be RFC 5952 as updated by RFC 5952.

RFC 5952 specifies (in section 5) that the least-significant 32 bits MAY be written in dotted-quad notation if "it is known by some external method that a given prefix is used to embed IPv4". People who make use of a general-purpose v6 addressing plans which incorporate mapped v4 addresses in the lower 32 bits fit clearly into this category, I would think. 5952 is silent on the distinction between parsing such addresses and using them in output.

I don't see any justification in the standards for rejecting v4-mapped addresses on input. For what that's worth.

I agree that this adds a step to input validation, and that using standard libraries for this stuff is a good idea.

Joe

On 01-Nov-2012, Owen DeLong <owen@delong.com> sent:

The only exceptions to this parsing would be if someone handed
you a textual representation of an IPv4 mapped address
(::ffff:192.0.2.50), which essentially represents the partial
decimal format Masataka is requesting.

I might be missing something here, but isn't that format already
valid for any IPv6 address, not just the special v4-in-v6
representation?

import socket
p = '2001:abcd::192.16.10.10'
n = socket.inet_pton(socket.AF_INET6, p)
socket.inet_ntop(socket.AF_INET6, n)

'2001:abcd::c010:a0a'

Or is the issue just the ntop part not giving you back the
decimalized string?

ooh.. that's a clever approach I hadn't seen before. Who should we credit
for this one?

That's not a problem and I certainly wouldn't expect it to do so.

I guess the silly notation is more widely supported than I thought, but, IMHO, it's a kind of poor choice of syntax outside of the limited use of displaying IPv4-mapped addresses for dual-stack socket connections displaying IPv4 connections in IPv6 format.

Owen

/120 works well until you get > 99 (if you want the decimal
representations of addresses to look the same)... or if your techs
understand hex.

10.0.0.123 <-> 2001:db8:vv:ww::7b

I have used /116 in the past. This gives you 1-fff at the end.

10.0.0.123 <-> 2001:db8:vv:ww::123

Hopefully, this is future proof(ish) in that IPv6 only hosts (...when
that happens...) on the same subnet can use
2001:db8:vv:ww::[a-f][0-f][0-f] without danger of collisions with
IPv4/IPv6 hosts.

- -DMM

There are better ways to avoid neighbor exhaustion attacks unless you have attackers
inside your network.

If you have attackers inside your network, you probably have bigger problems than
neighbor table attacks anyway, but that's a different issue.

Even if you're going to do something silly like use /120s on interfaces, I highly
recommend going ahead and reserving the enclosing /64 so that when you discover
/120 wasn't the best idea, you can easily retrofit.

Owen

In article <xs4all.963E27C7-A0C5-44AC-86AF-33E6286C9BC1@delong.com> you write:

There are better ways to avoid neighbor exhaustion attacks unless you
have attackers
inside your network.

You mean filtering. I haven't tried it recently, but a while ago
I put an output filter on a Juniper router that allowed just
the lower /120 out of a /64 on an interface. What happened was that
neighbor discovery happened /before/ filtering. I should probably
test that against recent JunOS releases, but that was a firm
reason to go with a /120 instead of a filter. Besides, configuring
a /120 is way less work than a filter per interface (yes we
do have per-interface filters but they're kind of generic).

Even if you're going to do something silly like use /120s on interfaces,
I highly
recommend going ahead and reserving the enclosing /64 so that when you discover
/120 wasn't the best idea, you can easily retrofit.

Sure, we do that, as soon as router vendors solve the NDP CE attack
problem we'll go back to /64s.

Mike.

I agree with you that we shouldn't introduce partially decimal format,

but I

don't see why you say IPv6 addresses are difficult to parse.

They are not simple to parse, but not particularly difficult either.

1. Tokenize (on : boundaries).
2. If n(tokens) < 8, expand null token to 9-n tokens.

It's a bit harder than that. You need to deal with the positioning of
the "::", which may be at the beginning or end. Scope identifiers need
to be handled. On output, you need to handle the requirements of RFC
5952.

You really shouldn't need to parse [mapped addresses] and it's

perfectly valid

to reject them as invalid input.

No, it's not OK to reject them. You can't just say they are invalid,
they are not.

Finally, at this point, if you're feeling like you have to write your

own IP address parser,

you're probably doing something wrong. PLEASE PLEASE PLEASE use the

standard

libraries whenever possible.

Definitely oh very yes! That said, I have had to write my own three
times now, because of errors or inadequacies in the existing parsers,
and I can confidently say it is slightly tricky, but not hard. The key,
the essential and vital thing, is to unit test that sucker until it is
gasping and limp.

There are similar library functions for virtually every other language

at this point as well.

Java's is broken, for a start. I have had to replace it for literals,
because it doesn't compress for output, and because it treats a mapped
IPv4 address as an IPv4 address! It's also hard to do some operations on
InetAddress objects. I still use InetAddress where actual names are
concerned, so as not to duplicate the Java DNS functionality.
Unfortunately Java appears to not properly prefer IPv6 addresses. There
is allegedly a system property to control that, but it is either
documented incorrectly or just doesn't work.

Regards, K.

I have always been kind of partial to the idea of taking advantage
IPv6 features and letting hosts set their own addresses with EUI-64
interface numbers.

That's all fine and dandy until the NIC card is swapped out for a new one. It's best to use fixed IPv6 addresses for services (and have the service bind() to those) and use the EUI-64 address for machine-related tasks (ssh, backups, etc). You can use the same EUI-64 network for both, as the EUI-64 space is sparse and there are lots of "never will be autoconfed" address, conveniently including those with lots of zeroes. The router(s) interface addresses should be hardcoded within that EUI-64 subnet, and …::1/64, …::2/64 are the obvious choices.

There's an issue of address exhaustion is you use /64 for router-router links, and the best suggestion I've seen there is to use /126, as that makes the last octet consistently …1 or …2 for each end of a point-to-point link, which is operationally nicer than stuffing about with binary in your head to determine which address to ping (i.e., you take your interface's address and replace the last hexnumeral with 1 or 2 to get your neighbours address).

The exception to router link addressing would be links with eBGP neighbours, where using the ASN of the networks is just so convenient.

You don't care much for correspondence between IPv4 and IPv6 addresses, except in the case of router loopback interfaces where it is very operationally convenient to be able to mentally determine "is this the same router which I just saw in IPv4". Since you'll be typing those most often they are the obvious candidate for "subnet zero" so that "::" reduces the typing to the minimum. The obvious thing to do is to reserve the entire …:00:00:00:00::/64 and use the bottom N bits of that to match the binary IPv4 address of the loopback. N could be 32 bits if you like excessive typing or have a really big network.

I've seen a few schemes which try to decimal numerals of the IPv4 address in the IPv6 address, but I don't find any of them compelling. If you really, really think you want that, then putting the top 16b in hex numerals and the lower 16b in decimal numerals will do what you want without excessive address consumption. This sounds difficult to use, but operationally you soon get used to the hex prefix and only notice when it isn't one of the common ones.

In article <xs4all.963E27C7-A0C5-44AC-86AF-33E6286C9BC1@delong.com> you write:

There are better ways to avoid neighbor exhaustion attacks unless you
have attackers
inside your network.

You mean filtering. I haven't tried it recently, but a while ago
I put an output filter on a Juniper router that allowed just
the lower /120 out of a /64 on an interface. What happened was that
neighbor discovery happened /before/ filtering. I should probably
test that against recent JunOS releases, but that was a firm
reason to go with a /120 instead of a filter. Besides, configuring
a /120 is way less work than a filter per interface (yes we
do have per-interface filters but they're kind of generic).

I mean assign your point to points from a particular /48 within your /32 or
a particular /56 within your /48 or whatever is appropriate to your situation.

Then, at your borders, filter that entire /48 or /56 or whatever it is so that
people outside simply aren't allowed to send packets to your point to point links
at all.

Even if you're going to do something silly like use /120s on interfaces,
I highly
recommend going ahead and reserving the enclosing /64 so that when you discover
/120 wasn't the best idea, you can easily retrofit.

Sure, we do that, as soon as router vendors solve the NDP CE attack
problem we'll go back to /64s.

FWIW, the NDP CE attack doesn't yield much in the way of incentives to most
attackers. As a DOS, it only prevents new nodes from joining the networks
attached to the router and they can generally only attack the NC of the
upstream router closer to them on each link, not the more distant one.

Since core routers tend to have pretty stable neighbor relations, the
actual attack surface in the real world is relatively small and there are
far more effective DOS vectors available.

Nonetheless, defense in depth is the right approach, but, do it in the
way that requires the least maintenance effort on your part. Filtering
an entire range of P2P links at the borders is about as low maintenance
as it gets. (Again, this is assuming you don't have to deal with
attackers inside your borders).

If you are a university, things get more complicated because your job
is to have attackers (or at least potential attackers) inside your
borders.

If you're not a university, then if you have attackers inside your
borders, you probably have bigger problems than NDP CE.

Owen

I agree with you that we shouldn't introduce partially decimal format,

but I

don't see why you say IPv6 addresses are difficult to parse.

They are not simple to parse, but not particularly difficult either.

1. Tokenize (on : boundaries).
2. If n(tokens) < 8, expand null token to 9-n tokens.

It's a bit harder than that. You need to deal with the positioning of
the "::", which may be at the beginning or end. Scope identifiers need
to be handled. On output, you need to handle the requirements of RFC
5952.

Expanding the :: assumed expanding it in place. That's all you need to
do to deal with the positioning of it. It can occur anywhere, not just
at the beginning or end, as in 2620:0:930::200:2 which is, btw, also
equivalent to 2620::930:0:0:0:200:2.

You really shouldn't need to parse [mapped addresses] and it's

perfectly valid

to reject them as invalid input.

No, it's not OK to reject them. You can't just say they are invalid,
they are not.

Yes, it was pointed out to me that for some silly reason passing
understanding, that syntax is supported. It's absurd, but supported.
Sigh

Probably we should deprecate it as it really doesn't make sense to
use it that way.

Owen