Finalised the zone generator scripts

Added optimized zone generator for larger zones.
This commit is contained in:
Pinga 2023-08-28 11:56:28 +03:00
parent 55b7f3260a
commit 8cae312a6a
2 changed files with 186 additions and 14 deletions

View file

@ -0,0 +1,172 @@
<?php
require_once 'vendor/autoload.php';
use Badcow\DNS\Zone;
use Badcow\DNS\Rdata\Factory;
use Badcow\DNS\ResourceRecord;
use Badcow\DNS\Classes;
use Badcow\DNS\ZoneBuilder;
$c = require_once 'config.php';
require_once 'helpers.php';
$dsn = "{$c['db_type']}:host={$c['db_host']};dbname={$c['db_database']};port={$c['db_port']}";
try {
$db = new PDO($dsn, $c['db_username'], $c['db_password']);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
$timestamp = time();
$ns1 = 'ns1.namingo.org';
$ns2 = 'ns2.namingo.org';
$sth = $db->prepare('SELECT id, tld FROM domain_tld');
$sth->execute();
while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$tldRE = preg_quote($tld, '/');
$cleanedTld = ltrim(strtolower($tld), '.');
$zone = new Zone('.');
$zone->setDefaultTtl(3600);
$soa = new ResourceRecord;
$soa->setName($cleanedTld . '.');
$soa->setClass(Classes::INTERNET);
$soa->setRdata(Factory::Soa(
$ns1 . '.',
'postmaster.' . $cleanedTld . '.',
$timestamp,
3600,
14400,
604800,
3600
));
$zone->addResourceRecord($soa);
$nsRecord1 = new ResourceRecord;
$nsRecord1->setName($cleanedTld . '.');
$nsRecord1->setClass(Classes::INTERNET);
$nsRecord1->setRdata(Factory::Ns($ns1 . '.'));
$zone->addResourceRecord($nsRecord1);
$nsRecord2 = new ResourceRecord;
$nsRecord2->setName($cleanedTld . '.');
$nsRecord2->setClass(Classes::INTERNET);
$nsRecord2->setRdata(Factory::Ns($ns2 . '.'));
$zone->addResourceRecord($nsRecord2);
// Fetch domains for this TLD
$sthDomains = $db->prepare('SELECT DISTINCT domain.id, domain.name FROM domain WHERE tldid = :id AND (exdate > CURRENT_TIMESTAMP OR rgpstatus = \'pendingRestore\') ORDER BY domain.name');
$sthDomains->execute([':id' => $id]);
while (list($did, $dname) = $sthDomains->fetch(PDO::FETCH_NUM)) {
$sthStatus = $db->prepare("SELECT id FROM domain_status WHERE domain_id = :did AND status LIKE '%Hold' LIMIT 1");
$sthStatus->bindParam(':did', $did, PDO::PARAM_INT);
$sthStatus->execute();
$status_id = $sthStatus->fetchColumn();
if ($status_id) continue;
$dname_clean = trim($dname, "$tldRE.");
$dname_clean = ($dname_clean == "$tld.") ? '@' : $dname_clean;
// NS records for the domain
$sthNsRecords = $db->prepare('SELECT DISTINCT host.name FROM domain_host_map INNER JOIN host ON domain_host_map.host_id = host.id WHERE domain_host_map.domain_id = :did');
$sthNsRecords->execute([':did' => $did]);
while (list($hname) = $sthNsRecords->fetch(PDO::FETCH_NUM)) {
$nsRecord = new ResourceRecord;
$nsRecord->setName($dname_clean . '.');
$nsRecord->setClass(Classes::INTERNET);
$nsRecord->setRdata(Factory::Ns($hname . '.'));
$zone->addResourceRecord($nsRecord);
}
// A/AAAA records for the domain
$sthHostRecords = $db->prepare("SELECT host.name, host_addr.ip, host_addr.addr FROM host INNER JOIN host_addr ON host.id = host_addr.host_id WHERE host.domain_id = :did ORDER BY host.name");
$sthHostRecords->execute([':did' => $did]);
while (list($hname, $type, $addr) = $sthHostRecords->fetch(PDO::FETCH_NUM)) {
$hname_clean = trim($hname, "$tldRE.");
$hname_clean = ($hname_clean == "$tld.") ? '@' : $hname_clean;
$record = new ResourceRecord;
$record->setName($hname_clean . '.');
$record->setClass(Classes::INTERNET);
if ($type == 'v4') {
$record->setRdata(Factory::A($addr));
} else {
$record->setRdata(Factory::AAAA($addr));
}
$zone->addResourceRecord($record);
}
// DS records for the domain
$sthDS = $db->prepare("SELECT keytag, alg, digesttype, digest FROM secdns WHERE domain_id = :did");
$sthDS->execute([':did' => $did]);
while (list($keytag, $alg, $digesttype, $digest) = $sthDS->fetch(PDO::FETCH_NUM)) {
$dsRecord = new ResourceRecord;
$dsRecord->setName($dname_clean . '.');
$dsRecord->setClass(Classes::INTERNET);
$dsRecord->setRdata(Factory::Ds($keytag, $alg, $digest, $digesttype));
$zone->addResourceRecord($dsRecord);
}
}
$builder = new ZoneBuilder();
$completed_zone = $builder->build($zone);
if ($c['dns_server'] == 'bind') {
$basePath = '/etc/bind/zones';
} elseif ($c['dns_server'] == 'nsd') {
$basePath = '/etc/nsd';
} elseif ($c['dns_server'] == 'knot') {
$basePath = '/etc/knot';
} else {
// Default path
$basePath = '/etc/bind/zones';
}
file_put_contents("{$basePath}/{$cleanedTld}.zone", $completed_zone);
}
if ($c['dns_server'] == 'bind') {
exec("rndc reload .{$cleanedTld}", $output, $return_var);
if ($return_var != 0) {
print "Failed to reload BIND. $return_var \n";
}
exec("rndc notify .{$cleanedTld}", $output, $return_var);
if ($return_var != 0) {
print "Failed to notify secondary servers. $return_var \n";
}
} elseif ($c['dns_server'] == 'nsd') {
exec("nsd-control reload", $output, $return_var);
if ($return_var != 0) {
print "Failed to reload NSD. $return_var \n";
}
} elseif ($c['dns_server'] == 'knot') {
exec("knotc reload", $output, $return_var);
if ($return_var != 0) {
print "Failed to reload Knot DNS. $return_var \n";
}
exec("knotc zone-notify .{$cleanedTld}", $output, $return_var);
if ($return_var != 0) {
print "Failed to notify secondary servers. $return_var \n";
}
} else {
// Default
exec("rndc reload .{$cleanedTld}", $output, $return_var);
if ($return_var != 0) {
print "Failed to reload BIND. $return_var \n";
}
exec("rndc notify .{$cleanedTld}", $output, $return_var);
if ($return_var != 0) {
print "Failed to notify secondary servers. $return_var \n";
}
}

