我的主路由时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不在本教程提供,主要是提供一个实现思路和核心脚本代码。
下面说几个注意点:
- CF的workder提供的免费域名xxx.workers.dev最要不要直接用,用自己域名给你的workders做一个别名,默认域名容器访问不通。
- zoneId就是你cf点开域名右下角有个API旁边的那个zoneid
- API KEY就是你点右下角那个API旁边有个 get your api token,点进去 点create token 选择 Edit zone DNS模板,模板里面Zone Resources选择你的域名就行了别的不用改,点击最下面创建就能拿到token
- ros的ddns脚本里面的 recordId 就是通过你的workers脚本的 /cf/records 接口请求拿到,如果结果里面没有,那你要先再cf上面增加这个子域名。