来自 yoyolife 的投稿。

目前的资料收集情况来说,只有中国电信可以开通外网IP。另外,不能使用80端口。如果你要80就不用往下看了。

我的开通过程是。微信找到中国电信公众号,找到客服,和他说你要开通IP回退(公网IP),他问你必须的验证资料后,然后等那个半天。电信小哥会到你的社区里面,把你的网口从一个盒子换到另外一个盒子,然后他会打电话给你。你重启一下。进入路由,看到的外网的ip,和你去baidu 打 ip 看到的ip是一样的了。如果不这么做,你得到的只是一个大局域网的ip。外面是不能访问的。

当你有了外网ip。然后你就要开始设置你的光猫和路由器。我用的是TPLink路由,你们用啥基本上是大同小异。

我们要做的事情是,关闭光猫的自动拨号功能,用路由器来拨号。现在默认光猫出厂,就能自己上网,因为光猫会自动帮你拨号了。我们要换成自己的路由器拨号,并开启DMZ公开你的树莓派到网外。

进入192.168.0.1 进入超级管理员

username=”telecomadmin”

web_passwd=”nE7jA%5m”

然后到 网络-宽带设置 把你拨号模式改成Bridge模式VLAN ID 设为41 如图

树莓派 + DDNS 绑定域名实现外网访问_html

然后进入你的路由器192.168.1.1 进入WAN设置,使用PPPoE拨号

树莓派 + DDNS 绑定域名实现外网访问_json_02

这个时候,你的IP和你外网的IP是一样了。

然后进去DMZ主机

树莓派 + DDNS 绑定域名实现外网访问_外网_03

把树莓派内网地址写上去。

这个时候,你用你的外网IP 就能进入SSH

重点来了。现在你要设置DDNS让你的域名当IP改变时可以自己绑定新的IP

登陆阿里云后

进入 https://ram.console.aliyun.com/users RAM 访问控制

新建立用户给权限

树莓派 + DDNS 绑定域名实现外网访问_python_04

把这4个权限选上。然后开始跑我下面的python代码

先安装




1


2




​pip3 ​​​​install​​ ​​aliyunsdkcore​


​pip3 ​​​​install​​ ​​aliyun-python-sdk-alidns​





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




​# coding: utf-8​


​from​​ ​​aliyunsdkcore.client ​​​​import​​ ​​AcsClient​


​from​​ ​​aliyunsdkalidns.request.v20150109.DescribeSubDomainRecordsRequest ​​​​import​​ ​​DescribeSubDomainRecordsRequest​


​from​​ ​​aliyunsdkalidns.request.v20150109.AddDomainRecordRequest ​​​​import​​ ​​AddDomainRecordRequest​


​from​​ ​​aliyunsdkalidns.request.v20150109.UpdateDomainRecordRequest ​​​​import​​ ​​UpdateDomainRecordRequest​


 


​import​​ ​​time​


​import​​ ​​json​


​import​​ ​​urllib.request​


 


​##这里要换成自己的哟​


​client ​​​​=​​ ​​AcsClient(​​​​'AccessKey ID'​​​​, ​​​​'Access Key'​​​​, ​​​​'cn-hangzhou'​​​​)​


 


​def​​ ​​get_internet_ip():​


​with urllib.request.urlopen(​​​​'http://www.3322.org/dyndns/getip'​​​​) as response:​


​html ​​​​=​​ ​​response.read()​


​ip ​​​​=​​ ​​str​​​​(html, encoding​​​​=​​​​'utf-8'​​​​).replace(​​​​"\n"​​​​, "")​


​return​​ ​​ip​


 


​def​​ ​​Describe_SubDomain_Records(client,record_type,subdomain):​


​request ​​​​=​​ ​​DescribeSubDomainRecordsRequest()​


​request.set_accept_format(​​​​'json'​​​​)​


 


​request.set_Type(record_type)​


​request.set_SubDomain(subdomain)​


 


​response ​​​​=​​ ​​client.do_action_with_exception(request)​


​response ​​​​=​​ ​​str​​​​(response, encoding​​​​=​​​​'utf-8'​​​​)​


​relsult ​​​​=​​ ​​json.loads(response)​


​return​​ ​​relsult​


 


 


​def​​ ​​add_record(client,priority,ttl,record_type,value,rr,domainname):​


​request ​​​​=​​ ​​AddDomainRecordRequest()​


​request.set_accept_format(​​​​'json'​​​​)​


 


​request.set_Priority(priority)​


​request.set_TTL(ttl)​


​request.set_Value(value)​


​request.set_Type(record_type)​


​request.set_RR(rr)​


​request.set_DomainName(domainname)​


 


​response ​​​​=​​ ​​client.do_action_with_exception(request)​


​response ​​​​=​​ ​​str​​​​(response, encoding​​​​=​​​​'utf-8'​​​​)​


​relsult ​​​​=​​ ​​json.loads(response)​


