在CF托管域名?无法关闭的CloudFlare拉平机制如何解决

在CF托管域名?无法关闭的CloudFlare拉平机制如何解决

起因

20250225104917467-image

起因是发现网站套了cdn后ping出的ip跟cdn的IP并不一样,查询cnmae解析也查询不到

20250225105100159-image

我还以为这个cdn服务商有什么高级的技术,经过一番查验过后,这是因为海外dns服务商,如cloudflare的拉平机制

根据RFC1912,域名根目录不得存在CNAME记录,因为根目录下的CNAME记录会使得整个域名的MX邮箱记录、TXT域名验证记录等全部失效。
因此,CloudFlare推出了拉平根目录CNAME的功能,通过CloudFlare的服务器,将CNAME解析为A记录,避免了冲突问题。
但是有一点问题,如果像CDN这样的,会根据请求者的IP而改变的动态CNAME记录,将会被CloudFlare拉平为一个固定的 A 记录。
CloudFlare的主服务器位于境外,即使你的用户主要是在国内,CloudFlare仍然会将其拉平为美国的服务器,使得这个固定的 A 记录经常速度太慢、延迟过高甚至超时。
以上来自——让 CloudFlare 根目录 CNAME 拉平更好用

解决方法

解决方法有三种,一种是不使用cloudflare以及一些海外的dns服务,换到国内dnspod以及阿里云dns等等…..

dnspod也有提供展平服务,为了兼容cname与mx和txt记录,但是这个只能高级dns套餐可以开启,放心食用

第二种就是不使用根目录的cname,将@记录换成www,m等,即可避免根目录的拉平机制影响

第三种 则是利用python程序解决

import requests
import socket

def get_dns_id(email, api_key, zone_id, record_name):
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records"
    headers = {
        "Content-Type": "application/json",
        "X-Auth-Email": email,
        "X-Auth-Key": api_key
    }

    try:
        response = requests.request("GET", url, headers=headers)
        data = response.json()
    except:
        print(f"Some thing went wrong while listing the DNS record: Network Error")
        exit(-1)

    if(not data["success"]):
        print(f"Some thing went wrong while listing the DNS record: {data['errors'][0]['message']}")
        exit(-1)
    else:
        for record in data["result"]:
            if(record["name"] == record_name):
                return record["id"]
        print(f"Some thing went wrong while listing the DNS record: Record doesn't exist.")
        exit(-1)

def get_dns(email, api_key, zone_id, record_id):
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records/{record_id}"
    headers = {
        "Content-Type": "application/json",
        "X-Auth-Email": email,
        "X-Auth-Key": api_key
    }

    try:
        response = requests.request("GET", url, headers=headers)
        data = response.json()
    except:
        print(f"Some thing went wrong while getting the DNS record: Network Error")
        exit(-1)

    if(not data["success"]):
        print(f"Some thing went wrong while getting the DNS record: {data['errors'][0]['message']}")
        exit(-1)
    else:
        return data["result"]["content"]

def update_dns(email, api_key, zone_id, record_name, record_id, record_type, value):
    url = f"https://api.cloudflare.com/client/v4/zones/{zone_id}/dns_records/{record_id}"
    payload = {
        "content": value,
        "name": record_name,
        "type": record_type
    }
    headers = {
        "Content-Type": "application/json",
        "X-Auth-Email": email,
        "X-Auth-Key": api_key
    }

    try:
        response = requests.request("PUT", url, json=payload, headers=headers)
        data = response.json()
    except:
        print(f"Some thing went wrong while updating the DNS record: Network Error")
        exit(-1)
    
    if(not data["success"]):
        print(f"Some thing went wrong while updating the DNS record: {data['errors'][0]['message']}")
        exit(-1)
    else:
        return data["result"]["content"]

def resolve_domain(domain_name):
    try:
        ip_address = socket.gethostbyname(domain_name)
        return ip_address
    except socket.gaierror as e:
        print("Something went error while resolving the domain: ", e)
        exit(-1)

email = "Your Email"
api_key = "Your API-Key (https://dash.cloudflare.com/profile/api-tokens)"
zone_id = "Domain's Zone ID"
flatten_record_name = "Record name that wanted to be flatten"
target_cname = "Target CNAME"
flatten_record_type = "A" # Fixed, do not modify

print(f"Accoount Email: {email}")
print(f"Account API-Key: {api_key}")
print(f"Zone ID: {zone_id}")

flatten_rercord_id = get_dns_id(email, api_key, zone_id, flatten_record_name)
print(f"Flatten Record Name: {flatten_record_name} (ID = {flatten_rercord_id})")

current_dns = get_dns(email, api_key, zone_id, flatten_rercord_id)
print(f"Current DNS: {current_dns}")

fastest_ip = resolve_domain(target_cname)
if(fastest_ip == current_dns):
    print(f"Fastest IP: {fastest_ip}, everything up to date")
else:
    print(f"Fastest IP: {fastest_ip}, trying to update dns...")
    print(f"Updated DNS: {update_dns(email, api_key, zone_id, flatten_record_name, flatten_rercord_id, flatten_record_type, fastest_ip)}, done.")

将这个程序部署于你的网站大部分用户所在的区域,并每隔 5~10 分钟运行一次,程序会从你的区域获取最快的 IP 并应用到 CloudFlare DNS 记录上。

注意请在部署前填入 CloudFlare 账户信息、欲拉平的域名以及要解析的目标 CNAME:

exit(-1)

email = "Your Email"
api_key = "Your API-Key (https://dash.cloudflare.com/profile/api-tokens)"
zone_id = "Domain's Zone ID"
flatten_record_name = "Record name that wanted to be flatten"
target_cname = "Target CNAME"
flatten_record_type = "A" # Fixed, do not modify

print(f"Accoount Email: {email}")

拉平程序来自

让 CloudFlare 根目录 CNAME 拉平更好用

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容