# pvl-hosts
DNS/DHCP hosts management/integration for ISC bind9 and dhcpd.
## Hosts
The `pvl.hosts-*` tools read hosts files as input, which have an ini format, using section names as hostnames to configure attributes for that host:
[foo]
ip = 192.0.2.1
ethernet = 00:11:22:33:44:55
[bar]
ip = 192.0.2.2
ethernet = 01:23:45:67:89:ab
The domain name for a host is determined from the basename of the config file, so this example file would generate something like the following output for use in a `zone "example.com" { ... }` zonefile:
$ bin/pvl.hosts-forward etc/hosts/example.com
foo A 192.0.2.1
bar A 192.0.2.2
And correspondingly, the reverse zone for `2.0.192.in-addr.arpa`:
$ bin/pvl.hosts-reverse --zone-prefix=192.0.2.0/24 etc/hosts/example.com
1 PTR foo.example.com.
2 PTR bar.example.com.
And the associated DHCP hosts:
$ bin/pvl.hosts-dhcp etc/hosts/example.com
host foo {
option host-name foo;
hardware ethernet 00:11:22:33:44:55;
fixed-address 192.0.2.1;
}
host bar {
option host-name bar;
hardware ethernet 01:23:45:67:89:ab;
fixed-address 192.0.2.2;
}
### Include directories
Host configs can be included:
$ cat etc/hosts/test
include = test.d/
$ cat etc/hosts/test.d/foo
ip = 192.0.2.1
$ cat etc/hosts/test.d/bar
ip = 192.0.2.2
$ bin/pvl.hosts-forward etc/hosts/test
foo A 192.0.2.1
bar A 192.0.2.2
Including a directory of files is equivalent to substituiting each file as a named section at the level of the include = statement. Note that this means that included files are treated directly as host definitions, IOW, you should NOT include a section name in an included host file unless you want to declare an additional subdomain:
$ cat etc/hosts/wrong.test
include = wrong.d/
$ etc/hosts/wrong.d/host
[host]
ip = 192.0.2.6
Using the --root-zone option to generate the full FQDN for the host:
$ bin/pvl.hosts-forward --root-zone etc/hosts/wrong.test
host.host.wrong.test A 192.0.2.6
### Host aliases
Hosts can specify DNS aliases:
[foo]
ip = 127.0.0.1
alias = test1
alias4 = test
[bar]
ip = 127.0.0.2
alias = test2
alias4 = test
$ bin/pvl.hosts-forward etc/hosts/alias.test
foo A 127.0.0.1
test1 CNAME foo
test A 127.0.0.1
bar A 127.0.0.2
test2 CNAME bar
test A 127.0.0.2
Normal CNAME aliases cannot overlap with other hosts, but the IPv4/IPv6-only `alias4`/`alias6` may overlap.
### Generated hosts
The hosts file format supports something similar to bind9's $GENERATE directive for hosts:
[dyn{1-8}]
ip = 10.1.16.$
$ bin/pvl.hosts-forward etc/hosts/dyn.test
dyn1 A 10.1.16.1
dyn2 A 10.1.16.2
dyn3 A 10.1.16.3
dyn4 A 10.1.16.4
dyn5 A 10.1.16.5
dyn6 A 10.1.16.6
dyn7 A 10.1.16.7
dyn8 A 10.1.16.8
This feature can be used for generating reverse delegations:
[foo-{240-247}]
forward =
reverse = $.240/29.0.0.10.in-addr.arpa
ip = 10.0.0.$
$ bin/pvl.hosts-reverse --zone-prefix=10.0.0.0/16 etc/hosts/reverse.test
240.0 CNAME 240.240/29.0.0.10.in-addr.arpa.
241.0 CNAME 241.240/29.0.0.10.in-addr.arpa.
242.0 CNAME 242.240/29.0.0.10.in-addr.arpa.
243.0 CNAME 243.240/29.0.0.10.in-addr.arpa.
244.0 CNAME 244.240/29.0.0.10.in-addr.arpa.
245.0 CNAME 245.240/29.0.0.10.in-addr.arpa.
246.0 CNAME 246.240/29.0.0.10.in-addr.arpa.
247.0 CNAME 247.240/29.0.0.10.in-addr.arpa.
### DHCP Options
The hosts need not specify any fixed ip address, leaving IP address allocation to dhcpd:
[foo]
ethernet = 00:11:22:33:44:55
$ bin/pvl.hosts-dhcp etc/hosts/dhcp.test
host foo {
option host-name foo;
hardware ethernet 00:11:22:33:44:55;
}
### DHCP Boot options
The hosts can specify DHCP boot server/file options:
boot.next-server = boot.test
[foo]
ethernet = 00:11:22:33:44:55
boot = boot2.test:/debian/wheezy/pxelinux.0
[bar]
ethernet = 00:11:22:33:44:55
boot.filename = /debian/jessie/pxelinux.0
$ bin/pvl.hosts-dhcp etc/hosts/boot.test
host foo {
option host-name foo;
hardware ethernet 00:11:22:33:44:55;
next-server boot2.test;
filename "/debian/wheezy/pxelinux.0";
}
host bar {
option host-name bar;
hardware ethernet 00:11:22:33:44:55;
next-server boot.test;
filename "/debian/jessie/pxelinux.0";
}
### DHCP hosts in multiple subnets/domains
A host with different interfaces in multiple domains must specify unique interface names:
[foo]
[[asdf]]
ip = 10.1.0.1
ethernet.eth1 = 00:11:22:33:44:55
[bar]
[[asdf]]
ip = 10.2.0.1
ethernet.eth2 = 55:44:33:22:11:00
$ bin/pvl.hosts-dhcp etc/hosts/dhcp-test
host asdf-eth1 {
option host-name asdf;
hardware ethernet 00:11:22:33:44:55;
fixed-address 10.1.0.1;
}
host asdf-eth2 {
option host-name asdf;
hardware ethernet 55:44:33:22:11:00;
fixed-address 10.2.0.1;
}
### DHCP subgroups
Hosts can be assigned to DHCP subgroups by hardware ethernet:
#### `dhcpd.conf`
class "test-hosts" {
match hardware;
}
#### `etc/hosts/dhcp-classes.test`
[foo]
ethernet = 00:11:22:33:44:55
dhcp:subclass = test-hosts
#### `bin/pvl.hosts-dhcp etc/hosts/dhcp-classes.test`
host foo {
option host-name foo;
hardware ethernet 00:11:22:33:44:55;
}
subclass "test-hosts" 1:00:11:22:33:44:55;
# `update`
A script to drive the *pvl.hosts* tools for maintaing a set of zone/host files for a DNS/DHCP server.
## Source host files
Creating a tree of symlinks for managing split zonefile domains can be useful:
$ tree etc/zones/
etc/zones/
├── forward
│ └── test
│ ├── asdf.test -> ../../../hosts/asdf.test
│ └── test -> ../../../hosts/test
├── reverse
│ └── 192.0.2
│ ├── asdf.test -> ../../../hosts/asdf.test
│ └── test -> ../../../hosts/test
└── test
Given a structure like above, the `pvl.hosts-forward` can generate a single forward zone containing all sub-domains:
$ bin/pvl.hosts-forward --hosts-include etc/hosts/ etc/zones/forward/test/
foo A 192.0.2.1
bar A 192.0.2.2
quux.asdf A 192.0.2.5
Note that the directory name is treated separately as a zone origin; the file names within the domain are still treated as a flat namespace independent of the directory name (which is different than *pvl.hosts* would behave for `include = etc/zones/forward/test/`).
The same trick also works for `pvl.hosts-reverse`:
$ bin/pvl.hosts-reverse --hosts-include etc/hosts/ etc/zones/reverse/192.0.2/
1 PTR foo.test.
2 PTR bar.test.
5 PTR quux.asdf.test.
## Source zone files
The zonefile header should be written out manually, using an `$INCLUDE` directive to reference the (generated) hosts zonefile:
$ cat etc/zones/test
$TTL 3600
@ SOA foo.test. hostmaster.test. (
0 ; serial
1d ; refresh
5m ; retry
10d ; expiry
300 ; negative
)
NS foo
NS bar
$INCLUDE "forward/test"
## Operation
Use the *update* script to generate a complete set of output zonefiles:
$ ./bin/update
Commit...
Using commit timestamp: 1425049508
Updating forward host zones...
var/zones/forward/test: Generating forward hosts zone: etc/zones/forward/test
Updating reverse host zones...
var/zones/reverse/192.0.2: Generating reverse hosts zone: etc/zones/reverse/192.0.2
Updating DHCP hosts...
Copying zone includes...
Updating zones...
var/serials/test: Update serial: 1425049508 <- 1425049508
var/zones/test: Generate zone: etc/zones/test
Updating DHCP confs...
Testing zones...
Reload zones...
Reload zones
rndc: server reload successful
Testing DHCP...
Reload DHCP...
## Output zone files
The generated zone files can then be loaded by bind:
$ cat var/zones/test
$TTL 3600
@ SOA foo.test. hostmaster.test. 1425049508 1d 5m 10d 300
NS foo
NS bar
$INCLUDE "./var/zones/forward/test"
$ cat var/zones/forward/test
foo A 192.0.2.1
bar A 192.0.2.2
quux.asdf A 192.0.2.5
# *pvl-dns*
Low-level zonefile utilities.
## `bin/pvl.dns-process`
Process a zonefile to modify:
* `SOA` record serial
* `$INCLUDE` paths
$ bin/pvl.dns-process --serial $(date +%s) --include-path var/zones etc/zones/test
$TTL 3600
@ SOA foo.test. hostmaster.test. 1425049088 1d 5m 10d 300
NS foo
NS bar
$INCLUDE "var/zones/forward/test"
## `bin/pvl.dns-zone`
Load a zonefile and output any ZoneRecords that it contains, including `$GENERATE`ed and `$INCLUDE`ed records:
$ bin/pvl.dns-zone --zone=test var/zones/test
@ 3600 SOA foo.test. hostmaster.test. 1425049248 1d 5m 10d 300
@ 3600 NS foo
@ 3600 NS bar
foo 3600 A 192.0.2.1
bar 3600 A 192.0.2.2
quux.asdf 3600 A 192.0.2.5
Optionally `--check-hosts` for dupliates `A`/`AAAA` records.
Use `--reverse-prefix=192.0.2` to generate a reverse-dns zone from `A`/`AAAA` records:
$ bin/pvl.dns-zone --zone=test var/zones/test --reverse-prefix=192.0.2
1 PTR foo.test.
2 PTR bar.test.
5 PTR quux.asdf.test.
# Experimental features
Features that are still under development
* DHCP host status tracking from syslog/dhcpd.leases into a database
* SNMP network topology discovery