IPv6 to IPv4 using proxies : lessons learned
As we progress into IPv6 networks, one of the more common transitory scenarios we will see will be similar to the following:
Especially in earlier stages, it is to be expected that isolated “pools” of IPv6 networks will need to communicate with a still predominantly IPv4 internet. One of the many ways of facilitating this is using an explicit proxy deployment which converts IPv6 requests to IPv4 requests. More experienced IPv6 users will argue that this is equivalent to the now depreciated NAT-PT (protocol translation) and there are now better ways such as tunnelling and relays to get an equivalent scenario working… but this is quite an easy and cheap way of achieving relatively good results.
Of course in this article i’m assuming that you already have an IPv6 network up and running. This isn’t such a big deal if you’re running relatively up to date OS such as windows 7 or ubuntu 10.10. In my case it was simply an issue of enabling IPv6 for the OS in question. Usually it’s enabled by default so it’s even less of a worry.
Initially I was testing using link-local addresses (FE80::/10 – see my previous post for more details) however this proved to be a bit of a pain for two main reasons:
1. Link-local addresses are not unique, so you must always specify an outgoing interface. To illustrate this a bit better, consider the output from this linux box when using ping6 or telnet with link-local addresses:
[root@localhost ~]# ping6 fe80::2d0:83ff:fe05:685
connect: Invalid argument
[root@localhost ~]# ping6 -I eth0 fe80::2d0:83ff:fe05:685
PING fe80::2d0:83ff:fe05:685(fe80::2d0:83ff:fe05:685) from fe80::20c:29ff:fe75:25fa eth0: 56 data bytes
64 bytes from fe80::2d0:83ff:fe05:685: icmp_seq=0 ttl=64 time=40.0 ms
64 bytes from fe80::2d0:83ff:fe05:685: icmp_seq=1 ttl=64 time=0.960 ms
64 bytes from fe80::2d0:83ff:fe05:685: icmp_seq=2 ttl=64 time=0.895 ms
— fe80::2d0:83ff:fe05:685 ping statistics —
3 packets transmitted, 3 received, 0% packet loss, time 2117ms
rtt min/avg/max/mdev = 0.895/13.951/40.000/18.419 ms, pipe 2
[root@localhost ~]# telnet fe80::2d0:83ff:fe05:685 8082
telnet: connect to address fe80::2d0:83ff:fe05:685: Invalid argument
telnet: Unable to connect to remote host: Invalid argument
[root@localhost ~]# telnet fe80::2d0:83ff:fe05:685%eth0 8082
Connected to fe80::2d0:83ff:fe05:685%eth0 (fe80::2d0:83ff:fe05:685%eth0).
Note how in either case i needed to either add the –I eth0 switch or append the %eth0 to the IP address for the tool to work. The same goes for firefox by the way. If you explicitly define the proxy link local IP in firefox you will need to include the %interface:
Internet Explorer is more forgiving, no need to use the %interface, but remember to enclose the proxy IP in square brackets [ ] :
It may not seem like a big deal to many, but trust me you will forget to do this at some point.
2. One other major troubleshooting drawback when using link local IPv6 addresses is that wireshark will not resolve link local addresses. If you’ve ever seen an IPv6 capture, you know it’s a nightmare to keep track of connections Wireshark can use it’s own local hosts file where you can define IP to hostname mappings to make it easier to keep track of addresses. But this will only work if you are using non link-local addresses. More about how to configure this in a later post.
For those reasons I decided to use unicast unique local (FC00::/7) IPv6 addresses in my testing. Strictly speaking you can use any IPv6 address within that prefix, but in my testing I simply copied the link-local address and changed the first octet from FE80 to FC00. So for example on my linux box I ran:
[root@localhost ~]# ifconfig eth0 add fc00::20c:29ff:fe75:25fa/64
Obviously configure similar IP addresses on the rest of your nodes.
From the proxy side of things, I got this working using both a bluecoat proxy and using the latest squid 3.1 (note: I found that the squid being served in the standard repositories was an older version, so make sure you get the latest squid 3.1).
So on the bluecoat it was relatively easy to get IPv6 working. Via command line we run:
Enter configuration commands, one per line. End with CTRL-Z.
#(config interface 0:1)ipv6 auto-linklocal enable
There is no need to enable ipv6 forwarding. If you then navigate to the interfaces section, you can then see a link local IPv6 address configured on the interface. Simply add your unique unicast local address there:
Make sure that the proxy listeners is set to intercept all explicit communication. The default gateway was of course set to an IPv4 gateway. There is no IPv6 gateway configured. Add the proxy IPv6 address to the browser. That’s it!. You can then see the traffic entering in IPv6 and leaving in IPv4:
Squid wasn’t any more difficult to setup. Make sure that the appropriate IP addresses are configured on your interface. In this case I’m using a one-armed proxy:
[root@localhost ~]# ifconfig eth0
eth0 Link encap:Ethernet HWaddr 00:0C:29:75:25:FA
inet addr:10.91.25.49 Bcast:10.91.25.255 Mask:255.255.255.0
inet6 addr: fc00::20c:29ff:fe75:25fa/64 Scope:Global
inet6 addr: fe80::20c:29ff:fe75:25fa/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:129282 errors:174 dropped:0 overruns:0 frame:0
TX packets:12553 errors:0 dropped:0 overruns:0 carrier:0
RX bytes:102065746 (97.3 MiB) TX bytes:1682607 (1.6 MiB)
Interrupt:59 Base address:0x2000
The default gateway was of course set to an IPv4 gateway. There is no IPv6 gateway configured.
For testing, I didnt change the squid.conf file much, just simply allowed all traffic, and ran
Make sure squid is listening on the IPv6 address:
[root@localhost ~]# netstat -na | grep 3128
tcp 0 0 :::3128 :::* LISTEN
Point your browser to the IPv6 address and that’s about it: