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
安装软件
按下列命令安装必备软件,全默认
1 |
apt install pdns-server pdns-tools pdns-backend-mysql |
配置powerdns
考虑到现在的linux服务器,本地53端口经常被占用,所以需要修改 /etc/powerdns/pdns.conf,指定监听的IP
1 |
local-address=1.2.3.4 |
配置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
1 2 3 |
# 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记录
1 2 3 4 5 |
# 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
1 2 3 4 |
# 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的更新接口参数类似:
1 |
/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']; } |
20分钟搭建一个自用的DDNS服务 by @sskaje: https://sskaje.me/2017/07/set-up-simple-ddns-server-in-20-minutes/
Incoming search terms:
- 自建DDNS
- 自己搭建ddns
- 搭建DDNS
- DDNS服务
- 搭建DDNS服务
- ddns搭建
- ddns ttl
- pdnsutil 修改soa
- sm2185855
- 部署ddns
- ddns 搭建
- 自建 ddns
- DDNS 建网站
- DDNS MySQL
- ddns 自己搭建
- coldg91
- 部署自己的ddns
- builtp4v
- brassbgm
- afterlhx
Link to this post!