146 lines
2.9 KiB
Go
146 lines
2.9 KiB
Go
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
|
||
}
|
||
}
|
||
}
|