基于Cloudflare搭建DDNS

很多场景下我们都可能需要自建DDNS:

  • 需要最大限度的保持对一台拥有浮动公网IP的Linux主机的连接。
  • 需要连接具有浮动公网IP的家庭宽带。

前提条件

  • 拥有自己的域名。
  • 该域名已经被Cloudflare托管。

获取 CFKEY

前往 dash.cloudflare.com/profile 查看 Global API Key。(点击 Global API Key 旁边的 view 按钮)

设置用于解析的二级域名

在Cloudflare的该域名的托管页面(假定使用的域名的 my.site)添加一条 A 记录,随便指向一个IP地址(无实际意义,仅用于验证DDNS是否起效),并且不被 Cloudflare CDN 代理。

下载 DDNS 脚本

注意:脚本会随着 Cloudflare API 的改变而更新,要注意使用最新版本。

1
wget https://raw.githubusercontent.com/yulewang/cloudflare-api-v4-ddns/master/cf-v4-ddns.sh

修改脚本

1
vim cf-v4-ddns.sh

找到该代码块:

1
2
3
4
5
6
7
8
9
10
11
12
# API key, see https://www.cloudflare.com/a/account/my-account,
# incorrect api-key results in E_UNAUTH error
CFKEY=

# Username, eg: user@example.com
CFUSER=

# Zone name, eg: example.com
CFZONE_NAME=

# Hostname to update, eg: homeserver.example.com
CFRECORD_NAME=

CFKEY 是刚刚获取的 Global API Key。

CFUSER 是你的 Cloudflare 账户邮箱。

CFZONE_NAME 是你的主域名。

CFRECORD_NAME 是你用于 DDNS 解析的子域名。

执行脚本

1
2
chmod +x cf-v4-ddns.sh
./cf-v4-ddns.sh

执行完之后去 Cloudflare 托管页面查看解析的 A 记录是否发生改变,如果成功改变则表示 API 调用成功。

设置定时任务

按道理这里应该设置 crontab 的,但是我怎么设置也无法成功(语法正确),查阅发现 crontab 工作的成功与否与很多玄学(误)因素有关,例如脚本末尾是否有换行符(?wtf),故而放弃,然后写了个 Python3 脚本:

1
2
3
4
5
6
7
#!/bin/python3
import time
import os

while True:
time.sleep(30)
os.system("/root/cf-v4-ddns.sh")

然后用 systemd 守护:

1
2
3
4
5
6
7
8
9
10
11
12
[Unit]
Description=Cloudflare DDNS Service Daemon

[Service]
User=root
Group=root
Type=simple
ExecStart=/bin/python3 /root/ddns.py
Restart=always

[Install]
WantedBy=multi-user.target

注意,如果不指定用户会提示HOME未定义。HOME其实是一个shell变量,表示当前用户的“家路径”路径。

当然你也可以手动指定:

1
HOME=/root/

等号后面是你下载的脚本所在的目录即可。

真是太草了。

此外,由于30s一次轮询,会产生大量无用log(显示无变化),只需要在shell里找到那行代码给注释掉就行,使其只在IP变化时输出日志。