DDNS动态解析

DDNS动态解析脚本

1.代码

package main

import (
	`crypto/tls`
	`encoding/json`
	"fmt"
	`github.com/aliyun/alibaba-cloud-sdk-go/sdk`
	`github.com/aliyun/alibaba-cloud-sdk-go/sdk/auth/credentials`
	`github.com/aliyun/alibaba-cloud-sdk-go/services/alidns`
	"github.com/jordan-wright/email"
	`io`
	`log`
	`net/http`
	`net/smtp`
	`os`
	"time"
)

type T struct {
	Code int `json:"code"`
	Data struct {
		Myip     string `json:"myip"`
		Location string `json:"location"`
		Country  string `json:"country"`
		Local    string `json:"local"`
		Ver4     string `json:"ver4"`
		Ver6     string `json:"ver6"`
		Count4   int    `json:"count4"`
		Count6   int    `json:"count6"`
	} `json:"data"`
}
type Aliyun struct {
	AccessKeyId     string `json:"accessKeyId"`
	AccessKeySecret string `json:"accessKeySecret"`
	Username        string `json:"username"`
	Password        string `json:"password"`
	To              string `json:"to"`
}

var aliyun = Aliyun{}

//此脚本用来动态解析dns,每天请求一次,记录ipv6地址,当发现ipv6变化时候,主动修改阿里云dns解析

func init() {
	file, err := os.OpenFile("aliyun.json", os.O_RDONLY, 0644)
	if err != nil {
		log.Println(err)
	}
	data := make([]byte, 512)
	n, err := file.Read(data)
	if err != nil {
		log.Println("读取配置文件错误")
	}

	err = json.Unmarshal(data[:n], aliyun)
	if err != nil {
		log.Println("json错误")
	}
}

func GetIpv6() string {

	req, err := http.NewRequest("GET", "https://v6.ip.zxinc.org/info.php?type=json", nil)
	if err != nil {
		log.Println(err)
	}
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.62")
	client := &http.Client{}
	resp, err := client.Do(req)
	if err != nil {
		log.Println(err)
	}
	defer resp.Body.Close()
	res, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Println(err)
	}
	t := new(T)
	err = json.Unmarshal(res, t)
	if err != nil {
		log.Println("json解析错误")
	}
	log.Println("Ipv6获取成功", t.Data.Myip)
	return t.Data.Myip
}
func GetIpv4() (string, bool) {
	req, err := http.NewRequest("GET", "https://v4.ip.zxinc.org/info.php?type=json", nil)
	if err != nil {
		log.Println(err)
	}
	req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/116.0.0.0 Safari/537.36 Edg/116.0.1938.62")
	req.Header.Set("User-Agent", "My-User-Agent")
	req.Header.Set("User-Agent", "My-User-Agent")

	client := &http.Client{}
	resp, err := client.Do(req)
	defer resp.Body.Close()
	res, err := io.ReadAll(resp.Body)
	if err != nil {
		log.Println("读取失败" + err.Error())
		return "", false

	}
	v := new(T)
	err = json.Unmarshal(res, v)
	if err != nil {
		log.Println("json解析错误")
		return "", false
	}
	log.Println("ipv4获取成功", v.Data.Myip)
	return v.Data.Myip, true

}

func Set(v4, v6 string, ) bool {
	config := sdk.NewConfig()

	// Please ensure that the environment variables ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET are set.
	credential := credentials.NewAccessKeyCredential(aliyun.AccessKeyId, aliyun.AccessKeySecret)
	/* use STS Token
	credential := credentials.NewStsTokenCredential(os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), os.Getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"), os.Getenv("ALIBABA_CLOUD_SECURITY_TOKEN"))
	*/
	client, err := alidns.NewClientWithOptions("cn-hangzhou", config, credential)
	if err != nil {
		log.Println(err)
	}

	request := alidns.CreateUpdateDomainRecordRequest()

	request.Scheme = "https"
	request.Type = "AAAA" //AAAA为ipv6
	request.Value = v6
	request.RR = "@"
	request.RecordId = "" //自己去查
	request.Lang = "en"
	request.UserClientIp = v4
	response, err := client.UpdateDomainRecord(request)
	if err != nil {
		fmt.Print(err.Error())
	}
	fmt.Printf("response is %#v\n", response)

	return response.IsSuccess()
}

