1
0

Merge branch 'master' of github.com:anaganisk/digitalocean-dynamic-dns-ip

This commit is contained in:
John Aylward 2020-03-04 12:42:56 -05:00
commit 84f2163003
8 changed files with 143 additions and 27 deletions

45
.circleci/config.yml Normal file
View File

@ -0,0 +1,45 @@
version: 2
jobs:
build:
docker:
- image: circleci/golang:1.11
working_directory: ~/app
steps:
- checkout
- run:
name: Build
command: |
./ci-build-script.sh .
- persist_to_workspace:
root: .
paths:
- ./releases
publish-github-release:
docker:
- image: cibuilds/github:0.10
working_directory: ~/app
steps:
- attach_workspace:
at: ~/app
- run:
name: "Publish Release on GitHub"
command: |
ghr -t ${GITHUB_TOKEN} -u ${CIRCLE_PROJECT_USERNAME} -r ${CIRCLE_PROJECT_REPONAME} -c ${CIRCLE_SHA1} -delete ${CIRCLE_TAG} ./releases/
workflows:
version: 2
main:
jobs:
- build:
filters:
tags:
only: /^\d+\.\d+\.\d+$/
- publish-github-release:
requires:
- build
filters:
branches:
ignore: /.*/
tags:
only: /^\d+\.\d+\.\d+$/

4
.gitignore vendored
View File

@ -2,3 +2,7 @@ config.json
digitalocean-dynamic-ip
digitalocean-dynamic-dns-ip
digitalocean-dynamic-ip.json
# GoLand IDE
.idea/
releases

View File

