Tuesday, 16 February 2016

Quiz: Weird IPv6 Traffic on the Local Network (updated with solution)

One thing that I enjoy a lot is capturing network traffic to subsequently try to figure out whether the captured traffic makes any sense -- you learn a lot that way.

The following packet was shared with me by Timo Hilbrink during the 10th Slovenian IPv6 Summit.

The quiz consists in explaining the packet trace bellow.

  • Apple iOS 8.3
  • Fritz!Box CPE

The "Crime Scene" (tcpdump packet trace):

Two packets:

19:00:02.246726 IP6 truncated-ip6 - 16011 bytes missing!(class 0x50, flowlabel 0x00040,
hlim 0, next-header unknown (64) payload length: 16035)
4006:a0bd:c0a8:b229:40e9:a79c:f129:50 > f141:8159::b002:ffff:32fc:0: ip-proto-64
19:00:02.252529 IP6 (hlim 255, next-header ICMPv6 (58) payload length: 256)
fe80::be05:43ff:feea:be92 > ip6-allnodes: [icmp6 sum ok]
ICMP6, router
, length 256
hop limit 255, Flags [other stateful], pref high, router lifetime 1800s, reachable time
0s, retrans time 0s
prefix info option (3), length 32 (4): 4006:a0bd:c0a8:b229::/64, Flags [onlink, auto],
valid time 7200s, pref. time 0s
prefix info option (3), length 32 (4): 4006:11b:c0a8:b229::/64, Flags [onlink, auto],
valid time 6973s, pref. time 0s
prefix info option (3), length 32 (4): 4006:3e38:c0a8:b229::/64, Flags [onlink, auto],
valid time 6972s, pref. time 0s
prefix info option (3), length 32 (4): 2001:980:376d:1::/64, Flags [onlink, auto], valid
time 6603s, pref. time 3600s
rdnss option (25), length 24 (3): lifetime 1200s, addr: fd00::be05:43ff:feea:be92
mtu option (5), length 8 (1): 1500
unknown option (24), length 8 (1):
0x0000: 0008 0000 0708

So... can you explain what this packet trace is all about?


The solution to this quiz boils down to explaining the two packets in question.

Upon first inspection, the first packet looks like a malformed/corrupted IPv6 packet: the packet is truncated, has an IPv6 Source Address that does not really belong to the local subnet, and even has an unknown upper protocol (Next Header=64). Quite surprisingly, the second 32-bits of the IPv6 Source Address are c0a8:b229 which, if converted to decimal on a byte-by-byte basis, results in

Is this just a coincidence? -- Let's look at the first packet a bit closer, with Wireshark:

Looking at the packet decode, it's clear that while the Ethernet "Type" field is set to 0x86dd (IPv6), the IPv6 version field is actually set to version 4!

What we infer from this packet, is that the sending system (Apple iOS 8.3) fails to properly set the Ethernet Type field (i.e., bug #1). Hence, this IPv4 packet is identified at layer-2 as an IPv4 packet, and hence parsed as an IPv4 packet.

This is what the packet should look like (but doesn't):

Now.. what about the second packet? How and why is it actually generated?

First of all, it seems that the Fritz!Box CPE fails to perform a very simple sanity check: that the IP version field matches the protocol type identified by the Ethernet header. In this particular case, they do not patch, and the Fritz!Box CPE should have discarded the packet rather than process it (i.e., bug #2).

That said, the Fritz!Box CPE seems to detect that the sending system is sending packets from an incorrect IPv6 prefix, and hence sends a Router Advertisement message with a Prefix Information Option (PIO) that advertises the corresponding prefix with a preferred lifetime of 0 -- in the hopes that this prefix is "disabled" in the sending system. This seems to be some sort of feature of the Fritz!Box CPE that aims to mitigate e.g. misconfigurations. Obviously, in this particular case the RA sent by the Fritz!Box CPE will be of no use, since the sending system is not really employing the 4006:a0bd:c0a8:b229/64 prefix -- it is simply sending IPv4 packets with an incorrect Ethernet Type (0x86DD rather than 0x800).

So... what's the real IP packet that is being sent by Apple iOS 8.3? If we overwrite the incorrect EtherType of the first packet with 0x0800, and now decode the first packet again (such that it is decoded as an IPv4 packet rather than as an IPv6 packet), the output is:

19:00:02.246726 IP > Flags [S], seq 4047602009, win 65535, options [mss 1460,nop,wscale 5,nop,nop,TS val 1228667736 ecr 0,sackOK,eol], length 0

That is, the first packet of the packet trace was really an IPv4-based TCP SYN packet, which obviously looked like a malformed IPv6 packet when "incorrectly" decoded as an IPv6 packet.

Folks willing to take a closer look at the packet trace may find the corresponding pcap file here. The "corrected" pcap file (with the EtherType overwritten with 0x0800, such that the first packet is decoded as an IPv4 packet) can be found here.

  -- Fernando Gont


Jaime Olmos de la Cruz said...

First, IPv6 address consist of 4006:a0bd:c0a8:b229:40e9:a79c:f129:50. This could be some part of an IPv4 address, c0a8:b229 corresponds to and 40e9:a79c corresponds to Why? I don't know. Could you share more information?

Unknown said...

The first red flag for me was the fact the IPv6 address started with 4006. Is there any reason why valid IPv6 packets would be outside the 2000::/3 or fe80::/10 ranges?

Mark said...

Fritz!boxes probably aren't that smart. They were one of the worst offenders and also the strangest (trying to swap ULA for GUA and vice versa based on WAN status)

Post a Comment