Files
ddns-updater/main.go

123 lines
3.4 KiB
Go
Raw Permalink Normal View History

2023-04-28 14:57:21 +02:00
package main
import (
"context"
"log"
"net"
"os/signal"
"syscall"
"time"
"hub.cybercinch.nz/cybercinch/ddns-update/internal"
"hub.cybercinch.nz/cybercinch/ddns-update/internal/dns_providers"
"hub.cybercinch.nz/cybercinch/ddns-update/internal/notifications"
"hub.cybercinch.nz/cybercinch/ddns-update/internal/public_resolvers"
2023-04-28 14:57:21 +02:00
)
type PublicIpResolver interface {
ResolvePublicIp(ctx context.Context) (net.IP, error)
}
2023-05-01 10:01:43 +02:00
func getResolver(resolverName string) (PublicIpResolver, string) {
2023-04-28 14:57:21 +02:00
switch resolverName {
// HERE add another resolver if needed
2023-05-03 23:06:57 +02:00
case public_resolvers.CloudflareTraceTag:
return public_resolvers.NewDefaultCloudflareTrace(), public_resolvers.CloudflareTraceTag
2023-05-01 10:01:43 +02:00
case public_resolvers.V4IdentMeTag:
return public_resolvers.NewV4IdentMeDefault(), public_resolvers.V4IdentMeTag
2024-02-21 22:38:19 +13:00
case public_resolvers.IcanhazipTag:
return public_resolvers.NewIcanhazipDefault(), public_resolvers.IcanhazipTag
2023-04-28 14:57:21 +02:00
case public_resolvers.IfConfigMeTag:
fallthrough
default:
2023-05-01 10:01:43 +02:00
return public_resolvers.NewDefaultIfConfigMe(), public_resolvers.IfConfigMeTag
2023-04-28 14:57:21 +02:00
}
}
func getProvider(ctx context.Context, config internal.Config) (dns_providers.DNSProvider, string) {
switch config.DNSProviderTag {
case dns_providers.DirectadminTag:
return dns_providers.NewDirectAdminProvider(ctx, config), dns_providers.DirectadminTag
case dns_providers.CloudflareTag:
fallthrough
default:
return dns_providers.NewCloudflareProvider(ctx, config), dns_providers.CloudflareTag
}
}
2023-04-28 14:57:21 +02:00
func main() {
ctx, stop := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stop()
config := internal.NewConfig()
if err := config.Validate(); err != nil {
log.Fatalln(err)
}
2023-05-04 17:28:25 +02:00
notifiers := notifications.GetNotifiers(config.Notifiers)
2023-05-04 11:44:27 +02:00
2023-04-30 08:46:25 +02:00
// public ip resolver
2023-05-01 10:01:43 +02:00
publicIpResolver, resolverTag := getResolver(config.PublicIpResolverTag)
dnsProvider, providerTag := getProvider(ctx, config)
log.Printf("Using DNS Provider %s", providerTag)
2023-04-30 08:46:25 +02:00
checkFunc := func() {
currentPublicIP, err := publicIpResolver.ResolvePublicIp(ctx)
if err != nil {
log.Fatal(err)
}
2023-05-03 23:06:57 +02:00
log.Printf("Current public ip `%s` (resolver: %s)", currentPublicIP, resolverTag)
2023-04-30 08:46:25 +02:00
if err != nil {
log.Fatal(err)
}
for _, dnsRecord := range config.DnsRecordsToCheck {
current_dns_record, err := dnsProvider.FetchRecord(dnsRecord)
if err != nil {
log.Fatalf("Failed to fetch DNS record: %s", err)
}
log.Printf("Checking record `%s` with current value `%s` ...", dnsRecord, current_dns_record)
if currentPublicIP.String() == current_dns_record {
log.Println("OK")
continue // no update needed
}
if err := dnsProvider.UpdateRecord(dnsRecord, currentPublicIP.String()); err != nil {
log.Printf("error updating dns record: %s", err)
continue
2023-04-30 08:46:25 +02:00
}
if err := notifiers.NotifyWithLog(ctx, notifications.Notification{
OldIp: net.ParseIP(string(current_dns_record)),
NewIp: currentPublicIP,
CheckedAt: time.Now(),
ResolverTag: resolverTag,
Domain: dnsRecord,
WebhookToken: config.WebhookToken,
}); err != nil {
log.Printf("errors in notifications: %s", err)
}
log.Printf("Updated to `%s`", currentPublicIP)
2023-04-30 08:46:25 +02:00
}
}
log.Printf("checking ...")
checkFunc()
log.Println("waiting for check tick ...")
ticker := time.NewTicker(config.CheckInterval)
defer ticker.Stop()
for {
select {
case <-ticker.C:
log.Println("tick received checking ...")
checkFunc()
2023-04-29 12:45:21 +02:00
case <-ctx.Done():
break
2023-04-28 14:57:21 +02:00
}
}
}