阿里ddns动态更新域名ip地址

package main

import (
	"flag"
	"fmt"
	"io/ioutil"
	"log"
	"net/http"
	"os"
	"time"

	"github.com/aliyun/alibaba-cloud-sdk-go/sdk/requests"
	"github.com/aliyun/alibaba-cloud-sdk-go/services/alidns"
	"github.com/tidwall/gjson"
)

var (
	ak         = flag.String("ak", "xxxxxx", "accessKeyId")
	aks        = flag.String("aks", "xxxxxx", "accessKeySecret")
	domainName = flag.String("dn", "domain.com", "Domain Name")
	rr         = flag.String("rr", "test", "RR")
	interval   = flag.Duration("t", 10*time.Second, "check interval")

	client *alidns.Client
)

func init() {
	flag.Parse()

	log.SetOutput(os.Stdout)
	log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
}

func main() {
	var err error
	client, err = alidns.NewClientWithAccessKey("cn-hangzhou", *ak, *aks)
	if err != nil {
		log.Fatalln(err)
	}

	for {
		select {
		case <-time.After(*interval):
			// 获取外网ip
			myIP := GetIP()
			if myIP == "" {
				continue
			}
			// 获取域名记录
			record, err := GetRecord()
			if err != nil {
				log.Println(err)
				continue
			}

			if record == nil {
				log.Printf("not found %s.%s record\n", *rr, *domainName)
				AddRecord(myIP)
				continue
			}

			if myIP == record.Value {
				continue
			}

			log.Printf("%s.%s current record: %+v\n", *rr, *domainName, record)
			// 更新记录
			UpdateRecordIP(record, myIP)
		}
	}

}

func GetIP() string {
	// https://forge.speedtest.cn/api/location/info
	resp, err := http.Get("https://ip.cn/api/index?ip=&type=0")
	if err != nil {
		log.Println(err)
		return ""
	}
	defer resp.Body.Close()
	res, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
		return ""
	}

	return gjson.Get(string(res), "ip").String()
}

func AddRecord(ip string) bool {
	request := alidns.CreateAddDomainRecordRequest()
	request.Scheme = "https"
	request.DomainName = *domainName
	request.RR = *rr
	request.Type = "A"
	request.Value = ip

	_, err := client.AddDomainRecord(request)
	if err != nil {
		fmt.Println(err.Error())
		return false
	}
	log.Printf("add %s.%s record success\n", *rr, *domainName)
	return true
}

func GetRecord() (*alidns.Record, error) {
	request := alidns.CreateDescribeDomainRecordsRequest()
	request.Scheme = "https"
	request.DomainName = *domainName

	response, err := client.DescribeDomainRecords(request)
	if err != nil {
		return nil, err
	}

	// 找到匹配的记录
	for _, v := range response.DomainRecords.Record {
		if v.RR == *rr {
			return &v, nil
		}
	}

	return nil, nil
}

func UpdateRecordIP(oldRecord *alidns.Record, newIP string) {
	request := alidns.CreateUpdateDomainRecordRequest()
	request.Scheme = "https"
	request.RecordId = oldRecord.RecordId
	request.RR = oldRecord.RR
	request.Type = oldRecord.Type
	request.Value = newIP
	request.TTL = requests.NewInteger64(oldRecord.TTL)

	_, err := client.UpdateDomainRecord(request)
	if err != nil {
		log.Println(err.Error())
		return
	}
	log.Println("update record ip success, current ip", newIP)
}