Monday, January 30, 2006

IPv6 Behind NAT Using FreeBSD and Miredo

Thanks to the generosity of a TaoSecurity Blog reader, I have been experimenting with a dual-stack IPv4 and IPv6 system at a university. I connect to the IPv4 address using OpenSSH. Once on the box, I can use IPv6.

I've been looking for ways to connect my home network directly to IPv6. At the moment I'm using a common gateway/router to perform NAT for my cable network connection. I needed a way to provide IPv6 for systems behind the NAT. Enter Teredo and the Miredo project.

Now, before you decide that I'm giving this protocol my "thumbs up," I'm going to explicitly tell you I just wanted to get the software working and use ping6. That's it for now.

Teredo, which is now a draft RFC, is a Microsoft protocol. Basically you take IPv6 traffic, tunnel it in UDP, and send it to a relay server. The relay pulls off the UDP and sends the traffic using IPv6 to the destination. The process is reversed for return traffic. Obviously sending your traffic elsewhere, especially to one of the Microsoft relays, is enough to scare most people.

Installing Miredo is simple. Thanks to author RĂ©mi Denis-Courmont responding to my troubleshooting emails, the latest version compiles flawlessly on FreeBSD 6.0. The standard ./configure, make, make install is all that is needed.

Once installed, I run Miredo in the foreground.

orr:/home/richard$ sudo miredo --foreground

***********************************************************************
* IMPORTANT NOTICE *
* *
* At the time of release of this version of the program, the IETF had *
* not yet published the Teredo protocol specification (RFC). As such, *
* this version of the program still uses experimental provisional *
* settings, which will most likely be altered when the specification *
* is published. A new version of the program will then be released to *
* take these changes into consideration. Until then, this program *
* might not work properly and should be considered experimental. *
***********************************************************************

miredo[684]: Starting...
miredo[685]: Qualified (NAT type: restricted)
miredo[685]: Teredo pseudo-tunnel started
miredo[685]: (address: 3ffe:831f:8ac3:9ddd:0:3650:ba0c:d759, MTU: 1280)

Miredo creates a tun0 interface for IPv6.

orr:/home/richard$ ifconfig -a
fxp0: flags=8943 mtu 1500
options=8
inet6 fe80::203:47ff:fe0f:1f3c%fxp0 prefixlen 64 scopeid 0x1
inet 192.168.2.5 netmask 0xffffff00 broadcast 192.168.2.255
ether 00:03:47:0f:1f:3c
media: Ethernet autoselect (100baseTX )
status: active
plip0: flags=108810 mtu 1500
lo0: flags=8049 mtu 16384
inet6 ::1 prefixlen 128
inet6 fe80::1%lo0 prefixlen 64 scopeid 0x3
inet 127.0.0.1 netmask 0xff000000
tun0: flags=80d1 mtu 1280
inet6 fe80::203:47ff:fe0f:1f3c%tun0 prefixlen 64 scopeid 0x4
inet6 fe80::5445:5245:444f%tun0 prefixlen 64 scopeid 0x4
inet6 3ffe:831f:8ac3:9ddd:0:3650:ba0c:d759 prefixlen 32
Opened by PID 685

Teredo encapsulates IPv6 inside UDP packets sent to port 3544.

Here is what it looks like to Tcpdump when Teredo starts. All we can see at this point is Miredo doing a DNS lookup for its default relay server, followed by UDP traffic to that server.

11:08:15.389255 IP 192.168.2.5.64226 > 192.168.2.1.53: 58453+ A? teredo.via.ecp.fr. (35)
11:08:15.394528 IP 192.168.2.1.53 > 192.168.2.5.64226: 58453 1/0/0 A 138.195.157.221 (51)
11:08:15.395024 IP 192.168.2.5.51631 > 138.195.157.221.3544: UDP, length 77
11:08:19.396616 IP 192.168.2.5.51631 > 138.195.157.221.3544: UDP, length 77
11:08:23.396031 IP 192.168.2.5.51631 > 138.195.157.221.3544: UDP, length 77
11:08:27.396404 IP 192.168.2.5.51631 > 138.195.157.222.3544: UDP, length 77
11:08:27.517795 IP 138.195.157.222.3544 > 192.168.2.5.51631: UDP, length 117
11:08:27.518031 IP 192.168.2.5.51631 > 138.195.157.221.3544: UDP, length 77
11:08:27.639923 IP 138.195.157.221.3544 > 192.168.2.5.51631: UDP, length 117
11:09:01.396212 IP 192.168.2.5.51631 > 138.195.157.221.3544: UDP, length 77
11:09:01.514967 IP 138.195.157.221.3544 > 192.168.2.5.51631: UDP, length 117

