From 9e82a6618eb5ed626d4f87aad4b20ac4b7ea3f33 Mon Sep 17 00:00:00 2001 From: Jamie Curnow Date: Mon, 11 May 2020 20:06:15 +1000 Subject: [PATCH] Added support for updating both ipv4 and ipv6 with config --- go.mod | 2 +- go.sum | 5 ++- pkg/config/config.go | 8 ++++ pkg/model/aws_config.go | 1 + pkg/model/route53_state.go | 3 +- pkg/updater/updater.go | 82 +++++++++++++++++++++++++++++--------- 6 files changed, 78 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index e16ab01..a083a43 100644 --- a/go.mod +++ b/go.mod @@ -8,6 +8,6 @@ require ( github.com/alexflint/go-arg v1.3.0 github.com/aws/aws-sdk-go v1.30.24 github.com/borderstech/logmatic v0.0.0-20190113143657-d43b0f3c9ded - github.com/glendc/go-external-ip v0.0.0-20170425150139-139229dcdddd github.com/gregdel/pushover v0.0.0-20200416074932-c8ad547caed4 + github.com/jc21/go-external-ip v0.0.0-20200511063623-13fd30ed5433 ) diff --git a/go.sum b/go.sum index 25089e4..70f4b7b 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,4 @@ +github.com/AlecAivazis/survey v1.8.8 h1:Y4yypp763E8cbqb5RBqZhGgkCFLRFnbRBHrxnpMMsgQ= github.com/AlecAivazis/survey/v2 v2.0.7 h1:+f825XHLse/hWd2tE/V5df04WFGimk34Eyg/z35w/rc= github.com/AlecAivazis/survey/v2 v2.0.7/go.mod h1:mlizQTaPjnR4jcpwRSaSlkbsRfYFEyKgLQvYTzxxiHA= github.com/JeremyLoy/config v1.3.0 h1:EQgVA/owXB7thqhe3ec3Q7P29USfB57NIzqcp8Rgg0Y= @@ -15,12 +16,12 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSs github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= -github.com/glendc/go-external-ip v0.0.0-20170425150139-139229dcdddd h1:1BzxHapafGJd/XlpMvocLeDBin2EKn90gXv2AQt5sfo= -github.com/glendc/go-external-ip v0.0.0-20170425150139-139229dcdddd/go.mod h1:o9OoDQyE1WHvYVUH1FdFapy1/rCZHHq3O5wS4VA83ig= github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= github.com/gregdel/pushover v0.0.0-20200416074932-c8ad547caed4 h1:QZVozMeLCqyMOOhA+OuqQdNXkyu4uUQEu4+mPBB5pPQ= github.com/gregdel/pushover v0.0.0-20200416074932-c8ad547caed4/go.mod h1:EcaO66Nn1StkpEm1iKtBTV3d2A16SoMsVER1PthX7to= github.com/hinshun/vt10x v0.0.0-20180616224451-1954e6464174/go.mod h1:DqJ97dSdRW1W22yXSB90986pcOyQ7r45iio1KN2ez1A= +github.com/jc21/go-external-ip v0.0.0-20200511063623-13fd30ed5433 h1:eht2lIbH/vT0NONLq9VyubaKtWNyDBkceUQ/d/JWrYg= +github.com/jc21/go-external-ip v0.0.0-20200511063623-13fd30ed5433/go.mod h1:04gPHKKRIWiyI44qPdlRDyr2LrJu8mUu7t5ldnfb3E0= github.com/jmespath/go-jmespath v0.3.0 h1:OS12ieG61fsCg5+qLJ+SsW9NicxNkg3b25OyT2yCeUc= github.com/jmespath/go-jmespath v0.3.0/go.mod h1:9QtRXoHjLGCJ5IBSaohpXITPlowMeeYCZ7fLUTSywik= github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= diff --git a/pkg/config/config.go b/pkg/config/config.go index bfa0f59..2f070c5 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -51,6 +51,14 @@ func SetupAWSConfig() { Prompt: &survey.Input{Message: "Route53 Record Set:"}, Validate: survey.Required, }, + { + Name: "protocols", + Prompt: &survey.Select{ + Message: "Which IP Protocals do you update?", + Options: []string{"IPv4 Only", "IPv6 Only ", "Both"}, + }, + Validate: survey.Required, + }, { Name: "pushover_user_token", Prompt: &survey.Input{Message: "Pushover User Token: (leave blank to disable)"}, diff --git a/pkg/model/aws_config.go b/pkg/model/aws_config.go index e54f038..798115f 100644 --- a/pkg/model/aws_config.go +++ b/pkg/model/aws_config.go @@ -13,6 +13,7 @@ type AWSConfig struct { AWSKeySecret string `survey:"aws_key_secret"` ZoneID string `survey:"zone_id"` Recordset string `survey:"recordset"` + Protocols string `survey:"protocols"` PushoverUserToken string `survey:"pushover_user_token"` } diff --git a/pkg/model/route53_state.go b/pkg/model/route53_state.go index 17954dd..a2168b5 100644 --- a/pkg/model/route53_state.go +++ b/pkg/model/route53_state.go @@ -12,7 +12,8 @@ import ( type Route53State struct { ZoneID string `survey:"zone_id"` Recordset string `survey:"recordset"` - LastIP string `survey:"last_ip"` + LastIPv4 string `survey:"last_ipv4"` + LastIPv6 string `survey:"last_ipv6"` LastUpdateTime time.Time `survey:"last_update_time"` } diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index 9a8efb1..cb8c1cb 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "io/ioutil" + "net" "os" "strings" "time" @@ -13,7 +14,7 @@ import ( "github.com/aws/aws-sdk-go/aws/credentials" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/route53" - externalip "github.com/glendc/go-external-ip" + externalip "github.com/jc21/go-external-ip" "github.com/gregdel/pushover" "github.com/jc21/route53-ddns/pkg/helper" "github.com/jc21/route53-ddns/pkg/logger" @@ -26,17 +27,64 @@ const defaultStateFile = "~/.aws/route53-ddns-state.json" func Process(argConfig model.ArgConfig, awsConfig model.AWSConfig) { // Determine the current public ip consensus := externalip.DefaultConsensus(nil, nil) - ip, err := consensus.ExternalIP() - if err != nil { - logger.Error(err.Error()) - os.Exit(1) - } - - // Determine if we need to update it state := GetRoute53State(argConfig) logger.Trace("STATE: %+v", state) - if ip.String() != state.LastIP || argConfig.Force || awsConfig.ZoneID != state.ZoneID || awsConfig.Recordset != state.Recordset { + // Apply state + state.ZoneID = awsConfig.ZoneID + state.Recordset = awsConfig.Recordset + state.LastUpdateTime = time.Now() + + if awsConfig.ZoneID != state.ZoneID || awsConfig.Recordset != state.Recordset { + argConfig.Force = true + } + + awsConfig.Protocols = strings.Trim(awsConfig.Protocols, " ") + changed := false + hasError := false + + if awsConfig.Protocols == "IPv4 Only" || awsConfig.Protocols == "Both" || awsConfig.Protocols == "" { + // Determine IPv4 + consensus.UseIPProtocol(4) + ipv4, errv4 := consensus.ExternalIP() + if errv4 == nil { + changed, errv4 = updateIPProtocol(ipv4, state.LastIPv4, argConfig, awsConfig) + } + + if errv4 != nil { + logger.Error(errv4.Error()) + hasError = true + } else if changed { + state.LastIPv4 = ipv4.String() + state.Write(getRoute53StateFilename(argConfig)) + } + } + + if awsConfig.Protocols == "IPv6 Only" || awsConfig.Protocols == "Both" { + // Determine IPv6 + consensus.UseIPProtocol(6) + ipv6, errv6 := consensus.ExternalIP() + if errv6 == nil { + changed, errv6 = updateIPProtocol(ipv6, state.LastIPv6, argConfig, awsConfig) + } + + if errv6 != nil { + logger.Error(errv6.Error()) + hasError = true + } else if changed { + state.LastIPv6 = ipv6.String() + state.Write(getRoute53StateFilename(argConfig)) + } + } + + if hasError { + os.Exit(1) + } +} + +// updateIPProtocol returns: changed, error +func updateIPProtocol(ip net.IP, lastIP string, argConfig model.ArgConfig, awsConfig model.AWSConfig) (bool, error) { + if ip.String() != lastIP || argConfig.Force { // Update the Route53 IP and save to new state logger.Info("Updating IP to %v", ip.String()) @@ -49,15 +97,9 @@ func Process(argConfig model.ArgConfig, awsConfig model.AWSConfig) { updateErr := updateIP(awsConfig, ip.String(), recordType) if updateErr != nil { logger.Error("Could not update Route53: %v", updateErr.Error()) + return false, updateErr } else { - logger.Info("IP has been updated to %v for %v", ip.String(), awsConfig.Recordset) - - // Save state - state.ZoneID = awsConfig.ZoneID - state.Recordset = awsConfig.Recordset - state.LastIP = ip.String() - state.LastUpdateTime = time.Now() - state.Write(getRoute53StateFilename(argConfig)) + logger.Info("'%s' record has been updated to %v for %v", recordType, ip.String(), awsConfig.Recordset) if awsConfig.PushoverUserToken != "" { pushoverApp := pushover.New("a4dhut1a7waegz6p2xh7enzegjedgo") @@ -80,16 +122,18 @@ func Process(argConfig model.ArgConfig, awsConfig model.AWSConfig) { _, err := pushoverApp.SendMessage(message, recipient) if err != nil { logger.Error(err.Error()) - os.Exit(1) } else { logger.Info("Pushover Notification Sent OK") } } - } + return true, nil + } } else { logger.Info("IP %v hasn't changed, not updating Route53", ip.String()) } + + return false, nil } func updateIP(awsConfig model.AWSConfig, ip, recordType string) error {