Other 树莓派动态域名解析

树莓派动态域名解析

pic1

因为想想买台VPS玩玩,跑个Flask应用或者当数据库用用, 结果逛了一圈,买了个5刀一个月的低配VPS, 结果分配的IP均处于长城外,而且其他阿里云或者腾讯的实在是买不起,所以放弃了这个想法.
想起之前买的树莓派也有远程SSH过, 但是因为室友的联通网每天都强制断网而且IP地址每天都在变,所以直接用IP连上去会很麻烦.
所以决定找找看有没有什么能够动态更新IP的方法.幸运的是前人已经完成了这项工作.

因为阿里云提供了更新DNS的API,所以直接使用这个API即可.
思路就是

  • 程序开机自启->启动应用
  • 树莓派获取自己IP->准备更新
  • 调用阿里云的API->进行更新
  • 随时随地通过域名SSH上树莓派
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    # -*- coding: utf-8 -*-
    import json
    import os
    import re
    import sys
    from datetime import datetime
    import time
    import requests
    from aliyunsdkalidns.request.v20150109 import UpdateDomainRecordRequest, DescribeDomainRecordsRequest, \
    DescribeDomainRecordInfoRequest
    from aliyunsdkcore import client

    access_key_id = "你的access_key_id"
    access_Key_secret = "你的access_Key_secret"

    # 请填写你的账号ID, 看下条注释
    account_id = '你创建的账号ID'

    # 如果填写yes,则运行程序后仅显示域名信息,并不会更新记录,用于获取解析记录ID。
    # 如果填写no,则运行程序后不显示域名信息,仅更新记录。
    i_dont_know_record_id = 'no'

    # 请填写你的一级域名
    rc_domain = 'chaosgoo.com'

    # 请填写你的解析记录
    rc_rr = 'fgo'

    # 请填写你的记录类型,DDNS请填写A,表示A记录
    rc_type = 'A'

    # 请填写解析记录ID
    rc_record_id = '解析记录ID'

    # 请填写解析有效生存时间TTL,单位:秒
    rc_ttl = '600'

    # 请填写返还内容格式,json,xml
    rc_format = 'json'


    def my_ip_method_1():
    get_ip_method = os.popen('curl -s ip.cn')
    get_ip_responses = get_ip_method.readlines()[0]
    get_ip_pattern = re.compile(r'\d+\.\d+\.\d+\.\d+')
    get_ip_value = get_ip_pattern.findall(get_ip_responses)[0]
    return get_ip_value


    def my_ip_method_2():
    get_ip_method = os.popen('curl -s http://ip-api.com/json')
    get_ip_responses = get_ip_method.readlines()[0]
    get_ip_responses = eval(str(get_ip_responses))
    get_ip_value = get_ip_responses['query']
    return get_ip_value


    def my_ip_method_3():
    get_ip_method = requests.get('http://ifconfig.co/json').content
    get_ip_value = eval(get_ip_method)
    get_ip_value = get_ip_value['ip']
    return get_ip_value


    def check_records(dns_domain):
    clt = client.AcsClient(access_key_id, access_Key_secret, 'cn-hangzhou')
    request = DescribeDomainRecordsRequest.DescribeDomainRecordsRequest()
    request.set_DomainName(dns_domain)
    request.set_accept_format(rc_format)
    result = clt.do_action_with_exception(request)
    result = result.decode()
    result_dict = json.JSONDecoder().decode(result)
    result_list = result_dict['DomainRecords']['Record']
    for j in result_list:
    print('Subdomain:' + j['RR'] + ' ' + '| RecordId:' + j['RecordId'])
    return


    def old_ip():
    clt = client.AcsClient(access_key_id, access_Key_secret, 'cn-hangzhou')
    request = DescribeDomainRecordInfoRequest.DescribeDomainRecordInfoRequest()
    request.set_RecordId(rc_record_id)
    request.set_accept_format(rc_format)
    result = clt.do_action_with_exception(request).decode()
    result = json.JSONDecoder().decode(result)
    result = result['Value']
    return result


    def update_dns(dns_rr, dns_type, dns_value, dns_record_id, dns_ttl, dns_format):
    clt = client.AcsClient(access_key_id, access_Key_secret, 'cn-hangzhou')
    request = UpdateDomainRecordRequest.UpdateDomainRecordRequest()
    request.set_RR(dns_rr)
    request.set_Type(dns_type)
    request.set_Value(dns_value)
    request.set_RecordId(dns_record_id)
    request.set_TTL(dns_ttl)
    request.set_accept_format(dns_format)
    result = clt.do_action_with_exception(request)
    return result


    def write_to_file():
    time_now = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    current_script_path = '/mnt/Python'
    log_file = current_script_path + '/' + 'aliyun_ddns_log.txt'
    write = open(log_file, 'a')
    write.write(time_now + ' ' + str(rc_value) + '\n')
    write.close()
    return

    while True:
    # 因为学校晚上强制断网, 所以加入一个时间检测,只在特定时段内进行更新
    time_now = datetime.now().strftime('%H')
    if int(time_now) > 23 or int(time_now) < 7:
    if i_dont_know_record_id == 'yes':
    check_records(rc_domain)
    elif i_dont_know_record_id == 'no':
    rc_value = my_ip_method_2()
    rc_value_old = old_ip()
    if rc_value_old == rc_value:
    write_to_file()
    print('The specified value of parameter Value is the same as old')
    else:
    print(update_dns(rc_rr, rc_type, rc_value, rc_record_id, rc_ttl, rc_format))
    write_to_file()
    time.sleep(600)

要想正常运行这个程序,就需要到阿里云的控制台申请acesskey,然后创建一个用户,进行身份验证.
进入阿里云控制台,然后点击右上角头像,选择accesskey,然后创建一个用户

参考资料:

阅读量: