使用 cloudflare worker 对托管在 cloudflare 的域名 进行 ddns
前言
假如我们现在有一个域名 yourdomain.com 托管在 cloudflare , 现在需要对 ddns.yourdomain.com 进行 ddns,这时候我们可以将逻辑放在免费的 cloudflare worker 上面,目标设备只要定时(例如每隔5分钟)访问一次这个 worker , 就可以更新dns解析记录。
准备
-
首先在 cloudflare 中添加一个子域名 ddns.yourdomain.com
-
然后我们需要获取 几个token ,一个是 AUTH_KEY, ZONE_ID 还有 ddns.yourdomain.com 的 DNSRecordID ,获取方法可以通过官方文档来学习 https://developers.cloudflare.com/fundamentals/setup/find-account-and-zone-ids/
-
获取到以后,新建一个 worker 起名 worker1 ,绑定自定义域名,例如, w1.yourdomain.com ,然后等一会看这个域名的解析ip是多少 例如 101.22.33.44 ,这时候我们再添加一个 dns 解析例如 v4ddns.yourdomain.com -> 101.22.33.44 ,注意不要选择 cf 代理。
-
添加 worker 路由 v4ddns.yourdomain.com/* 选择 worker1。 测试 v4ddns.yourdomain.com 能不能访问到 默认的 hello world,这么搞是为了防止cf 获取本地ip的时候走的是ipv6。
-
最后把之前获取的几个值,填写到下面的代码, 并且设置访问密码 ,最后把代码改到 worker 部署。然后在本地设置定时访问 https://v4ddns.yourdomain.com/?KEY=你设置的密码
// Learn more at https://developers.cloudflare.com/workers/
export default {
async fetch(request, env, ctx) {
/********鉴权***********/
const PASSWORD = "卧槽,怎么能没有密码";
const params = new URLSearchParams((new URL(request.url)).search)
const KEY = params.get('KEY') || '';
if(KEY!==PASSWORD){
// 密码不对, 正确格式 https://你这个wordker的域名/?KEY=密码
return new Response('',{status:403});
}
/********初始化一些必要的配置项目********/
const YOUR_EMAIL = '[email protected]';
const YOUR_AUTH_KEY = '3333333333333333333333333333333333333';
const YOUR_ZONE_ID = '33333333333333333333333333333333';
const DNSRecordID = '66666666666666666666666666666666';
const RECORDNAME = 'ddns.yourdomain.com';
//获取当前访问者的IP ,注意这里优先支持IPV6 所以需要在 CF的DNS端设置一个V4的优选IP 参考 https://post.smzdm.com/p/adm7n4kn/ 第二节
let now_ip = request.headers.get('cf-connecting-ip');
/*
*
*
*
* 调试用 假IP
*
*
*
*
*/
//now_ip = '127.0.0.1';
// 查询目前域名对应的IP结果
let dns_result_response = await fetch('https://api.cloudflare.com/client/v4/zones/' + YOUR_ZONE_ID + '/dns_records/' + DNSRecordID,{
headers: {
"X-Auth-Email" : YOUR_EMAIL,
"X-Auth-Key" : YOUR_AUTH_KEY,
"Content-Type" : 'application/json'
},
});
let old_ip = await dns_result_response.json();
old_ip = old_ip.result.content;
if(old_ip === now_ip){
return new Response('IP没有发生变化,不需要修改解析记录');
}else{
// 请求dns的API重新做解析
let result = await fetch('https://api.cloudflare.com/client/v4/zones/' + YOUR_ZONE_ID + '/dns_records/' + DNSRecordID,{
method: 'PUT',
headers: {
"X-Auth-Email" : YOUR_EMAIL,
"X-Auth-Key" : YOUR_AUTH_KEY,
"Content-Type" : 'application/json'
},
body: JSON.stringify({
type : 'A',
name : RECORDNAME,
content : now_ip,
ttl : 600,
proxied : false
})
});
//console.log(await result.json());
return new Response('done');
}
},
};
后记
虽然代码不长,但是过程写的很凌乱,很多细节都没写,还是建议读一下源码,里面包含了更多细节,并不是很复杂。