Stupid IPv6 Tricks

June 22nd, 2015

Today, I was given a VM with an IPv6 address, but it had no IPv6 default route:

$ route -A inet6
Kernel IPv6 routing table
Destination Next Hop Flags Metric Ref Use Iface
2001:db8:80:fd::/64 * U 256 1 0 eth1
fe80::/64 * U 256 0 0 eth1
localhost/128 * U 0 48 1 lo
2001:db8:80:fd::67:8/128 * U 0 77 1 lo
fe80::a00:32ff:feb7:73cd/128 * U 0 53 1 lo
ff00::/8 * U 256 0 0 eth1

Sadness.

I was also not given the router I needed to set the default route to. But no fear, we can ping the router multicast address!

$ ping6 ff02::2 -I eth1 -c1
PING ff02::2(ff02::2) from fe80::a00:32ff:feb7:73cd eth1: 56 data bytes
64 bytes from fe80::a00:32ff:fe4f:9ebc: icmp_seq=1 ttl=64 time=0.411 ms
--- ff02::2 ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.411/0.411/0.411/0.000 ms

And all is solved!

# route -A inet6 add default gw fe80::a00:43ff:fe4f:9ebc dev eth1
$ route -A inet6
Kernel IPv6 routing table
Destination Next Hop Flags Metric Ref Use Iface
2001:db8:80:fd::/64 * U 256 1 0 eth1
fe80::/64 * U 256 0 0 eth1
*/0 fe80::a00:32ff:fe4f:9ebc UG 1 0 0 eth1
localhost/128 * U 0 48 1 lo
2001:db8:80:fd::67:8/128 * U 0 77 1 lo
fe80::a00:32ff:feb7:73cd/128 * U 0 53 1 lo
ff00::/8 * U 256 0 0 eth1
$ ping6 facebook.com -c1
PING facebook.com(edge-star6-shv-12-frc3.facebook.com) 56 data bytes
64 bytes from edge-star6-shv-12-frc3.facebook.com: icmp_seq=1 ttl=48 time=163 ms
--- facebook.com ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 163.953/163.953/163.953/0.000 ms

And there was much rejoicing!

Enabling a DHCPv6 client with Prefix Delegation ability on Ubuntu Server

April 11th, 2013

What is Prefix Delegation?
Prefix Delegation (PD) is a mechanism for a DHCPv6 server to let a home networking router ask for an IPv6 prefix (subnet) that the router can then split up and delegate to the clients it serves.

Why?
In the (hopefully) not too distant future, ISPs will be offering native IPv6. Since there is no NAT in IPv6, and most people have at least a couple of computers sitting behind a hardware NAT box, they will need to get IPv6 addresses for every device they have. This is done via DHCPv6 and PD. When your ISP is ready (if it isn’t already) you’ll be able to use this to participate in the IPv6 world!

How?
Let’s just dig in then!
Required software:

  • wide-dhcp6c
  • RADVD

 

Why wide-dhcp6c, instead of ISC’s dhclient with IPv6 options?

  1. IPv6 documentation on dhclient is lacking and almost non-existant.
  2. wide-dhcp6c has the ability to assign a block from the received PD block to an interface.
  3. ISC requires you to run a separate instance for v6 anyway.

 

For this example network:
eth0 = WAN (ISP facing) interface
eth1 = LAN (home network) interface

in /etc/sysctl.conf add/set:

net.ipv6.conf.all.forwarding = 1
net.ipv6.conf.eth0.accept_ra=2

This makes the server a router (forwarding = 1) and allows eth0 to continue accepting Router Advertisements to get it’s default route. (by default, it will no longer accept Router Advertisements when forwarding is set.)

in /etc/network/interfaces add/set:

iface eth0 inet6 static

We set it to static because we will not be using the ISC DHCP client to obtain our IPv6 address and prefix, we will be using the wide dhcpv6 client.

To install the wide dhcpv6 client run this on the command line:

sudo apt-get install wide-dhcpv6-client

