Press "Enter" to skip to content

利用cloudfare的workers写一个转发脚本来更新域名ddns

我的主路由时mikrotik,我想用mikrotik的script写一个脚本在我ros的ip发生变化时来更新部署在cf上面域名的解析地址。

我在cf上面写了类似下面一个脚本,脚本检测pppoe-out1对应的IP,如发现IP和我的域名test.mydomain.com解析出来的不一致,则证明我们外网地址变了,需要执行ddns操作。

那我这个脚本会像类似:

https://ddns.mycf.org/cf/updateRecord/recore_id/A/test/192.168.0.2

的地址发送一个get请求,后面path路径类似:

const path = `/cf/updateRecord/${recordId}/${sub_domain_type}/${sub_domain_name}/${ip}`

:local tempFile "testDomainRequest"
:local domain "test.mydomain.com"
:local resolvedIP [:resolve $domain]
:local pppoeIP [/ip address get [find interface="pppoe-out1"] address]
:local currentIP [:pick $pppoeIP 0 [:find $pppoeIP "/"]]

:if ($currentIP != $resolvedIP) do={
:log info ("test.mydomain.com resolved: " .$resolvedIP)
:log info ("current pppoe-out1: " . $currentIP)

/tool fetch url=("https://ddns.mycf.org/cf/updateRecord/recore_id/A/test/" . $currentIP ) mode=https dst-path=$tempFile
:delay 2
:local requestResult [/file get $tempFile contents]
:log info ($tempFile . ": " .$requestResult)
/file remove $tempFile;
}

我再增加个scheduler,每10分钟执行下就好了。

这个脚本里面有几个是要修改的:

test.mydomain.com :这个是你要ddns的域名,要改成你实际需要的

pppoe-out1:这个是你公网ip对应的接口

“https://ddns.mycf.org/cf/updateRecord/recore_id/A/test/”:这个是 你 自己部署的ddns脚本请求路径,https://ddns.mycf.org/ 这个是部署的workders域名。recore_id 是个占位符,要从后面部署的worers脚本获取。A 是解析类型,一般就是A。test是你子域名的domain,本例就是test

脚本逻辑很清晰,但是我们cf的ddns接口逻辑肯定没有这么简单,下面我们要在cloudflare上面使用他们免费的workers来实现我们的ddns接口,再帮请求转发到cf官方。

addEventListener("fetch", (event) => {
  event.respondWith(
    handleRequest(event).catch(
      (err) => new Response(err.stack, { status: 500 })
    )
  );
});

// Additional Cloudflare configuration
const cloudflareConfig = {
  email: 'admin@yourdomain.com',
  apiKey: 'aaaabbbbbcccccc',
  zoneId: 'cccccbbbbaaaaaaa',
  baseUrl: 'https://api.cloudflare.com/client/v4'
};

const cloudflareHeaders = {
  "Content-Type": "application/json",
  "Authorization": ` Bearer ${cloudflareConfig.apiKey}`,
  "X-Auth-Email": cloudflareConfig.email
};

async function cloudflareGetDNSRecords() {
  return fetch(`${cloudflareConfig.baseUrl}/zones/${cloudflareConfig.zoneId}/dns_records`, {
    headers: cloudflareHeaders
  });
}

async function cloudflareUpdateDNSRecord(recordId, type, name, content) {
  const body = JSON.stringify({ type, name, content });
  return fetch(`${cloudflareConfig.baseUrl}/zones/${cloudflareConfig.zoneId}/dns_records/${recordId}`, {
    method: 'PUT',
    headers: cloudflareHeaders,
    body: body
  });
}

async function handleRequest(event) {
  const { request } = event;
  const { pathname } = new URL(request.url);

  if (pathname.startsWith("/cf/records")) {
    return cloudflareGetDNSRecords();
  }

  // const path = `/cf/updateRecord/${recordId}/${sub_domain_type}/${sub_domain_name}/${ip}`
  // const example_path = /cf/updateRecord/1234567890/A/www/192.0.2.1
  if (pathname.startsWith("/cf/updateRecord")) {
    const segments = pathname.split("/");
    if (segments.length === 7) {
      const [recordId, type, name, ip] = segments.slice(3);
      return cloudflareUpdateDNSRecord(recordId, type, name, ip);
    } else {
      return new Response("Invalid Cloudflare update path!");
    }
  }

  return new Response("404")
}

怎么去写一个cf的workers和怎么获取cf的token不在本教程提供,主要是提供一个实现思路和核心脚本代码。

下面说几个注意点:

  1. CF的workder提供的免费域名xxx.workers.dev最要不要直接用,用自己域名给你的workders做一个别名,默认域名容器访问不通。
  2. zoneId就是你cf点开域名右下角有个API旁边的那个zoneid
  3. API KEY就是你点右下角那个API旁边有个 get your api token,点进去 点create token 选择 Edit zone DNS模板,模板里面Zone Resources选择你的域名就行了别的不用改,点击最下面创建就能拿到token
  4. ros的ddns脚本里面的 recordId 就是通过你的workers脚本的 /cf/records 接口请求拿到,如果结果里面没有,那你要先再cf上面增加这个子域名。
发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注