Dynamic Host Configuration on OpenBSD

Many of my projects at home use embedded computing, sometimes an Arduino clone, but usually a Raspberry Pi. For the Pis, I like to clone an SD card image. By its nature, cloning gives each Pi an identical filesystem, and thus, an identical configuration. So how can I have two Pis with identical filesystems, but one is called "alpha" and has IP address 10.1.1.2, while another is called "beta" and has IP address 10.6.6.3?

Well, on my OpenBSD gateway, I run DHCP and DNS. I configure this DHCP daemon to recognize the unique MAC address of the network adapter of every Raspberry Pi. DHCP assigns a unique IP and a corresponding unique hostname to each host. Finally, the DNS server running on the gateway resolves each of these hostnames to their respective IP addresses (and also resolves the IP to the name).

This article outlines the configuration necessary for a proper setup to accomplish this dynamic host configuration. Here, I'm using the network block 10.1.1.0/24. The gateway (which runs DHCPD and BIND for DNS) is on 10.1.1.1, and the domain is foreverlarz.com.

Of course, you don't have to use OpenBSD. FreeBSD, NetBSD, or Debian Linux would also work, as would a packaged (read: easier) solution like pfSense, BSDRP, or OpenWRT. I use a PC Engines alix2d2 for my gateway hardware; I highly recommend their products for embedded network devices. I bought the alix2d2 back in 2010; today, in 2016, I would undoubtedly choose one of their APU2 computers. However, I think you could also accomplish a similar result with an old Linksys modem and OpenWRT (then iterate toward OpenBSD on a PC Engines APU2!).

DHCPD Configuration

Add dhcpd_flags="int0" to your /etc/rc.conf.local, where int0 is your local network interface.

/etc/dhcpd.conf

One must specify use-host-decl-names to send the hostname to the DHCP client.

option domain-name "foreverlarz.com";  
option domain-name-servers 10.1.1.1;

subnet 10.1.1.0 netmask 255.255.255.0 {

    option routers 10.1.1.1;

    range 10.1.1.10 10.1.1.19;

    use-host-decl-names on;

    host alpha {
        hardware ethernet aa:aa:aa:aa:aa:aa;
        fixed-address 10.1.1.2;
        # comment on alpha
    }

    host beta {
        hardware ethernet bb:bb:bb:bb:bb:bb;
        fixed-address 10.1.1.3;
        # comment on beta
    }

}
DNS Configuration

Add named_flags="" to your /etc/rc.conf.local.

/var/named/etc/named.conf

Start with your installed configuration. Notice that I'm doing a few important things:

  • Allow clients to query and recurse. This is essential if you want to allow hosts on your network to use this as their DNS server.
  • Add forwarders (such as your ISP's DNS servers) so you get responses with lower latency, and you do not add unnecessary traffic to the root DNS servers. Alternatively, you can use free public DNS servers, such as Google's at 8.8.8.8 and 8.8.4.4.
  • Add your domain's zone for forward lookup (e.g., resolves alpha.foreverlarz.com to 10.6.6.2).
  • Add your domain's reverse zone for reverse lookup (e.g., resolves 10.6.6.2 to alpha.foreverlarz.com).
acl clients {  
        localnets;
        ::1;
};

options {  
        version "";             // remove this to allow version queries
        auth-nxdomain no;       // conform to RFC1035

        allow-recursion { clients; };
        allow-query { clients; };

        listen-on    { any; };
        listen-on-v6 { any; };

        forwarders {
                8.8.8.8;
                8.8.4.4;
        };  // Google's public DNS servers

};

logging {  
        category lame-servers { null; };
};

// Standard zones

zone "." {  
        type hint;
        file "etc/root.hint";
};

zone "localhost" {  
        type master;
        file "standard/localhost";
        allow-transfer { localhost; };
};

zone "127.in-addr.arpa" {  
        type master;
        file "standard/loopback";
        allow-transfer { localhost; };
};

zone "1.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa" {  
        type master;
        file "standard/loopback6.arpa";
        allow-transfer { localhost; };
};

// My zones

zone "foreverlarz.com" {  
        type master;
        file "master/foreverlarz.com";
};

zone "1.1.10.in-addr.arpa" {  
        type master;
        file "master/foreverlarz.com.rev";
};
/var/named/master/foreverlarz.com

You may want to read a book on BIND to fully understand zone configuration if you don't know your way around a DNS zone. A few tips:

  • Trailing periods are necessary for a fully-qualified-domain-name. Omitting the trailing period adds the zone to the end (e.g., "gateway" becomes "gateway.foreverlarz.com.").
  • Increment the zone's serial number each time you make a change to the zone. This is easily accomplished using the date with a couple digits at the end to increment for changes you make within a day. Clearly you don't need to increment by 1 with each change; you should increment by at least 1.
$TTL 6h

@ IN SOA gateway.foreverlarz.com. larz.foreverlarz.com. ( 2016111500 6h 1h 1d 6h )
  IN NS gateway

gateway IN A 10.6.6.1  
alpha   IN A 10.6.6.2  
beta    IN A 10.6.6.3  
modem   IN A 192.168.100.1
/var/named/master/foreverlarz.com.rev
$TTL 6h

@ IN SOA gateway.foreverlarz.com. larz.foreverlarz.com. ( 2016111500 6h 1h 1d 6h )
  IN NS  gateway.foreverlarz.com.
1 IN PTR gateway.foreverlarz.com.  
2 IN PTR alpha.foreverlarz.com.  
3 IN PTR beta.foreverlarz.com.  

I hope this article was brief, without being overly terse. Bon courage!