On install, you will get a prompt like this:
click to embiggen!
Enter the WAN interface (eth0 in our case)

Configure wide dhcp6c

cd /etc/wide-dhcp6c
sudo nano dhcp6c.conf

make it look like:

interface eth0 { # external facing interface (WAN)
  send ia-na 1;
  send ia-pd 1;
  request domain-name-servers;
  request domain-name;
  script "/etc/wide-dhcpv6/dhcp6c-script";
};

id-assoc pd 1 {
  prefix-interface eth1 { #internal facing interface (LAN)
    sla-id 0; # subnet. Combined with ia-pd to configure the subnet for this interface.
    ifid 1; #IP address "postfix". if not set it will use EUI-64 address of the interface. Combined with SLA-ID'd prefix to create full IP address of interface.
    sla-len 8; # prefix bits assigned. Take the prefix size you're assigned (something like /48 or /56) and subtract it from 64. In my case I was being assigned a /56, so 64-56=8
    };
  };

  id-assoc na 1 {
  # id-assoc for eth1
};

Install RADVD

sudo apt-get install radvd

Then change the default start from S20 to S98 and add a 10 second delay (to run *after* wide-DHCPv6 is done, otherwise it can’t pick up the IPv6 prefix that has been assigned)
– get normal runlevel:

/sbin/runlevel
N 2

Go to the runlevel directory:

cd /etc/rc2.d

(replace the 2 with the number from previous command)

mv S20radvd S98radvd

Edit S98radvd and add

sleep 10

after the first set of comments.
We move it to S98 so pretty much everything else is done starting and we’re not delaying anything important by that 10 seconds.

Configure the following in /etc/radvd.conf
interface eth1 # LAN interface
{
AdvManagedFlag off; # no DHCPv6 server here.
AdvOtherConfigFlag off; # not even for options.
AdvSendAdvert on;
AdvDefaultPreference high;
AdvLinkMTU 1280;
prefix ::/64 #pick one non-link-local prefix assigned to the interface and start advertising it
{
AdvOnLink on;
AdvAutonomous on;
};
};

Restart radvd
sudo /etc/init.d/radvd restart

And if your ISP has a DHCPv6 server running, you should have a happy IPv6 address everywhere.
To check if things are working:
ifconfig eth0
ifconfig eth1
(to see if IPv6 addresses are assigned.)
If you don’t have an IPv6 address on these interfaces that doesn’t start with fe80::, then it’s likely (at this point) that your ISP doesn’t have IPv6 enabled.

Writing an IPv6 Address – The 6 Commandments of RFC5952

February 13th, 2012

When we write down IPv4 addresses, no one really has to go over just how you write them. Most people get it after only a little while of seeing it done. 4 sets of numbers, from 0 to 255, each separated by a “.”.
When IPv6 started to be developed, it quickly became apparent that there needed to be an easier way to write it out than (for example)
2001:0db8:0000:0000:0000:0000:0000:0001.
Even if you quickly realize that you could drop the leading zeros (as we naturally do in “dotted decimal”), it’s still fairly unwieldy:
2001:db8:0:0:0:0:0:1
even if it is much better.
So the idea of the double colon was introduced to combine sets of zero’s together. The first RFC’s said that 1 or more groups of 16 bits of zeros could be combined to “::”
2001:db8::1
That’s almost usable! Of course it won’t always go that easily, especially if you start using SLAAC to configure your network:
2001:db8::93e6:baff:febd:6533
Darn. But still better than nothing.
Unfortunately, even with these rules, there wasn’t enough of them for the machines who are the ultimate users of these. By the rules that are defined in earlier RFC’s, all of these are valid:
2001:db8::1
2001:0db8::1
2001:0db8:0::1
2001:0db8:0::0:0001
(etc)
and case wasn’t ever discussed either:
2001:dB8:0::DeAd:BEEF
is perfectly legit.
This makes it harder to write code for things that need to decode these addresses. And RFC 5952 was written to try and address these shortcomings.

