diff --git a/README.md b/README.md index 5a9f328..d3ad551 100644 --- a/README.md +++ b/README.md @@ -9,6 +9,8 @@ This module is designed for use with the following DNS providers: - [Vultr](https://www.vultr.com/) +- [BIND](https://www.isc.org/bind/) + ## FOSSBilling Module Installation instructions ### 1. Download and Install FOSSBilling: @@ -21,13 +23,19 @@ First, download this repository. After successfully downloading the repository, Go to `[FOSSBilling]/modules/Servicedns/Providers` directory and run the `composer install` command. -### 3. Addition of Synchronization Scripts: +### (BIND Module only) 3. Addition of Synchronization Scripts: + +The BIND provider has an additional synchronization script which can be found at `[FOSSBilling]/modules/Servicedns/Crons/Bind.php`. It needs to be configured with your BIND installation parameters, so it can generate the zones regularly. + +### (BIND Module only) 4. Setting Up the Cron Job: + +You need to set up a hourly cron job that runs the sync module. Open crontab using the command `crontab -e` in your terminal. -**not yet implemented** +Add the following cron job: -### 4. Setting Up the Cron Job: +`0 * * * * php [FOSSBilling]/modules/Servicedns/Crons/Bind.php` -**not yet implemented** +This command schedules the synchronization script to run hourly. ### 5. Activate the DNS hosting module: diff --git a/Servicedns/Crons/Bind.php b/Servicedns/Crons/Bind.php new file mode 100644 index 0000000..5bf1200 --- /dev/null +++ b/Servicedns/Crons/Bind.php @@ -0,0 +1,117 @@ +setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + // Fetch domain names and IDs from service_dns table + $domainsStmt = $pdo->query("SELECT id, domain_name FROM service_dns"); + $domains = $domainsStmt->fetchAll(PDO::FETCH_ASSOC); + $timestamp = time(); + + foreach ($domains as $domain) { + $domainName = $domain['domain_name']; + $domainId = $domain['id']; + + $stmt = $pdo->prepare("SELECT * FROM service_dns_records WHERE domain_id = :domainId"); + $stmt->execute(['domainId' => $domainId]); + + $zone = new Zone($domainName.'.'); + $zone->setDefaultTtl(3600); + + $soa = new ResourceRecord; + $soa->setName('@'); + $soa->setClass(Classes::INTERNET); + $soa->setRdata(Factory::Soa( + 'example.com.', + 'post.example.com.', + $timestamp, + 3600, + 14400, + 604800, + 3600 + )); + $zone->addResourceRecord($soa); + + $ns1 = new ResourceRecord; + $ns1->setName('@'); + $ns1->setClass(Classes::INTERNET); + $ns1->setRdata(Factory::Ns('ns1.nameserver.com.')); + $zone->addResourceRecord($ns1); + + $ns2 = new ResourceRecord; + $ns2->setName('@'); + $ns2->setClass(Classes::INTERNET); + $ns2->setRdata(Factory::Ns('ns2.nameserver.com.')); + $zone->addResourceRecord($ns2); + + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) { + $recordType = $row['type']; + $host = $row['host']; + $value = $row['value']; + $ttl = $row['ttl'] ?? 3600; // Default TTL + + $record = new ResourceRecord(); + $record->setName($host); + $record->setTtl($ttl); + + switch ($recordType) { + case 'A': + $record->setRdata(Factory::A($value)); + break; + case 'AAAA': + $record->setRdata(Factory::Aaaa($value)); + break; + case 'MX': + $priority = $row['priority'] ?? 0; + $record->setRdata(Factory::Mx($priority, $value)); + break; + case 'CNAME': + $record->setRdata(Factory::Cname($value)); + break; + case 'TXT': + $formattedValue = trim($value, '"'); + $record->setRdata(Factory::Txt($formattedValue)); + break; + case 'SPF': + $formattedValue = trim($value, '"'); + $record->setRdata(Factory::Spf($formattedValue)); + break; + case 'DS': + // DS record typically requires key tag, algorithm, digest type, and digest + // Assuming these are provided in a formatted string or individual columns + // $value format should be "keyTag algorithm digestType digest" + list($keyTag, $algorithm, $digestType, $digest) = explode(' ', $value); + $record->setRdata(Factory::Ds($keyTag, $algorithm, $digestType, $digest)); + break; + // ... Other record types + } + + $zone->addResourceRecord($record); + } + + // Generate zone file content for each domain + $builder = new AlignedBuilder(); + $zoneFileContent = $builder->build($zone); + + // Generate zone for each domain and reload BIND + file_put_contents("/var/lib/bind/db.$domainName", $zoneFileContent); + + exec("rndc reload {$domainName}.", $output, $return_var); + exec("rndc notify {$domainName}.", $output, $return_var); + } + +} catch (PDOException $e) { + echo "Connection failed: " . $e->getMessage(); +} diff --git a/Servicedns/Providers/Bind.php b/Servicedns/Providers/Bind.php new file mode 100644 index 0000000..e16dedc --- /dev/null +++ b/Servicedns/Providers/Bind.php @@ -0,0 +1,86 @@ +dnsProvider = new Providers\Vultr($apiToken); break; + case 'Bind': + $this->dnsProvider = new Providers\Bind(); + break; // Add more cases for additional providers default: throw new \FOSSBilling\Exception("Unknown DNS provider: {$providerName}"); diff --git a/Servicedns/html_admin/mod_servicedns_config.html.twig b/Servicedns/html_admin/mod_servicedns_config.html.twig index 56d53b0..a83d98c 100644 --- a/Servicedns/html_admin/mod_servicedns_config.html.twig +++ b/Servicedns/html_admin/mod_servicedns_config.html.twig @@ -11,6 +11,7 @@ +