怎样批量修改CloudFlare记录

2023年8月19日 | 分类: 【源码】
<?php
 
    /**
     * Title:  批量修改CloudFlare上的所有域名的DNS
     * Author: Rudon <[email protected]>
     * 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 = '[email protected]';
    $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: [email protected]" \
            -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: [email protected]" \
            -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: [email protected]" \
            -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
     */
 

原文:https://blog.csdn.net/qq285744011/article/details/88357409