Thursday, March 19, 2015

RA and Prefix Delegation on Ubuntu 14.04

I want my CIS-192 class to have access to public IP addresses for their projects. Unfortunately, there's just not enough IPv4 addresses for everyone. Rick setup prefix delegation on our router at school and I figured out how to integrate DHCP-PD and RA on Ubuntu. I based my efforts on the how-to here, but my network setup is quite different.

My Network

My network is loosely represented on the right. It consists of a Cisco router that is configured for SLAAC for addresses and prefix delegation for routers. Ubuntu has two interfaces. Their configuration is:

eth0: (External Interface) SLAAC
eth1: (Internal Interface) Generated by DHCP-PD from eth0.

Procedure 

Before you begin Ubuntu has to be configured to forward IPv6 packets. The following sysctl settings are required to make that work:

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

In order for a router to accept RAs you must set the accept_ra variable to 2. The accept_ra variable is documented here. The documentation states: 

accept_ra - INTEGER 
  Accept Router Advertisements; autoconfigure using them. 

  It also determines whether or not to transmit Router Solicitations. If and only if the functional setting is to accept Router Advertisements, Router Solicitations will be transmitted. 

  Possible values are: 
    0 Do not accept Router Advertisements. 
    1 Accept Router Advertisements if forwarding is disabled. 
    2 Overrule forwarding behaviour. Accept Router Advertisements even if forwarding is enabled. Functional default: enabled if local forwarding is disabled. disabled if local forwarding is enabled.

Since I must accept RAs to be able to use eth0 this variable must be set to 2. Here's the IPv6 configuration of /etc/network/interfaces:

iface eth0 inet6 static
address 2001:db8::1
netmask 64

iface eth1 inet6 manual 

I've replaced my actual address with the RFC-3949 documentation address. Now I need to acquire a prefix from my DHCP server. I was not able to find any documentation that explained how to make the ISC DHCP client do this. Instead I installed the WIDE DHCP client:

apt-get install wide-dhcpv6-client 

Apt has a configuration script that asks what interface the DHCP client should use for performing DHCP. Be sure to set the interface that's facing the DCHP server (that's eth0 for me). The WIDE DHCP client needs to be told to ask for a prefix. In my case that's all it asks for. 

## this is: /etc/wide-dhcpv6/dhcp6c.conf

# Send a PD request on eth0 (external facing interface)
interface eth0 { 
  send ia-pd 1;
  script "/etc/wide-dhcpv6/dhcp6c-script";
};

# Upon receiving a prefix use the 
# information to set eth1 (internal facing interface)
id-assoc pd 1 {
  prefix-interface eth1 {
    ifid 1;
    sla-id 1;  
    sla-len 0; 
  };
};

It's worth describing the contents of the id-assoc stanza above. The information comes from the manual page. The DHCP client takes the prefix and computes new prefixes and interface addresses based on the lease and the information you've given. For each interface it generates the following:

Network: 
<delegated-prefix:prefix-length>|<sla-id:sla-len>::/64-<sla-len>

Address: 
<delegated-prefix:prefix-length>|<sla-id:sla-len>|<ifid>/64-<sla-len>

The composition is a bit tricky, so let's take an example. Suppose you receive a lease for 2001:db8::/48 and you want to have up to 256 delegated subnets (i.e. sla-len is 8 bits) and had the following configuration:

id-assoc pd 1 {
  prefix-interface eth1 {
    ifid 1;
    sla-id 1;  
    sla-len 8; 
  };
  prefix-interface eth2 {
    ifid 1;
    sla-id 2;  
    sla-len 8; 
  };
  prefix-interface eth3 {
    ifid 1;
    sla-id 3;  
    sla-len 8; 
  };
};

If all worked correctly you would have the following configuration: 

eth1: 2001:db8:0:1::1/56  
eth2: 2001:db8:0:2::1/56
eth3: 2001:db8:0:3::1/56

Astute observers will note that it's not possible to assign networks with a mask greater than 64. This means that if your DCHP server delegates /64 addresses (like mine does) you do not have any bits left for your sla-id so you must set sla-len to 0. If you don't set sla-len correctly the DHCP client silently fails. Grrr.

If all the above works you should be able to see an assigned address on your internal interface. The last step is to restart radvd and have it use the new address as the basis for sending out RAs. First configure radvd to pick up the prefix that's assigned to the interface: 

## this is /etc/radvd.conf
interface eth1
{
   AdvSendAdvert on;
   prefix ::/64 
   {
        AdvOnLink on;
        AdvAutonomous on;
   };
};

The empty prefix (::/64) directive will initially cause an error because radvd starts before the prefix delegation happens. There doesn't seem to be a upstart-y way to fix that so I added the following line to the bottom of my /etc/wide-dhcpv6/dhcp6c-script:

( sleep 10 ; service radvd reload )& 

Anytime the lease is renewed radvd will reload it's configuration files. This is probably close to what you want. The radvd.conf option DecrementLifetimes should probably be set to on. That is what you're supposed to do when you receive a prefix from DHCP. I haven't tried that option yet.

EDIT: This was necessary to make wide-dhcp start at the right time:

mv /etc/rc2.d/S20wide-dhcpv6-client /etc/rc2.d/S99wide-dhcpv6-client


No comments:

Post a Comment