package main import ( "fmt" "io" "log" "net" "net/http" "os" "strings" "time" "github.com/aliyun/alibaba-cloud-sdk-go/services/alidns" ) // getPublicIP 通过外部 API 获取公网 IPv4 地址 func getPublicIP() (string, error) { // 使用多个 IP 查询服务作为备选 apis := []string{ "https://api.ipify.org", "https://ifconfig.me/ip", "https://ipecho.net/plain", } for _, api := range apis { resp, err := http.Get(api) if err != nil { log.Printf("Error fetching IP from %s: %v", api, err) continue } body, err := io.ReadAll(resp.Body) resp.Body.Close() if err != nil { log.Printf("Error reading response from %s: %v", api, err) continue } ip := strings.TrimSpace(string(body)) if net.ParseIP(ip) != nil { return ip, nil } } return "", fmt.Errorf("failed to get public IP from all APIs") } func main() { domain := os.Getenv("DOMAIN") rr := os.Getenv("RR") regionID := os.Getenv("REGIONID") if regionID == "" { regionID = "cn-hangzhou" } accessKeyID := os.Getenv("ACCESSKEYID") accessSecret := os.Getenv("ACCESSSECRET") ip4 := "" for { time.Sleep(10 * time.Second) currentIPV4, err := getPublicIP() if err != nil { log.Println("Error getting public IP:", err) continue } if currentIPV4 == "" || currentIPV4 == ip4 { continue } client, err := alidns.NewClientWithAccessKey(regionID, accessKeyID, accessSecret) if err != nil { log.Println(err.Error()) continue } drRequest := alidns.CreateDescribeDomainRecordsRequest() drRequest.KeyWord = rr drRequest.DomainName = domain drRequest.TypeKeyWord = "A" drResponse, err := client.DescribeDomainRecords(drRequest) if err != nil { log.Println(err) continue } if !drResponse.IsSuccess() { continue } rid := "" for _, r := range drResponse.DomainRecords.Record { rid = r.RecordId if r.Value == currentIPV4 { ip4 = currentIPV4 rid = "" } break } if rid == "" { continue } //修改域名对应的IP,修改成功后continue req := alidns.CreateUpdateDomainRecordRequest() req.Scheme = "https" req.RR = rr req.RecordId = rid req.Value = currentIPV4 req.Type = "A" resp, err := client.UpdateDomainRecord(req) if err != nil { log.Println(err.Error()) if !strings.Contains(err.Error(), fmt.Sprintf("not %s", domain)) { continue } } if resp.IsSuccess() { ip4 = currentIPV4 log.Println("update success: ", ip4) continue } //当域名修改失败时判断是否是没有对应的记录,不存在时创建新的域名记录 request := alidns.CreateAddDomainRecordRequest() request.Scheme = "https" request.Value = currentIPV4 request.Type = "A" request.RR = rr request.DomainName = domain response, err := client.AddDomainRecord(request) if err != nil { fmt.Print(err.Error()) continue } if !response.IsSuccess() { fmt.Print(response.GetHttpContentString()) ip4 = currentIPV4 } } }