​return​​ ​​relsult​


 


 


​def​​ ​​update_record(client,priority,ttl,record_type,value,rr,record_id):​


​request ​​​​=​​ ​​UpdateDomainRecordRequest()​


​request.set_accept_format(​​​​'json'​​​​)​


 


​request.set_Priority(priority)​


​request.set_TTL(ttl)​


​request.set_Value(value)​


​request.set_Type(record_type)​


​request.set_RR(rr)​


​request.set_RecordId(record_id)​


 


​response ​​​​=​​ ​​client.do_action_with_exception(request)​


​response ​​​​=​​ ​​str​​​​(response, encoding​​​​=​​​​'utf-8'​​​​)​


​return​​ ​​response​


 


​def​​ ​​wirte_to_file(path,ip):​


​f ​​​​=​​ ​​open​​​​(path, ​​​​'w'​​​​)  ​​​​# 若是'wb'就表示写二进制文件​


​f.write(ip)​


​f.close()​


 


​def​​ ​​domains(domain):​


​try​​​​:​


​des_relsult ​​​​=​​ ​​Describe_SubDomain_Records(client, ​​​​"A"​​​​, domain[​​​​'full'​​​​])​


​# 判断子域名解析记录查询结果,TotalCount为0表示不存在这个子域名的解析记录,需要新增一个​


​if​​ ​​des_relsult[​​​​"TotalCount"​​​​] ​​​​=​​​​=​​ ​​0​​​​:​


​add_relsult ​​​​=​​ ​​add_record(client, ​​​​"5"​​​​, ​​​​"600"​​​​, ​​​​"A"​​​​, ip, domain[​​​​'left'​​​​], domain[​​​​'right'​​​​])​


​record_id ​​​​=​​ ​​add_relsult[​​​​"RecordId"​​​​]​


​print​​​​(​​​​"域名解析新增成功!"​​​​)​


​# 判断子域名解析记录查询结果,TotalCount为1表示存在这个子域名的解析记录,需要更新解析记录,更新记录需要用到RecordId,这个在查询函数中有返回des_relsult["DomainRecords"]["Record"][0]["RecordId"]​


​elif​​ ​​des_relsult[​​​​"TotalCount"​​​​] ​​​​=​​​​=​​ ​​1​​​​:​


​record_id ​​​​=​​ ​​des_relsult[​​​​"DomainRecords"​​​​][​​​​"Record"​​​​][​​​​0​​​​][​​​​"RecordId"​​​​]​


​update_record(client, ​​​​"5"​​​​, ​​​​"600"​​​​, ​​​​"A"​​​​, ip, domain[​​​​'left'​​​​], record_id)​


​print​​​​(​​​​"域名解析更新成功!"​​​​)​


​else​​​​:​


​record_id ​​​​=​​ ​​0​


​path ​​​​=​​ ​​'./RecordId'​


​wirte_to_file(path, record_id)​


​except​​ ​​Exception as e:​


​print​​​​(e)​


​while​​ ​​True​​​​:​


​ip ​​​​=​​ ​​get_internet_ip()​


​with ​​​​open​​​​(​​​​"./ip"​​​​, ​​​​'r'​​​​) as f:​


​old_ip ​​​​=​​ ​​f.read()​


 


​if​​ ​​ip ​​​​=​​​​=​​ ​​old_ip:​


​print​​​​(​​​​"noupdate"​​ ​​+​​ ​​"\nnew_ip:"​​ ​​+​​ ​​ip ​​​​+​​ ​​"\nold_ip:"​​ ​​+​​ ​​old_ip)​


​else​​​​:​


​wirte_to_file(​​​​"./ip"​​​​, ip)​


 


​##多个域名​


​domains({​​​​'full'​​​​:​​​​"*.tunnel.xxx.fun"​​​​,​​​​'left'​​​​:​​​​"*.tunnel"​​​​,​​​​"right"​​​​:​​​​"xxx.fun"​​​​})​


​domains({​​​​'full'​​​​:​​​​"tunnel.xxx.fun"​​​​,​​​​'left'​​​​:​​​​"tunnel"​​​​,​​​​"right"​​​​:​​​​"xxx.fun"​​​​})​


​domains({​​​​'full'​​​​:​​​​"*.frp.xxx.fun"​​​​,​​​​'left'​​​​:​​​​"*.frp"​​​​,​​​​"right"​​​​:​​​​"xxx.fun"​​​​})​


 


 


​time.sleep(​​​​10​​​​)​



保存为 ddns.py 文件

在同级目录输入




1


2




​touch​​ ​​ip​


​touch​​ ​​RecordId​



然后运行




1




​python3 ddns.py​



就会每10秒刷新一次ip 有改变就会去修改ddns

然后你可以把py放到supervisor里面守护

也可以放到 /etc/rc.local启动运行

也可以放到后台进程




1




​nuhup python3 ddns.py &​