From 8109865f081e482dea6d52b8e519ef63db98659d Mon Sep 17 00:00:00 2001 From: Jonathan Mainguy Date: Mon, 4 Nov 2019 10:03:57 -0500 Subject: [PATCH] initial mvp --- .gitignore | 1 + README.md | 20 +++++++++++++++++ config.go | 19 +++++++++++++++++ exampleConfig.yaml | 6 ++++++ grabDynamicIp.sh | 16 ++++++++++++++ internetbs.go | 53 ++++++++++++++++++++++++++++++++++++++++++++++ main.go | 36 +++++++++++++++++++++++++++++++ structs.go | 7 ++++++ 8 files changed, 158 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 config.go create mode 100644 exampleConfig.yaml create mode 100755 grabDynamicIp.sh create mode 100644 internetbs.go create mode 100644 main.go create mode 100644 structs.go diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..de7d99f --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +ibsdns diff --git a/README.md b/README.md new file mode 100644 index 0000000..b49a028 --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# ibsdns +InternetBS DNS Updater +## Why? +My buddy Keenan wanted to update home.example.com to point to his IP at home, +however he has a dynamic IP provided to home and so he needed a way to keep it current. +He was insistent on using InternetBS as compared to Route53 as he believed it would be less expensive (free basically) + +So I made this for him, though I did it in a way where it can be used by anyone with a InternetBS api key, +and a static host to ssh to and run the update tool from (internetBS limits their IP to a static IP you provide ahead of time) + +## HowTo +On server at home (or where the IP will be dynamicly changing) you need to add `grabDynamicIp.sh` to a cronjob, like once every 5 minutes perhaps + +```/bin/bash +*/5 * * * * /home/jmainguy/grabDynamicIp.sh jmainguy@remotehost.com > /home/jmainguy/dnsLog.txt 2>&1 +``` + +On remotehost add ibsdns binary to `/usr/sbin/ibsdns` and edit `/opt/ibsdns/config.yaml` for your values. + +Ensure passwordless ssh is setup from home to remote host, and that the user can read /opt/ibsdns/config.yaml diff --git a/config.go b/config.go new file mode 100644 index 0000000..726b87f --- /dev/null +++ b/config.go @@ -0,0 +1,19 @@ +package main + +import ( + "github.com/ghodss/yaml" + "io/ioutil" +) + +func config() (credents Config) { + config_file, err := ioutil.ReadFile("/opt/ibsdns/config.yaml") + check(err) + yaml.Unmarshal(config_file, &credents) + return +} + +type Config struct { + ApiKey string `json:"apiKey"` + Password string `json:"password"` + Domain string `json:"domain"` +} diff --git a/exampleConfig.yaml b/exampleConfig.yaml new file mode 100644 index 0000000..ce8aeb6 --- /dev/null +++ b/exampleConfig.yaml @@ -0,0 +1,6 @@ +# Get this from internet.bs +apiKey: RANDOMCHARACTERS +# Get this from intertnet.bs +password: MORERANDOMCHARACHTERS +# Domain you wish to keep updated to the dynamic ip +domain: home.jmainguy.com diff --git a/grabDynamicIp.sh b/grabDynamicIp.sh new file mode 100755 index 0000000..bb15c06 --- /dev/null +++ b/grabDynamicIp.sh @@ -0,0 +1,16 @@ +#!/bin/bash +CONNECTION=$1 +if [[ $CONNECTION == "" ]]; then + echo "Usage ./grabDynamicIp.sh user@remoteHost" + echo "You must pass connection string for remote box with a static IP where ibsdns is installed" + echo "Please setup ssh keys so you can add this to a cronjob" + exit 1 +fi +NEWIP=$(curl -s https://ip.jmainguy.com | awk '{print $4}') +OLDIP=$(cat ~/lastIP.txt) +if [[ $NEWIP != $OLDIP ]]; then + echo $NEWIP > ~/lastIP.txt + ssh $CONNECTION "/usr/sbin/ibsdns --value \"$NEWIP\"" +else + echo "No update needed" +fi diff --git a/internetbs.go b/internetbs.go new file mode 100644 index 0000000..730290b --- /dev/null +++ b/internetbs.go @@ -0,0 +1,53 @@ +package main + +import ( + "encoding/json" + "fmt" + "io/ioutil" + "net/http" + "net/url" + "strings" +) + +func updateDns(apiKey, password, fullrecordname, recordtype, newvalue string) (transactid, status, message string) { + + // Test Api + Url := "https://api.internet.bs/Domain/DnsRecord/Update" + + param := url.Values{} + param.Add("apiKey", apiKey) + param.Add("password", password) + param.Add("fullrecordname", fullrecordname) + param.Add("type", recordtype) + param.Add("newvalue", newvalue) + param.Add("ResponseFormat", "JSON") + + req, err := http.NewRequest("POST", Url, strings.NewReader(param.Encode())) + if err != nil { + fmt.Println(err) + } + req.Header.Set("Accept", "application/json") + req.Header.Set("Content-Type", "application/x-www-form-urlencoded") + + resp, err := http.DefaultClient.Do(req) + if err != nil { + fmt.Println(err) + } + defer resp.Body.Close() + jsonblob, err := ioutil.ReadAll(resp.Body) + if err != nil { + fmt.Println(err) + } + transactid, status, message = decodeResponse(jsonblob) + return +} + +func decodeResponse(jsonblob []byte) (transactid, status, message string) { + var response Response + json.Unmarshal(jsonblob, &response) + transactid = response.Transactid + status = response.Status + message = response.Message + + return +} diff --git a/main.go b/main.go new file mode 100644 index 0000000..a179317 --- /dev/null +++ b/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "fmt" + "os" + "flag" +) + +func check(e error) { + if e != nil { + fmt.Println(e) + } +} + +func main() { + + value := flag.String("value", "", "IP to update domain to, example 192.168.1.1") + flag.Parse() + + c := config() + recordtype := "A" + newvalue := *value + + if newvalue == "" { + fmt.Println("You must provide a value for the IP") + os.Exit(1) + } + + tid, status, message := updateDns(c.ApiKey, c.Password, c.Domain, recordtype, newvalue) + if message != "" { + fmt.Printf("TransactID: %s, Status: %s, Message: %s\n", tid, status, message) + } else { + fmt.Printf("TransactID: %s, Status: %s\n", tid, status) + } + +} diff --git a/structs.go b/structs.go new file mode 100644 index 0000000..49a85b5 --- /dev/null +++ b/structs.go @@ -0,0 +1,7 @@ +package main + +type Response struct { + Transactid string `json:"transactid"` + Status string `json:"status"` + Message string `json:"message"` +}