From fac7616c25e085f9cf0fc2de8a3bb5af98cc3872 Mon Sep 17 00:00:00 2001 From: Nils Blume Date: Wed, 23 Aug 2023 23:47:23 +0200 Subject: [PATCH] added domain restriction capability --- README.md | 27 ++++++++++-------- mydomain/.env.dist | 12 ++++++++ mydomain/update.php | 20 +++++++++++++ src/Config.php | 69 +++++++++++++++++++++++++++++++++++++++++++++ src/Handler.php | 32 ++++++++++++++------- 5 files changed, 139 insertions(+), 21 deletions(-) create mode 100644 mydomain/.env.dist create mode 100755 mydomain/update.php diff --git a/README.md b/README.md index 7e53618..d3b8e31 100644 --- a/README.md +++ b/README.md @@ -11,20 +11,25 @@ Self-hosted dynamic DNS php script to update netcup DNS API from Router like AVM ### Installation * Copy all files to your webspace * create a copy of `.env.dist` as `.env` and configure: - * `username` -> The username for your Router to authenticate (so not everyone can update your DNS) - * `password` -> password for your Router - * `apiKey` -> API key which is generated in netcup CCP - * `apiPassword` -> API password which is generated in netcup CCP - * `customerId` -> your netcup Customer ID - * `log` -> true|false enables logging - * `logFile` -> configures logfile location if enabled - * `debug` -> true|false enables debug mode and generates more output from update.php (normal operation has no output). Needed to receive stack traces from errors. - * `returnIp` -> true|false enables return of result if a record was changed - * `allowCreate` -> true|false allows creation of entries if parameter `create=true` in URL + +Parameter | Example | Explanation +---: | :--- | :--- +`username` | dnsupdater | The username for your Router to authenticate (so not everyone can update your DNS) +`password` | secretpleasechange | password for your Router +`apiKey` | 18neqwd91e21onei1p23841 | API key which is generated in netcup CCP +`apiPassword` | 82jewqde9m30 | API password which is generated in netcup CCP +`customerId` | 12345 | your netcup Customer ID +`log` | `true` / false | enables logging +`logFile` | log.json | configures logfile location if enabled +`debug` | true / `false` | enables debug mode and generates more output from update.php (normal operation has no output). Needed to receive stack traces from errors. +`returnIp` | `true` / false | enables return of result if a record was changed +`allowCreate` | true/`false` | allows creation of entries if parameter `create=true` in URL +`restrictDomain` | true / `false` | allows admin to restrict the domain to update to a given value `domain` and/or `host`. See URL parameters for host parameter explanation * alternatively you can use .configure.sh to create your .env file for you (if you are on a *NIX system) -* Create each host record in your netcup CCP (DNS settings) before using the script. The script does not create any missing records. +* Create each host record in your netcup CCP (DNS settings) before using the script. The script does not create any missing records.
+You can now set `allowCreate=true` in .env and pass `create=true` as URL parameter to create entries on the fly. ## URL possible uses: diff --git a/mydomain/.env.dist b/mydomain/.env.dist new file mode 100644 index 0000000..50635c3 --- /dev/null +++ b/mydomain/.env.dist @@ -0,0 +1,12 @@ +username="max_mustermann" +password="s3cr3t" +apiKey="netcup DNS API Key" +apiPassword="netcup DNS API Password" +customerId="netcup customer ID" +debug=true +log=true +logFile=log.json +returnIp=true +allowCreate=false +restrictDomain=false +domain="mydomain.example.com" diff --git a/mydomain/update.php b/mydomain/update.php new file mode 100755 index 0000000..bbb8b8e --- /dev/null +++ b/mydomain/update.php @@ -0,0 +1,20 @@ +doRun(); diff --git a/src/Config.php b/src/Config.php index 12e4d24..aa85c5c 100644 --- a/src/Config.php +++ b/src/Config.php @@ -55,6 +55,21 @@ final class Config */ private $allowCreate = false; + /** + * @var bool + */ + private $restrictDomain = false; + + /** + * @var string + */ + private $domain; + + /** + * @var string + */ + private $host; + public function __construct(array $config) { @@ -158,4 +173,58 @@ final class Config { return $this->allowCreate; } + + /** + * @return bool + */ + public function isRestrictDomain() + { + return $this->restrictDomain; + } + + /** + * @return string + */ + public function getDomain() + { + if (empty($this->host)) + { + return $this->domain; + } + else + { + return $this->host . "." . $this->domain; + } + } + + /** + * @return string + */ + public function getHost() + { + if (!empty($this->host)) + { + return $this->host; + } + else + { + $domainParts = explode('.', $this->domain); + return $domainParts[0]; + } + } + + /** + * @return string + */ + public function getDomainName() + { + // hack if top level domain are used for dynDNS + if (1 === substr_count($this->domain, '.')) { + return $this->domain; + } + + $domainParts = explode('.', $this->domain); + array_shift($domainParts); // remove sub domain + return implode('.', $domainParts); + } } diff --git a/src/Handler.php b/src/Handler.php index afa4278..9882782 100644 --- a/src/Handler.php +++ b/src/Handler.php @@ -124,8 +124,21 @@ final class Handler $this->doLog(sprintf('api login failed, message: %s', $loginHandle->longmessage)); } + // check if domain is restricted in config, force use of config values for domain and host + if ($this->config->isRestrictDomain()) { + $this->doLog('domain is restricted by .env file'); + $updateDomain = $this->config->getDomain(); + $updateDomainName = $this->config->getDomainName(); + $updateHost = $this->config->getHost(); + $this->doLog(sprintf('ignoring received domain, using configured domain: %s', $updateDomain)); + } else { + $updateDomain = $this->payload->getDomain(); + $updateDomainName = $this->payload->getDomainName(); + $updateHost = $this->payload->getHost(); + } + $infoHandle = $dnsClient->infoDnsRecords( - $this->payload->getDomainName(), + $updateDomainName, $this->config->getCustomerId(), $this->config->getApiKey(), $loginHandle->responsedata->apisessionid, @@ -138,10 +151,9 @@ final class Handler $txtchanges = false; foreach ($infoHandle->responsedata->dnsrecords as $key => $record) { - $recordHostnameReal = (!in_array($record->hostname, $this->payload->getMatcher())) ? $record->hostname . '.' . $this->payload->getDomainName() : $this->payload->getDomainName(); + $recordHostnameReal = (!in_array($record->hostname, $this->payload->getMatcher())) ? $record->hostname . '.' . $updateDomainName : $updateDomainName; - - if ($recordHostnameReal === $this->payload->getDomain()) { + if ($recordHostnameReal === $updateDomain) { // found matching entry, no need to create one $exists = true; @@ -154,7 +166,7 @@ final class Handler ) ) { $record->destination = $this->payload->getIpv4(); - $this->doLog(sprintf('IPv4 for %s set to %s', $record->hostname . '.' . $this->payload->getDomainName(), $this->payload->getIpv4())); + $this->doLog(sprintf('IPv4 for %s set to %s', $record->hostname . '.' . $updateDomainName, $this->payload->getIpv4())); $ipv4changes = true; } @@ -166,7 +178,7 @@ final class Handler ) ) { $record->destination = $this->payload->getIpv6(); - $this->doLog(sprintf('IPv6 for %s set to %s', $record->hostname . '.' . $this->payload->getDomainName(), $this->payload->getIpv6())); + $this->doLog(sprintf('IPv6 for %s set to %s', $record->hostname . '.' . $updateDomainName, $this->payload->getIpv6())); $ipv6changes = true; } @@ -178,7 +190,7 @@ final class Handler ) ) { $record->destination = $this->payload->getTxt(); - $this->doLog(sprintf('TXT for %s set to %s', $record->hostname . '.' . $this->payload->getDomainName(), $this->payload->getTxt())); + $this->doLog(sprintf('TXT for %s set to %s', $record->hostname . '.' . $updateDomainName, $this->payload->getTxt())); $txtchanges = true; } } @@ -195,7 +207,7 @@ final class Handler { $record = new Soap\Dnsrecord(); - $record->hostname = $this->payload->getHost(); + $record->hostname = $updateHost; $record->type = $type; $record->priority = "0"; // only for MX, can possibly be removed @@ -218,7 +230,7 @@ final class Handler $dnsClient->updateDnsRecords( - $this->payload->getDomainName(), + $updateDomainName, $this->config->getCustomerId(), $this->config->getApiKey(), $loginHandle->responsedata->apisessionid, @@ -235,7 +247,7 @@ final class Handler $recordSet->dnsrecords = $infoHandle->responsedata->dnsrecords; $dnsClient->updateDnsRecords( - $this->payload->getDomainName(), + $updateDomainName, $this->config->getCustomerId(), $this->config->getApiKey(), $loginHandle->responsedata->apisessionid,