(iBoyd)

January 26th, 2010

Converting a 6to4 IPv6 Address to its IPv4 equivalent (Dude, where’s my IPv4?)

Alright, here’s the scenario:

  • You’ve upgraded your web server to Windows 2008 and you have a bunch of Windows Vista and Windows 7 clients connecting to an ASP .NET application on that web server. The application uses My.Request.UserHostAddress to check the IP address of the client. For whatever reason, your application only expects an IPv4 address to be returned
  • Both the server and the client have IPv6 functionality enabled (by default) but are only configured with IPv4 addresses.
  • Since neither the client nor the server have an IPv6 address set, you would expect My.Request.UserHostAddress to return an IPv4 address. Instead, it returns an IPv6 address that starts with 2002 prefix.

How in the heckĀ  did this happen!? Well, it turns out that this behavior is by design. When Microsoft added IPv6 support beginning with Windows Vista, they added support for using IPv6 over an IPv4 network, for compatibility and transitioning purposes. By default, a Windows Vista or Windows 7 computer that only has an IPv4 address assigned to it will try to communicate over IPv6 by using a special IPv6 address called a 6to4 address. All 6to4 addresses start with the 2002 prefix. The good news is a 6to4 address is derived from the octets of an IPv4 address, so we can convert 6to4 addresses to their IPv4 equivalent. This Technet page goes into further detail about the 6to4 addressing scheme.

Here’s the code I wrote to convert 6to4 IPv6 addresses back to their IPv4 equivalent:

       ipAddress = System.Net.IPAddress.Parse(My.Request.UserHostAddress)
        If ipAddress.AddressFamily = Net.Sockets.AddressFamily.InterNetworkV6 Then '
            Dim tmpBytes() As Byte = ipAddress.GetAddressBytes
            If tmpBytes(0) = 32 And tmpBytes(1) = 2 Then 'Check it's a 6to4 address (it begins with "2002")
                ipAddress = System.Net.IPAddress.Parse(Convert.ToString(tmpBytes(2)) & "." & Convert.ToString(tmpBytes(3)) & "." & Convert.ToString(tmpBytes(4)) & "." & Convert.ToString(tmpBytes(5)))
            End If
        End If

Note that this code will only be applicable to 6to4 IPv6 addresses. Normal IPv6 addresses will be ignored because they can’t be converted to an IPv4 equivalent. This means that your code will eventually need to handle IPv6 addresses if clients that connect to the application are ever assigned IPv6 addresses.

Leave a Reply