Skip to content

Instantly share code, notes, and snippets.

@msaladna
Created November 29, 2020 21:13
Show Gist options
  • Save msaladna/809f67cd829babcf33befa4eca27bf8d to your computer and use it in GitHub Desktop.
Save msaladna/809f67cd829babcf33befa4eca27bf8d to your computer and use it in GitHub Desktop.
<?php
class Ipinfo_Module_Surrogate extends Ipinfo_Module
{
/** external MySQL connection to apnscp.domains */
private static $domain_db;
/**
* Legal DNS resource records permitted by provider
* A
* AAAA
* MX
* CNAME
* DNAME
* HINFO
* TXT
* NS
* SRV
*
* @var array
*/
protected static $permitted_records = array(
'A',
'AAAA',
'CAA',
'CNAME',
'HINFO',
'MX',
'NAPTR',
'NS',
'SOA',
'SRV',
'TXT',
);
private static function __parse($resp, $orig, $new = '', $nsCMD = '')
{
if (!$resp) {
return true;
}
if (false !== strpos($resp, 'NXRRSET')) {
return error('Non-existent DNS record `' . $orig . "'");
} else if (false !== strpos($resp, 'YXRRSET')) {
return error('DNS record `' . $new . "' exists");
} else if (false !== strpos($resp, 'NOTAUTH')) {
return error("Non-authoritative response on zone `$orig'");
} else if (false !== strpos($resp, 'REFUSED')) {
return error("DNS server refused record `$orig'");
} else if (false !== strpos($resp, 'invalid rdata format: not a valid number')) {
if (false !== strpos($nsCMD, ' MX ')) {
return error('MX records must be of format {NUMERIC PRIORITY} {HOSTNAME}');
} else {
return error('SRV records must be of format {NUMERIC PRIORITY} {WEIGHT} {PORT} {TARGET}');
}
} else if (false !== strpos($resp, ': unbalanced quotes')) {
return error('missing opening or ending quotation (") mark');
} else if (false !== strpos($resp, ': bad dotted quad')) {
return error('DNS record must be of numeric format, e.g. 127.0.0.1');
} else if (false !== strpos($resp, ': timed out') && $nsCMD) {
usleep(5000);
return self::__send($nsCMD) || fatal('cannot connect to DNS server');
}
Error_Reporter::report('Unknown DNS resp - ' . $resp);
return error("DNS server refused record: `%s'", trim($resp));
}
// {{{ domain_expiration()
private static function __send($cmd)
{
if (!\Dns_Module::MASTER_NAMESERVER) {
return false;
}
$key = explode(':', DNS_TSIG_KEY);
$cmd = 'server ' . \Dns_Module::MASTER_NAMESERVER . "\n" .
'key ' . $key[0] . ' ' . $key[1] . "\n" .
$cmd . "\n" . 'send' . "\n";
$file = tempnam('/tmp', 'dns');
file_put_contents($file, $cmd, LOCK_EX);
chmod($file, 0600);
$status = Util_Process::exec('nsupdate ' . $file, array('mute_stderr' => true));
unlink($file);
usleep(5000);
return $status;
}
/**
* Release PTR assignment from an IP
*
* @param $ip
* @param string $domain confirm PTR rDNS matches domain
* @return bool
*/
protected function _deleteIP(string $ip, string $domain = null): bool
{
$rev = \Opcenter\Dns\General::reverseIP($ip);
$node = substr($rev, 0, strpos($rev, '.'));
$fqdn = $rev . '.in-addr.arpa.';
if ($domain) {
$domain = ' ' . rtrim($domain) . '.';
}
$cmd = 'prereq yxrrset ' . $fqdn . ' PTR' . $domain . "\n" .
'update delete ' . $fqdn . ' PTR';
$resp = self::__send($cmd);
if (!is_debug() && !$resp['success']) {
error("cannot release $ip - " . $resp[1]);
return false;
}
info("Released $ip");
return true;
}
/**
* Change PTR name
*
* @param $ip IP address to alter
* @param $hostname new PTR name
* @param string $chk optional check hostname to verify
* @return bool
*/
protected function _changePTR(string $ip, string $hostname, string $chk = ''): bool
{
$rev = \Opcenter\Dns\General::reverseIP($ip);
$fqdn = $rev . '.in-addr.arpa.';
if ($chk) {
$chk = ' ' . rtrim($chk, '.') . '.';
}
$cmd = 'prereq yxrrset ' . $fqdn . ' PTR' . $chk . "\n";
'update delete ' . $fqdn . ' ' . \Dns_Module::DNS_TTL . ' PTR ' . "\n" .
'update add ' . $fqdn . ' ' . \Dns_Module::DNS_TTL . ' PTR ' . $hostname;
$resp = self::__send($cmd);
if (!is_debug() && !$resp['success']) {
error("cannot change PTR for $ip - " . $resp[1]);
report($cmd, var_export($resp, true));
return false;
}
// update ARP tables
return true;
}
protected function _addIP($ip, $hostname = '')
{
$rev = \Opcenter\Dns\General::reverseIP($ip);
$fqdn = $rev . '.in-addr.arpa.';
if (!$hostname) {
$hostname = $fqdn;
} else {
$hostname = rtrim($hostname, '.') . '.';
}
// no zone should be specificied
$cmd = 'prereq nxrrset ' . $fqdn . ' PTR' . "\n" .
'update add ' . $fqdn . ' ' . \Dns_Module::DNS_TTL . ' PTR ' . $hostname;
$resp = self::__send($cmd);
if (!$resp['success'] && !is_debug()) {
error("cannot add $ip - " . $resp[1]);
report($cmd, var_export($resp, true));
return false;
}
// update ARP tables
\Opcenter\Net\Ip4::announce($ip);
info("Added $ip");
return true;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment