Continuing my posts on Teredo, consider the following network:
There are two Windows clients behind two different NAT routers. There’s a Teredo server and a Teredo relay. And there are IPv6 only and IPv6/IPv4 resources on the Internet that these clients would like to access. The Teredo server and relay are on different networks and the Teredo relay is in a different network from the clients and IPv6 resources. They don’t need to be on different networks or even different servers; I just put them so to illustrate that they are independent devices and not necessarily on the same network as the client and resources.
The clients communicate with the Teredo server and relay through IPv6 packets in UDP messages in IPv4 packets. The Teredo server and relay communicate with the IPv6 parts of the Internet over IPv6, except when the host has both IPv4 and IPv6 in which case the host acts as its own relay and talks to the clients directly over IPv4 (using IPv6 in UDP messages as usual).
Once I configure both clients with the Teredo server address they get a Teredo IPv6 addresses as below. These are both link-local as well as
2001::/32 prefix addresses. The Teredo relay too gets Teredo IPv6 addresses while the Teredo server has link-local Teredo IPv6 addresses only.
Decoding the Teredo IPv6 address
Let’s decode the Teredo IPv6 address of one of the clients to see what it means.
Client 192.168.99.200 has address 2001:0:1117:34fa:1027:374b:e1fc:f635. So the network prefix is 2001:0:1117:34fa, host identifier is 1027:374b:e1fc:f635.
Dealing with the network prefix:
- 2001::/32 is the Teredo network prefix.
- 1117:34fa is 32 bits of the Teredo server IPv4 address in hex. 0x11 = 17, 0x17 = 23, 0x34 = 52, 0xFA = 250. Which converts to 220.127.116.11.
And the host identifier:
- 1027 is 16 bits of flags and random bits.
- 374b is 16 bits of the obfuscated external port of the NAT. (Obfuscation happens by XOR-ing the digits with 0xFFFF).
- 0x374b = 0xc8b4 unobfuscated =51380.
- e1fc:f635 is 32 bits of obfuscated external IPv4 address of the NAT.
- 0xe1 = 0x1e unobfuscated = 30
- 0xfc = 0x3 unobfuscated = 3
- 0xf6 = 0x9 unobfuscated = 9
- 0x35 = 0xca unobfuscated = 202
- So the NAT’s external IPv4 address is 18.104.22.168.
Let’s look at some Wireshark captures to see what happens. From one of the clients (192.168.20.200) I am pinging an IPv6 host and here’s what happens.
(The Teredo IPv6 addresses in these captures are different from the ones above because I made the captures a while later and the NAT IPv4 address and port changed by then).
First the client makes a DNS request (over IPv4) to resolve the name, one of the name servers replies with the IPv6 address (the AAAA records).
Next the client contacts the Teredo server to configure itself. It sends an ICMPv6 Router Solicitation message to the
ff02::2 multicast IPv6 address (link-local scope, all routers). The source is set to a link-local IPv6 address
fe80::ffff:ffff:fffe which as far as I can tell seems to be an anycast address but I am not too sure. (Typically Router Solicitation messages set the source address as fe80::/64 followed by a random or EUI-64 based host identifier).
It’s worth noting that this ICMPv6 message is actually sent within a UDP message in an IPv4 packet addresses to the Teredo server IPv4 address. Pay attention to the destination IPv4 address of this packet – it’s the first IPv4 address of the Teredo server. From the capture above you’ll see there are two Router Solicitation messages sent and two replies got. That’s because the second Router Solicitation message is to the second IPv4 address of the Teredo server. Both addresses send a reply and that’s how the Teredo client identifies whether it’s behind a symmetric NAT or not.
In the capture above it’s also worth noting the port number used by the client’s NAT: 52643. There is now a mapping on the NAT device from this port to the client. The mapping could be a cone or restricted, but that does not matter to us (as long as it’s not symmetric).
Moving on, the Teredo client sends an IPv6 Connectivity Test message from it’s Teredo IPv6 address to the IPv6 address of the destination. The client has auto configured an IPv6 address for itself. And it knows the destination IPv6 address from the initial DNS query. This test message is really an ICMPv6 ping request to the destination, sent within an UDP message over IPv4 to the Teredo server. I had mentioned this previously in the section on Teredo relays. This is how a Teredo client finds the Teredo relay closest to the destination.
The Teredo server now does a Neighbor Solicitation to find the MAC address of the destination. From the IPv6 address it knows the destination is on the same network as itself. If it were on different networks, the Teredo server would have sent this packet to its gateway for forwarding.
Notice the destination address
ff02::1:ff00:254. As mentioned in an earlier post this is a solicited node multicast address.
ff02indicates the scope is link-local.
::1:ffxx:xxxxis the solicited node address a host with last 24bits IPv6 address
xx:xxxxwould have subscribed to. For the destination host IPv6 address 2dcc:7c4e:3651:52::254, this would be 00:254.
The destination host now sends a Neighbor Solicitation message to find its default gateway’s MAC address, gets a reply, and sends the ping reply to the Teredo client. Notice the ping reply is a pure IPv6 ICMPv6 packet.
This packet reaches the Teredo relay as it is advertising the
2001::/32 prefix. This packet is discarded.
The Teredo relay sends a UDP message to the NAT router of client, on the port that’s mapped to it. The NAT router replies with a prohibited message. This tells the Teredo relay that any previous mappings the client NAT might have had for the relay are gone and so a new mapping must be made. Since it can’t contact the client directly it must take help from the Teredo server.
The Teredo relay now sends a bubble packet from itself to the IPv6 Teredo address of the client. This bubble packet is sent via UDP over IPv4 to the Teredo server. (Remember this is how the need for hole punching is communicated to the server).
The Teredo server sends this packet via UDP to the port that’s mapped on the client’s NAT router. Note the IPv6 portion of the packet it sends is same as the one it receives. This way the client is able to identify the Teredo relay’s IPv4 and Teredo IPv6 address.
I was under the impression the Teredo relay address is sent to the client as an “Origin Indication” by the Teredo server but apparently the client picks it up from the IPv6 packet the relay sends it. The Teredo server doesn’t modify the IPv6 payload. The payload is a bubble packet (next header is 59) and contains details of the relay.
Now the Teredo client contacts the Teredo relay and sends it bubble packets. The relay responds and thus the client and relay know of each other.
All this was just prep work done behind the scenes when the client wants to talk to an IPv6 host. I generated this traffic by trying to ping the IPv6 host from the client so below is the traffic for that:
The Teredo client contacts the relay via UDP/ IPv4 and passes on the ICMPv6 ping request packet. That’s sent on the IPv6 network to the destination. A reply arrives. The reply is passed via UDP/IPv4 to the client. No more additional steps.
Below is the capture for all four ping requests and replies.
And that’s it!
Microsoft has a good page on Teredo that’s worth looking at. Goes into more details with the processes and scenarios that I don’t go into above.