Here are the 6 commandments of RFC 5952:
1) Thou shalt not SHOUT your IPv6 address.

    IPv6 must be written in lowercase. 2001:db8::1 not 2001:DB8::1

2) Thou shall destroy leading zeros.

    Always truncate leading zeros. 2001:0db8::1 is not acceptable, you must use 2001:db8::1

3) Thou shalt not use the double colon where there is only one 16 bit set of zeros.

    If you only have one set of 4 zeros, you can no longer use the double colon, instead it just gets shortened to one zero. An address such as 2001:db8:0000:4:5:6:7:8 can’t use the double colon and only gets shortened to 2001:db8:0:4:5:6:7:8

4) Thou shall use the double colon to it’s greatest potential.

    If you have multiple sets of more than 8 zeros, you have to use the set with the most zeros. So if you have 2001:db8:0000:0000:1:0000:0000:0000 you have to use the double colon on the right set of 0’s – 2001:db8:0:0:1::

5) Wheresoever thou has two places to use the double colon, thou shall use the leftmost.

    If there are 2 equal sets of zeros, use the double colon on the one on the left, and single zeros on the right. 2001:db8:0000:0000:1:0000:0000:1 would become 2001:db8::1:0:0:1

6) Thou shall use the square brackets to separate IPv6 address from thy port number.

    When writing an IPv6 address with a port number, use square brackets around the IPv6 address to keep confusion at bay, since ports are appended with a : (the same separator as IPv6 sections): [2001:db8::1]:80 With the square brackets, we know it’s IPv6 address 2001:db8::1 on port 80, not IPv6 address 2001:db8::1:80

IPv6 Friday

February 13th, 2012

This site looks to be quite the resource. I think it’s my favorite new IPv6 website/blog. Every Friday, IPv6 Friday encourages you to spend 30 minutes learning/testing something new about IPv6. Take some time out of your Friday and get on the bandwagon!

World IPv6 Launch

February 12th, 2012

Just under one year after World IPv6 Day comes World IPv6 Launch. Organizations are coming together to *permanantly* enable IPv6 for their sites/customers. This is the event most of us have been waiting for. Once IPv6 is running on major sites full time, we’ll really get to test out infrastructure and troubleshooting on it. However, it will also mean that anyone that is looking to enable IPv6 on their network from that point onward will have to be very careful about how they do it. Much more will be at stake, as there will be major sites that will prefer IPv6, so any issues will be quickly noticed! Of course that also means that the days of multi-day IPv6 outages should be over! 🙂

Simple Approach to Prefix Distribution in Basic Home Networks

January 31st, 2012

Here’s a draft (on it’s way to becoming an RFC) up at the IETF that describes how home networks could distribute IPv6 addresses obtained from an ISP.

http://tools.ietf.org/html/draft-chakrabarti-homenet-prefix-alloc-01

It’s nice to see some of this work finally being done! Also, while they say “Basic Home Networks”, by today’s standards, some of the examples are quite advanced (however that’s not saying it will always remain that way!)

UPDATE
As is often the case, this draft expired. However, it’s not forgotten as it’s been resurrected here

World IPv6 Day is here!

June 7th, 2011

World IPv6 day appears to be off and running to a pretty awesome start, if Hurricane Electric’s stats are anything to go by. They posted an image of their traffic about 1 hour after the start of IPv6 and, well, take a look:
he.net traffic

Akaimai also has a nice graph of their traffic at http://www.akamai.com/ipv6
Boom!

IPv6 Firewalling with ip6tables

March 30th, 2011

Now that you’ve gotten IPv6 configured on your home network, forget about relying on NAT to be your “firewall”. All your devices now have a globally routed IP (v6) address, so it’s time to get familiar with a setting up a “real” firewall.

Since my IPv6 router is a linux box that is also other things (server, wireless access point, etc) I can’t set up a nice dedicated firewall like pfsense (currently IPv6 is enabled on the beta versions) without spending more money and quite a bit more work. So I’ll work with what I have – ip6tables

