<?php
/**
* Title: 批量修改CloudFlare上的所有域名的DNS
* Author: Rudon <285744011@qq.com>
* Date: 2019-03-08
*
* https://dash.cloudflare.com/
* https://api.cloudflare.com/
* https://segmentfault.com/q/1010000009595203/a-1020000009598171
*
*
* === 第一步 ===
* 获取你的所有域名的zone_identifier, 保存为./result_zone_id_and_domain.json
* 可以参考:
* 获取CloudFlare上的所有域名的ID (zone_identifier) - by PHP
* https://blog.csdn.net/qq285744011/article/details/88345077
*
* === 第二步 ===
* 遍历json文件里的域名,
* 根据官方手册,先查询这个zone(和域名一对一)的现存DNS纪录
* 再根据自己的需要,增删改查。
* 增 https://api.cloudflare.com/#dns-records-for-a-zone-create-dns-record
* 删 https://api.cloudflare.com/#dns-records-for-a-zone-delete-dns-record
* 改 https://api.cloudflare.com/#dns-records-for-a-zone-update-dns-record
* 查 https://api.cloudflare.com/#dns-records-for-a-zone-list-dns-records
*
* <本文的目标>
* 每个域名,只允许存在一条A纪录(where type = 'A' and name = 'yourdomain.com' and content = '6.6.6.6')
* 多了就删除,
* 不存在就创建
* content不是6.6.6.6的就更新为6.6.6.6 (或者先全部删除,再新建)
*
*/
ini_set('max_execution_time', 1800);
/* https://dash.cloudflare.com/ Email address associated with your account */
$config_IP_wanted = '6.6.6.6';
$x_email = 'you@demo.com';
$x_auth_key = '165419c1be6c1be6605dd605dd16540'; /* 登陆后,右上角头像,MyProfile,API Tokens,Global API Key */
$json_file_with_domains_and_zone_id = __DIR__.'/result_zone_id_and_domain.json';
$domains_ignored = array(
'aaa.com',
'ccc.com',
'ddd.cn'
);
/**
* https://blog.csdn.net/qq285744011/article/details/87859137
*
* @param type $url
* @param type $my_head_array | array() | array('key1:value1', 'key2:value2')
* @return string
*/
function geturl($url, $my_head_array = array()){
$headerArray =array("Content-Type: application/json;","Accept: application/json");
if(is_array($my_head_array) && count($my_head_array)){
$headerArray = $my_head_array;
}
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_HTTPHEADER, $headerArray);
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
function posturl($url,$data = array(),$my_head_array = array()){
$data = (is_array($data)) ? json_encode($data,JSON_UNESCAPED_UNICODE) : $data;
$headerArray =array("Content-type:application/json;charset='utf-8'","Accept:application/json");
if(is_array($my_head_array) && count($my_head_array)){
$headerArray = $my_head_array;
}
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, $url);
//curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
//curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,FALSE);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
curl_setopt($curl, CURLOPT_HTTPHEADER, $headerArray);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
$output = curl_exec($curl);
curl_close($curl);
return $output;
}
function puturl($url,$data = array(),$my_head_array = array()){
$data = (is_array($data)) ? json_encode($data,JSON_UNESCAPED_UNICODE) : $data;
$headerArray =array("Content-type:application/json;charset='utf-8'","Accept:application/json");
if(is_array($my_head_array) && count($my_head_array)){
$headerArray = $my_head_array;
}
$ch = curl_init(); //初始化CURL句柄
curl_setopt($ch, CURLOPT_URL, $url); //设置请求的URL
curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-type:application/json'));
curl_setopt($ch, CURLOPT_RETURNTRANSFER,1); //设为TRUE把curl_exec()结果转化为字串,而不是直接输出
curl_setopt($ch, CURLOPT_CUSTOMREQUEST,"PUT"); //设置请求方式
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);//设置提交的字符串
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
function delurl($url, $my_head_array = array()){
$headerArray =array('Content-type:application/json');
if(is_array($my_head_array) && count($my_head_array)){
$headerArray = $my_head_array;
}
$ch = curl_init();
curl_setopt ($ch, CURLOPT_URL, $url);
curl_setopt ($ch, CURLOPT_HTTPHEADER, $headerArray);
curl_setopt ($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt ($ch, CURLOPT_CUSTOMREQUEST, "DELETE");
$output = curl_exec($ch);
curl_close($ch);
return $output;
}
function p ($v = '-Your-Variable-Here-') {
header('Content-Type: text/css; charset=utf-8');
print_r($v);
die;
}
/* Check */
if(!is_file($json_file_with_domains_and_zone_id)){
die('Missing json file for zones');
}
$arr_domain_and_id = json_decode(file_get_contents($json_file_with_domains_and_zone_id), true);
if(!is_array($arr_domain_and_id) || !count($arr_domain_and_id)){
die('Invalid array for domains and zone ID');
}
/* Loop and check */
$conf_wanted = array(
'type' => 'A',
'name' => '', // Your domain name
'content' => $config_IP_wanted,
// 'ttl' => 1,
// 'proxied' => false
);
foreach ($arr_domain_and_id as $cur_domain => $cur_zone_id) {
print('<hr />');
error_log('Dealing with '.$cur_domain);
print("<div>Checking {$cur_domain}</div>");
$cur_domain = strtolower($cur_domain);
/* Ignore */
if(in_array($cur_domain, $domains_ignored)){
continue;
}
$existing_dns_records = array();
$identifier_of_entries_to_delete = array();
$identifier_of_entries_to_update = array();
$curl_head = array(
"X-Auth-Email: {$x_email}",
"X-Auth-Key: {$x_auth_key}",
"Content-Type: application/json"
);
/* Get the list of DNS record at first */
$curl_url_base = "https://api.cloudflare.com/client/v4/zones/{$cur_zone_id}/dns_records"; // 注意!结尾没有斜杠!
$q_str = '?type='.$conf_wanted['type'].'&name='.$cur_domain.'&per_page=100';
/**
* curl -X GET "https://api.cloudflare.com/client/v4/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records?type=A&name=example.com&content=127.0.0.1&page=1&per_page=20&order=type&direction=desc&match=all" \
-H "X-Auth-Email: user@example.com" \
-H "X-Auth-Key: c2547eb70b638f5e225cf483cc5cfdda41" \
-H "Content-Type: application/json"
*/
$curl_url_list = $curl_url_base.$q_str;
/**
* curl -X POST "https://api.cloudflare.com/client/v4/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records" \
-H "X-Auth-Email: user@example.com" \
-H "X-Auth-Key: c2547eb70b638f5e225cf483cc5cfdda41" \
-H "Content-Type: application/json" \
--data '{"type":"A","name":"example.com","content":"127.0.0.1","ttl":120,"priority":10,"proxied":false}'
*/
/**
* curl -X DELETE "https://api.cloudflare.com/client/v4/zones/023e105f4ecef8ad9ca31a8372d0c353/dns_records/372e67954025e0ba6aaa6d586b9e0b59" \
-H "X-Auth-Email: user@example.com" \
-H "X-Auth-Key: c2547eb70b638f5e225cf483cc5cfdda41" \
-H "Content-Type: application/json"
*/
$res_str = geturl($curl_url_list, $curl_head);
$res_arr = json_decode($res_str, true);
if(!is_array($res_arr) || !count($res_arr) || !key_exists('success', $res_arr) || !$res_arr['success']){
error_log('ERROR for '.$cur_domain.': '.$res_str);
print("<div>Error {$cur_domain}</div><div>{$res_str}</div><hr />");
continue;
}
$list_of_record = $res_arr['result'];
$count_entries = count($list_of_record);
$perfect_entry = array(); // id,type,name,content,proxiable,proxied,ttl,locked,zone_id,zone_name,etc
foreach ($list_of_record as $k=>$v) {
if($v['content'] == $conf_wanted['content']){
$perfect_entry = $v;
}
}
/* Compare */
if($count_entries == 1 && count($perfect_entry)){
$message = 'Everything is fine for '.$cur_domain;
error_log($message);
print('<div>'.$message.'</div>');
continue;
} else {
$need_to_create = false;
if ($count_entries == 0) {
/* Create at last */
$need_to_create = true;
} elseif (!count($perfect_entry)) {
/* There's no correct entries, delete them and rebuild */
foreach ($list_of_record as $one) {
$identifier_of_entries_to_delete[] = $one['id'];
}
/* Create at last */
$need_to_create = true;
} else {
/* There's one or more correct entries, just keep them */
foreach ($list_of_record as $one) {
if($one['content'] != $conf_wanted['content']){
$identifier_of_entries_to_delete[] = $one['id'];
}
}
$need_to_create = false;
}
/* Delete */
if(count($identifier_of_entries_to_delete)){
foreach ($identifier_of_entries_to_delete as $oneIDdel) {
$url = $curl_url_base . '/' . $oneIDdel;
$res_curl = delurl($url, $curl_head);
$res_curl_arr = json_decode($res_curl, true);
if(!is_array($res_curl_arr) || !count($res_curl_arr) || !key_exists('success', $res_curl_arr) || !$res_curl_arr['success']){
$message = 'Failed to delete A record #'.$oneIDdel.' for '.$cur_domain;
error_log($message);
print('<div>'.$message.'</div>');
print('<div>'.$url.'</div>');
print("<div>{$res_curl}</div>");
} else {
$message = 'Succeeded to delete A record #'.$oneIDdel.' for '.$cur_domain;
error_log($message);
print('<div>'.$message.'</div>');
}
}
}
/* Build */
if($need_to_create){
$good_data = $conf_wanted;
$good_data['name'] = $cur_domain;
$url = $curl_url_base;
$res_curl = posturl($url, $good_data, $curl_head);
$res_curl_arr = json_decode($res_curl, true);
if(!is_array($res_curl_arr) || !count($res_curl_arr) || !key_exists('success', $res_curl_arr) || !$res_curl_arr['success']){
$message = 'Failed to create A record for '.$cur_domain;
error_log($message);
print('<div>'.$message.'</div>');
print('<div>'.$message.'</div>');
print('<div>'.$url.'</div>');
print("<div>{$res_curl}</div>");
} else {
$message = 'Succeeded to create A record for '.$cur_domain;
error_log($message);
print('<div>'.$message.'</div>');
}
}
}
}
/**
* End
*/