get wan ip from router

send mail with gomail
a lot of parameters in the conf file
This commit is contained in:
Laurent Le Houerou 2019-06-16 15:08:18 +04:00
parent a1e5510e49
commit b13a95b638
3 changed files with 94 additions and 58 deletions

2
go.mod
View File

@ -5,4 +5,6 @@ go 1.12
require ( require (
github.com/sirupsen/logrus v1.4.2 github.com/sirupsen/logrus v1.4.2
github.com/urfave/cli v1.20.0 github.com/urfave/cli v1.20.0
gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc // indirect
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df
) )

15
go.sum
View File

@ -1,22 +1,19 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk= github.com/konsorten/go-windows-terminal-sequences v1.0.1 h1:mweAR1A6xJ3oS2pRaGiHgQ4OO8tzTaLawm8vnODuwDk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2 h1:DB17ag19krx9CFsz4o3enTrPXyIXCl+2iCXH/aMAp9s=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4= github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw= github.com/urfave/cli v1.20.0 h1:fDqGv3UG/4jbVl/QkFwEdddtEDjh/5Ov6X+0B/3bPaw=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894 h1:Cz4ceDQGXuKRnVBDTS23GTn/pU5OE2C0WrNTOYK1Uuc=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190609082536-301114b31cce h1:CQakrGkKbydnUmt7cFIlmQ4lNQiqdTPt6xzXij4nYCc= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc h1:2gGKlE2+asNV9m7xrywl36YYNnBG5ZQ0r/BOOxqPpmk=
golang.org/x/sys v0.0.0-20190609082536-301114b31cce/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= gopkg.in/alexcesaro/quotedprintable.v3 v3.0.0-20150716171945-2caba252f4dc/go.mod h1:m7x9LTH6d71AHyAX77c9yqWCCa3UKHcVEj9y7hAtKDk=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df h1:n7WqCuqOuCbNr617RXOY0AWRXxgwEyPp2z+p0+hgMuE=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=

125
main.go
View File