Tethereal strips off the UDP traffic by default and shows the underlying IPv6 traffic. Keep this in mind if you're using Tethereal and think you're seeing native IPv6. This is the same trace as examined above with Tcpdump.

Now with the help of Tethereal, we see Miredo making ICMPv6 router solicitations. Later we see ICMPv6 router advertisements from fe80::8000:dd8:753c:6222.

1 2006-01-30 11:08:15.389255 192.168.2.5 -> 192.168.2.1 DNS Standard query A
teredo.via.ecp.fr
2 2006-01-30 11:08:15.394528 192.168.2.1 -> 192.168.2.5 DNS Standard query response A 138.195.157.221
3 2006-01-30 11:08:15.395024 fe80::8000:5445:5245:444f -> ff02::2 ICMPv6 Router solicitation
4 2006-01-30 11:08:19.396616 fe80::8000:5445:5245:444f -> ff02::2 ICMPv6 Router solicitation
5 2006-01-30 11:08:23.396031 fe80::8000:5445:5245:444f -> ff02::2 ICMPv6 Router solicitation
6 2006-01-30 11:08:27.396404 fe80::5445:5245:444f -> ff02::2 ICMPv6 Router solicitation
7 2006-01-30 11:08:27.517795 fe80::8000:dd8:753c:6222 -> fe80::5445:5245:444f ICMPv6 Router advertisement
8 2006-01-30 11:08:27.518031 fe80::5445:5245:444f -> ff02::2 ICMPv6 Router solicitation
9 2006-01-30 11:08:27.639923 fe80::8000:dd8:753c:6222 -> fe80::5445:5245:444f
ICMPv6 Router advertisement
12 2006-01-30 11:09:01.396212 fe80::5445:5245:444f -> ff02::2 ICMPv6 Router solicitation
13 2006-01-30 11:09:01.514967 fe80::8000:dd8:753c:6222 -> fe80::5445:5245:444f ICMPv6 Router advertisement

Here is what the routing table for IPv6 looks like once Miredo is running.

orr:/home/richard$ netstat -nr -f inet6
Routing tables

Internet6:
Destination Gateway Flags Netif Expire
default link#4 ULS tun0
::1 ::1 UH lo0
3ffe:831f::/32 link#4 UC tun0
3ffe:831f:8ac3:9ddd:0:3650:ba0c:d759 link#4 UHL lo0
fe80::%fxp0/64 link#1 UC fxp0
fe80::203:47ff:fe0f:1f3c%fxp0 00:03:47:0f:1f:3c UHL lo0
fe80::%lo0/64 fe80::1%lo0 U lo0
fe80::1%lo0 link#3 UHL lo0
fe80::%tun0/64 link#4 UC tun0
fe80::5445:5245:444f%tun0 link#4 UHL lo0
fe80::203:47ff:fe0f:1f3c%tun0 link#4 UHL lo0
ff01::/32 ::1 U lo0
ff02::%fxp0/32 link#1 UC fxp0
ff02::%lo0/32 ::1 UC lo0
ff02::%tun0/32 link#4 UC tun0

Interface tun0 is the default for IPv6. That is good news. Let's try to ping6 an IPv6 enabled host.

orr:/home/richard$ ping6 -c 2 www6.olympus-zone.net
PING6(56=40+8+8 bytes) 3ffe:831f:8ac3:9ddd:0:3650:ba0c:d759 --> 2001:1638:305:4::1
16 bytes from 2001:1638:305:4::1, icmp_seq=0 hlim=56 time=766.023 ms
16 bytes from 2001:1638:305:4::1, icmp_seq=1 hlim=56 time=394.536 ms

--- www6.olympus-zone.net ping6 statistics ---
2 packets transmitted, 2 packets received, 0.0% packet loss
round-trip min/avg/max/std-dev = 394.536/580.279/766.023/185.744 ms

