树莓派动态域名解析
因为想想买台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,然后创建一个用户
参考资料: