namedhcp
is an IPv6 DHCP server implementation for IPV6 stateful
autoconfiguration. When namedhcp
receives a DHCP query including the fqdn
option (option 39 as defined in RFC4704) it queries the DNS for an AAAA record.
If there is such a record, the IPv6 address is returned to the DHCP client.
The configuration of the networking nodes (hosts, servers, internet of things
objects, internet of threads processes)
is very simple in this way, it is sufficient to provide each
node with its own fully qualified domain name. It very convenient to use this
tool is together with
iothnamed
configured to provide hash based IP addresses.
In fact, each node provided with a fully qualified domain name can receive from
iothnamed
(through namedhcp
) its corresponding hash based IPv6 address and
it is reachable by that name without any further configuration.
The same idea of namedhcp
can be used in IPV4. Hash based addresses cannot be implemented in IPv4 due to the narrow
address space provided by four bytes only.
Anyway the ability to provide hosts with IPv4 addresses depending only on their names (fully qualified names) is useful for
network administrators aiming to manage large numbers of hosts (and networking namespaces).
namedhcp4
permits to keep the map of the name to address translation in one file. This information is
neither distributed on several hosts or file
nor duplicated.
Without namedhcp4
, IPv4 addresses need to be configured consistently both on the host (or on the dhcp server)
and in the dns server configuration files.
Install prerequisite libraries: libioth volatilestream iothdns iothconf stropt vdeplug
Get the source code, from the root of the source tree run:
$ mkdir build
$ cd build
$ cmake ..
$ make
$ sudo make install
The syntax of the namedhcp
and namedhcp4
command is the same:
namedhcp OPTIONS
namedhcp4 OPTIONS
where options are:
--rcfile|-f <conffile>
: read the options from a configuration file, see the next section.--stack|-s <ioth_stack_conf> or VNL
: the configuration of the ioth stack to provide the dhcp service (using the syntax ofioth_newstackc
in iothconf) OR a VDE VNL (see vdeplug4). In this latter case a UDPv6 emulation is used.namedhcp
uses the kernel stack if this option is omitted.--dnsstack|-R <resolver_ioth_stack_conf>
: the configuration of the stack used to DNS queries. If this option is omitted the same stack used for dhcp is used (or the kernel stack if--stack
argument is a VNL)--iface|-i <interface>
: select the inteerface for dhcp (default valuevde0
)--resolvconf|-r <resolvconf_file>
: resolv.conf file (see resolv.conf(5)),/etc/resolv.conf
if omitted.--nameserver|-n <dns_server_list>
: set a list of dns servers (alternative to--resolvconf
).--macaddr|-m <mac_address>
: set the dhcp server MAC addr.--dns|-D <dns_server_list>
: dhcp option sent to clients (option 23, RFC 8415 -- option 6, RFC 2132 for IPv4)--dnssearch|-S <domain_list>
: dhcp option sent to clients (option 24, RFC 8415 -- option 15, RFC 2132 for IPv4)--ntp|-N <ntp_server_list>
: dhcp option sent to clients (option 31, RFC 8415 -- option 42, RFC 2132 for IPv4)--daemon|-d
: run the program in daemon mode (see daemon(3)).--pidfile|-p <pidfile>
: save the pid in the file (useful for scripts).
The configuration file loaded using the option -f
or --rcfile
has the following syntax:
- lines beginning by '#' are comments.
- the other lines have a tag and may have an argument if required by the tag.
The tags have the same name of the long options (
--something
) of the command line, their arguments have the same syntax and meaning of each equivalent command line option. Command line arguments have priority on the configuration file specifications: if the same tag is specified as a command line option and in the configuration file, the value in the command line is taken and the other ignored.
stack <ioth_stack_conf> or VNL
dnsstack <resolver_ioth_stack_conf>
iface <interface>
resolvconf <resolvconf_file>
nameserver <dns_server_list>
macaddr <mac_address>
dns <dns_server_list>
dnssearch <domain_list>
ntp <ntp_server_list>
daemon
pidfile <pidfile>
In IPv6 the network prefix and the router address is normally provided by the Router Advertisement/ Router Solicitation protocol as defined in "Neighbor Discovery for IP Version 6 (IPv6)" (RFC 4861).
DHCPv6 provides the host/node address, and other configuration parameters (like DNS or NTP servers).
The first example tests how to configure some network nodes using pre-defined addresses, in a second example we'll see how to use hash based addresses.
First of all let we start a VDE network. For example we can use a virtual HUB (useful if you want to add a vdens and trace all the networks packets using wireshark).
$ vde_plug null:// hub:///tmp/hub
The IPv6 network used in this test is not connected to the Internet and has no router, thus we need a router advertisement daemon server to provide nodes with the right prefix. This step is not needed if real global IPv6 addresses are used and the network is routed to the Internet.
iothradvd -s vde:///tmp/hub -P 10 fc00::/64/L/86400/14400
Then we need to set up a DNS server providing the IPv6
Let us write the following configuration file for iothnamed (named iothnamed.dhcp.test
):
rstack stack=vdestack,vnl=vde:///tmp/hub
rstack mac=80:01:01:01:01:01,eth
rstack ip=fc00::24/64
fstack stack=kernel
dns 8.8.8.8
dns 80.80.80.80
net local fc00::/64
auth accept local
auth static local .test.local
auth static local fc00::/64
static AAAA one.test.local fc00::1
static AAAA two.test.local fc00::2
static PTR fc00::1 one.test.local
static PTR fc00::2 two.test.local
auth cache local .
auth fwd local .
and start the DNS server:
iothnamed iothnamed.dhcp.test
The next step consists of starting the namedhcp server:
$ namedhcp -s "stack=vdestack,vnl=vde:///tmp/hub,ip=fc00::ffff/64,eth" -n fc00::24
Now the infrastructure is complete and we can start two vdens.
$ vdens -R fc00::24 /tmp/hub
$ ip link set vde0 up
$ echo 'send fqdn.fqdn "one.test.local";' > one.conf
$ truncate -s 0 one.leases
$ /sbin/dhclient -6 -cf one.conf -v vde0 -lf one.leases -pf /dev/null
ad the other is:
$ vdens -R fc00::24 /tmp/hub
$ ip link set vde0 up
$ echo 'send fqdn.fqdn "two.test.local";' > two.conf
$ truncate -s 0 two.leases
$ /sbin/dhclient -6 -cf two.conf -v vde0 -lf two.leases -pf /dev/null
Now it is possible to ping one vdens from the other and viceversa.
$ ping -n two.test.local
$ ping -n one.test.local
A second example involves hash based ipv6 addresses.
Use the VDE network previously defined for the first experiment or restart it:
vde_plug null:// hub:///tmp/hub
the configration for the name server iothnamed is the file iothnamed.hash.test
:
rstack stack=vdestack,vnl=vde:///tmp/hub
rstack mac=80:01:01:01:01:01,eth
rstack ip=fc00::24/64
fstack stack=kernel
dns 8.8.8.8
dns 80.80.80.80
net local fc00::/64
auth accept local
auth static local hash.local
static AAAA hash.local fc00::
auth hash local .hash.local hash.local
auth hrev local hash.local/64
auth cache local .
auth fwd local .
option hrevmode always
thus the iothnamed server can be started:
iothnamed iothnamed.hash.test
The namedhcp
can be started as in the previous example
namedhcp -s "stack=vdestack,vnl=vde:///tmp/hub,ip=fc00::ffff/64,eth" -n fc00::24
as well as the radvd (given that the test netowrk has not a real router):
iothradvd -s vde:///tmp/hub -P 10 fc00::/64/L/86400/14400
Start two (or more) vdens:
$ vdens -R fc00::24 /tmp/hub
$ ip link set vde0 up
$ echo 'send fqdn.fqdn "h1.hash.local";' > h1.conf
$ truncate -s 0 h1.leases
$ /sbin/dhclient -6 -cf h1.conf -v vde0 -lf h1.leases -pf /dev/null
and
$ vdens -R fc00::24 /tmp/hub
$ ip link set vde0 up
$ echo 'send fqdn.fqdn "h2.hash.local";' > h2.conf
$ truncate -s 0 h2.leases
$ /sbin/dhclient -6 -cf h2.conf -v vde0 -lf h2.leases -pf /dev/null
... Several nodes can be added just by naming them something.hash.local
. Each node receives its own
IPv6 address via DHCP and the DNS is able to resolve its name without any specific configuration.
IPv4 has a narrow address set so it is not possible to use hash based IP addresses. Anyway a DHCPv4 server retrieving the address from the DNS can be useful: the configuration of IP addresses, masks, routing can be gotten from the DNS. In this way hosts, as well as namespaces, virtual machines or IoTh processes can be configured given their fully qualified domain name (FQDN) only. Updates of the hardware settings (e.g. using a different network interface) or relocating virtual network nodes require in this way no changes in their configuration.
This example needs a DNS server able to resolve the FQDNs of the hosts. For each host the IP address
returned by namedhcpv4
is the A record defined in the DNS.
For the other DHCP options namedhcpv4
uses a TXT record, a list of tag=value entries. e.g.:
mask=255.255.255.0,broadcast=192.168.1.255,router=192.168.1.254,dns=192.168.1.24
This example uses a VDE network. In a terminal window type:
vde_plug null:// hub:///tmp/hub
A test configuration file for iothnamed is the follwing:
## example: define local names and forward other request.
rstack stack=vdestack,vnl=vde:///tmp/hub
rstack mac=80:01:01:01:01:01,eth
rstack ip=192.168.1.24/24
fstack stack=kernel
dns 8.8.8.8
dns 80.80.80.80
net local 192.168.1.0/24
auth accept local
auth static local .test.local
auth static local 192.168.1.0/24
auth cache local .
auth fwd local .
static A one.test.local 192.168.1.1
static TXT one.test.local "mask=255.255.255.0,broadcast=192.168.1.255,router=192.168.1.254,dns=192.168.1.24"
static A two.test.local 192.168.1.2
static TXT two.test.local "mask=255.255.255.0,broadcast=192.168.1.255,router=192.168.1.254,dns=192.168.1.24"
static PTR 192.168.1.1 one.test.local
static PTR 192.168.1.2 two.test.local
Let us name the configuration above namedhcp4.named.conf
.
The iothnamed
service can be start by the command (at a shell prompt, e.g. a terminal window):
$ iothnamed namedhcp4.named.conf
Now start namedhcp4
:
$ namedhcp4 -s "stack=vdestack,vnl=vde:///tmp/hub,ip=192.168.1.25/24,eth" -n 192.168.1.24
The infrastructure is complete.
Let us start two vdens
and configure them just by naming them one.test.local
and
two.test.local
. We need a trick as glibc has the file /etc/resolv/conf
hardcoded in its source code
(see this comment on VirtualSquare wiki)
We'll use udhcpc
provided as a service by busybox, and the following dhcpscript
:
#!/bin/busybox sh
#set -x
RESOLV_CONF="/etc/resolv.conf"
[ -z "$1" ] && echo 'Error: should be called from udhcpc' && exit 1
case "$1" in
deconfig)
# bring interface up, but with no IP configured:
ip addr flush dev $interface
ip link set $interface up
;;
bound)
# configure interface and routes:
ip addr flush dev $interface
ip addr add ${ip}/${mask} dev $interface
[ -n "$router" ] && ip route add default via ${router%% *} dev $interface
# set the DNS
[ -n "$domain" ] && R="domain $domain" || R=""
for i in $dns; do
R="$R
nameserver $i"
done
echo "$R" > "$RESOLV_CONF"
;;
renew)
;;
esac
exit 0
Start the first vdens:
$ touch /tmp/rc1
$ vdens -r /tmp/rc1 /tmp/hub
$ busybox udhcpc -s dhcpscript -f -q -F one.test.local -i vde0
and the second:
$ touch /tmp/rc2
$ vdens -r /tmp/rc2 /tmp/hub
$ busybox udhcpc -s dhcpscript -f -q -F two.test.local -i vde0
Now it is possible to ping the second from the fist and viceversa.
$ ping -n two.test.local
PING two.test.local (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.379 ms
...
$ ping -n one.test.local
PING one.test.local (192.168.1.1) 56(84) bytes of data.
64 bytes from 192.168.1.1: icmp_seq=1 ttl=64 time=0.303 ms
...
The two namespaces have been configured just by defining their FQDN, no IP address appears in any command.