08年的时候,在学校,花了点时间做了个ddns服务,不知道现在是否还活着,ddns.bitunion.org。 当时的方案,powerdns + mysql + php ui,php ui是自己做的,简单地做了个校内邮箱的校验,使用了个简单的token机制来更新记录。 这回,有个需求是需要做一个ttl < 10的ddns服务,之前所有域名都在dns.he.net上,最小ttl限制到了300,这样以来,更新的延迟特定场景下不够用。 自用DDNS的需求里,域名不会被广泛知晓并使用,否则NS服务器的压力会是个问题。 方案还是一样,powerdns + mysql,写了个最简单的http接口页面给ddclient用。 服务器是 ubuntu 17.04,公网IP 1.2.3.4. 目标域名 xxx.ddns.sskaje.me 安装软件 按下列命令安装必备软件,全默认
|
apt install pdns-server pdns-tools pdns-backend-mysql |
配置powerdns 考虑到现在的linux服务器,本地53端口经常被占用,所以需要修改 /etc/powerdns/pdns.conf,指定监听的IP
配置zone和records 在sskaje.me的域名服务器上,添加NS记录 ddns.sskaje.me,指向IP 1.2.3.4。考虑到未来可能改IP,可以加一个A记录 ddns1.sskaje.me,指向 1.2.3.4,这样ddns.sskaje.me的NS设置成 ddns1.sskaje.me。 创建zone
|
# pdnsutil create-zone ddns.sskaje.me Jul 16 08:59:55 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed Creating empty zone 'ddns.sskaje.me' |
更正SOA记录
|
# pdnsutil add-record ddns.sskaje.me @ SOA 2592000 "dns.sskaje.me. dns.sskaje.me. 1 10800 3600 604800 3600" Jul 16 09:13:47 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed New rrset: ddns.sskaje.me. IN SOA 3600 a.misconfigured.powerdns.server hostmaster.ddns.sskaje.me 1 10800 3600 604800 3600 ddns.sskaje.me. IN SOA 2592000 dns.sskaje.me dns.sskaje.me 1 10800 3600 604800 3600 |
添加 xxx.ddns.sskaje.me,设置ttl=10
|
# pdnsutil add-record ddns.sskaje.me xxx A 10 127.0.0.1 Jul 16 09:14:55 [bindbackend] Done parsing domains, 0 rejected, 0 new, 0 removed New rrset: xxx.ddns.sskaje.me. IN A 10 127.0.0.1 |
简单的更新脚本 DynDNS的更新接口参数类似:
|
/nic/update?system=dyndns&hostname=xxx.ddns.sskaje.me&myip=4.3.2.1 |
认证使用 http basic auth 完成的。 所以一个简单的服务端脚本
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
|
<?php $auth = [ 'xxx.ddns.sskaje.me' => 'This.15.p4ssw0rd', ]; if (!isset($_SERVER['PHP_AUTH_USER']) || !isset($_SERVER['PHP_AUTH_PW'])) { die('badauth'); } if (!isset($auth[$_SERVER['PHP_AUTH_USER']])) { die('badauth'); } if ($auth[$_SERVER['PHP_AUTH_USER']] != $_SERVER['PHP_AUTH_PW']) { die('badauth'); } if (!isset($_GET['hostname'])) { die('badauth'); } if ($_GET['hostname'] != $_SERVER['PHP_AUTH_USER']) { die('badauth'); } $db = new mysqli('localhost', 'root', '123123123', 'pdns'); $db->set_charset('utf8'); try { $db->autocommit(0); $result = $db->query("SELECT * FROM records WHERE name='{$_SERVER['PHP_AUTH_USER']}' FOR UPDATE "); if (!$result->num_rows) { throw new Exception('nohost'); } $record = $result->fetch_assoc(); if ($record['type'] != 'A') { throw new Exception('nohost'); } if (!isset($_GET['myip'])) { $ip = get_client_ip(); } else { $ip = long2ip(ip2long($_GET['myip'])); } if ($ip == $record['content']) { throw new Exception('nochg'); } $db->query("UPDATE records SET content='{$ip}' WHERE id={$record['id']}"); $db->commit(); echo "good {$ip}\n"; } catch (Exception $e) { $db->rollback(); echo $e->getMessage() . "\n"; } finally { $db->close(); } function get_client_ip() { if (isset($_SERVER['HTTP_CF_CONNECTING_IP'])) { return $_SERVER['HTTP_CF_CONNECTING_IP']; } return $_SERVER['REMOTE_ADDR']; } |
Incoming search terms:自建DDNS自己搭建ddns搭建DDNSDDNS服务搭建DDNS服务ddns … Continue reading “20分钟搭建一个自用的DDNS服务”