func SendEmail(v6, v4 string) {
	e := email.NewEmail()
	//发送者
	e.From = "服务器IPV6IPV4地址<2673893724@qq.com>"
	//接收者
	e.To = []string{aliyun.To}
	//主题
	e.Subject = "IP地址"
	//html
	e.HTML = []byte("<!DOCTYPE html>\n<html>\n<head>\n    <title>IPv6 & IPv4 Address</title>\n    <style>\n        body {\n            font-family: Arial, sans-serif;\n         " +
		"   background-color: #f7f7f7;\n            margin: 0;\n            padding: 20px;\n        }\n        \n        h1 {\n            text-align: center;\n           " +
		" color: #333;\n        }\n        \n        .container {\n            max-width: 400px;\n            margin: 0 auto;\n            background-color: #fff;\n    " +
		"        border-radius: 5px;\n            box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);\n            padding: 20px;\n        }\n        \n        .address {\n          " +
		"  margin-bottom: 10px;\n        }\n        \n        .label {\n            font-weight: bold;\n        }\n        \n        .ipv6 {\n            font-family: monospace;\n        " +
		"    color: #333;\n            background-color: #f7f7f7;\n            padding: 5px;\n            border-radius: 3px;\n        }\n        \n        .ipv4 {\n            font-family: monospace;\n   " +
		"         color: #333;\n            background-color: #f7f7f7;\n            padding: 5px;\n            border-radius: 3px;\n        }\n    </style>\n</head>\n<body>\n    <div class=\"container\">\n  " +
		"      <h1>IPv6 & IPv4 Address</h1>\n        \n        <div class=\"address\">\n            <span class=\"label\">IPv6:</span>\n          " +
		" <span class=\"ipv6\">" + v6 + "</span>\n       " +
		" </div>\n        \n        <div class=\"address\">\n           " +
		" <span class=\"label\">IPv4:</span>\n          " +
		"  <span class=\"ipv4\">" + v4 + "1</span>\n      " +
		"  </div>\n    </div>\n</body>\n</html> ")

	err := e.SendWithStartTLS("smtp.qq.com:587", smtp.PlainAuth("", aliyun.Username, aliyun.Password, "smtp.qq.com"), &tls.Config{InsecureSkipVerify: true, ServerName: "smtp.gmail.com:465"})
	if err != nil {
		log.Println("stmp:", err)

	}
	log.Println("发送成功!")
}

func timing() {
	file, err := os.OpenFile("ip.txt", os.O_CREATE|os.O_RDWR, 0755)
	if err != nil {
		log.Println("打开失败!" + err.Error())
		return
	}
	b := make([]byte, 1024)

	n, err := file.Read(b)
	if err != nil {
		if err==io.EOF{
			file.Write([]byte("123"))
		}else {
			log.Println("文件读取失败" + err.Error())
			return	
		}
	}
	 file.Close()

	v6 := GetIpv6()
	v4, ok := GetIpv4()
	SendEmail(v6, v4)
	fmt.Println(string(b[:n]) == v6, string(b[:n]), v6)
	if string(b[:n]) != v6 {
		file, err := os.OpenFile("ip.txt", os.O_WRONLY, 0755)
		_, err = file.Write([]byte(v6))
		if err != nil {
			log.Println("文件写入失败", err)
		}
		file.Close()
		if ok {
			f := Set(v4, v6)
			if f {
				log.Println("设置成功")
				return
			}
			fmt.Println("设置失败!" + err.Error())
		}
		log.Println("获取ipv4失败")
	}
	log.Println("ipv6地址没有改变")
}

/**
 * 使用AK&SK初始化账号Client
 * @param accessKeyId
 * @param accessKeySecret
 * @return Client
 * @throws Exception
// */

func main() {
	defer func() {
		if err := recover(); err != nil {
			fmt.Println("错误捕获", err)
		}
	}()
	t1 := time.Now()
	//启动1分钟以后
	t2 := time.Date(t1.Year(), t1.Month(), t1.Day(), t1.Hour(), t1.Minute()+1, 0, 0, t1.Location())
	log.Println("任务启动," + t2.Sub(t1).String() + "后开始执行")

	t3 := time.NewTimer(t2.Sub(t1))

	for {
		select {
		case <-t3.C:
			log.Println("开始执行任务")
			go timing()
			t1 = time.Now()
			//一天以后执行
			t2 = time.Date(t1.Year(), t1.Month(), t1.Day()+1, t1.Hour(), t1.Minute(), 0, 0, t1.Location())
			t3 = time.NewTimer(t2.Sub(t1))
		}
	}
}

1.支持阿里云解析

运行前配置

{
  "accessKeyId": "", //阿里云accessKeyId
  "accessKeySecret": "", //阿里云accessKeySecret
  "username": "邮箱",
  "password": "授权码",
  "to": "接收者邮箱"
}

2.运行

nohup  go run ddns.go &

3.建议开机启动脚本

脚本为一天解析一次,运行时会发送邮件告知今天的ipv4,ipv6地址
4.已开源

DDNS动态解析

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值