检测外网IP变化,动态更新阿里云域名解析 您所在的位置:网站首页 腾讯网域名解析api 检测外网IP变化,动态更新阿里云域名解析

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

2024-04-19 16:30| 来源: 网络整理| 查看: 265

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

目录获取域名解析IP获取实时外网IP更新阿里云域名解析开机自动运行脚本

可以看出,WAN口IP地址需要通过DHCP获取,并且lease time为一天

获取域名解析地址

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

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

可以通过左边的方式,直接从最近的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 lookup ips, _ := 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 IP resp, err := http.Get("http://ifconfig.me") // the ip discover service, choose a nearby one if 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的接口:

通过 AddDomainRecord 根据传入参数添加解析记录。通过 UpdateDomainRecord 根据传入参数修改解析记录。通过 DescribeDomainRecords 根据传入参数获取指定主域名的所有解析记录列表。通过 DescribeSubDomainRecords 根据传入参数获取某个固定子域名的所有解析记录列表。通过 DescribeDomainRecordInfo 根据传入参数获取某个固定子域名下的解析记录信息。

这里我们需要用到的是UpdateDomainRecord和DescribeDomainRecords。通过DescribeDomainRecord获取对应域名解析记录的Record ID,使用Record ID作为参数调用UpdateDomainRecord修改对应解析记录。

func descRecords(domain string) (string, error) func updateDomainRecord(ipAddr string, recordID string) error if 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

开机自动运行脚本

最后一步,开机自动运行脚本。这个脚本我跑在树莓派上,树莓派装的系统是[email protected] 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. # Log exec 2> /tmp/rc.local.log # send stderr from rc.local to a log file exec 1>&2 # send stdout to the same log file set -x # tell sh to display commands before execution # Run the dynamic dns update service runuser -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 # End exit 0

关于后台运行,我使用了tmux这个工具(一款优秀的终端复用软件)。由于/etc/rc.local会使用root身份执行,而我的tmux 和go都属于ubuntu。这里使用了runuser -u -- 命令,可以以任意user身份执行--后的命令。

推荐原文lang dynamicDNS.go 开机启动脚本 rc.local.sh tmux 使用手册

原文:



【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有