Here’s a simple set of ip6tables rules I’ve come up with. You’ll want to tweak these for your specific site. Mine are called from /etc/rc.local

# IPv6 firewall (ipv6tables)
WAN_IF=he-ipv6
LAN_IF=eth0
WLAN_IF=wlan0
#flush tables
ip6tables -F

#Define Policy
ip6tables -P INPUT DROP
ip6tables -P FORWARD DROP
ip6tables -P OUTPUT ACCEPT

# Input to the router
# Allow all loopback traffic
ip6tables -A INPUT -i lo -s 0/0 -d 0/0 -j ACCEPT

#Allow unrestricted access on internal network
ip6tables -A INPUT -i $LAN_IF -j ACCEPT
ip6tables -A INPUT -i $WLAN_IF -j ACCEPT

#Allow unrestricted outgoing connections
ip6tables -A INPUT -i $WAN_IF -m state --state RELATED,ESTABLISHED -j ACCEPT

# Forwarding through from the internal network
# For now allow unrestricted access out from the internal network
ip6tables -A FORWARD -i $LAN_IF -j ACCEPT
ip6tables -A FORWARD -i $WLAN_IF -j ACCEPT

#Allow unrestricted outgoing connections
ip6tables -A FORWARD -i $WAN_IF -m state --state RELATED,ESTABLISHED -j ACCEPT

# allow SSH in
ip6tables -A FORWARD -s 2000::/3 -i $WAN_IF -p tcp -m tcp --dport 22 -j ACCEPT

# allow remote desktop in
ip6tables -A FORWARD -s 2000::/3 -i $WAN_IF -p tcp -m tcp --dport 3389 -j ACCEPT

# Drop everything else
ip6tables -A FORWARD -i $WAN_IF -j DROP

#allow everything to our router/server.
ip6tables -A INPUT -s 0/0 -d 2001:470:81e5::1/128 -j ACCEPT

# Drop everything else
ip6tables -A INPUT -i $WAN_IF -j DROP

In a few places, I only allow packets from 2000::/3. Currently this encompasses all of the global IPv6 addresses, so I could have easily used 0/0 (equivalent to ::/0 or “anywhere”) but I’m okay with being a little more specific here. In fact, for some of them (like ssh and remote desktop) I should be even more specific, but this is a start.

Ensure you can test your rules before leaving them on. I had some rules ordered incorrectly (I tried adding some rules after the “Drop everything else” rule for the chain) and broke www to ipcalypse.ca for a while. (oops!). To verify www, dns and smtp on my server, I used http://go6.se/check/ to test these rules.

Enable IPv6 Privacy Extensions on Ubuntu

March 19th, 2011

With SLAAC, your MAC address is embedded into your IPv6 address. When you connect to the world, you’re giving them something that can be traced back to you (or at least a piece of hardware you have). RFC3041 was created to help address this privacy issue. It’s since been obsoleted by RFC4941. The Linux kernel does support these RFCs, but most distributions do not turn it on by default. While the below was tested on Ubuntu, it should theoretically work for most flavors of Linux.

First, determine which interface(s) you want to enable the privacy extensions:


$ ifconfig
eth2      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx  
          inet addr:192.168.0.2  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: 2001:db8::xxxx:xxff:fexx:xxxx/64 Scope:Global
          inet6 addr: fe80::xxxx:xxff:fexx:xxxx/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6547155 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3594147 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:9470877266 (9.4 GB)  TX bytes:313893925 (313.8 MB)
          Interrupt:42 Base address:0xe000 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:859192 errors:0 dropped:0 overruns:0 frame:0
          TX packets:859192 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:418471854 (418.4 MB)  TX bytes:418471854 (418.4 MB)

In my case it’s eth2 (and no, I don’t know what happened to eth0 and eth1 ;).

Add the following lines to /etc/sysctl.conf:

