起因
起因是发现网站套了cdn后ping出的ip跟cdn的IP并不一样,查询cnmae解析也查询不到
我还以为这个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
暂无评论内容