update bind9.php
[GitHub/Stricted/Domain-Control-Panel.git] / bind9.php
1 <?php
2 /**
3 * @author Jan Altensen (Stricted)
4 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
5 * @copyright 2014-2016 Jan Altensen (Stricted)
6 */
7 $data = file_get_contents("https://dns-control.eu/API/?key=xxx");
8 $data = json_decode($data, true);
9 if (is_array($data) && !isset($data['error'])) {
10 shell_exec("rm -rf /srv/bind/*");
11 shell_exec("mkdir -p /srv/bind/signed/");
12 shell_exec("mkdir -p /srv/bind/unsigned/");
13 shell_exec("mkdir -p /srv/bind/dnssec/");
14 shell_exec("mkdir -p /srv/bind/dsset/");
15
16 foreach ($data as $zone) {
17 $out = $zone['soa']['origin']."\t".$zone['soa']['minimum']."\tIN\tSOA\t".$zone['soa']['ns']." ".$zone['soa']['mbox']." (\n";
18 $out .= "\t\t\t\t".$zone['soa']['serial']."\t; Serial\n";
19 $out .= "\t\t\t\t".$zone['soa']['refresh']."\t\t; Refresh\n";
20 $out .= "\t\t\t\t".$zone['soa']['retry']."\t\t; Retry\n";
21 $out .= "\t\t\t\t".$zone['soa']['expire']."\t\t; Expire\n";
22 $out .= "\t\t\t\t180 )\t\t; Negative Cache TTL\n";
23 $out .= ";\n";
24
25 $signed = false;
26 $zsk = false;
27 $ksk = false;
28 foreach ($zone['rr'] as $record) {
29 if ($record['type'] == "DNSKEY") {
30 if ($record['aux'] == 256) {
31 $zsk = true;
32 }
33 else if ($record['aux'] == 257) {
34 $ksk = true;
35 }
36
37 $out .= $record['name']."\t".$record['ttl']."\tIN\t".$record['type']."\t".$record['aux']."\t".$record['data']."\n";
38 }
39 else if ($record['type'] == "MX" || $record['type'] == "SRV" || $record['type'] == "TLSA" || $record['type'] == "DS") {
40 $out .= $record['name']."\t".$record['ttl']."\tIN\t".$record['type']."\t".$record['aux']."\t".$record['data']."\n";
41 }
42 else if ($record['type'] == "TXT") {
43 $txt = $record['data'];
44
45 if (strpos($txt, " ") !== false && strpos($txt, '" "') !== false && $txt != '" "') {
46 if (substr($txt, 0, 1) != '(' && substr($txt, -1) != ')') {
47 if (substr($txt, 0, 1) != '"' && substr($txt, -1) != '"') {
48 $record['data'] = '("'.$txt.'")';
49 }
50 else {
51 $record['data'] = '('.$txt.')';
52 }
53 }
54 }
55 else if (substr($txt, 0, 1) != '"' && substr($txt, -1) != '"') {
56 $record['data'] = '"'.$txt.'"';
57 }
58
59 if (strpos($record['data'], "v=spf1") !== false) {
60 $out .= $record['name']."\t".$record['ttl']."\tIN\tSPF\t" . $record['data']."\n";
61 }
62
63 $out .= $record['name']."\t".$record['ttl']."\tIN\t".$record['type']."\t" . $record['data']."\n";
64 }
65 else {
66 $out .= $record['name']."\t".$record['ttl']."\tIN\t".$record['type']."\t\t" . $record['data']."\n";
67 }
68 }
69
70 $zskkey = false;
71 $kskkey = false;
72 foreach ($zone['sec'] as $sec) {
73 $dir = "/srv/bind/dnssec/".$zone['soa']['origin']."/";
74 if (!file_exists($dir)) {
75 shell_exec("mkdir -p " . escapeshellcmd($dir));
76 }
77
78 if ($sec['type'] == "ZSK" || $sec['type'] == "KSK") {
79 if (!empty($sec['public']) && !empty($sec['private'])) {
80 preg_match("/; This is a (key|zone)-signing key, keyid ([0-9]+), for ".$zone['soa']['origin']."/i", $sec['public'], $match);
81 $filename1 = getFileName ($zone['soa']['origin'], $sec['algo'], $match[2], "key");
82 $filename2 = getFileName ($zone['soa']['origin'], $sec['algo'], $match[2], "private");
83
84 if (file_exists($dir.$filename1)) {
85 unlink($dir.$filename1);
86 }
87
88 if (file_exists($dir.$filename2)) {
89 unlink($dir.$filename2);
90 }
91
92 $handler = fOpen($dir.$filename1, "a+");
93 fWrite($handler, $sec['public']);
94 fClose($handler);
95
96 $handler = fOpen($dir.$filename2, "a+");
97 fWrite($handler, $sec['private']);
98 fClose($handler);
99
100 if (file_exists($dir.$filename1) && file_exists($dir.$filename2)) {
101 /* fallback for missing DNSKEY record */
102 if ($zsk === false || $ksk === false) {
103 preg_match("/".$zone['soa']['origin']." IN DNSKEY ([0-9]+) ([0-9]+) ([0-9]+) ([\s\S]+)/i", $sec['public'], $match);
104 $out .= $zone['soa']['origin']."\t60\tIN\tDNSKEY\t".$match[1]."\t".$match[2]." ".$match[3]." ".$match[4]."\n";
105 if ($sec['type'] == "ZSK") {
106 $zsk = true;
107 }
108 else if ($sec['type'] == "KSK") {
109 $ksk = true;
110 }
111 }
112
113 if ($sec['type'] == "ZSK") {
114 $zskkey = true;
115 }
116 else if ($sec['type'] == "KSK") {
117 $kskkey = true;
118 }
119 }
120 }
121 }
122 }
123
124 $sign = false;
125 if ($zsk === true && $ksk === true && $zskkey === true && $kskkey === true) {
126 $sign = true;
127 }
128
129 $handler = fOpen("/srv/bind/unsigned/".$zone['soa']['origin']."db", "a+");
130 fWrite($handler, $out);
131 fClose($handler);
132
133 $signed = false;
134 if ($sign === true) {
135 shell_exec("cd /srv/bind/ && /usr/sbin/dnssec-signzone -r /dev/urandom -A -N INCREMENT -d dsset/ -f signed/".escapeshellcmd($zone['soa']['origin'])."db -K dnssec/".escapeshellcmd($zone['soa']['origin'])."/ -o ".escapeshellcmd($zone['soa']['origin'])." unsigned/".escapeshellcmd($zone['soa']['origin'])."db");
136 if (file_exists("/srv/bind/signed/".$zone['soa']['origin']."db")) {
137 $signed = true;
138 }
139 }
140
141 $cout = "zone \"" . $zone['soa']['origin'] . "\" {\n";
142 $cout .= "\ttype master;\n";
143 $cout .= "\tnotify no;\n";
144 $cout .= "\tfile \"/srv/bind/".($signed === true ? "signed" : "unsigned")."/".$zone['soa']['origin']."db\";\n";
145 $cout .= "};\n\n";
146
147 $handler = fOpen("/srv/bind/domains.cfg", "a+");
148 fWrite($handler, $cout);
149 fClose($handler);
150 }
151
152 shell_exec("/etc/init.d/bind9 reload");
153 }
154
155 function getFileName ($zone, $algo, $id, $type) {
156 $id = str_repeat('0', 5 - strlen($id)).$id;
157 $algo = str_repeat('0', 3 - strlen($algo)).$algo;
158 return "K".$zone."+".$algo."+".$id.".".$type;
159 }