Awesome. Here is how Tcpdump sees the traffic.

11:09:16.646506 IP 192.168.2.5.55205 > 192.168.2.1.53: 58174+ AAAA? www6.olympus-zone.net. (39)
11:09:16.648419 IP 192.168.2.1.53 > 192.168.2.5.55205: 58174 1/0/0 AAAA 2001:1638:305:4::1 (67)
11:09:16.649738 IP 192.168.2.5.51631 > 138.195.157.221.3544: UDP, length 64
11:09:16.977910 IP 138.195.157.221.3544 > 192.168.2.5.51631: UDP, length 48
11:09:16.978090 IP 192.168.2.5.51631 > 213.172.48.140.51246: UDP, length 40
11:09:17.130790 IP 213.172.48.140.51246 > 192.168.2.5.51631: UDP, length 64
11:09:17.130940 IP 192.168.2.5.51631 > 213.172.48.140.51246: UDP, length 56
11:09:17.415124 IP 213.172.48.140.51246 > 192.168.2.5.51631: UDP, length 56
11:09:17.649746 IP 192.168.2.5.51631 > 213.172.48.140.51246: UDP, length 56
11:09:18.043784 IP 213.172.48.140.51246 > 192.168.2.5.51631: UDP, length 56

Packet 3 would appear to be the ICMPv6 request, with packet 4 the response. But what about the last 6 packets?

Here is the same traffic in Tethereal.

14 2006-01-30 11:09:16.646506 192.168.2.5 -> 192.168.2.1 DNS Standard query AAAA www6.olympus-zone.net
15 2006-01-30 11:09:16.648419 192.168.2.1 -> 192.168.2.5 DNS Standard query response AAAA 2001:1638:305:4::1
16 2006-01-30 11:09:16.649738 3ffe:831f:8ac3:9ddd:0:3650:ba0c:d759 -> 2001:1638:305:4::1 ICMPv6 Echo request
17 2006-01-30 11:09:16.977910 fe80::8000:5445:5245:444f -> 3ffe:831f:8ac3:9ddd:0:3650:ba0c:d759 IPv6 IPv6 no next header
18 2006-01-30 11:09:16.978090 192.168.2.5 -> 213.172.48.140 UDP Source port: 51631 Destination port: 51246
19 2006-01-30 11:09:17.130790 213.172.48.140 -> 192.168.2.5 UDP Source port: 51246 Destination port: 51631
20 2006-01-30 11:09:17.130940 192.168.2.5 -> 213.172.48.140 UDP Source port: 51631 Destination port: 51246
21 2006-01-30 11:09:17.415124 213.172.48.140 -> 192.168.2.5 UDP Source port: 51246 Destination port: 51631
22 2006-01-30 11:09:17.649746 192.168.2.5 -> 213.172.48.140 UDP Source port: 51631 Destination port: 51246
23 2006-01-30 11:09:18.043784 213.172.48.140 -> 192.168.2.5 UDP Source port: 51246 Destination port: 51631

Tethereal sees the ICMPv6 request and reply, but it can't decode the last 6 packets.

I plan to investigate this further.

3 comments:

Anonymous said...

Using the TSP client works really well if you are behind a NAT router, we've been using it in the UK for the UKERNA IPv6 Tunnel Broker hosted at Southampton University. If you have access to a real public IP then tunneling 6 -> 4 over protocol 41 works well to.

http://www.broker.ipv6.ac.uk/

When I read about the honeynet incident where hackers enabled IPv6 tunneling for their IRC backdoor to avoid detecion I came up with the following snort rule that would spot protocol 41 packets with a IPv6 src port of 6667 providing there are no extension headers in place.

# Detect source port 6667 for v6 in v4 traffic
alert ip any any -> any any (ip_proto:41; content: "|1a 0b|"; offset:0;)

Richard Bejtlich said...

For reference -- TSP.

Richard Bejtlich said...

For reference:

neely-bsd# miredo -f
miredo[46477]: Starting...
miredo[46478]: Unsupported symmetric NAT detected.

Also review this news group

http://news.gmane.org/gmane.network.ipv6.miredo.devel

for similar problems.