根据服务器是否能 ping 通自动修改域名解析

饱受 ddos 攻击的烦恼,上次将网站放在果核大佬那里有一份,但是由于诸多原因,最大的问题就是 ftp 不方便和自己不能在服务器上进行一些操作,还是将网站放在了自己的服务器。

泄露了 ip 为什么不换,原因就是我用 zerotier 搭建了异地组网,换 ip 是小事,因为重新搭建一个也不费时间,但是手机上操作会比较麻烦。

所以选择了将果核那边的网站当作一个备用站点,服务器进黑洞了就直接切换解析,于是想到了写 python 脚本来解决这个问题。

说明一下,阿蛮君这边使用的是腾讯云的 dnspod 域名解析,所以需要安装相关模块。

pip3 install --upgrade tencentcloud-sdk-python

python 脚本内容如下:

import json
import subprocess
import time
from tencentcloud.common import credential
from tencentcloud.common.profile.client_profile import ClientProfile
from tencentcloud.common.profile.http_profile import HttpProfile
from tencentcloud.common.exception.tencent_cloud_sdk_exception import TencentCloudSDKException
from tencentcloud.dnspod.v20210323 import dnspod_client, models

# 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
secret_id = "xxx"
secret_key = "xxx"
endpoint = "dnspod.tencentcloudapi.com"
# 填写自己的域名相关信息,domain_id 就是域名的主键,在dnspod域名列表可以通过f12查看
domain = "test.com"
domain_id = 91234862
# 这是自己服务器的 ip,是否修改解析看这个ip是否能ping通
ip_address = "127.0.0.1"
# 这个是域名解析记录对应的id,在dnspod域名解析列表可以通过f12获取查看
record_ids = {
    "test1": 1504279986,
    "test2": 1504280312
}
record_line = "境内"
# 防止多次解析设置的变量
flag = '';

def init_flag():
    # 初始化状态,不进行初始化会不清楚开始的状态
    global flag
    if check_ip_reachability(ip_address):
        print(print_time() + "[初始化]服务器正常,准备修改解析记录...")
        flag = True
        update_normal_record()
    else:
        print(print_time() + "[初始化]服务器异常,准备修改解析记录...")
        update_abnormal_record()
        flag = False
    print(print_time() + "初始化状态成功")

def print_time():
    return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) + " "

def check_ip_reachability(ip_address):
    # 尝试ping命令的最大次数
    max_attempts = 30
    # 每次尝试之间的等待时间(秒)
    wait_time = 1

    for _ in range(max_attempts):
        # 使用subprocess模块执行ping命令
        ping_process = subprocess.Popen(["ping", "-c", "1", ip_address], stdout=subprocess.PIPE)
        ping_output, _ = ping_process.communicate()
        ping_exit_code = ping_process.returncode

        if ping_exit_code == 0:
            # 如果ping成功,则返回True
            return True

        # 如果ping失败,则等待一段时间再进行下一次尝试
        time.sleep(wait_time)

    # 在指定次数的尝试之后,仍然ping失败,则返回False
    return False

def modify_dns_record(record, record_type, value):
    try:
        # 实例化一个认证对象,入参需要传入腾讯云账户 SecretId 和 SecretKey,此处还需注意密钥对的保密
        # 代码泄露可能会导致 SecretId 和 SecretKey 泄露,并威胁账号下所有资源的安全性。以下代码示例仅供参考,建议采用更安全的方式来使用密钥,请参见:https://cloud.tencent.com/document/product/1278/85305
        # 密钥可前往官网控制台 https://console.cloud.tencent.com/cam/capi 进行获取
        cred = credential.Credential(secret_id, secret_key)
        # 实例化一个http选项,可选的,没有特殊需求可以跳过
        httpProfile = HttpProfile()
        httpProfile.endpoint = endpoint

        # 实例化一个client选项,可选的,没有特殊需求可以跳过
        clientProfile = ClientProfile()
        clientProfile.httpProfile = httpProfile
        # 实例化要请求产品的client对象,clientProfile是可选的
        client = dnspod_client.DnspodClient(cred, "", clientProfile)

        # 实例化一个请求对象,每个接口都会对应一个request对象
        req = models.ModifyRecordRequest()
        params = {
            "Domain": domain,
            "DomainId": domain_id,
            "SubDomain": record,
            "RecordType": record_type,
            "RecordLine": record_line,
            "Value": value,
            "RecordId": record_ids[record],
        }

        req.from_json_string(json.dumps(params))

        # 返回的resp是一个ModifyRecordResponse的实例,与请求对象对应
        resp = client.ModifyRecord(req)

        print(print_time() + f"域名解析修改成功:{record}, {record_type}, {value}")

    except TencentCloudSDKException as err:
        print(print_time() + f"域名解析修改失败:{err}")

def update_dns_record(ip_address):
    global flag
    if check_ip_reachability(ip_address):
        if flag == True:
            print(print_time() + "服务器持续正常,解析无需更改")
            return
        # IP地址可达,执行相应的解析修改
        print(print_time() + "服务器状态变更为正常,准备修改解析记录...")
        update_normal_record()
        flag = True
    else:
        if flag == False:
            print(print_time() + "服务器持续异常,解析无需更改")
            return
        # IP地址不可达,执行相应的解析修改
        print(print_time() + "服务器状态变更为异常,准备修改解析记录...")
        update_abnormal_record()
        flag = False

def update_normal_record():
    modify_dns_record("test1", "CNAME", "test1.11dundns.com.")
    modify_dns_record("test2", "CNAME", "test2.11dundns.com.")

def update_abnormal_record():
    modify_dns_record("test1", "CNAME", "test1.hcnamecdns.com.")
    modify_dns_record("test2", "CNAME", "test2.hcnamecdns.com.")

init_flag()
while True:
    update_dns_record(ip_address)
    time.sleep(5)

这里的参数根据自己的实际情况填写,并且如果你是直接解析 IP 的话,需要把 CNAME 改为 A 记录。test1 和 test2 这里是作为示例,实际一般使用 @ 和 www 解析记录。

运行脚本,服务器尝试禁 ping 和解除禁 ping,结果如下:

64894b6c156f7

阅读剩余
THE END