golang实现ddns

概览:

动态域名服务

DDNS(Dynamic Domain Name Server,动态域名服务)是将用户的动态IP地址映射到一个固定的域名解析服务上,用户每次连接网络的时候客户端程序就会通过信息传递把该主机的动态IP地址传送给位于服务商主机上的服务器程序,服务器程序负责提供DNS服务并实现动态域名解析。

编写代码

代码域名提供商(阿里云)为例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package main

import (
"fmt"
"log"
"net"
"os"
"strings"

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

var (
record_host = "www"
record_domainName = "<你的域名>"

err error = nil
localIp string = "127.0.0.1"
client *alidns.Client = nil
)

func init() {
client, err = alidns.NewClientWithAccessKey(
"<regin> eg:cn-hangzhou",
"<yourAccessKeyID>",
"<yourAccessKeySecret>",
)
if err != nil {
log.Println(err)
return
}

localIp = getLocalIpV4()
}

func main() {
// get origin dns
var origin_domain alidns.Record

DDR := alidns.CreateDescribeDomainRecordsRequest()
DDR.Scheme = "https"
DDR.DomainName = record_domainName
DDR.RRKeyWord = record_host

ddr_response, err := client.DescribeDomainRecords(DDR)
if err != nil {
os.Exit(-1)
}
origin_domain = ddr_response.DomainRecords.Record[0]

// need update ?
if origin_domain.Value == localIp {
log.Printf("%s ---> %s : %v\n", origin_domain.Value, localIp, "No Change")
return
}

// update dns record
UDR := alidns.CreateUpdateDomainRecordRequest()
UDR.Scheme = "https"
UDR.RR = origin_domain.RR
UDR.RecordId = origin_domain.RecordId
UDR.Value = localIp
UDR.Type = origin_domain.Type

udr_response, err := client.UpdateDomainRecord(UDR)
if err != nil {
fmt.Print(err)
}

log.Printf("%s ---> %s : %v\n", origin_domain.Value, localIp, udr_response.IsSuccess())

}

func getLocalIpV4() string {
inters, err := net.Interfaces()
if err != nil {
panic(err)
}
for _, inter := range inters {
// net is open && is local loop
if inter.Flags&net.FlagUp != 0 && !strings.HasPrefix(inter.Name, "lo") {
// grep net interface
if inter.Name != os.Args[1] {
continue
}
// get net all address
addrs, err := inter.Addrs()
if err != nil {
continue
}

for _, addr := range addrs {
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() {
//is ipv4
if ipnet.IP.To4() != nil {
return ipnet.IP.String()
}
}
}
}
}
return ""
}

构建代码

构建

  • 构建代码之前,请将代码中的空位补充下自己的。
1
go build -tags netgo -installsuffix 'static' -ldflags "-s -w" -o ddns main.go

运行

1
./ddns <your network interface> # eg: ddns eth0