@ -6,11 +6,12 @@ import (
"fmt" "fmt"
log "github.com/sirupsen/logrus" log "github.com/sirupsen/logrus"
"github.com/urfave/cli" "github.com/urfave/cli"
"gopkg.in/gomail.v2"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"net/smtp"
"os" "os"
"path" "path"
"regexp"
) )
type Configuration struct { type Configuration struct {
@ -18,6 +19,18 @@ type Configuration struct {
Email string `json:"email"` Email string `json:"email"`
GandiKey string `json:"gandikey"` GandiKey string `json:"gandikey"`
Domains []string `json:"domains"` Domains []string `json:"domains"`
RouterLogin string `json:"router_login"`
RouterPassword string `json:"router_password"`
RouterStatusUrl string `json:"router_status_url"`
WanIPRegex string `json:"wan_ip_regex"`
MailSettings *struct {
Sender string `json:"sender"`
To []string `json:"to"`
SmtpHost string `json:"smtp_host"`
SmtpLogin string `json:"smtp_login"`
SmtpPassword string `json:"smtp_password"`
SmtpPort int `json:"smtp_port"`
} `json:"mail_settings"`
} }
type DnsResponse struct { type DnsResponse struct {
@ -28,6 +41,7 @@ type DnsResponse struct {
} }
var ( var (
configuration *Configuration
configPath string configPath string
) )
@ -35,15 +49,15 @@ func main() {
app := cli.NewApp() app := cli.NewApp()
app.Name = "dnsupdater" app.Name = "dnsupdater"
app.Version = "0.0.1"
app.Usage = "Automatically update dns" app.Usage = "Automatically update dns"
app.Before = before
app.Action = start app.Action = start
app.Flags = []cli.Flag{ app.Flags = []cli.Flag{
cli.StringFlag{ cli.StringFlag{
Name: "config, C", Name: "config, C",
Usage: "path to config file", Usage: "path to config file",
Value: "/config/conf.json", Value: "/config",
EnvVar: "CONFIG_PATH", EnvVar: "CONFIG_PATH",
}, },
} }
@ -53,26 +67,35 @@ func main() {
} }
} }
func start(c *cli.Context) { func before(c *cli.Context) error {
if err := update(c); err != nil { log.SetLevel(log.InfoLevel)
log.Errorln(err)
SendStatusMail(fmt.Sprintf("Error during update process : %s", err))
}
}
func update(c *cli.Context) error {
configPath = c.String("config")
configPath = path.Join(c.String("config"), "conf.json")
if confPathExists, _ := exists(configPath); !confPathExists { if confPathExists, _ := exists(configPath); !confPathExists {
configPath = "./data" return fmt.Errorf("config file does not exist : %s", configPath)
} }
file, _ := os.Open(path.Join(configPath, "conf.json")) file, _ := os.Open(configPath)
defer file.Close() defer file.Close()
decoder := json.NewDecoder(file) decoder := json.NewDecoder(file)
configuration := Configuration{} configuration = &Configuration{}
err := decoder.Decode(&configuration) err := decoder.Decode(configuration)
if err != nil {
return err
}
return nil
}
func start(c *cli.Context) error {
SendStatusMail("test")
if err := update(); err != nil {
SendStatusMail(fmt.Sprintf("Error during update process : %s", err))
return err
}
return nil
}
func update() error {
newIp, err := GetOutboundIP() newIp, err := GetOutboundIP()
if err != nil { if err != nil {
return err return err
@ -80,7 +103,7 @@ func update(c *cli.Context) error {
updatedDomains := "" updatedDomains := ""
for _, domain := range configuration.Domains { for _, domain := range configuration.Domains {
currentIp, err := GetCurrentIp(configuration, domain) currentIp, err := GetCurrentIp(*configuration, domain)
if err != nil { if err != nil {
return err return err
} }
@ -89,9 +112,9 @@ func update(c *cli.Context) error {
continue continue
} }
fmt.Printf("%s -> Ip has changed %s -> %s\n", domain, currentIp, newIp) log.Infoln("%s -> Ip has changed %s -> %s\n", domain, currentIp, newIp)
err = SetCurrentIp(newIp, domain, configuration) err = SetCurrentIp(newIp, domain, *configuration)
if err != nil { if err != nil {
return err return err
} }
@ -108,33 +131,30 @@ Dns updated successfully for domains
} }
func SendStatusMail(messageText string) { func SendStatusMail(messageText string) {
// user we are authorizing as
from := "laurent@lehouerou.net"
// use we are sending email to settings := configuration.MailSettings
to := "laurent@lehouerou.net" if settings == nil{
log.Warnln("no smtp settings defined > status mail not sent")
return
}
// server we are authorized to send email through d := gomail.NewDialer(settings.SmtpHost, settings.SmtpPort, settings.SmtpLogin, settings.SmtpPassword)
host := "smtp.fastmail.com" s, err := d.Dial()
if err != nil {
log.Errorln("error while dialing smtp server : %v", err)
}
// Create the authentication for the SendMail() m := gomail.NewMessage()
// using PlainText, but other authentication methods are encouraged for _, r := range settings.To {
auth := smtp.PlainAuth("", from, "c9bd8fb8l4bhs2f8", host) m.SetHeader("From", settings.Sender)
m.SetAddressHeader("To", r, "")
m.SetHeader("Subject", "DnsUpdater Status")
m.SetBody("text/plain", messageText)
// NOTE: Using the backtick here ` works like a heredoc, which is why all the if err := gomail.Send(s, m); err != nil {
// rest of the lines are forced to the beginning of the line, otherwise the log.Warnln("could not send email to %q: %v", r, err)
// formatting is wrong for the RFC 822 style }
message := fmt.Sprintf(`To: "Laurent Le Houerou" <laurent@lehouerou.net> m.Reset()
From: "Laurent Le Houerou" <laurent@lehouerou.net>
Subject: DnsUpdater Status
%s
`, messageText)
if err := smtp.SendMail(host+":587", auth, from, []string{to}, []byte(message)); err != nil {
fmt.Println("Error SendMail: ", err)
} else {
fmt.Println("Email Sent!")
} }
} }
@ -191,11 +211,17 @@ func SetCurrentIp(newip string, domain string, configuration Configuration) erro
} }
func GetOutboundIP() (string, error) { func GetOutboundIP() (string, error) {
url := "https://api.ipify.org" url := configuration.RouterStatusUrl
if url == "" {
url = "http://192.168.1.1/Status_Internet.live.asp"
}
req, err := http.NewRequest("GET", url, nil) req, err := http.NewRequest("GET", url, nil)
if err != nil { if err != nil {
return "", err return "", err
} }
if configuration.RouterLogin != "" && configuration.RouterPassword != "" {
req.SetBasicAuth(configuration.RouterLogin, configuration.RouterPassword)
}
res, err := http.DefaultClient.Do(req) res, err := http.DefaultClient.Do(req)
if err != nil { if err != nil {
return "", err return "", err
@ -205,7 +231,18 @@ func GetOutboundIP() (string, error) {
if err != nil { if err != nil {
return "", err return "", err
} }
return string(body), nil
log.Debugln(string(body))
wanipregex := configuration.WanIPRegex
if wanipregex == "" {
wanipregex = "wan_ipaddr::([0-9.]*)}"
}
r := regexp.MustCompile(wanipregex)
matches := r.FindStringSubmatch(string(body))
if len(matches) < 2 {
return "", fmt.Errorf("unable to find WAN IP with regex %s in %s", wanipregex, string(body))
}
return matches[1], nil
} }
func exists(path string) (bool, error) { func exists(path string) (bool, error) {