Setup NSD
Create new zone file
vi /var/nsd/etc/nsd.conf
zone:
name: "dynamic.example.com"
# under /var/nsd/zones/
zonefile: "master/dynamic.example.com.zone"
Create zone file(example)
/var/nsd/zones/master/dynamic.example.com.zone
$ORIGIN example.com. ; default zone domain
$TTL 86400 ; default time to live
@ IN SOA dynamic.example.com. admin.example.com. (
0;serial
28800 ; Refresh
7200 ; Retry
864000 ; Expire
86400 ; Min TTL
)
NS ns1.example.com.
;
Enable remote control
Deactivate control-interface on nsd.conf
/var/run/nsd.sock is not see in www chroot
vi /var/nsd/etc/nsd.conf
remote-control:
control-enable: yes
# control-interface: /var/run/nsd.sock
Setup remote-control
nsd-control-setup
Enable NSD
rcctl enable nsd
rcctl start nsd
Set up Slowcgi
Copy perl to www chroot
Detect library for perl and nsd-control
nsd# ldd /usr/bin/perl
/usr/bin/perl:
Start End Type Open Ref GrpRef Name
00000fbcf6721000 00000fbcf6726000 exe 1 0 0 /usr/bin/perl
00000fbfe3210000 00000fbfe359a000 rlib 0 1 0 /usr/lib/libperl.so.22.0
00000fbfb3b94000 00000fbfb3bc5000 rlib 0 2 0 /usr/lib/libm.so.10.1
00000fbf63961000 00000fbf63a56000 rlib 0 2 0 /usr/lib/libc.so.96.2
00000fbf0115e000 00000fbf0115e000 ld.so 0 1 0 /usr/libexec/ld.so
nsd# ldd /usr/sbin/nsd-control
/usr/sbin/nsd-control:
Start End Type Open Ref GrpRef Name
00000bcd4e8c6000 00000bcd4e95d000 exe 1 0 0 /usr/sbin/nsd-control
00000bd01d97f000 00000bd01d9f0000 rlib 0 1 0 /usr/lib/libssl.so.53.0
00000bcf73a7f000 00000bcf73cd4000 rlib 0 2 0 /usr/lib/libcrypto.so.50.0
00000bcfa0d7d000 00000bcfa0d8e000 rlib 0 1 0 /usr/lib/libevent.so.4.1
00000bcfd4c9a000 00000bcfd4d8f000 rlib 0 1 0 /usr/lib/libc.so.96.2
00000bd024370000 00000bd024370000 ld.so 0 1 0 /usr/libexec/ld.so
nsd#
Copy binary and library to www chroot
mkdir -p /var/www/usr/lib/
mkdir -p /var/www/usr/libexec/
cp /usr/bin/perl /var/www/bin/perl
cp /usr/lib/libperl.so.22.0 /var/www/usr/lib/
cp /usr/lib/libc.so.96.2 /var/www/usr/lib/
cp /usr/libexec/ld.so /var/www/usr/libexec/
mkdir -p /var/www/usr/libdata/perl5
cp /usr/libdata/perl5/utf8.pm /var/www/usr/libdata/perl5/
cp /usr/libdata/perl5/strict.pm /var/www/usr/libdata/perl5/
cp /usr/sbin/nsd-control /var/www/bin/nsd-control
cp /usr/lib/libssl.so.53.0 /var/www/usr/lib/
cp /usr/lib/libcrypto.so.50.0 /var/www/usr/lib/
cp /usr/lib/libevent.so.4.1 /var/www/usr/lib/
cp /usr/lib/libc.so.96.2 /var/www/usr/lib/
cp /usr/libexec/ld.so /var/www/usr/libexec/
Enable slowcgi
rcctl enable slowcgi
rcctl start slowcgi
CGI script to edit zone file
Hard link zone file to www chroot
NSD not support dynamic update zone file yet Need CGI to edit zone file and reload
mkdir /var/www/zones
ln /var/nsd/zones/master/dynamic.example.com.zone /var/www/zones/dynamic.example.com.zone
chown www:www /var/www/zones/dynamic.example.com.zone
Copy nsd control key to www chroot
Need copy control key to use nsd-control
mkdir -p /var/www/var/nsd/etc/
cp /var/nsd/etc/nsd.conf /var/www/var/nsd/etc/
chown www:www /var/www/var/nsd/etc/nsd.conf
cp /var/nsd/etc/nsd_control.pem /var/www/var/nsd/etc/
chown www:www /var/www/var/nsd/etc/nsd_control.pem
cp /var/nsd/etc/nsd_control.key /var/www/var/nsd/etc/
chown www:www /var/www/var/nsd/etc/nsd_control.key
cp /var/nsd/etc/nsd_server.pem /var/www/var/nsd/etc/
chown www:www /var/www/var/nsd/etc/nsd_server.pem
CGI script
touch /var/www/cgi-bin/dns-dyn chmod +x /var/www/cgi-bin/dns-dyn vi /var/www/cgi-bin/dns-dyn
#!/bin/perl
use utf8;
use strict;
my $file = '/zones/dynamic.example.com.zone';
my $serial = 'serial';
sub update {
my $rec = shift;
my $ip = shift;
my $ip6 = shift;
open( my $fh, "<$file" ) or die "File not found";
my @lines = <$fh>;
close($fh);
my $found = 0;
my $change = 0;
foreach (@lines) {
if (/\d+;$serial/) {
my $t = time;
$_ =~ s/\d+;\Q$serial\E/$t;$serial/;
}
elsif ( $ip && /^\Q$rec\E.*(\d+\.\d+\.\d+\.\d+)/ ) {
$found = 1;
next if ( $ip eq $1 );
$_ =~ s/\Q$1\E/$ip/;
$change = 1;
}
elsif ( $ip6 && /^\Q$rec\E.*([0-9a-fA-F]+\:[\:0-9a-fA-F]+)/ ) {
$found = 1;
next if ( $ip6 eq $1 );
$_ =~ s/\Q$1\E/$ip6/;
$change = 1;
}
}
unless ($found) {
push( @lines, sprintf( '%-35s A %s', $rec, $ip ), "\n" )
if ($ip);
push( @lines, sprintf( '%-35s AAAA %s', $rec, $ip6 ), "\n" )
if ($ip6);
$change = 1;
}
if ($change) {
open( my $fh, ">$file" ) or die "File not found";
print $fh @lines;
close($fh);
}
return $change;
}
my $query_string = $ENV{'QUERY_STRING'};
my %query = map { split '=' } split( '&', $query_string );
my $ipv4 = $query{'ipv4'};
my $ipv6 = $query{'ipv6'};
my $ip = $query{'ip'} || $ENV{'REMOTE_ADDR'};
my $host = $query{'host'} || $ENV{'REMOTE_USER'};
if ( $ENV{'REMOTE_USER'} && ( $host ne $ENV{'REMOTE_USER'} ) ) {
print "Status: 403\n";
print "Content-type: text/plain\n\n";
print "Not authorization. Username not match record.\n";
exit;
}
if ( $host !~ /^([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\-]*[A-Za-z0-9])$/ ) {
print "Status: 400\n";
print "Content-type: text/plain\n\n";
print "Hostname invalid: $host\n";
exit;
}
if ( !$ipv4 && !$ipv6 ) {
if ( $ip =~ /(\d+\.\d+\.\d+\.\d+)/ ) { $ipv4 = $1; }
elsif ( $ip =~ /([\:0-9a-fA-F]+)/ ) { $ipv6 = $1; }
}
if ( $ipv4 && $ipv4 !~ /(\d+\.\d+\.\d+\.\d+)/ ) {
print "Status: 400\n";
print "Content-type: text/plain\n\n";
print "IPv4 invalid: $ipv4\n";
exit;
}
if ( $ipv6 && $ipv6 !~ /([0-9a-fA-F]+\:[\:0-9a-fA-F]+)/ ) {
print "Status: 400\n";
print "Content-type: text/plain\n\n";
print "IPv6 invalid: $ipv6\n";
exit;
}
print "Content-type: text/plain\n\n";
print "Record $host: $ip\n";
print "nsd-control: ", qx(/bin/nsd-control reload 2>&1)
if ( update( $host, $ipv4, $ipv6 ) );
Set up httpd
httpd config
vi /etc/httpd.conf
server "default" {
listen on * port 80
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
#block return 301 "https://$HTTP_HOST$REQUEST_URI"
}
server "dns.example.com" {
listen on * port 80
root "/htdocs/"
location "/dyn/update" {
fastcgi
root "/cgi-bin/dns-dyn"
}
}
Optional password protect
Make .htpasswd file, repeat command to add multiple user
htpasswd /var/www/conf/.htpasswd USERNAME
nsd# htpasswd /var/www/conf/.htpasswd test1
Password:
Retype Password:
nsd# htpasswd /var/www/conf/.htpasswd test2
Password:
Retype Password:
nsd#
Add authenticate to httpd.conf
vi /etc/httpd.conf
location "/dyn/update" {
authenticate with "/conf/.htpasswd"
fastcgi
root "/cgi-bin/dns-dyn"
}
Enable httpd
rcctl enable httpd
rcctl start httpd
Access url to update IP
Example url
http://dns.example.com/dyn/update?host=test
http://dns.example.com/dyn/update?host=test&ip=1.2.3.4
With password protect
http://test1:test@dns.example.com/dyn/update
http://test1:test@dns.example.com/dyn/update&ip=1.2.3.4