I'm starting to provide Chinese / English versions of some articles, switch with the Language menu above. 我开始提供部分文章的中文、英文翻译,请使用顶部语言菜单切换。

在 DN42 中注册自己的域名

DN42 全称 Decentralized Network 42(42 号去中心网络),是一个大型的 VPN 网络。但是与其它传统 VPN 不同的是,DN42 使用了大量在互联网骨干上应用的技术(例如 BGP),可以很好的模拟一个真实的网络环境。

我在先前的一篇文章中加入了 DN42 网络,并连接了大部分自己拥有的 VPS。(剩下几台是没有 Tun/Tap 的 OpenVZ VPS,无法加入)之前我就知道 DN42 拥有自己的域名体系,例如 DN42 的 Wiki 站(https://wiki.dn42.us/Home)就可以在 DN42 中以 https://internal.dn42 的域名访问,但是之前没有时间去完成域名注册,并且当时对 DN42 的了解还不够。这个月我完成了域名注册,就来分享一下过程。

搭建权威 DNS 服务器

权威 DNS 服务器,就是指管理某个域名记录的服务器。例如本站主域名 lantian.pub 的权威服务器是 lv3ns[1-4].ffdns.net,就是 CloudXNS。在互联网上注册域名时,我们可以用现成的 CloudXNS、Cloudflare 等免费 DNS 服务,但是在 DN42 中,虽然有人提供这样的服务,但是需要在 IRC 上与他们交流申请,我觉得太麻烦,就干脆自建了。

Linux 下自建 DNS 一般使用 Bind 或 PowerDNS 两款软件。Bind 以文件形式保存 DNS 记录,跨服务器同步有些麻烦,而 PowerDNS 不仅可以用文件保存,还可以用 MySQL 等数据库形式保存,同时自己也提供记录同步功能。

由于我配置 PowerDNS 自带的记录同步功能总是失败,查不出原因,我就干脆设置了 MySQL 主从复制来进行同步。

搭建 DNS:设置 MySQL 主从同步

首先,在每台服务器中安装一个 MySQL,并且在 my.cnf 设置上这些内容:

# 每台服务器的编号,随便设置,但不能重复
server-id=1
# 每台服务器的名称,设置后可以在 phpMyAdmin 中看到从服务器的名字
report-host=Master
# MySQL 日志文件的位置,主从复制的核心文件
log_bin=mysql-bin
log_error=mysql-bin.err

然后用 phpMyAdmin 登录主 MySQL 服务器,在 “Replication / 主从复制” 页面将这台服务器设置为 Master / 主服务器,并创建一个用于主从复制的用户(拥有 REPLICATION SLAVE 和 REPLICATION CLIENT 权限)。

设置完后你应该可以看到类似这样的状态:

主服务器状态

其中的 “File / 文件名” 就是日志文件名,“Position / 位置” 就是当前记录的行数。记下这两个值。

然后,关闭所有服务器上的 MySQL,用 rsync 之类方法把数据库复制到从服务器上,覆盖掉各自的数据目录,再打开所有的 MySQL。如果是没什么数据库写入操作的站,例如个人小博客,可以尝试不关主服务器 MySQL,但是可能会造成复制出去的数据损坏。

然后,用 phpMyAdmin 登录从 MySQL 服务器。因为 phpMyAdmin 在设置从服务器时有奇怪的 bug,所以我没用它的向导来设置,而是直接执行 SQL:

change master to master_host='服务器 IP',
master_user='主从复制用户名',
master_password='主从复制用户密码',
master_log_file='主服务器日志文件名',
master_log_pos=主服务器记录行数;
start slave;

然后进入 “Replication / 主从复制” 页面,点击 “See slave status table / 查看从服务器状态表”,确认 Slave_IO_Running 和 Slave_SQL_Running 均为 Yes,主从同步就已经开始了。

主从同步正常状态

搭建 DNS:设置 PowerDNS

设置完数据库,我们就可以设置 PowerDNS 了。先在 MySQL 给 PowerDNS 建立一个用户和数据库。

然后安装 PowerDNS,因为我是 Docker 用户,所以在主服务器上,直接用 docker-compose 下载镜像并启动:

  powerdns:
    image: psitrax/powerdns
    container_name: powerdns
    restart: always
    entrypoint: "/entrypoint.sh --cache-ttl=120 --master=yes --slave=yes"
    environment:
      - MYSQL_HOST=数据库服务器地址
      - MYSQL_USER=数据库用户名
      - MYSQL_PASS=数据库密码
      - MYSQL_DB=数据库名字
    ports:
      - "DN42 内的 IP 地址:53:53"
      - "DN42 内的 IP 地址:53:53/udp"

然后 PowerDNS 可能会启动失败,提示在创建 comments 表时某些列过长。这是因为 MySQL 的一些配置被修改了,导致数据表的行为发生了变化,而这些列最长可达 64000 Bytes,修改后的数据表存不下。

解决这个问题不需要再改数据库配置,只需要把 64000 改小,例如 16000,然后手动创建表即可:

以下语句对于新版 PowerDNS 可能已经过时,请参照 https://doc.powerdns.com/authoritative/backends/generic-mysql.html 查看新版的创建语句,并相应修改长度。

CREATE TABLE domains (
  id                    INT AUTO_INCREMENT,
  name                  VARCHAR(255) NOT NULL,
  master                VARCHAR(128) DEFAULT NULL,
  last_check            INT DEFAULT NULL,
  type                  VARCHAR(6) NOT NULL,
  notified_serial       INT DEFAULT NULL,
  account               VARCHAR(40) DEFAULT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE UNIQUE INDEX name_index ON domains(name);

CREATE TABLE records (
  id                    INT AUTO_INCREMENT,
  domain_id             INT DEFAULT NULL,
  name                  VARCHAR(255) DEFAULT NULL,
  type                  VARCHAR(10) DEFAULT NULL,
  content               VARCHAR(16000) DEFAULT NULL,
  ttl                   INT DEFAULT NULL,
  prio                  INT DEFAULT NULL,
  change_date           INT DEFAULT NULL,
  disabled              TINYINT(1) DEFAULT 0,
  ordername             VARCHAR(255) BINARY DEFAULT NULL,
  auth                  TINYINT(1) DEFAULT 1,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX nametype_index ON records(name,type);
CREATE INDEX domain_id ON records(domain_id);
CREATE INDEX recordorder ON records (domain_id, ordername);

CREATE TABLE supermasters (
  ip                    VARCHAR(64) NOT NULL,
  nameserver            VARCHAR(255) NOT NULL,
  account               VARCHAR(40) NOT NULL,
  PRIMARY KEY (ip, nameserver)
) Engine=InnoDB;

CREATE TABLE comments (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  name                  VARCHAR(255) NOT NULL,
  type                  VARCHAR(10) NOT NULL,
  modified_at           INT NOT NULL,
  account               VARCHAR(40) NOT NULL,
  comment               VARCHAR(16000) NOT NULL,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX comments_domain_id_idx ON comments (domain_id);
CREATE INDEX comments_name_type_idx ON comments (name, type);
CREATE INDEX comments_order_idx ON comments (domain_id, modified_at);

CREATE TABLE domainmetadata (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  kind                  VARCHAR(32),
  content               TEXT,
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE INDEX domainmetadata_idx ON domainmetadata (domain_id, kind);

CREATE TABLE cryptokeys (
  id                    INT AUTO_INCREMENT,
  domain_id             INT NOT NULL,
  flags                 INT NOT NULL,
  active                BOOL,
  content               TEXT,
  PRIMARY KEY(id)
) Engine=InnoDB;

CREATE INDEX domainidindex ON cryptokeys(domain_id);

CREATE TABLE tsigkeys (
  id                    INT AUTO_INCREMENT,
  name                  VARCHAR(255),
  algorithm             VARCHAR(50),
  secret                VARCHAR(255),
  PRIMARY KEY (id)
) Engine=InnoDB;

CREATE UNIQUE INDEX namealgoindex ON tsigkeys(name, algorithm);

这下 PowerDNS 就能成功启动了,但是它还没有任何记录。

搭建 DNS:安装 PowerAdmin

PowerAdmin 是一个 PowerDNS 的控制面板,可以去 https://github.com/poweradmin/poweradmin 下载安装。安装过程只需要跟着向导走即可,在此略过。

安装完后,进入主界面:

PowerAdmin 主界面

点 “Add Master Zone / 添加主区域”,这里是添加你要解析的域名的地方。在 “Zone Name / 域名” 中填入域名,然后直接确定。

返回主界面,点 “List Zones / 域名列表”,点击域名左边的编辑按钮进行管理,进入如下界面,这里以我的 DN42 域名 lantian.dn42 为例:

域名管理界面

最开始装完 PowerAdmin 之后,创建的 SOA 记录开头可能是没有类似 ns1.lantian.dn42 一类的内容的,这样的 SOA 记录就不符合规范。我的 SOA 记录是 “ns1.lantian.dn42 lantian.lantian.dn42 0 28800 7200 604800 60”,解释如下:

  • ns1.lantian.dn42:主要 DNS 服务器的名字,一般就是你现在在操作的服务器之后要取的域名。
  • lantian.lantian.dn42:DNS 服务器管理者的邮箱,但是 @ 符号被句点代替了,例如这里就是 lantian@lantian.dn42。在 DN42 中不一定需要真实地址。
  • 0:记录编号,如果使用 AXFR 等进行 DNS 记录同步,从 DNS 服务器可能会根据这个编号判断记录有没有更改。我们使用 MySQL 主从复制,所以这里不重要。这里设置为 0 代表 PowerDNS 会自动管理这一项,无需人工操作。
  • 28800:刷新时间,AXFR 从服务器两次拉取的间隔,同样不重要。
  • 7200:重试时间,AXFR 从服务器拉取失败后,再次拉取的时间,同样不重要。
  • 604800:过期时间,AXFR 从服务器拉取失败后,最多用先前最后一次拉取成功的记录继续提供服务这么长时间,之后停止应答。同样不重要。
  • 60:最小 TTL,所有记录的最小刷新时间,至少过了这么长时间才会刷新。

点击 SOA 记录左边的编辑按钮,对应着设置好,保存。

接下来要设置 NS 记录,指明你的域名由这几台 DNS 服务器提供服务。我这次设置 3 台服务器,分别是 ns [1-3].lantian.dn42,需要分别创建相应的 NS 记录,这样填写即可:

填写 NS 记录

一一提交即可。

最后设置 A 记录 指明域名指向某台服务器,这样填写即可:

填写 A 记录

主 PowerDNS 服务器到此设置完成。因为设置了 MySQL 主从同步,所以你的配置也已经同步到了其它服务器上,在相应的服务器上安装 PowerDNS 即可。

最后 dig 一下自己的服务器测试:

DIG 测试

在 DN42 注册域名

DN42 最近进行了一次升级,弃用了原来的 Monotone 管理界面,改用 Git 管理。首先去 https://git.dn42.us/explore/repos 上面注册一个账号,Fork dn42/registry,Clone 到本地。

首先,DN42 要求 Git Commit 经过 GPG 数字签名。我在 Mac 上使用的软件是 GPG Keychain。大致流程是:创建密钥,将公钥提交到 SKS 等公开 GPG 服务器上供查询,然后复制下 Fingerprint。

然后设置 git,打开自动签名每次 commit 的功能:

git config --global user.signingKey [你的 Fingerprint]
git config --global commit.gpgSign true

因为我是 DN42 老用户,已经有了自己的 MNT Handle,就打开 data/mntner/LANTIAN-MNT,加入相应的指纹信息,类似如下:

mntner:             LANTIAN-MNT
admin-c:            LANTIAN-DN42
tech-c:             LANTIAN-DN42
mnt-by:             LANTIAN-MNT
source:             DN42
auth:               pgp-fingerprint 23067C13B6AEBDD7C0BB567327F31700E751EC22

然后创建 data/dns/lantian.dn42:

domain:             lantian.dn42
admin-c:            LANTIAN-DN42
tech-c:             LANTIAN-DN42
mnt-by:             LANTIAN-MNT
nserver:            ns1.lantian.dn42 172.22.76.186
nserver:            ns1.lantian.dn42 fdbc:f9dc:67ad::8b:c606:ba01
nserver:            ns2.lantian.dn42 172.22.76.185
nserver:            ns2.lantian.dn42 fdbc:f9dc:67ad::dd:c85a:8a93
nserver:            ns3.lantian.dn42 172.22.76.187
nserver:            ns3.lantian.dn42 fdbc:f9dc:67ad::18:ca0f:741d
source:             DN42

(2020-03-22 更新:在我最初写此文时,文件里还有如下一行:

status:             CONNECT

但是在 2018 年 11 月的一次更新中,这行被去掉了(不再需要)。

作此更新是因为看到 Telegram 群里的群友踩了坑。)

然后 git add,git commit,git push,然后发 Pull Request 等待合并,并根据管理员的提示修改可能出现的错误。

DN42 Pull Request 记录

因为 DN42 中采用 Anycast DNS,每个人都能建立递归 DNS 服务器,而每个人从中心库拉取配置的频率不一,因此可能要等最长一个星期的时间,你的域名才能生效。

域名生效

到此 DN42 域名就注册成功了,接下来就可以在上面配置网站、邮件、IRC、游戏服务器等等了。

本站使用运行在 Vercel 上的 Waline 评论系统,中国大陆访问可能不稳定。