net.ipv6.conf.eth2.use_tempaddr = 2
net.ipv6.conf.all.use_tempaddr = 2
net.ipv6.conf.default.use_tempaddr = 2

*Note that the first line could (and most likely would) be different for your particular set up.

after that, restart your network (or if you like, restart your computer altogether) and you should see a new address


$ ifconfig
eth2      Link encap:Ethernet  HWaddr xx:xx:xx:xx:xx:xx  
          inet addr:192.168.0.2  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: 2001:db8::xxxx:xxff:fexx:xxxx/64 Scope:Global
          inet6 addr: fe80::xxxx:xxff:fexx:xxxx/64 Scope:Link
          inet6 addr: 2001:db8::9dd7:675f:8d2b:d78a/64 Scope:Global
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:6565518 errors:0 dropped:0 overruns:0 frame:0
          TX packets:3607197 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:9493464492 (9.4 GB)  TX bytes:315035089 (315.0 MB)
          Interrupt:42 Base address:0xe000 

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:861796 errors:0 dropped:0 overruns:0 frame:0
          TX packets:861796 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0 
          RX bytes:419488499 (419.4 MB)  TX bytes:419488499 (419.4 MB)

Outgoing connections will now use the new “random” ipv6 address. You can verify by going to http://test-ipv6.com

xkcd.com

February 25th, 2011

Just noticed (via @henet on twitter) that xkcd.com is now sporting an AAAA record:

$ dig aaaa xkcd.com

; <<>> DiG 9.7.0-P1 <<>> aaaa xkcd.com
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 28275 ;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0 ;; QUESTION SECTION: ;xkcd.com. IN AAAA ;; ANSWER SECTION: xkcd.com. 270 IN AAAA 2001:48c8:1:d:0:23:5482:d026 ;; Query time: 636 msec ;; SERVER: 64.59.135.143#53(64.59.135.143) ;; WHEN: Fri Feb 25 06:33:11 2011 ;; MSG SIZE rcvd: 54

The best part is that it doesn’t seem to be a tunnel, and xkcd’s host (Voxel) is running true native dual stack:

$ traceroute xkcd.com -f 7
traceroute to xkcd.com (72.26.203.99), 30 hops max, 60 byte packets
7 equinix-ix.ord1.us.voxel.net (206.223.119.107) 43.713 ms 47.946 ms 52.495 ms
8 910.te4-3.tsr1.lga3.us.voxel.net (208.122.44.133) 70.260 ms 70.248 ms 70.456 ms
9 0.ae59.tsr1.lga5.us.voxel.net (208.122.44.202) 71.796 ms 69.963 ms 69.826 ms
10 0.ae57.csr2.lga6.us.voxel.net (208.122.44.210) 69.970 ms 71.774 ms 71.762 ms
11 72.26.203.99 (72.26.203.99) 71.628 ms 69.762 ms 69.435 ms

$ traceroute6 xkcd.com -f 4
traceroute to xkcd.com (2001:48c8:1:d:0:23:5482:d026), 30 hops max, 80 byte packets
4 equinix-ix.sjc1.us.v6.voxel.net (2001:504:0:1:0:2:9791:1) 51.188 ms 58.107 ms 60.402 ms
5 ve16.tsr2.iad1.us.voxel.net (2001:48c8::801) 146.855 ms 146.911 ms 146.821 ms
6 0.te6-2.tsr1.ewr1.us.voxel.net (2001:48c8::811) 137.073 ms 137.044 ms 137.029 ms
7 0.te1-4.tsr1.lga5.us.voxel.net (2001:48c8::819) 135.758 ms 136.719 ms 135.739 ms
8 0.ae2.csr2.lga6.us.voxel.net (2001:48c8::82e) 136.702 ms 139.450 ms 139.429 ms
9 2001:48c8:1:d:0:23:5482:d026 (2001:48c8:1:d:0:23:5482:d026) 139.242 ms 121.606 ms 126.777 ms

Welcome to the IPv6 fold xkcd!