天天看点

利用阿里云API为树莓派做DDNS  引一、准备二、实施三、其他

  引

 一直想利用树莓派亲手搭建几种服务器来加深了解,奈何电信光猫每次重启后都会重新分配公网IP。

     只能先想办法解决这个最基本的问题,起初的时候没想到该怎么搞。当时手里有一个便宜买的海外虚拟主机,打算让树莓派每次开机后自动发送自己的IP到那个主机上,然后我需要外网访问的时候,从海外主机获取到ip然后在访问。。。。。后来想了想我图个啥。      最后从网络上找了这种通过阿里API去动态解析IP的方式,不过网上找到的虽然思路基本相同,但方法五花八门,而且调用api方法我至今没完全搞懂,只好摸索着用现在这个办法,记录一下。

思路:

1、树莓派利用api获取自己的公网ip

2、调用阿里云api将我的域名解析到当前树莓派的公网ip上,并且避免解析的地址相同(api会报错)

一、准备

  1、树莓派 、阿里云的域名(便宜的几块钱一年)、有公网ip且可以设置端口映射的路由

  2、安装阿里云的python版本的sdk,我这个只用了核心库,里面有api的泛用型调用命令。

https://developer.aliyun.com/tools/sdk?spm=5176.11122631.962077.5.d8f63801lb9te1#/python

利用阿里云API为树莓派做DDNS  引一、准备二、实施三、其他

我是直接用下面这个pip命令安装的,因为别的方法我不会,官方提供了一个httpdns的sdk。我估摸着应该是把方法都封装了更简便的样子。

3、得到你自己的AccessKey

在网页端阿里云控制台点击你的头像就能看到了,会生成一个AccessKey ID和Access Key Secret。这两个东西是过会调用api时验证你身份用的。

二、实施

  1、获取树莓派当前的公网IP

          调用网上找的获取IP地址的API,返回的就是自己访问公网的IP。我用的是这个: https://www.xxorg.com/tools/getip/

def getip():
 res=request.urlopen('https://www.xxorg.com/tools/getip/')
 return str(res.read(),'utf-8')
           

这个返回的就是自己公网的IP字符串。

2、构建客户端对象

     构建一个包含你的AccessKey ID和Access Key Secret的客户段对象,后面会加到请求中

     导入

from aliyunsdkcore.client import AcsClient
           

    创建

client = AcsClient('你的AccessKey ID', '你的Access Key Secret', 'cn-hangzhou')
           

3、定义查询方法

导入

from aliyunsdkcore.request import CommonRequest
           

 CommonRequest使用的介绍: 

  https://help.aliyun.com/document_detail/61476.html?spm=5176.10695662.1996646101.searchclickresult.61f2243bEt8PWL

def queryrecordid():
 request = CommonRequest()
 request.set_accept_format('json')  #设置接收格式,有json和xml两种
 request.set_domain('alidns.aliyuncs.com') #请求地址
 request.set_method('POST')                #请求方式,GET和POST两种
 request.set_version('2015-01-09')         #版本信息
 request.set_action_name('DescribeDomainRecordInfo') #set_action_name这个是设置调用的方法
 request.add_query_param('RecordId', '解析记录的ID')  #request.add_query_param添加参数
 response = client.do_action_with_exception(request) 
 return json.loads(str(response,'utf-8'))['Value']  #只读取返回数据中的value也就是IP
           

 图中调用的时候应该有异常处理,但我对python还不熟悉,所以当时没敢搞,回头再来解决。

基本调用api就是更改一下action参数和参数的变化,具体的参数信息也都能从api文档里找到

解析记录的id需要调用DescribeDomainRecords获取解析记录的方法,可以调用之后记下来,后面只需要对这条记录进行更改和查询就行了。

def querylist():
 request=CommonRequest()
 request.set_accept_format('json')
 request.set_domain('alidns.aliyuncs.com')
 request.set_method('POST')
 request.set_version('2015-01-09')
 request.set_action_name('DescribeDomainRecords')
 request.add_query_param('DomainName','你的域名')
 response=client.do_action_with_exception(request)
 print(str(response,'utf-8'))
           

4、定义更新方法

def updaterecordid(value):
 request = CommonRequest()
 request.set_accept_format('json')
 request.set_domain('alidns.aliyuncs.com')
 request.set_method('POST')
 request.set_version('2015-01-09')
 request.set_action_name('UpdateDomainRecord')
 request.add_query_param('RecordId', '解析记录ID')
 request.add_query_param('RR', '*')
 request.add_query_param('Type', 'A')
 request.add_query_param('Value', '解析到的IP地址') #上面三个值的解释都在api文档
 response = client.do_action_with_exception(request)
           

api地址:https://help.aliyun.com/document_detail/29774.html?spm=a2c4g.11186623.6.641.7b435eb4WHrsn4

5、防止解析到同一个地址

ip=getip()
oldip=queryrecordid()
if oldip!=ip:
  updaterecordid(ip)
  print('The new IP is',ip)
else:
 print("IP address not updated")
           

网上有的方法是直接将上次解析的地址写入本地,这样就可以减少api的调用次数,不过我水平有限也不太喜欢在本地再生成一个文件,于是就直接用当前地址和解析记录中的地址对比了。

6、部署

因为我家的路由和派是在同一个插排上的,所以每次开启路由器时树莓派也一块启动,这样就可以把这个代码放到树莓派的开机执行里运行,不过路由器开机时间长,所以我设置树莓派开机3分钟后自动执行。

执行命令 

vi /etc/rc.local
           

加一段代码到exit 0之前

sleep 3m && python3 ddns.py &
           

休眠三分钟之后执行这个python程序,不过好像在rc.local中会阻塞开机,所以最后加一个&放到新的线程中运行

三、其他

在手机或者pc访问的时候会优先使用本机储存的dns缓存,所以更新的ip同步不过来,需要刷新dns缓存。win是在cmd中执行ipconfig  /flushdns,手机直接飞行模式貌似就可以。