Merge branch 'master' of github.com:anaganisk/digitalocean-dynamic-dns-ip
This commit is contained in:
commit
84f2163003
45
.circleci/config.yml
Normal file
45
.circleci/config.yml
Normal 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
4
.gitignore
vendored
@ -2,3 +2,7 @@ config.json
|
|||||||
digitalocean-dynamic-ip
|
digitalocean-dynamic-ip
|
||||||
digitalocean-dynamic-dns-ip
|
digitalocean-dynamic-dns-ip
|
||||||
digitalocean-dynamic-ip.json
|
digitalocean-dynamic-ip.json
|
||||||
|
|
||||||
|
# GoLand IDE
|
||||||
|
.idea/
|
||||||
|
releases
|
54
README.md
54
README.md
@ -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.
|
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
|
## Requirements
|
||||||
Requires Git and Go for building.
|
|
||||||
|
|
||||||
Requires that the record already exists in DigitalOcean's DNS so that it can 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)
|
(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
|
## 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 in your home directory. Add the following JSON (or refer to the sample configuration file, `digitalocean-dynamic-ip.sample.json`):
|
||||||
```
|
|
||||||
create a file ".digitalocean-dynamic-ip.json"(dot prefix to hide the file) and place it user home directory and add the following json
|
|
||||||
|
|
||||||
```json
|
```json
|
||||||
{
|
{
|
||||||
"apikey": "samplekeydasjkdhaskjdhrwofihsamplekey",
|
"apikey": "samplekeydasjkdhaskjdhrwofihsamplekey",
|
||||||
"doPageSize" : 20,
|
"doPageSize": 20,
|
||||||
"useIPv4": true,
|
"useIPv4": true,
|
||||||
"useIPv6": false,
|
"useIPv6": false,
|
||||||
"allowIPv4InIPv6": false,
|
"allowIPv4InIPv6": false,
|
||||||
|
"ipv4CheckUrl": "https://ipv4bot.whatismyipaddress.com",
|
||||||
"domains": [
|
"domains": [
|
||||||
{
|
{
|
||||||
"domain": "example.com",
|
"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.
|
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.
|
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 `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
|
```bash
|
||||||
#run
|
# after running `go build digitalocean-dynamic-ip.go`, run:
|
||||||
go build digitalocean-dynamic-ip.go
|
|
||||||
./digitalocean-dynamic-ip
|
./digitalocean-dynamic-ip
|
||||||
```
|
```
|
||||||
|
|
||||||
Optionally, you can create the configuration file with any name wherever you want, and pass it as a command line argument:
|
Optionally, you can create the configuration file with any name wherever you want, and pass it as a command line argument:
|
||||||
````bash
|
|
||||||
#run
|
```bash
|
||||||
./digitalocean-dynamic-ip /path/tp/my/config.json
|
#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.
|
You can either set this to run periodically with a cronjob or use your own method.
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# run crontab -e
|
# run `crontab -e` to edit your crontab
|
||||||
# sample cron job task
|
# sample cron job task
|
||||||
|
|
||||||
# m h dom mon dow command
|
# m h dom mon dow command
|
||||||
|
25
ci-build-script.sh
Executable file
25
ci-build-script.sh
Executable 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
|
@ -31,6 +31,8 @@ type ClientConfig struct {
|
|||||||
DOPageSize int `json:"doPageSize"`
|
DOPageSize int `json:"doPageSize"`
|
||||||
UseIPv4 *bool `json:"useIPv4"`
|
UseIPv4 *bool `json:"useIPv4"`
|
||||||
UseIPv6 *bool `json:"useIPv6"`
|
UseIPv6 *bool `json:"useIPv6"`
|
||||||
|
IPv4CheckURL string `json:"ipv4CheckUrl"`
|
||||||
|
IPv6CheckURL string `json:"ipv6CheckUrl"`
|
||||||
AllowIPv4InIPv6 bool `json:"allowIPv4InIPv6"`
|
AllowIPv4InIPv6 bool `json:"allowIPv4InIPv6"`
|
||||||
Domains []Domain `json:"domains"`
|
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
|
//CheckLocalIPs : get current IP of server. checks both IPv4 and Ipv6 to support dual stack environments
|
||||||
func CheckLocalIPs() (ipv4, ipv6 net.IP) {
|
func CheckLocalIPs() (ipv4, ipv6 net.IP) {
|
||||||
var ipv4String, ipv6String string
|
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) {
|
if config.UseIPv4 == nil || *(config.UseIPv4) {
|
||||||
ipv4String, _ = getURLBody("https://ipv4bot.whatismyipaddress.com")
|
ipv4String, _ = getURLBody(ipv4CheckURL)
|
||||||
if ipv4String == "" {
|
if ipv4String == "" {
|
||||||
log.Println("No IPv4 address found. Consider disabling IPv4 checks in the config `\"useIPv4\": false`")
|
log.Println("No IPv4 address found. Consider disabling IPv4 checks in the config `\"useIPv4\": false`")
|
||||||
} else {
|
} else {
|
||||||
@ -128,6 +138,7 @@ func CheckLocalIPs() (ipv4, ipv6 net.IP) {
|
|||||||
if ipv4 != nil {
|
if ipv4 != nil {
|
||||||
// make sure we got back an actual ipv4 address
|
// make sure we got back an actual ipv4 address
|
||||||
ipv4 = ipv4.To4()
|
ipv4 = ipv4.To4()
|
||||||
|
log.Printf("Discovered IPv4 address `%s`", ipv4.String())
|
||||||
}
|
}
|
||||||
if ipv4 == nil {
|
if ipv4 == nil {
|
||||||
log.Printf("Unable to parse `%s` as an IPv4 address", ipv4String)
|
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) {
|
if config.UseIPv6 == nil || *(config.UseIPv6) {
|
||||||
ipv6String, _ = getURLBody("https://ipv6bot.whatismyipaddress.com")
|
ipv6String, _ = getURLBody(ipv6CheckURL)
|
||||||
if ipv6String == "" {
|
if ipv6String == "" {
|
||||||
log.Println("No IPv6 address found. Consider disabling IPv6 checks in the config `\"useIPv6\": false`")
|
log.Println("No IPv6 address found. Consider disabling IPv6 checks in the config `\"useIPv6\": false`")
|
||||||
} else {
|
} else {
|
||||||
ipv6 = net.ParseIP(ipv6String)
|
ipv6 = net.ParseIP(ipv6String)
|
||||||
if ipv6 == nil {
|
if ipv6 == nil {
|
||||||
log.Printf("Unable to parse `%s` as an IPv6 address", ipv6String)
|
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) {
|
func getURLBody(url string) (string, error) {
|
||||||
request, err := http.Get(url)
|
request, err := http.Get(url)
|
||||||
if err != nil {
|
checkError(err)
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
defer request.Body.Close()
|
defer request.Body.Close()
|
||||||
body, err := ioutil.ReadAll(request.Body)
|
body, err := ioutil.ReadAll(request.Body)
|
||||||
checkError(err)
|
checkError(err)
|
||||||
@ -206,10 +217,10 @@ func UpdateRecords(domain Domain, ipv4, ipv6 net.IP) {
|
|||||||
doRecords := GetDomainRecords(domain.Domain)
|
doRecords := GetDomainRecords(domain.Domain)
|
||||||
// look for the item to update
|
// look for the item to update
|
||||||
if len(doRecords) < 1 {
|
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
|
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 {
|
for _, toUpdateRecord := range domain.Records {
|
||||||
if toUpdateRecord.Type != "A" && toUpdateRecord.Type != "AAAA" {
|
if toUpdateRecord.Type != "A" && toUpdateRecord.Type != "AAAA" {
|
||||||
log.Printf("%s: Unsupported type (Only A and AAAA records supported) for updates %+v", domain.Domain, toUpdateRecord)
|
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()
|
config = GetConfig()
|
||||||
currentIPv4, currentIPv6 := CheckLocalIPs()
|
currentIPv4, currentIPv6 := CheckLocalIPs()
|
||||||
if currentIPv4 == nil && currentIPv6 == nil {
|
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 {
|
for _, domain := range config.Domains {
|
||||||
log.Printf("%s: START", domain.Domain)
|
log.Printf("%s: START", domain.Domain)
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
"doPageSize": 20,
|
"doPageSize": 20,
|
||||||
"useIPv4": true,
|
"useIPv4": true,
|
||||||
"useIPv6": true,
|
"useIPv6": true,
|
||||||
|
"ipv4CheckUrl": "https://ipv4bot.whatismyipaddress.com",
|
||||||
|
"ipv6CheckUrl": "https://ipv6bot.whatismyipaddress.com",
|
||||||
"allowIPv4InIPv6": false,
|
"allowIPv4InIPv6": false,
|
||||||
"domains": [
|
"domains": [
|
||||||
{
|
{
|
||||||
@ -11,6 +13,10 @@
|
|||||||
{
|
{
|
||||||
"name": "subdomainOrRecord",
|
"name": "subdomainOrRecord",
|
||||||
"type": "A"
|
"type": "A"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "subdomainOrRecord",
|
||||||
|
"type": "AAAA"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
|
5
go.mod
Normal file
5
go.mod
Normal 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
|
Loading…
Reference in New Issue
Block a user