Skip to contentSkip to conversation

nftables: How to match ICMPv6 subtype in a rule?

DISCUSSION William N. 3 participants 9 messages Mar 30, 2024 – Apr 2, 2024

lore
Share & tools
lore

William N.

author
#0 lore raw

Hello,

I have been reading RFC 4890 and 4443, as well as nftables wiki and man page.

It is obvious how to match ICMPv6 types using 'icmpv6 type'. However, as RFC 4890 recommends, there are situations where only a specific SUBtype must be accepted, e.g. section 4.3.1:

o Time Exceeded (Type 3) - Code 0 only
o Parameter Problem (Type 4) - Codes 1 and 2 only

I have been searching for days and I can't find any info about matching ICMPv6 subtypes. ip6tables can do that (as shown in the example in the RFC) but no info about nftables. ip6tables-translate cannot translate subtype rules (it converts them to a comment).

So, what is the nftables syntax to accept only a specific subtype of an ICMPv6 type?

FWIW, I am on Debian 12:

# nft -V
nftables v1.0.6 (Lester Gooch #5)
  cli:          editline
  json:         yes
  minigmp:      no
  libxtables:   yes
#1 lore raw
Quoted 8 lines · William N.

Hello,

I have been reading RFC 4890 and 4443, as well as nftables wiki and man page.

It is obvious how to match ICMPv6 types using 'icmpv6 type'. However, as RFC 4890 recommends, there are situations where only a specific SUBtype must be accepted, e.g. section 4.3.1:

As far as the ICMPv6 header is concerned, there are only types and codes.

Quoted 4 lines

o Time Exceeded (Type 3) - Code 0 only
o Parameter Problem (Type 4) - Codes 1 and 2 only

Those are types and codes.

Quoted 7 lines

I have been searching for days and I can't find any info about matching ICMPv6 subtypes. ip6tables can do that (as shown in the example in the RFC) but no info about nftables. ip6tables-translate cannot translate subtype rules (it converts them to a comment).

So, what is the nftables syntax to accept only a specific subtype of an ICMPv6 type?

These are the relevant sections of the manual:

LESS=+/'ICMPV6 HEADER EXPRESSION' man nft
LESS=+'/ICMPV6 TYPE TYPE' man nft
LESS=+'/ICMPV6 CODE TYPE' man nft

However, there are some errors in the manual. One is that the ICMPV6 HEADER EXPRESSION section does not make it clear that the type/keyword for the ICMPv6 Code is "icmpv6_code", instead generically describing it as "integer (8 bit)". Another is that it erroneously documents the keyword for the ICMPv6 Type as being "icmpx_code" in the ICMPV6 CODE TYPE section.

Anyway, the syntax is:

icmpv6 type <icmpv6_type> # where <icmpv6_type> is any valid ICMPV6 TYPE value icmpv6 code <icmpv6_code> # where <icmpv6_code> is any valid ICMPV6 CODE value

Both of this header expressions may be combined within a single rule. All of the possible values are documented by the aforementioned sections of the manual. Alternatively, you may ask for nft(8) to print out the supported values for you.

# nft describe icmpv6_type
# nft describe icmpv6_code
Signature · 1 line
Kerin Millar
author
#2 lore raw

Thanks for clarifying.

I actually found the magic word "code" after posting here but I still wanted to wait for a reply. Yours explained it perfectly. I suppose I have been confused by reading too much from different sources :)

Quoted 1 line · On Sun, 31 Mar 2024 07:33:42 +0100 Kerin Millar wrote:

However, there are some errors in the manual. [...]

Have those been reported anywhere?

Quoted 2 lines

icmpv6 code <icmpv6_code> # where <icmpv6_code> is any valid ICMPV6 CODE value

Having such possibility is interesting, as the integer code has different meaning depending on the type, i.e. it has no meaning per se and it looks strange to filter based on it only. I thought they must go "hand in hand" but obviously not. I wonder what purpose such filtering may serve.

In that sense, the output of:

Quoted 1 line
# nft describe icmpv6_code

is somewhat confusing (e.g. compare type 1 and type 3 or 4 in RFC 4443).

#3 lore raw
Quoted 11 lines · On Sun, 31 Mar 2024 17:02:59 -0000 "William N." <[email protected]> wrote:

Thanks for clarifying.

I actually found the magic word "code" after posting here but I still wanted to wait for a reply. Yours explained it perfectly. I suppose I have been confused by reading too much from different sources :)

Quoted 1 line · On Sun, 31 Mar 2024 07:33:42 +0100 Kerin Millar wrote:

