Subject: Comments on <draft-gont-6man-rfc6564bis-01>

From: Bob Hinden <[email-masked]>
Date: Fri, 23 Oct 2015 15:52:21 -0700

Hi,

I have read this draft a few times, and I guess I don’t really see how this draft changes anything from RFC6554.

The only difference from RFC6554 I see is that a “subtype” is added to the header.  But the contents of the “subtype” are not defined in the document.  The text says:

      Subtype

      8-bit unsigned integer.  Specifies the subtype for this extension
      header.  It uses a new namespace managed by IANA [IANA-UEH].

I don’t see how this helps nodes understand what to do if they receive a header with with an unknown next header value.  Are they supposed to lookup the what the subtype it means in the IANA registry in real time?  That, of course, won’t work on many levels.  [Even if it did work, there isn’t anything in the document that says what format they should be in.  There isn’t anything to keep them from having different incompatible syntax.]

I don’t see how this changes the situation we have with RFC6554.  A node receiving an unknown next header value doesn’t know what to do with it.  It can either skip it or drop the packet.  I don’t see that it matters if a node knows it is an extension header or an upper layer header.  The problem is that it doesn’t know how to interpret it.

Please explain how this draft fixes the underlying problem?  What am I missing?

I do think it is worthwhile to have a registry that identifies IPv6 Extension headers.  The good thing that this was created in RFC7045.

   http://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml#extension-header

However, I think that is all we can do to distinguish extension headers and any other headers.  The base problem of having nodes know how to process new headers (of any type) without know about them beforehand, is as far as I can tell unsolvable.

Thanks,
Bob

---

From: Hagen Paul Pfeifer <[email-masked]>
Date: Sat, 24 Oct 2015 14:48:03 +0200

* Bob Hinden | 2015-10-23 15:52:21 [-0700]:

Hey Bob!

>draft changes anything from RFC6554.

The difference from 6554 - An IPv6 Routing Header for Source Routes with the
Routing Protocol for Low-Power and Lossy Networks - is enormously! ;-) Just
kidding.

Let me explain the difference from a user (kernel, software) point of view.
With 6564 the kernel do *not* know how to interpret a unknown/upcoming
extension header or protocol. Say Next Header is 666 how to interpret this? As
a 6564 uniform extension header? As a legacy extension header? As a protocol?
Right, the kernel has no information about the type and the required
treatment. What the kernel normally do is a treatment as a protocol and
looking for the registered proto handler.  If 666 is not a registered
transport protocol the kernel will drop the packet, generate icmp, whatever.
Simple defining a shiny uniform extension header is only half of the coin.

The only way to solve this issue is to provide the kernel a *guaranteed
promise* that a extension header is formated in the uniform extension format.
This can only be done by providing a unique next-header value. The kernel now
must *not* know the particular new encapsulated extension header and their
meaning.  The most important characteristic is that the kernel is now in the
ability to ignore unknown extension header and jump over their because the
kernel know that the Universal Extension Header implement a TLV like encoding
(hdr_ext_len).

It is all about *knowing* in advanced if a particular header is encoded as a
Universal Extension Header or not.

Pseudo Code (only some known ext header supported to point to the problem):

func process_header() {
	while (more_ext_header) {
		switch (next_header) {
			case EXT_HOP_HOP:
					hdr_size = process_ext_hop_hop();
					break;
			case EXT_ROUTING:
					hdr_size = process_ext_routing();
					break;
			case EXT_FRAGMENT:
					hdr_size = process_ext_fragment();
					break;
			case EXT_UNIVERSAL_HEADER():
					hdr_size = process_ext_universal();
					break;
			default:
					// hdr processing ends here
					return treat_as_transport_protocol();
		}

		packet_ptr += size_of_known_ext_hdr;
	}
}

func process_ext_universal() {
		switch (subtype) {
				case EXT_NEW_BACK_TO_FUTURE:
						process_ext_back_to_future();
					  break;
				default:
						// unknown extension header
						// do nothing, simple ignore it
						// great!
					  break;
		}

		// We know the extact len of the
		// ext hdr, for known AND unknown (upcoming)
		// universal extension header, because they are
		// always encoded in hdr_ext_len - really great!
		return hdr->hdr_ext_len;
}

func process_ext_hop_hop() {
		// do hop-by-hop processing here
		//
		// We return the exact length of this header, we must
		// known the length and format in advance.
		return EXT_HEADER_KNOWN_LENGTH
}

I hope the text/pseudo-code was understandable! ;)

Cheers and a nice weekend,

Hagen

---

From: Bob Hinden <[email-masked]>
Date: Mon, 26 Oct 2015 08:49:38 -0700

Hagan,

> On Oct 24, 2015, at 5:48 AM, Hagen Paul Pfeifer <[email-masked]> wrote:
> 

Sorry about that :-)

> Simple defining a shiny uniform extension header is only half of the coin.

OK, so the other change is the allocation of a protocol value.  The document says this in the start of Section 5, but there isn’t an allocation request is the IANA considerations section.  I think that is why I missed it.