View file

@ -14,8 +14,8 @@ require_once 'helpers.php';
$dsn = "{$c['db_type']}:host={$c['db_host']};dbname={$c['db_database']};port={$c['db_port']}";
try {
$dbh = new PDO($dsn, $c['db_username'], $c['db_password']);
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db = new PDO($dsn, $c['db_username'], $c['db_password']);
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
die("Connection failed: " . $e->getMessage());
}
@ -24,13 +24,13 @@ $timestamp = time();
$ns1 = 'ns1.namingo.org';
$ns2 = 'ns2.namingo.org';
$sth = $dbh->prepare('SELECT id, tld FROM domain_tld');
$sth = $db->prepare('SELECT id, tld FROM domain_tld');
$sth->execute();
while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$tldRE = preg_quote($tld, '/');
$cleanedTld = ltrim(strtolower($tld), '.');
$zone = new Zone($cleanedTld . '.');
$zone = new Zone('.');
$zone->setDefaultTtl(3600);
$soa = new ResourceRecord;
@ -59,7 +59,7 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$nsRecord2->setRdata(Factory::Ns($ns2 . '.'));
$zone->addResourceRecord($nsRecord2);
$sth2 = $dbh->prepare('SELECT DISTINCT domain.id, domain.name, domain.rgpstatus, host.name
$sth2 = $db->prepare('SELECT DISTINCT domain.id, domain.name, domain.rgpstatus, host.name
FROM domain
INNER JOIN domain_host_map ON domain.id = domain_host_map.domain_id
INNER JOIN host ON domain_host_map.host_id = host.id
@ -77,7 +77,7 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$sth2->execute([':id' => $id]);
while (list($did, $dname, $rgp, $hname) = $sth2->fetch(PDO::FETCH_NUM)) {
$sthStatus = $dbh->prepare("SELECT id FROM domain_status WHERE domain_id = :did AND status LIKE '%Hold' LIMIT 1");
$sthStatus = $db->prepare("SELECT id FROM domain_status WHERE domain_id = :did AND status LIKE '%Hold' LIMIT 1");
$sthStatus->bindParam(':did', $did, PDO::PARAM_INT);
$sthStatus->execute();
$status_id = $sthStatus->fetchColumn();
@ -88,13 +88,13 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$dname = ($dname == "$tld.") ? '@' : $dname;
$nsRecord = new ResourceRecord;
$nsRecord->setName($dname);
$nsRecord->setName($dname . '.');
$nsRecord->setClass(Classes::INTERNET);
$nsRecord->setRdata(Factory::Ns($hname . '.'));
$zone->addResourceRecord($nsRecord);
}
$sth2 = $dbh->prepare("SELECT host.name, host.domain_id, host_addr.ip, host_addr.addr
$sth2 = $db->prepare("SELECT host.name, host.domain_id, host_addr.ip, host_addr.addr
FROM domain
INNER JOIN host ON domain.id = host.domain_id
INNER JOIN host_addr ON host.id = host_addr.host_id
@ -104,7 +104,7 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$sth2->execute([':id' => $id]);
while (list($hname, $did, $type, $addr) = $sth2->fetch(PDO::FETCH_NUM)) {
$sthStatus = $dbh->prepare("SELECT id FROM domain_status WHERE domain_id = :did AND status LIKE '%Hold' LIMIT 1");
$sthStatus = $db->prepare("SELECT id FROM domain_status WHERE domain_id = :did AND status LIKE '%Hold' LIMIT 1");
$sthStatus->bindParam(':did', $did, PDO::PARAM_INT);
$sthStatus->execute();
$status_id = $sthStatus->fetchColumn();
@ -115,7 +115,7 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$hname = ($hname == "$tld.") ? '@' : $hname;
$record = new ResourceRecord;
$record->setName($hname);
$record->setName($hname . '.');
$record->setClass(Classes::INTERNET);
if ($type == 'v4') {
@ -128,7 +128,7 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
}
// Fetch DS records for domains from the secdns table
$sthDS = $dbh->prepare("SELECT domain_id, keytag, alg, digesttype, digest
$sthDS = $db->prepare("SELECT domain_id, keytag, alg, digesttype, digest
FROM secdns
WHERE domain_id IN (
SELECT id FROM domain
@ -138,7 +138,7 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$sthDS->execute([':id' => $id]);
while (list($did, $keytag, $alg, $digesttype, $digest) = $sthDS->fetch(PDO::FETCH_NUM)) {
$sthStatus = $dbh->prepare("SELECT id FROM domain_status WHERE domain_id = :did AND status LIKE '%Hold' LIMIT 1");
$sthStatus = $db->prepare("SELECT id FROM domain_status WHERE domain_id = :did AND status LIKE '%Hold' LIMIT 1");
$sthStatus->bindParam(':did', $did, PDO::PARAM_INT);
$sthStatus->execute();
$status_id = $sthStatus->fetchColumn();
@ -146,7 +146,7 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
if ($status_id) continue;
// Fetch domain name based on domain_id for the DS record
$sthDomainName = $dbh->prepare("SELECT name FROM domain WHERE id = :did LIMIT 1");
$sthDomainName = $db->prepare("SELECT name FROM domain WHERE id = :did LIMIT 1");
$sthDomainName->bindParam(':did', $did, PDO::PARAM_INT);
$sthDomainName->execute();
$dname = $sthDomainName->fetchColumn();
@ -155,7 +155,7 @@ while (list($id, $tld) = $sth->fetch(PDO::FETCH_NUM)) {
$dname = ($dname == "$tld.") ? '@' : $dname;
$dsRecord = new ResourceRecord;
$dsRecord->setName($dname);
$dsRecord->setName($dname . '.');
$dsRecord->setClass(Classes::INTERNET);
$dsRecord->setRdata(Factory::Ds($keytag, $alg, $digest, $digesttype));