前言

假如我们现在有一个域名 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');
      }
    },
  };

后记

虽然代码不长,但是过程写的很凌乱,很多细节都没写,还是建议读一下源码,里面包含了更多细节,并不是很复杂。