Files
cloudflare-dynamic-dns/main.go
2025-03-24 19:46:23 -04:00

133 lines
2.5 KiB
Go

package main
import (
_ "embed"
"fmt"
"log"
"strings"
"sync"
"time"
)
//go:embed title.txt
var appNameASCII string
type publicIP struct {
v4 string
v6 string
}
func getPublicIP() publicIP {
var publicIP publicIP
var wg sync.WaitGroup
if UseIPv4() {
wg.Add(1)
go func() {
publicIP.v4 = GetPublicIP(4)
wg.Done()
}()
}
if UseIPv6() {
wg.Add(1)
go func() {
publicIP.v6 = GetPublicIP(6)
wg.Done()
}()
}
wg.Wait()
return publicIP
}
func getDNSRecords() []DNSRecords {
apiKey := GetAPIKey()
zoneID := GetZoneID()
domainNames := GetDomainNames()
ch := make(chan DNSRecords, len(domainNames))
defer close(ch)
for _, domainName := range domainNames {
go func() {
ch <- GetDNSRecord(zoneID, domainName, apiKey)
}()
}
var dnsRecords []DNSRecords
for i := 0; i < len(domainNames); i++ {
dnsRecord := <-ch
dnsRecords = append(dnsRecords, dnsRecord)
}
return dnsRecords
}
func initialize() {
fmt.Print(appNameASCII)
var recordType string
if UseIPv4() && UseIPv6() {
recordType = "A and AAAA"
} else if UseIPv4() {
recordType = "A"
} else if UseIPv6() {
recordType = "AAAA"
}
domainNames := strings.Join(GetDomainNames(), ", ")
interval := GetInterval()
fmt.Printf("Updating %v records of %v every %v minutes\n\n", recordType, domainNames, interval)
}
func main() {
initialize()
for {
var publicIP publicIP
var dnsRecords []DNSRecords
var wg sync.WaitGroup
// concurrently fetch public ip and dns records
wg.Add(2)
go func() {
publicIP = getPublicIP()
wg.Done()
}()
go func() {
dnsRecords = getDNSRecords()
wg.Done()
}()
wg.Wait()
// concurrently create/update dns entries if their content is not current public ip
apiKey := GetAPIKey()
zoneID := GetZoneID()
for _, dnsRecord := range dnsRecords {
if UseIPv4() && publicIP.v4 != dnsRecord.a.content {
wg.Add(1)
go func() {
UpdateDNSRecord(zoneID, dnsRecord.a.id, apiKey, DNSRecordBody{Type: "A", Name: dnsRecord.name, Content: publicIP.v4})
log.Printf("Set DNS A record %v to %v", dnsRecord.name, publicIP.v4)
wg.Done()
}()
}
if UseIPv6() && publicIP.v6 != dnsRecord.aaaa.content {
wg.Add(1)
go func() {
UpdateDNSRecord(zoneID, dnsRecord.aaaa.id, apiKey, DNSRecordBody{Type: "AAAA", Name: dnsRecord.name, Content: publicIP.v6})
log.Printf("Set DNS AAAA record %v to %v", dnsRecord.name, publicIP.v6)
wg.Done()
}()
}
}
wg.Wait()
time.Sleep(time.Duration(GetInterval()) * time.Minute)
}
}