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"` +}