184 lines
4.3 KiB
Go
184 lines
4.3 KiB
Go
|
package main
|
|||
|
|
|||
|
import (
|
|||
|
"context"
|
|||
|
"flag"
|
|||
|
"fmt"
|
|||
|
"net"
|
|||
|
"strings"
|
|||
|
"time"
|
|||
|
)
|
|||
|
|
|||
|
// 判断IPv6 地址类型
|
|||
|
func classifyIPv6(ip net.IP) string {
|
|||
|
if ip.IsLoopback() {
|
|||
|
return "Loopback"
|
|||
|
} else if ip.IsLinkLocalUnicast() {
|
|||
|
return "Link-Local"
|
|||
|
} else if ip.IsGlobalUnicast() {
|
|||
|
return "Global"
|
|||
|
}
|
|||
|
return "Unknown"
|
|||
|
}
|
|||
|
|
|||
|
// getIPv6Addresses 获取网络接口的 IPv6 地址。
|
|||
|
// 它会跳过回环接口,并且只考虑已启用的接口。
|
|||
|
func getIPv6Addresses() (map[string][]net.IP, error) {
|
|||
|
// 创建一个 map 用于存储接口名称及其对应的 IPv6 地址。
|
|||
|
addresses := make(map[string][]net.IP)
|
|||
|
|
|||
|
// 获取系统上的所有网络接口。
|
|||
|
interfaces, err := net.Interfaces()
|
|||
|
if err != nil {
|
|||
|
return nil, err // 如果无法获取接口信息,则返回错误。
|
|||
|
}
|
|||
|
|
|||
|
// 遍历所有网络接口。
|
|||
|
for _, iface := range interfaces {
|
|||
|
// 跳过未启用的接口或回环接口。
|
|||
|
if iface.Flags&net.FlagUp == 0 || iface.Flags&net.FlagLoopback != 0 {
|
|||
|
continue
|
|||
|
}
|
|||
|
|
|||
|
// 获取与该接口关联的地址。
|
|||
|
addrs, err := iface.Addrs()
|
|||
|
if err != nil {
|
|||
|
return nil, err // 如果无法获取地址,则返回错误。
|
|||
|
}
|
|||
|
|
|||
|
// 遍历该接口的所有地址。
|
|||
|
for _, addr := range addrs {
|
|||
|
var ip net.IP
|
|||
|
switch v := addr.(type) {
|
|||
|
case *net.IPNet:
|
|||
|
ip = v.IP // 从 IPNet 类型中提取 IP。
|
|||
|
case *net.IPAddr:
|
|||
|
ip = v.IP // 从 IPAddr 类型中提取 IP。
|
|||
|
}
|
|||
|
|
|||
|
// 检查 IP 是否为 IPv6 地址(即不是 IPv4)。
|
|||
|
if ip != nil && ip.To4() == nil {
|
|||
|
// 将 IPv6 地址添加到对应的接口名称列表中。
|
|||
|
addresses[iface.Name] = append(addresses[iface.Name], ip)
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return addresses, nil // 返回包含 IPv6 地址的映射。
|
|||
|
}
|
|||
|
|
|||
|
// 获取指定接口的 IPv6 地址
|
|||
|
func pppoe_interface_ipv6(_interface string) string {
|
|||
|
addresses, err := getIPv6Addresses()
|
|||
|
if err != nil {
|
|||
|
fmt.Printf("获取 IPv6 地址失败: %v\n", err)
|
|||
|
return "NULL"
|
|||
|
}
|
|||
|
|
|||
|
//fmt.Println("IPv6 地址列表:")
|
|||
|
for iface, ips := range addresses {
|
|||
|
//fmt.Printf("Interface: %s\n", iface)
|
|||
|
if iface == _interface {
|
|||
|
for _, ip := range ips {
|
|||
|
addrType := classifyIPv6(ip)
|
|||
|
|
|||
|
if addrType == "Global" {
|
|||
|
|
|||
|
return ip.String()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return "NULL"
|
|||
|
}
|
|||
|
|
|||
|
// 使用指定的 DNS 服务器解析域名的 IPv6 地址
|
|||
|
func check_domain_ipv6(domain string) string {
|
|||
|
// 自定义解析器,使用 8.8.8.8 作为 DNS 服务器
|
|||
|
resolver := &net.Resolver{
|
|||
|
PreferGo: true,
|
|||
|
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|||
|
d := net.Dialer{
|
|||
|
Timeout: time.Second * 5,
|
|||
|
}
|
|||
|
return d.DialContext(ctx, "udp", "8.8.8.8:53") // 指定 Google DNS
|
|||
|
},
|
|||
|
}
|
|||
|
|
|||
|
// 查询域名的 IP 地址
|
|||
|
ips, err := resolver.LookupIP(context.Background(), "ip6", domain)
|
|||
|
if err != nil {
|
|||
|
return "NULL"
|
|||
|
}
|
|||
|
|
|||
|
// 遍历返回的 IP 地址,返回第一个 IPv6 地址
|
|||
|
for _, ip := range ips {
|
|||
|
if ip.To4() == nil {
|
|||
|
return ip.String()
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
return "NULL"
|
|||
|
}
|
|||
|
|
|||
|
// 循环获取域名解析地址和当前地址,并判断是否需要更新域名解析地址
|
|||
|
func Loop() {
|
|||
|
|
|||
|
var Domain_ipv6_addr string
|
|||
|
var Now_ipv6_addr string
|
|||
|
var Domain = "aixiao.me"
|
|||
|
var _interface = "pppoe-wan"
|
|||
|
|
|||
|
key := "28b94fdd541d213de7bcaef" // 你的 API Key
|
|||
|
Subdomain := "v6.aixiao.me" // 你要获取的特定子域名(可选)
|
|||
|
|
|||
|
Domain_ipv6_addr = check_domain_ipv6(Subdomain)
|
|||
|
Now_ipv6_addr = pppoe_interface_ipv6(_interface)
|
|||
|
|
|||
|
if Now_ipv6_addr != Domain_ipv6_addr {
|
|||
|
fmt.Printf("域名解析地址: %s\n", Domain_ipv6_addr)
|
|||
|
fmt.Printf("当前地址: %s\n", Now_ipv6_addr)
|
|||
|
fmt.Printf("域名解析地址与现在地址不相等!!!\n")
|
|||
|
|
|||
|
RecordID := FetchSubdomainRecord(key, Domain, Subdomain)
|
|||
|
fmt.Printf("RecordID:%s\n", RecordID)
|
|||
|
if RecordID != "NULL" {
|
|||
|
rrid := RecordID
|
|||
|
rrhost := strings.Split(Subdomain, ".")[0] // 获取子域名前缀 v6
|
|||
|
rrvalue := Now_ipv6_addr
|
|||
|
|
|||
|
r := ProcessDNSUpdateForDomain(key, Domain, rrid, rrhost, rrvalue)
|
|||
|
if r == 1 {
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
} else {
|
|||
|
fmt.Printf("域名解析地址: %s\n", Domain_ipv6_addr)
|
|||
|
fmt.Printf("当前地址: %s\n", Now_ipv6_addr)
|
|||
|
fmt.Printf("域名解析地址与现在地址相等,无需处理!!!\n")
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
// Sleep 函数
|
|||
|
func Sleep(m int) {
|
|||
|
time.Sleep(time.Duration(m) * time.Minute)
|
|||
|
}
|
|||
|
|
|||
|
func main() {
|
|||
|
daemon := flag.Bool("d", false, "守护进程模式")
|
|||
|
flag.Parse()
|
|||
|
|
|||
|
// 守护进程模式
|
|||
|
if *daemon {
|
|||
|
Daemon()
|
|||
|
}
|
|||
|
|
|||
|
for {
|
|||
|
Loop()
|
|||
|
Sleep(15)
|
|||
|
}
|
|||
|
}
|