1
0
Fork 0
mirror of https://github.com/fernwerker/ownDynDNS.git synced 2025-07-13 23:15:43 +02:00

added domain restriction capability

This commit is contained in:
Nils Blume 2023-08-23 23:47:23 +02:00
parent f2bfa9008f
commit fac7616c25
5 changed files with 139 additions and 21 deletions

View file

@ -11,20 +11,25 @@ Self-hosted dynamic DNS php script to update netcup DNS API from Router like AVM
### Installation ### Installation
* Copy all files to your webspace * Copy all files to your webspace
* create a copy of `.env.dist` as `.env` and configure: * 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 Parameter | Example | Explanation
* `apiKey` -> API key which is generated in netcup CCP ---: | :--- | :---
* `apiPassword` -> API password which is generated in netcup CCP `username` | dnsupdater | The username for your Router to authenticate (so not everyone can update your DNS)
* `customerId` -> your netcup Customer ID `password` | secretpleasechange | password for your Router
* `log` -> true|false enables logging `apiKey` | 18neqwd91e21onei1p23841 | API key which is generated in netcup CCP
* `logFile` -> configures logfile location if enabled `apiPassword` | 82jewqde9m30 | API password which is generated in netcup CCP
* `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. `customerId` | 12345 | your netcup Customer ID
* `returnIp` -> true|false enables return of result if a record was changed `log` | `true` / false | enables logging
* `allowCreate` -> true|false allows creation of entries if parameter `create=true` in URL `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) * 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. <s>The script does not create any missing records.</s><br>
You can now set `allowCreate=true` in .env and pass `create=true` as URL parameter to create entries on the fly.
## URL possible uses: ## URL possible uses:

12
mydomain/.env.dist Normal file
View file

@ -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"

20
mydomain/update.php Executable file
View file

@ -0,0 +1,20 @@
<?php
error_reporting(-1);
ini_set('display_errors', 1);
ini_set('html_errors', 0);
header('Content-Type: text/plain; charset=utf-8');
require_once __DIR__ . '/../src/Soap.php';
require_once __DIR__ . '/../src/Config.php';
require_once __DIR__ . '/../src/Payload.php';
require_once __DIR__ . '/../src/Handler.php';
if (!file_exists('.env')) {
throw new RuntimeException('.env file missing');
}
$config = parse_ini_file('.env', false, INI_SCANNER_TYPED);
(new netcup\DNS\API\Handler($config, $_REQUEST))->doRun();

View file

@ -55,6 +55,21 @@ final class Config
*/ */
private $allowCreate = false; private $allowCreate = false;
/**
* @var bool
*/
private $restrictDomain = false;
/**
* @var string
*/
private $domain;
/**
* @var string
*/
private $host;
public function __construct(array $config) public function __construct(array $config)
{ {
@ -158,4 +173,58 @@ final class Config
{ {
return $this->allowCreate; 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);
}
} }

View file

@ -124,8 +124,21 @@ final class Handler
$this->doLog(sprintf('api login failed, message: %s', $loginHandle->longmessage)); $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( $infoHandle = $dnsClient->infoDnsRecords(
$this->payload->getDomainName(), $updateDomainName,
$this->config->getCustomerId(), $this->config->getCustomerId(),
$this->config->getApiKey(), $this->config->getApiKey(),
$loginHandle->responsedata->apisessionid, $loginHandle->responsedata->apisessionid,
@ -138,10 +151,9 @@ final class Handler
$txtchanges = false; $txtchanges = false;
foreach ($infoHandle->responsedata->dnsrecords as $key => $record) { 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 === $updateDomain) {
if ($recordHostnameReal === $this->payload->getDomain()) {
// found matching entry, no need to create one // found matching entry, no need to create one
$exists = true; $exists = true;
@ -154,7 +166,7 @@ final class Handler
) )
) { ) {
$record->destination = $this->payload->getIpv4(); $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; $ipv4changes = true;
} }
@ -166,7 +178,7 @@ final class Handler
) )
) { ) {
$record->destination = $this->payload->getIpv6(); $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; $ipv6changes = true;
} }
@ -178,7 +190,7 @@ final class Handler
) )
) { ) {
$record->destination = $this->payload->getTxt(); $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; $txtchanges = true;
} }
} }
@ -195,7 +207,7 @@ final class Handler
{ {
$record = new Soap\Dnsrecord(); $record = new Soap\Dnsrecord();
$record->hostname = $this->payload->getHost(); $record->hostname = $updateHost;
$record->type = $type; $record->type = $type;
$record->priority = "0"; // only for MX, can possibly be removed $record->priority = "0"; // only for MX, can possibly be removed
@ -218,7 +230,7 @@ final class Handler
$dnsClient->updateDnsRecords( $dnsClient->updateDnsRecords(
$this->payload->getDomainName(), $updateDomainName,
$this->config->getCustomerId(), $this->config->getCustomerId(),
$this->config->getApiKey(), $this->config->getApiKey(),
$loginHandle->responsedata->apisessionid, $loginHandle->responsedata->apisessionid,
@ -235,7 +247,7 @@ final class Handler
$recordSet->dnsrecords = $infoHandle->responsedata->dnsrecords; $recordSet->dnsrecords = $infoHandle->responsedata->dnsrecords;
$dnsClient->updateDnsRecords( $dnsClient->updateDnsRecords(
$this->payload->getDomainName(), $updateDomainName,
$this->config->getCustomerId(), $this->config->getCustomerId(),
$this->config->getApiKey(), $this->config->getApiKey(),
$loginHandle->responsedata->apisessionid, $loginHandle->responsedata->apisessionid,