@ -1,29 +1,43 @@
# DIGITAL OCEAN DYNAMIC IP API CLIENT
# DIGITAL OCEAN DYNAMIC IP API CLIENT [![CircleCI](https://circleci.com/gh/anaganisk/digitalocean-dynamic-dns-ip/tree/master.svg?style=svg)](https://circleci.com/gh/anaganisk/digitalocean-dynamic-dns-ip/tree/master)
A simple script in Go language to automatically update Digital ocean DNS records if you have a dynamic IP. Since it can be compiled on any platform, you can use it along with raspberrypi etc.
To find your Dynamic IP, this program will call out to https://ipv4bot.whatismyipaddress.com for ipv4 addresses and https://ipv6bot.whatismyipaddress.com for ipv6 addresses. This is to support dual-stack environments.
To find your Dynamic IP, this program will call out to https://ipv4bot.whatismyipaddress.com for ipv4 addresses and https://ipv6bot.whatismyipaddress.com for ipv6 addresses. This is to support dual-stack environments. (These URLs can be customized; see Usage, below.)
## requirements
Requires Git and Go for building.
## Requirements
Requires that the record already exists in DigitalOcean's DNS so that it can be updated.
(manually find your IP and add it to DO's DNS it will later be updated)
- The record must already exist in DigitalOcean's DNS so that it can be updated.
(manually find your IP and add it to DO's DNS it will later be updated)
- A Digital Ocean API key that can be created at https://cloud.digitalocean.com/account/api/tokens.
Requires a Digital Ocean API key that can be created at https://cloud.digitalocean.com/account/api/tokens.
## Installation
Download the prebuilt binaries from [releases](https://github.com/anaganisk/digitalocean-dynamic-dns-ip/releases),
or Build from source
```bash
# Requires Git, Go 1.8+(GO 1.11 if you want to use GO111MODULE=on).
# clone the repo in ~/go/src/github.com/anaganisk:
git clone https://github.com/anaganisk/digitalocean-dynamic-dns-ip.git
# Skip to next step, if you have GO111MODULE=on in your environment it is fetched automatically
go get github.com/mitchellh/go-homedir
# build the project
go build
```
## Usage
```bash
git clone https://github.com/anaganisk/digitalocean-dynamic-dns-ip.git
```
create a file ".digitalocean-dynamic-ip.json"(dot prefix to hide the file) and place it user home directory and add the following json
Create a file `.digitalocean-dynamic-ip.json` (dot prefix to hide the file) and place it in your home directory. Add the following JSON (or refer to the sample configuration file, `digitalocean-dynamic-ip.sample.json`):
```json
{
"apikey": "samplekeydasjkdhaskjdhrwofihsamplekey",
"doPageSize" : 20,
"doPageSize": 20,
"useIPv4": true,
"useIPv6": false,
"allowIPv4InIPv6": false,
"ipv4CheckUrl": "https://ipv4bot.whatismyipaddress.com",
"domains": [
{
"domain": "example.com",
@ -47,6 +61,7 @@ create a file ".digitalocean-dynamic-ip.json"(dot prefix to hide the file) and p
]
}
```
The TTL can optionally be updated if passed in the configuration. Digital Ocean has a minimum TTL of 30 seconds. The `type` and the `name` must match existing records in the Digital Ocean DNS configuration. Only `types` of `A` and `AAAA` allowed at the moment.
If you want to reduce the number of calls made to the digital ocean API and have more than 20 DNS records in your domain, you can adjust the `doPageSize` parameter. By default, Digital Ocean returns 20 records per page. Digital Ocean has a max page size of 200 items.
@ -55,21 +70,24 @@ By default, the configuration checks both IPv4 and IPv6 addresses assuming your
The `allowIPv4InIPv6` configuration option will allow adding an IPv4 address to be used in a AAAA record for IPv6 lookups.
The `ipv4CheckUrl` and `ipv6CheckUrl` configuration settings are optional. If set, they must be URLs which respond to a GET request, with a plaintext response containing only your IP address. If unset, they default to `https://ipv_bot.whatismyipaddress.com`.
```bash
#run
go build digitalocean-dynamic-ip.go
# after running `go build digitalocean-dynamic-ip.go`, run:
./digitalocean-dynamic-ip
```
Optionally, you can create the configuration file with any name wherever you want, and pass it as a command line argument:
````bash
#run
./digitalocean-dynamic-ip /path/tp/my/config.json
```bash
#run:
./digitalocean-dynamic-ip /path/to/my/config.json
```
You can either set this to run periodically with a cronjob or use your own method.
```bash
# run crontab -e
# run `crontab -e` to edit your crontab
# sample cron job task
# m h dom mon dow command

25
ci-build-script.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/bash
package=$1
if [[ -z "$package" ]]; then
echo "usage: $0 <package-name>"
exit 1
fi
package_split=(${package//\// })
package_name=${package_split[-1]}
platforms=("windows/amd64" "windows/386" "darwin/amd64" "linux/386" "linux/amd64" "linux/arm" "linux/arm64")
mkdir releases
for platform in "${platforms[@]}"
do
platform_split=(${platform//\// })
GOOS=${platform_split[0]}
GOARCH=${platform_split[1]}
output_name='digitalocean-dynamic-dns-ip-'$GOOS'-'$GOARCH
if [ $GOOS = "windows" ]; then
output_name+='.exe'
fi
env GOOS=$GOOS GOARCH=$GOARCH go build -o releases/$output_name $package_name
if [ $? -ne 0 ]; then
echo 'An error has occurred! Aborting the script execution...'
exit 1
fi
done

View File

@ -31,6 +31,8 @@ type ClientConfig struct {
DOPageSize int `json:"doPageSize"`
UseIPv4 *bool `json:"useIPv4"`
UseIPv6 *bool `json:"useIPv6"`
IPv4CheckURL string `json:"ipv4CheckUrl"`
IPv6CheckURL string `json:"ipv6CheckUrl"`
AllowIPv4InIPv6 bool `json:"allowIPv4InIPv6"`
Domains []Domain `json:"domains"`
}
@ -118,9 +120,17 @@ func usage() {
//CheckLocalIPs : get current IP of server. checks both IPv4 and Ipv6 to support dual stack environments
func CheckLocalIPs() (ipv4, ipv6 net.IP) {
var ipv4String, ipv6String string
ipv4CheckURL := "https://ipv4bot.whatismyipaddress.com"
ipv6CheckURL := "https://ipv6bot.whatismyipaddress.com"
if len(config.IPv4CheckURL) > 0 {
ipv4CheckURL = config.IPv4CheckURL
}
if len(config.IPv6CheckURL) > 0 {
ipv6CheckURL = config.IPv6CheckURL
}
if config.UseIPv4 == nil || *(config.UseIPv4) {
ipv4String, _ = getURLBody("https://ipv4bot.whatismyipaddress.com")
ipv4String, _ = getURLBody(ipv4CheckURL)
if ipv4String == "" {
log.Println("No IPv4 address found. Consider disabling IPv4 checks in the config `\"useIPv4\": false`")
} else {
@ -128,6 +138,7 @@ func CheckLocalIPs() (ipv4, ipv6 net.IP) {
if ipv4 != nil {
// make sure we got back an actual ipv4 address
ipv4 = ipv4.To4()
log.Printf("Discovered IPv4 address `%s`", ipv4.String())
}
if ipv4 == nil {
log.Printf("Unable to parse `%s` as an IPv4 address", ipv4String)
@ -136,13 +147,15 @@ func CheckLocalIPs() (ipv4, ipv6 net.IP) {
}
if config.UseIPv6 == nil || *(config.UseIPv6) {
ipv6String, _ = getURLBody("https://ipv6bot.whatismyipaddress.com")
ipv6String, _ = getURLBody(ipv6CheckURL)
if ipv6String == "" {
log.Println("No IPv6 address found. Consider disabling IPv6 checks in the config `\"useIPv6\": false`")
} else {
ipv6 = net.ParseIP(ipv6String)
if ipv6 == nil {
log.Printf("Unable to parse `%s` as an IPv6 address", ipv6String)
} else {
log.Printf("Discovered IPv6 address `%s`", ipv6.String())
}
}
}
@ -151,9 +164,7 @@ func CheckLocalIPs() (ipv4, ipv6 net.IP) {
func getURLBody(url string) (string, error) {
request, err := http.Get(url)
if err != nil {
return "", err
}
checkError(err)
defer request.Body.Close()
body, err := ioutil.ReadAll(request.Body)
checkError(err)
@ -206,10 +217,10 @@ func UpdateRecords(domain Domain, ipv4, ipv6 net.IP) {
doRecords := GetDomainRecords(domain.Domain)
// look for the item to update
if len(doRecords) < 1 {
log.Printf("%s: No DNS records found in Digital Ocean", domain.Domain)
log.Printf("%s: No DNS records found in DigitalOcean", domain.Domain)
return
}
log.Printf("%s: %d DNS records found in Digital Ocean", domain.Domain, len(doRecords))
log.Printf("%s: %d DNS records found in DigitalOcean", domain.Domain, len(doRecords))
for _, toUpdateRecord := range domain.Records {
if toUpdateRecord.Type != "A" && toUpdateRecord.Type != "AAAA" {
log.Printf("%s: Unsupported type (Only A and AAAA records supported) for updates %+v", domain.Domain, toUpdateRecord)
@ -327,7 +338,7 @@ func main() {
config = GetConfig()
currentIPv4, currentIPv6 := CheckLocalIPs()
if currentIPv4 == nil && currentIPv6 == nil {
log.Fatal("current IP addresses are not a valid, or both are disabled in the config. Check you configuration and internet connection")
log.Fatal("Current IP addresses are not valid, or both are disabled in the config. Check your configuration and internet connection.")
}
for _, domain := range config.Domains {
log.Printf("%s: START", domain.Domain)

View File

@ -3,6 +3,8 @@
"doPageSize": 20,
"useIPv4": true,
"useIPv6": true,
"ipv4CheckUrl": "https://ipv4bot.whatismyipaddress.com",
"ipv6CheckUrl": "https://ipv6bot.whatismyipaddress.com",
"allowIPv4InIPv6": false,
"domains": [
{
@ -11,6 +13,10 @@
{
"name": "subdomainOrRecord",
"type": "A"
},
{
"name": "subdomainOrRecord",
"type": "AAAA"
}
]
},

5
go.mod Normal file
View File

@ -0,0 +1,5 @@
module github.com/anaganisk/digitalocean-dynamic-dns-ip
require github.com/mitchellh/go-homedir v1.1.0
go 1.8

2
go.sum Normal file
View File

@ -0,0 +1,2 @@
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=