-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 5bc0af0
Showing
5 changed files
with
203 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
*.json | ||
*.log | ||
dyndns_route53 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
FROM centos:centos7 | ||
MAINTAINER Gert Leenders <[email protected]> | ||
|
||
|
||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# DynDNS Route53 | ||
|
||
This is a little program written in [Go](https://golang.org/project/) that | ||
takes the WAN ip of your current infrastructure to update a hostname hosted | ||
on [Amazon Route53](https://aws.amazon.com/route53/). | ||
|
||
## Installation | ||
|
||
### Make a binary | ||
One of the main reasons to choose Go to develop this program was the fact | ||
that Go can build executable binaries, which makes installation very easy. Secondly | ||
with Go it's also very easy to cross compile the program for different platforms. | ||
|
||
To make a binary just run: | ||
``` | ||
go build dyndns_route53.go | ||
``` | ||
This will result in an executable binary named `dyndns_route53`. | ||
|
||
#### Cross compile | ||
This real power however is that you can cross compile the code for a number of | ||
platforms. | ||
Personally I have this program running on my (Synology) NAS. | ||
This NAS is running Linux and has a x86-64 architecture. In order to | ||
get the program running on that device you need to cross compile it for that specific platform. | ||
To achieve this, you have to specify two extra parameters on the build command: | ||
`GOOS` and `GOARCH`, you can find the appropriate values for | ||
these variables [here](https://golang.org/doc/install/source#environment). | ||
|
||
Here's how I build an executable binary for my NAS: | ||
``` | ||
# env GOOS=linux GOARCH=amd64 go build dyndns_route53.go | ||
``` | ||
|
||
### Configuration | ||
Put a file named `config.json` in the same directory as you executable. A file named `config.example` is included in the repository to make your life easy. It looks like this: | ||
``` | ||
{ | ||
"aws_access_key_id": "ABC...", | ||
"aws_secret_access_key: "XYZ...", | ||
"hosted_zone_id": "A1..", | ||
"fqdn": "www.example.com" | ||
} | ||
``` | ||
|
||
### Logging | ||
The program will write its output to a file named `dyndns.log` under the same directory as you executable. | ||
|
||
## Usage | ||
|
||
Test and run locally: | ||
``` | ||
go build dyndns_route53.go | ||
go run dyndns_route53.go | ||
``` | ||
|
||
## Contributing | ||
|
||
1. Fork it! | ||
2. Create your feature branch: `git checkout -b my-new-feature` | ||
3. Commit your changes: `git commit -am 'Add some feature'` | ||
4. Push to the branch: `git push origin my-new-feature` | ||
5. Submit a pull request :D | ||
|
||
## License | ||
|
||
MIT: http://rem.mit-license.org |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
{ | ||
"aws_access_key_id": "ABC...", | ||
"aws_secret_access_key: "XYZ...", | ||
"hosted_zone_id": "A1..", | ||
"fqdn": "www.example.com" | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,121 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"net" | ||
"net/http" | ||
"os" | ||
"path" | ||
|
||
"github.com/aws/aws-sdk-go/aws" | ||
"github.com/aws/aws-sdk-go/aws/credentials" | ||
"github.com/aws/aws-sdk-go/aws/session" | ||
"github.com/aws/aws-sdk-go/service/route53" | ||
"github.com/kardianos/osext" | ||
|
||
"github.com/op/go-logging" | ||
) | ||
|
||
var log = logging.MustGetLogger("dyndns") | ||
var format = logging.MustStringFormatter(`%{time:2006-01-02T15:04:05.999999999} %{shortfunc} - %{level:.5s} %{message}`) | ||
|
||
type Configuration struct { | ||
AwsAccessKeyId string | ||
AwsSecretAccessKey string | ||
HostedZoneId string | ||
Fqdn string | ||
} | ||
|
||
type Response struct { | ||
Ip string | ||
} | ||
|
||
func perror(err error, logger *logging.Logger) { | ||
if err != nil { | ||
logger.Error(err.Error()) | ||
panic(err) | ||
} | ||
} | ||
|
||
func main() { | ||
// Get the current directory | ||
dir, err := osext.ExecutableFolder() | ||
perror(err, log) | ||
|
||
// Initialze a log file | ||
logFile, err := os.OpenFile(path.Join(dir, "dyndns.log"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666) | ||
loggingBackend := logging.NewLogBackend(logFile, "", 0) | ||
backendFormatter := logging.NewBackendFormatter(loggingBackend, format) | ||
backendLeveled := logging.AddModuleLevel(backendFormatter) | ||
backendLeveled.SetLevel(logging.INFO, "") | ||
logging.SetBackend(backendLeveled) | ||
perror(err, log) | ||
|
||
// Read the config file | ||
configFile, err := os.Open(path.Join(dir, "config.json")) | ||
perror(err, log) | ||
decoder := json.NewDecoder(configFile) | ||
var config Configuration | ||
err = decoder.Decode(&config) | ||
perror(err, log) | ||
|
||
// Request your WAN ip | ||
url := "https://api.ipify.org?format=json" | ||
res, err := http.Get(url) | ||
perror(err, log) | ||
defer res.Body.Close() | ||
decoder = json.NewDecoder(res.Body) | ||
var body Response | ||
err = decoder.Decode(&body) | ||
perror(err, log) | ||
wanIp := body.Ip | ||
log.Debugf("Current WAN ip: %s", wanIp) | ||
|
||
// Obtain the current ip bounded to the FQDN | ||
ips, err := net.LookupHost(config.Fqdn) | ||
currentIp := ips[0] | ||
log.Debugf("Current ip bounded to '%s': %s", config.Fqdn, currentIp) | ||
|
||
// Update the FQDN's ip in case the current WAN ip is different from the ip bounded to the FQDN | ||
if currentIp != wanIp { | ||
|
||
log.Infof("'%s' out-of-date update '%s' to '%s'", config.Fqdn, currentIp, wanIp) | ||
|
||
var token string | ||
creds := credentials.NewStaticCredentials(config.AwsAccessKeyId, config.AwsSecretAccessKey, token) | ||
|
||
svc := route53.New(session.New(), &aws.Config{ | ||
Credentials: creds, | ||
}) | ||
|
||
params := &route53.ChangeResourceRecordSetsInput{ | ||
ChangeBatch: &route53.ChangeBatch{ // Required | ||
Changes: []*route53.Change{ // Required | ||
{ // Required | ||
Action: aws.String("UPSERT"), // Required | ||
ResourceRecordSet: &route53.ResourceRecordSet{ // Required | ||
Name: aws.String("synology.pixxis.be"), // Required | ||
Type: aws.String("A"), // Required | ||
ResourceRecords: []*route53.ResourceRecord{ | ||
{ // Required | ||
Value: aws.String(body.Ip), // Required | ||
}, | ||
}, | ||
TTL: aws.Int64(111), | ||
}, | ||
}, | ||
}, | ||
Comment: aws.String("IP update by GO script"), | ||
}, | ||
HostedZoneId: aws.String(config.HostedZoneId), // Required | ||
} | ||
resp, err := svc.ChangeResourceRecordSets(params) | ||
perror(err, log) | ||
|
||
// Pretty-print the response data. | ||
log.Debug(resp) | ||
|
||
} else { | ||
log.Infof("'%s' is up-to-date", config.Fqdn) | ||
} | ||
} |