18143453325 在线咨询 在线咨询
18143453325 在线咨询
所在位置: 首页 > 营销资讯 > 建站知识 > 检测外网IP变化,动态更新阿里云域名解析

检测外网IP变化,动态更新阿里云域名解析

时间:2023-02-19 23:44:01 | 来源:建站知识

时间:2023-02-19 23:44:01 来源:建站知识

检测外网IP变化,动态更新阿里云域名解析:置办宽带后,运营商一般会给猫(路由器)的WAN网口分配一个外网IP。再通过端口映射(port forwarding)功能,就能远程ssh访问家里的设备(PC/树莓派)或者将其作为服务器使用。为了方便,我将我的域名@.aaron-xin.tech解析到了该外网IP。使用一段时间后,突然有一天,突然所有服务都无法访问了,但是IP还是能够ping通。排查后发现,外网IP也是通过DHCP的方式获取的,意味着每次lease更新的时候,有比较大的概率IP会发生变化。所以,我通过家中的树莓派实时(每小时)监控外网IP的变化,并根据新的外网IP调用阿里云API更新域名解析。

目录

  1. 获取域名解析IP
  2. 获取实时外网IP
  3. 更新阿里云域名解析
  4. 开机自动运行脚本
可以看出,WAN口IP地址需要通过DHCP获取,并且lease time为一天

获取域名解析地址

第一步,获取域名解析到的IP地址(旧地址)。首先想到用最常见的ping命令,再从ping的输出中解析出想要的IP地址。

但是这种办法有一点风险,如果旧的IP地址没有被DHCP分配给别人,就会出现ping不通的情况。所以最自然最保险的办法应该是去做DNS Lookup,对应的Linux Command就是dig <domain name>:

可以通过左边的方式,直接从最近的DNS server,也就是192.168.0.1#53查询。也可以指定8.8.8.8#53(Google的DNS server)。

对应的Golang代码为:

func getResolver() *net.Resolver { return &net.Resolver{ PreferGo: true, Dial: func(ctx context.Context, network, address string) (net.Conn, error) { d := net.Dialer{ Timeout: time.Millisecond * time.Duration(10000), } return d.DialContext(ctx, "udp", "8.8.8.8:53") }, }}// DNS lookupips, _ := resolver.LookupHost(context.Background(), "aaron-xin.tech")dnsIP = ips[0]

获取实时外网地址

第二步,实时获取外网IP地址。子网中每一个设备都通过同一外网IP与外网链接。因为每次HTTP/HTTPs的GET都会包含该请求的外网IP地址,网上有很多网站利用此功能提供”IP Lookup“的功能。如我使用的ifconfig.me:

对应的Golang代码为:

var realIP string// Get real IPresp, err := http.Get("http://ifconfig.me") // the ip discover service, choose a nearby oneif err == nil { defer resp.Body.Close() body, _ := ioutil.ReadAll(resp.Body) realIP = string(body)} else { log.Println("Fail to get ip from ifconfig.me")}

更新阿里云域名解析

第三步,更新阿里云域名解析。这个需要通过调用阿里云的域名解析API完成。

阿里云云解析DNS调用TOP5的接口:

  1. 通过 AddDomainRecord 根据传入参数添加解析记录。
  2. 通过 UpdateDomainRecord 根据传入参数修改解析记录。
  3. 通过 DescribeDomainRecords 根据传入参数获取指定主域名的所有解析记录列表。
  4. 通过 DescribeSubDomainRecords 根据传入参数获取某个固定子域名的所有解析记录列表。
  5. 通过 DescribeDomainRecordInfo 根据传入参数获取某个固定子域名下的解析记录信息。
这里我们需要用到的是UpdateDomainRecordDescribeDomainRecords。通过DescribeDomainRecord获取对应域名解析记录的Record ID,使用Record ID作为参数调用UpdateDomainRecord修改对应解析记录。

func descRecords(domain string) (string, error)func updateDomainRecord(ipAddr string, recordID string) errorif dnsIP != realIP { log.Println("IPs do not match, requesting DNS change...") recordID, err := descRecords(domain) if err != nil { log.Fatal(err) } err = updateDomainRecord(realIP, recordID) if err != nil { log.Fatal(err) }}完整代码可参考 dynamicDNS.go

开机自动运行脚本

最后一步,开机自动运行脚本。这个脚本我跑在树莓派上,树莓派装的系统是ubuntu@20.14 Server。因为树莓派可能会存在突然宕机的可能,如果每次手动运行脚本比较麻烦。也有可能在树莓派宕机的时候,外网IP刚好发生了变化。因此,需要在树莓派每次开机后在后台自动运行检查IP变化的脚本。开机自动运行的方式有很多种,这里我选择使用了编写/etc/rc.local脚本的方式。/etc/rc.local是一个.sh脚本,会在系统启动后root身份执行命令。如果没有这个文件,可以通过sudo touch /etc/rc.local创建或者sudo vim /etc/rc.local创建并编辑。

#!/bin/sh -e## rc.local## This script is executed at the end of each multiuser runlevel.# Make sure that the script will "exit 0" on success or any other# value on error.## In order to enable or disable this script just change the execution# bits.## By default this script does nothing.# Logexec 2> /tmp/rc.local.log # send stderr from rc.local to a log fileexec 1>&2 # send stdout to the same log fileset -x # tell sh to display commands before execution# Run the dynamic dns update servicerunuser -u ubuntu -- /usr/bin/tmux new-session -s dns -d /usr/local/go/bin/go run /home/ubuntu/go/src/github.com/Airine/dynamic-dns/main.go# Endexit 0关于后台运行,我使用了tmux这个工具(一款优秀的终端复用软件)。由于/etc/rc.local会使用root身份执行,而我的tmuxgo都属于ubuntu。这里使用了runuser -u <username> -- <command>命令,可以以任意user身份执行--后的命令。

推荐

  1. 原文lang dynamicDNS.go
  2. 开机启动脚本 rc.local.sh
  3. tmux 使用手册
原文:



关键词:更新,动态,变化

74
73
25
news

版权所有© 亿企邦 1997-2025 保留一切法律许可权利。

为了最佳展示效果,本站不支持IE9及以下版本的浏览器,建议您使用谷歌Chrome浏览器。 点击下载Chrome浏览器
关闭