However, there are some errors in the manual. [...]

Have those been reported anywhere?

I'll open a bug.

Quoted 10 lines
Quoted 3 lines

icmpv6 code <icmpv6_code> # where <icmpv6_code> is any valid ICMPV6 CODE value

Having such possibility is interesting, as the integer code has different meaning depending on the type, i.e. it has no meaning per se and it looks strange to filter based on it only. I thought they must go "hand in hand" but obviously not. I wonder what purpose such filtering may serve.

Quoted 5 lines

In that sense, the output of:

Quoted 1 line
# nft describe icmpv6_code

is somewhat confusing (e.g. compare type 1 and type 3 or 4 in RFC 4443).

Yes, indeed. It seems that the symbolic names were selected under the presumption that they would be most convenient for the common case - probably with the reject keyword in mind. Come to think of it, that's probably why the manual does not reference the icmpv6_code type in the ICMPV6 HEADER EXPRESSION section. Fortunately, there is always the option to specify an arbitrary integer value.

Signature · 1 line
Kerin Millar
author
#6 lore raw

Is it possible to have proper symbolic naming ('describe') of codes depending on type too? (as per RFC 4443)

I also notice there are some types that don't even have a corresponding name (e.g. 139, 140).

ip6tables-translate does not translate codes either.

Has that been reported/considered?

Speaking of all that:

I have managed to "translate" the whole Appendix B of RFC 4890. However, I am not quite sure how complete the appendix itself is, because:

- it does not address the recommendations given regarding hop limits
- I have found one bug (so far) in that same appendix

I wonder if it would be appropriate to contact the email addresses given at the end of the RFC itself. What do you think?

Considering the importance of correct secure handling of ICMPv6, it would be great to have an example on wiki.nftables.org showing a proper implementation of RFC 4890.

#7 lore raw
Quoted 2 lines · William N.

Is it possible to have proper symbolic naming ('describe') of codes depending on type too? (as per RFC 4443)

This is not yet done. Add it to bugzilla as a feature request I'd suggest.

Quoted 2 lines

I also notice there are some types that don't even have a corresponding name (e.g. 139, 140).

I believe the existing ICMP types are based on iptables, and it seems iptables does not include those.

There is icmp6_type_tbl in src/proto.c that can be extended, better to use definitions available in icmp.h if available.

Quoted 1 line

ip6tables-translate does not translate codes either.

What iptables version are you using?

$ ip6tables-translate -I INPUT -m icmpv6 --icmpv6-type destination-unreachable
nft 'insert rule ip6 filter INPUT icmpv6 type destination-unreachable counter'
Quoted 9 lines

Has that been reported/considered?

Speaking of all that:

I have managed to "translate" the whole Appendix B of RFC 4890. However, I am not quite sure how complete the appendix itself is, because:

- it does not address the recommendations given regarding hop limits
- I have found one bug (so far) in that same appendix

What bug?

Quoted 6 lines

I wonder if it would be appropriate to contact the email addresses given at the end of the RFC itself. What do you think?

Considering the importance of correct secure handling of ICMPv6, it would be great to have an example on wiki.nftables.org showing a proper implementation of RFC 4890.

author
#8 lore raw
Quoted 1 line · On Tue, 2 Apr 2024 12:06:21 +0200 Pablo Neira Ayuso wrote:

What iptables version are you using?

# iptables -V
iptables v1.8.9 (nf_tables)
Quoted 2 lines
$ ip6tables-translate -I INPUT -m icmpv6 --icmpv6-type
destination-unreachable nft 'insert rule ip6 filter INPUT icmpv6 type destination-unreachable counter'

What you show works for me too, but e.g. this does not:

# ip6tables-translate -I INPUT -m icmpv6 --icmpv6-type ttl-zero-during-transit
nft # -I INPUT -m icmpv6 --icmpv6-type ttl-zero-during-transit

If you replace 'ip6tables' with 'ip6tables-translate' in the RFC example and run the whole script you will see the rest which don't translate.

Quoted 1 line

What bug?

For example, in section "TIME EXCEEDED ERROR MESSAGES", right after the comment saying:

# Allow incoming time exceeded code 0 messages

# only for existing sessions

the actual rules handle 'packet-too-big' (type 2), not 'time-exceeded' (type 3) with code 0, as recommended in section 4.3.1 and as it claims. The 'else' condition right after it does not do what it should either. As a result, type 3 (which is in the "must" section 4.3.1) seems not handled anywhere.

There is also some meaningless code, e.g. the loop around the 'bad-header'. Etc.