From 31b1b9ba58c00603cde473ccdd02896e117c3d6d Mon Sep 17 00:00:00 2001 From: Jorj Bauer Date: Mon, 22 Feb 2016 11:35:44 -0500 Subject: [PATCH] first fully functional version for vhosts --- DDNS.pm | 19 +++++++ Makefile.PL | 1 + bin/add-vhost | 3 +- bin/list-vhosts | 12 ++--- bin/sync-master-vhosts | 107 ++++++++++++++++++++++++++++++++++++++++ sync-master-vhosts.cron | 2 + 6 files changed, 136 insertions(+), 8 deletions(-) create mode 100755 bin/sync-master-vhosts create mode 100644 sync-master-vhosts.cron diff --git a/DDNS.pm b/DDNS.pm index 280d62d..8eddcc0 100644 --- a/DDNS.pm +++ b/DDNS.pm @@ -98,6 +98,25 @@ sub delvhost { $this->cleanup(); } +sub getvhosts { + my ($this) = @_; + + my $fh; + open($fh, "dig -t AXFR \@127.0.0.1 private.invalid. |") + || die "Can't open dig: $!"; + + my @vh; + + while (<$fh>) { + if (/^(\S+)._vhosts.private.invalid.\s+\d+\s+IN\s+TXT\s+\"(.+)\"$/) { + push (@vh, { zone => $1, + master => $2 }); + } + } + + return @vh; +} + sub cleanup { my ($this) = @_; # Merge the .jnl file in with the domain file diff --git a/Makefile.PL b/Makefile.PL index 7b0b069..d0898cb 100644 --- a/Makefile.PL +++ b/Makefile.PL @@ -10,6 +10,7 @@ WriteMakefile( 'EXE_FILES' => [ 'bin/add-vhost', 'bin/del-vhost', 'bin/list-vhosts', + 'bin/sync-master-vhosts', ], 'AUTHOR' => 'Jorj Bauer ', ); diff --git a/bin/add-vhost b/bin/add-vhost index 51c9b4d..dec4526 100755 --- a/bin/add-vhost +++ b/bin/add-vhost @@ -6,7 +6,8 @@ use Martnet::DDNS; use Regexp::Common qw/net/; my $host = shift || die "No vhost provided"; -my $master = shift || die "No master DNS IP provided"; +#my $master = shift || die "No master DNS IP provided"; +my $master = '74.109.12.14'; die "Hostname must end in a dot" unless ($host =~ /^[a-zA-Z0-9\.\-\_]+\.$/); diff --git a/bin/list-vhosts b/bin/list-vhosts index 8afcfe7..90c51fb 100755 --- a/bin/list-vhosts +++ b/bin/list-vhosts @@ -2,13 +2,11 @@ use strict; use warnings; +use Martnet::DDNS; -my $fh; -open($fh, "dig -t AXFR \@127.0.0.1 private.invalid. |") - || die "Can't open dig: $!"; +my $ddns = Martnet::DDNS->new(); -while (<$fh>) { - if (/^(\S+)._vhosts.private.invalid.\s+\d+\s+IN\s+TXT\s+\"(.+)\"$/) { - print $1, ". master: ", $2, "\n"; - } +my @vh = $ddns->getvhosts(); +foreach my $i (sort {$a->{zone} cmp $b->{zone}} @vh) { + print $i->{zone}, ". master: ", $i->{master},"\n"; } diff --git a/bin/sync-master-vhosts b/bin/sync-master-vhosts new file mode 100755 index 0000000..c2df879 --- /dev/null +++ b/bin/sync-master-vhosts @@ -0,0 +1,107 @@ +#!/usr/bin/perl + +use strict; +use warnings; +use Martnet::DDNS; +use File::Temp qw/tempfile/; + +my $ddns = Martnet::DDNS->new(); + +my @vh = $ddns->getvhosts(); + +# For each virtual host, generate a vhost zone file if there isn't one +my $changecount = 0; +foreach my $i (@vh) { + my $zf = "/etc/bind/vhost/db.$i->{zone}"; + unless ( -f $zf ) { + print "Generating new zone file for $i->{zone}\n"; + open(my $fh, ">", $zf) + || die "Can't create output file $zf: $!"; + create_zonefile($fh, $i); + $changecount++; + } +} + +# For each vhost in /etc/bind/vhost, make sure it has an entry in the zone file. +foreach my $i () { + my ($zone) = ($i =~ /\/db.(.+)$/); + next unless ($zone); + unless (contains_zone($zone, @vh)) { + print "Unlinking old zone file for $zone\n"; + unlink($i); + $changecount++; + } +} + +if ($changecount) { + # If we made any changes, then generate the full vhost list + my ($fh, $path) = tempfile(); + foreach my $i (sort {$a->{zone} cmp $b->{zone}} @vh) { + print $fh "zone \"$i->{zone}\" { type master; file \"/etc/bind/vhost/db.$i->{zone}\"; };\n"; + } + close $fh; + print "Installing new vhost list\n"; + system("install -o bind -g bind $path /etc/bind/vhost.zones.9"); + print "Reloading DNS files\n"; + system("rndc reload"); +} + +exit 0; + +sub contains_zone { + my ($zone, @zl) = @_; + + foreach my $i (@zl) { + return 1 + if ($i->{zone} eq $zone); + } + return 0; +} + +sub create_zonefile { + my ($fh, $i) = @_; + + my $zone = $i->{zone} . "."; + my @now = localtime(); + my $serial = sprintf("%.4d%.2d%.2d00", $now[5]+1900, $now[4]+1, $now[3]); + + print $fh <. +; # del-vhost . +; # list-vhosts +; +\$TTL 43200 +$zone IN SOA ns.martnet.com. root.ns.martnet.com. ( + $serial ; Serial + 43200 ; Refresh every 12 hours + 3600 ; Retry every hour + 604800 ; Expire after a week + 43200 ) ; Negative Cache TTL 12 hours + +; define name servers +$zone IN NS ns.martnet.com +$zone IN NS ns1.martnet.com +$zone IN NS ns2.martnet.com +$zone IN NS ns3.martnet.com +$zone IN NS ns4.martnet.com +$zone IN NS ns5.martnet.com + +; define localhost +localhost IN A 127.0.0.1 + +; define machine names +$zone IN A 74.109.12.4 +$zone IN MX 5 $zone +$zone IN MX 10 mx2.martnet.com. +$zone IN MX 15 mx3.martnet.com. + +*.$zone IN A 74.109.12.4 +*.$zone IN MX 5 $zone +*.$zone IN MX 10 mx2.martnet.com. +*.$zone IN MX 15 mx3.martnet.com. +EOF +; +} diff --git a/sync-master-vhosts.cron b/sync-master-vhosts.cron new file mode 100644 index 0000000..fc52996 --- /dev/null +++ b/sync-master-vhosts.cron @@ -0,0 +1,2 @@ +MAILTO=jorj@jorj.org +* * * * * bind /usr/local/bin/sync-master-vhosts