1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
<?php
// $filter = array(v4, v6, file('/srv/http/vhosts/eckner.net/ddns/ip-filters'))
// $x \in array($token, $token.$filter foreach $filter with match):
// $x.ddns.eckner.net (all)
function lifetime($addr) {
$addrTeile = explode('.', $addr);
if (($addrTeile[0] == '10') ||
(($addrTeile[0] == '192') && ($addrTeile[1] == '168')) ||
(($addrTeile[0] == '172') && ($addrTeile[1] >= 16) && ($addrTeile[1] < 32)))
return '7200';
return '120';
};
// invalid syntax?
if ((!array_key_exists('i', $_GET)) ||
(strlen($_GET['i']) != 64) ||
(preg_match('@^[0-9A-Za-z]{64}$@', $_GET['i']) != 1))
die();
$line = preg_grep('@^' . $_GET['i'] . ' @', file('/srv/http/vhosts/eckner.net/ddns/tokens'));
// unknown token?
if (count($line) != 1)
die();
$domain = substr(explode(' ', implode('', $line))[1], 0, -1);
if (array_key_exists('address', $_GET))
$ips = explode(',', $_GET['address']);
else
$ips[0] = 'auto';
foreach ($ips as $i => $ip)
if ($ip == 'auto')
$ips[$i] = $_SERVER['REMOTE_ADDR'];
$ips = array_unique($ips);
$hasRrType = array();
$rrTypes = array();
$filterMatches = array();
$filters = array();
foreach (file('/srv/http/vhosts/eckner.net/ddns/ip-filters') as $filterLine) {
if (substr($filterLine, 0, 1) == '#')
continue;
$filter = explode(' ', $filterLine);
if (count($filter) < 2)
continue;
$filters[] = array(
'name' => $filter[0],
'regex' => substr($filter[1], 0, -1)
);
}
foreach ($ips as $i => $ip) {
$filterMatches[$i] = array();
if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) {
$rrTypes[$i] = 'A';
$hasRrType['A'] = 1;
$filterMatches[$i][] = 'v4';
}
elseif (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) {
$rrTypes[$i] = 'AAAA';
$hasRrType['AAAA'] = 1;
$filterMatches[$i][] = 'v6';
}
else
die();
foreach ($filters as $filter) {
if (preg_match('@' . $filter['regex'] . '@', $ip) == 1)
$filterMatches[$i][] = $filter['name'];
else
$filterMatches[$i][] = 'non-' . $filter['name'];
}
$filterMatches[$i] = array_unique($filterMatches[$i]);
}
$updateCommand = "zone ddns.eckner.net.\n";
$logContent = '';
foreach ($hasRrType as $rrType => $dummy) {
// delete old record if existing
$updateCommand .=
"prereq yxrrset " . $domain . ".ddns.eckner.net IN " . $rrType . "\n" .
"update delete " . $domain . ".ddns.eckner.net IN " . $rrType . "\n" .
"send\n";
foreach ($filters as $filter) {
foreach (array('', 'non-') as $filter_prefix) {
$updateCommand .=
"prereq yxrrset " . $domain . "." . $filter_prefix . $filter['name'] . ".ddns.eckner.net IN " . $rrType . "\n" .
"update delete " . $domain . "." . $filter_prefix . $filter['name'] . ".ddns.eckner.net IN " . $rrType . "\n" .
"send\n";
}
}
}
// set new records no matter what
foreach ($ips as $i => $ip) {
$updateCommand .=
"update add " . $domain . ".ddns.eckner.net. " . lifetime($ip) . " IN " . $rrTypes[$i] . " " . $ip . "\n";
$logContent .=
date('Y-m-d H:i:s') . ' ' . $domain . ' ' . $ip . "\n";
foreach ($filterMatches[$i] as $filter) {
$updateCommand .=
"update add " . $domain . "." . $filter . ".ddns.eckner.net. " . lifetime($ip) . " IN " . $rrTypes[$i] . " " . $ip . "\n";
$logContent .=
date('Y-m-d H:i:s') . ' ' . $domain . '.' . $filter . ' ' . $ip . "\n";
}
}
$updateCommand .=
"send\n";
// actually do something
$pin = popen('nsupdate -l', 'w');
if ($pin === FALSE)
die();
fwrite($pin, $updateCommand);
pclose($pin);
file_put_contents('/srv/http/vhosts/eckner.net/ddns/log', $logContent, FILE_APPEND | LOCK_EX);
print "updated ips for domain \"" . $domain . ".ddns.eckner.net\": " . implode($ips,", ") . "\n";
|