I still don’t see how this changes the core problem of knowing how to process new unknown extension headers.  Even with what is proposed in this draft, if an implementation sees a subtype value it don’t know about, it will still won’t know how to process it.  It may or may not decide to drop it.  If it’s trying to do some sort of security validation, I suspect it will default to dropping.  I see this draft as just pushing the problem down a level to the subtype, from the next header.  The core problem remains.

I wish there was some solution to introducing new headers (extension and transport) to the Internet.  It’s an unfortunate problem not limited to IPv6 extension headers, but I don’t think the approach in this draft will make any material difference.  New headers and IANA registries IMHO won’t change anything.

> Pseudo Code (only some known ext header supported to point to the problem):

Nice pseudo code :-)

Bob

---

From: Hagen Paul Pfeifer <[email-masked]>
Date: Mon, 26 Oct 2015 18:23:18 +0100 (CET)

> On October 26, 2015 at 4:49 PM Bob Hinden <[email-masked]> wrote:

> OK, so the other change is the allocation of a protocol value.  The
> document says this in the start of Section 5, but there isn’t an
> allocation request is the IANA considerations section.  I think that is
> why I missed it.
> 
> I still don’t see how this changes the core problem of knowing how to
> process new unknown extension headers.  Even with what is proposed in
> this draft, if an implementation sees a subtype value it don’t know
> about, it will still won’t know how to process it.  It may or may not
> decide to drop it.  If it’s trying to do some sort of security
> validation, I suspect it will default to dropping.  I see this draft as
> just pushing the problem down a level to the subtype, from the next
> header.  The core problem remains.

Mhhh, really. I think draft-gont-6man-rfc6564bis-01 solves this problem!
After draft-gont-6man-rfc6564bis-01 is implemented, the kernel knows how
to process new extension header subtypes:

a) for known subtypes where a kernel handler is available and implemented
b) and even for unknown subtypes where the kernel just ignore this header,
jump over it, process the next header or transport protocol

The big difference is case b). Without this you are not in the ability to
ignore unknown extension header because you don't know the length and not
the exact position where the next ext-header/protocol starts. You don't
even know if it is a extension header or transport protocol.

Take a look at the Linux implementation:
http://lxr.free-electrons.com/source/net/ipv6/exthdrs_core.c#L71
Especially ipv6_ext_hdr() - this function return false if it is not a
known extension header. All known extension headers are there listed -
all. Later in the function you see the assignment to "hdrlen" - the exact
length of all extension header must also be known in advanced.

With draft-gont-6man-rfc6564bis it is a no-brainer:

1. Add NEXTHDR_GENERIC to ipv6_ext_hdr

2. Adjust ipv6_skip_exthdr() and friends with the following code:
    } else if (nexthdr == NEXTHDR_GENERIC) {
           hdrlen = hd->hdr_ext_len;
    }

After this you can add extension header (conforming to
draft-gont-6man-rfc6564bis, sure) all night long. The kernel is prepared
to all upcoming (subtype) extension headers. 

I hope the explanation was more understandable compare to my previous
pseudo-code-explanation. ;)

Hagen

---

From: Bob Hinden <[email-masked]>
Date: Mon, 26 Oct 2015 12:59:36 -0700

Hagen,

> On Oct 26, 2015, at 10:23 AM, Hagen Paul Pfeifer <[email-masked]> wrote:
> 

I understand your pseudo code, think this that is a policy decision.  For example, in your pseudo code:

It will skip over it if that is the way the code is written, but as I said a device doing security processing, isn’t going to do it that way, they will do something like:

						silently_drop_packet()
					  break;
		}

I understand we can write code to ignore the unknown header options, but we have a lot of experience that security devices won’t implement a skipping policy, even if it is written an RFC, to ignore things they don’t understand.  I don’t like that, but think it is reality.

Hope that helps.

Bob

---

From: Sander Steffann <[email-masked]>
Date: Mon, 26 Oct 2015 23:10:04 +0100

Hi Bob,

> I understand we can write code to ignore the unknown header options, but we have a lot of experience that security devices won’t implement a skipping policy, even if it is written an RFC, to ignore…

Security boxes will probably not accept unknown subtypes. However, routers that just want to look at the upper layer protocol for i.e. ACLs or constructing a 5-tuple for load balancing etc will be able to do so because they know that the thing they don't understand is an extension header and therefore it can be skipped to get to the upper layer protocol. Without this, the router can't know if it's seeing an unknown extension header or a unknown upper layer protocol.

I think there is value in being able to distinguish between unknown extension headers and unknown upper layer protocols.

Cheers,
Sander

---

From: Brian E Carpenter <[email-masked]>
Date: Tue, 27 Oct 2015 13:51:11 +1300

On 27/10/2015 06:23, Hagen Paul Pfeifer wrote:

...
> all. 

What I see is this list:

 17         return   (nexthdr == NEXTHDR_HOP)       ||
 18                  (nexthdr == NEXTHDR_ROUTING)   ||
 19                  (nexthdr == NEXTHDR_FRAGMENT)  ||
 20                  (nexthdr == NEXTHDR_AUTH)      ||
 21                  (nexthdr == NEXTHDR_NONE)      ||
 22                  (nexthdr == NEXTHDR_DEST);

That is 6 extension header types. There are 11 header types
currently registered:
http://www.iana.org/assignments/ipv6-parameters/ipv6-parameters.xhtml#extension-header .
Where does the code handle the other 5, and in particular how does it
handle the experimental values, whose structure is completely open?

The code fragment is dated 980726. No wonder it is hopelessly obsolete.

   Brian

---

From: Hagen Paul Pfeifer <[email-masked]>
Date: Tue, 27 Oct 2015 18:32:23 +0100 (CET)

> On October 27, 2015 at 1:51 AM Brian E Carpenter
> <[email-masked]> wrote:

Hey Brian

> .

The Linux Kernel must handle some types a little bit different. So for
example see
http://lxr.free-electrons.com/source/include/uapi/linux/in6.h#L130 and
click on IPPROTO_MH you will find the code how IP Mobility is implemented.
HIP and SHIM is not mainlined and not supported yet. Sure, a patch can
help to make these extension headers known to let the kernel ignore them.
If currently one of these extension header is received the packet will be
discarded. Maybe this is an indicator that HIP/SHIM is not widely adopted.
;-) Note: "received" means in particular the packet is locally delivered.
Let's skip the decision what happens to HIP/SHIM packets over netfiltered
forwarding paths.

The experimental range is not supported because it is impossible! This is
the central issue and it is addressed with this ID (among other things).
Supporting the "experimental range" is not possible because the kernel do
not know how the particular extension header is encoded! The kernel do not
know how to jump over unknown extension header. What is required is a
guarantee that a particular extension header is encoded in a pre-known
format. This is where draft-gont-6man-rfc6564bis comes into play.

1. Define a Universal Extension Header with a TLV like encoding where the
header size is always at the same position
2. Provide the Kernel a guarantee that a header is encoded with the
Universal Extension header

Hagen

---

From: [email-masked]
Date: Wed, 28 Oct 2015 04:02:37 +0900

Hagen,

> Universal Extension header

I presume this is in the context of a host.
you would only be able to do what you propose if the two highest order bits are 00 (section 4.2).
personally I would be in favour of making do with the 3 container options we have (HBH,DestOpt,RH), and make sure it is very unlikely that we will ever define new ones.

procedurally for 2460bis we might already have gone too far; we should not add features that have no implementations.

Best regards,
Ole

---

From: Brian E Carpenter <[email-masked]>
Date: Wed, 28 Oct 2015 08:16:17 +1300

> Let's skip the decision what happens to HIP/SHIM packets over netfiltered

No, we can't skip it, because that's the point. Of course, the receiving host
must contain code for any extension headers it is supposed to understand.
Taking the example of shim6, if a receiving host has installed linshim6
it works just fine *except* that some annoying firewall on the path drops
all the packets. A firewall built on Linux will do that, judging by the code
extract you supplied.

> know how to jump over unknown extension header. 

Sure, if we're talking about the receiving host. But a firewall should be
configurable to allow the packet through. That's the point of RFC7045.

> What is required is a

I think that buffer overflow attacks are built on the assumption that
such a 'guarantee' is meaningless. Isn't that the entire reason that firewall
people like to discard unknown headers?

   Brian

---

From: Hagen Paul Pfeifer <[email-masked]>
Date: Tue, 27 Oct 2015 21:26:00 +0100

>all the packets. A firewall built on Linux will do that, judging by the code

It currently depends on the exact netfilter configuration. If your rules say
"accept TCP/UDP port 80" and your port 80 traffic have shim6 (or any other
unknown ext hdr) in between transport layer and network layer it must stop
packet processing. I mean what should the kernel do? The kernel has no clue
how to process unknown extension header.

I mean you mentioned all details in RFC 7045 - "Introduction and Problem
Statement". You even mentioned "A Uniform Format for IPv6 Extension Headers"
(paragraph 12). The last remaining puzzle is to provide a IANA code point for
this extension header - that's all. We improve the overall situation - there
is no downside compared to the current situation. Sure, we do not solve all
problems we have, especially middle box problems, but we solve end-host
problems and some middle box problems too.

I ceremonially guarantee[TM] that since IANA will provide a number I (or
student of mine ;-) submit a kernel patch adding support for this extension
header and extend netfilter recognize this extension header too (i.e.
drop/accept). And as written several times: netfilter code is then in the
ability to parse the transport layer fields.

>configurable to allow the packet through. That's the point of RFC7045.

Right, this will be possible afterwards.

>people like to discard unknown headers?

Probably Bob may provide a superior answer. For our customers setups we tend
to configure the firewall ruleset more liberal than too strict because our
systems are separated from the public internet, the setups are employed for
10+ years and our customer will use new protocols/extend the network, etc. So
for us we would benefit from draft-gont-6man-rfc6564bis-01

Hagen