12.5. Filtering IPv6 Traffic

12.5.1. How come that IPv6 tc filters do not work?

The Routing Policy Database (RPDB) replaced the IPv4 routing and addressing structure within the Linux Kernel which lead to all the wonderful features this HOWTO describes. Unfortunately, the IPv6 structure within Linux was implemented outside of this core structure. Although they do share some facilities, the essential RPDB structure does not particpate in or with the IPv6 addressing and routing structures.

This will change for sure, we just have to wait a little longer.

FIXME: Any ideas if someone is working on this? Plans?

12.5.2. Marking IPv6 packets using ip6tables

ip6tables is able to mark a packet and assign a number to it:

# ip6tables -A PREROUTING -i eth0 -t mangle -p tcp -j MARK --mark 1

But still, this will not help because the packet will not pass through the RPDB structure.

12.5.3. Using the u32 selector to match IPv6 packet

IPv6 is normally encapsulated in a SIT tunnel and transported over IPv4 networks. See section IPv6 Tunneling for information on howto setup such a tunnel. This allows us to filter on the IPv4 packets holding the IPv6 packets as payload.

The following filter matches all IPv6 encapsulated in IPv4 packets:

# tc filter add dev $DEV parent 10:0 protocol ip prio 10 u32 \
            match ip protocol 41 0xff flowid 42:42

Let's carry on with that. Assume your IPv6 packets get sent out over IPv4 and these packets have no options set. One could use the following filter to match ICMPv6 in IPv6 in IPv4 with no options. 0x3a (58) is the Next-Header type for ICMPv6.

# tc filter add dev $DEV parent 10:0 protocol ip prio 10 u32 \
           match ip protocol 41 0xff \
           match u8 0x05 0x0f at 0 \
           match u8 0x3a 0xff at 26 \
           flowid 42:42

Matching the destination IPv6 address is a bit more work. The following filter matches on the destination address 3ffe:202c:ffff:32:230:4fff:fe08:358d:

# tc filter add dev $DEV parent 10:0 protocol ip prio 10 u32 \
            match ip protocol 41 0xff \
            match u8 0x05 0x0f at 0 \
            match u8 0x3f 0xff at 44 \
            match u8 0xfe 0xff at 45 \
            match u8 0x20 0xff at 46 \
            match u8 0x2c 0xff at 47 \
            match u8 0xff 0xff at 48 \
            match u8 0xff 0xff at 49 \
            match u8 0x00 0xff at 50 \
            match u8 0x32 0xff at 51 \
            match u8 0x02 0xff at 52 \
            match u8 0x30 0xff at 53 \
            match u8 0x4f 0xff at 54 \
            match u8 0xff 0xff at 55 \
            match u8 0xfe 0xff at 56 \
            match u8 0x08 0xff at 57 \
            match u8 0x35 0xff at 58 \
            match u8 0x8d 0xff at 59 \
            flowid 10:13

The same technique can be used to match subnets. For example 2001::

# tc filter add dev $DEV parent 10:0 protocol ip prio 10 u32 \
            match ip protocol 41 0xff \
            match u8 0x05 0x0f at 0 \
            match u8 0x20 0xff at 28 \
            match u8 0x01 0xff at 29 \
            flowid 10:13