mirror of
https://github.com/taigrr/godns
synced 2025-01-18 04:03:25 -08:00
commit
6a164f8b0b
30
README.md
30
README.md
@ -32,6 +32,7 @@ Now I rewrite [DynDNS](https://github.com/TimothyYe/DynDNS) by Golang and call i
|
|||||||
* HE.net (Hurricane Electric) ([https://dns.he.net/](https://dns.he.net/))
|
* HE.net (Hurricane Electric) ([https://dns.he.net/](https://dns.he.net/))
|
||||||
* AliDNS ([https://help.aliyun.com/product/29697.html](https://help.aliyun.com/product/29697.html))
|
* AliDNS ([https://help.aliyun.com/product/29697.html](https://help.aliyun.com/product/29697.html))
|
||||||
* DuckDNS ([https://www.duckdns.org](https://www.duckdns.org))
|
* DuckDNS ([https://www.duckdns.org](https://www.duckdns.org))
|
||||||
|
* Dreamhost ([https://www.dreamhost.com](https://www.dreamhost.com))
|
||||||
|
|
||||||
## Supported Platforms
|
## Supported Platforms
|
||||||
|
|
||||||
@ -101,7 +102,7 @@ Usage of ./godns:
|
|||||||
|
|
||||||
## Config fields
|
## Config fields
|
||||||
|
|
||||||
* provider: The providers that GoDNS supports, available values are: `Cloudflare`, `Google`, `DNSPod`, `AliDNS`, `HE`, `DuckDNS`.
|
* provider: The providers that GoDNS supports, available values are: `Cloudflare`, `Google`, `DNSPod`, `AliDNS`, `HE`, `DuckDNS`, `Dreamhost`.
|
||||||
* email: Email or account name of your DNS provider.
|
* email: Email or account name of your DNS provider.
|
||||||
* password: Password of your account.
|
* password: Password of your account.
|
||||||
* login_token: API token of your account.
|
* login_token: API token of your account.
|
||||||
@ -116,10 +117,11 @@ Usage of ./godns:
|
|||||||
|
|
||||||
Supported provider(s):
|
Supported provider(s):
|
||||||
* Cloudflare
|
* Cloudflare
|
||||||
* HE.net
|
|
||||||
* DNSPod
|
* DNSPod
|
||||||
|
* Dreamhost
|
||||||
* DuckDNS
|
* DuckDNS
|
||||||
* Google Domains
|
* Google Domains
|
||||||
|
* HE.net
|
||||||
|
|
||||||
To enable the `IPv6` mode of GoDNS, you only need two steps:
|
To enable the `IPv6` mode of GoDNS, you only need two steps:
|
||||||
* Set the `ip_type` as `IPv6`, and make sure the `ipv6_url` is configured.
|
* Set the `ip_type` as `IPv6`, and make sure the `ipv6_url` is configured.
|
||||||
@ -210,6 +212,30 @@ For DNSPod, you need to provide your API Token(you can create it [here](https://
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Config example for Dreamhost
|
||||||
|
|
||||||
|
For Dreamhost, you need to provide your API Token(you can create it [here](https://panel.dreamhost.com/?tree=home.api)), and config all the domains & subdomains.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"provider": "Dreamhost",
|
||||||
|
"login_token": "your_api_key",
|
||||||
|
"domains": [{
|
||||||
|
"domain_name": "example.com",
|
||||||
|
"sub_domains": ["www","test"]
|
||||||
|
},{
|
||||||
|
"domain_name": "example2.com",
|
||||||
|
"sub_domains": ["www","test"]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"ip_url": "https://myip.biturl.top",
|
||||||
|
"ip_type": "IPV4",
|
||||||
|
"interval": 300,
|
||||||
|
"resolver": "ns1.dreamhost.com",
|
||||||
|
"socks5_proxy": ""
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### Config example for Google Domains
|
### Config example for Google Domains
|
||||||
|
|
||||||
For Google Domains, you need to provide email & password, and config all the domains & subdomains.
|
For Google Domains, you need to provide email & password, and config all the domains & subdomains.
|
||||||
|
1
go.mod
1
go.mod
@ -5,6 +5,7 @@ require (
|
|||||||
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
github.com/bmizerany/assert v0.0.0-20160611221934-b7ed37b82869 // indirect
|
||||||
github.com/bogdanovich/dns_resolver v0.0.0-20170211073258-a8e42bc6a5b6
|
github.com/bogdanovich/dns_resolver v0.0.0-20170211073258-a8e42bc6a5b6
|
||||||
github.com/fatih/color v1.7.0
|
github.com/fatih/color v1.7.0
|
||||||
|
github.com/google/uuid v1.1.1
|
||||||
github.com/kr/pretty v0.1.0 // indirect
|
github.com/kr/pretty v0.1.0 // indirect
|
||||||
github.com/mattn/go-colorable v0.0.9 // indirect
|
github.com/mattn/go-colorable v0.0.9 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.4 // indirect
|
github.com/mattn/go-isatty v0.0.4 // indirect
|
||||||
|
2
go.sum
2
go.sum
@ -6,6 +6,8 @@ github.com/bogdanovich/dns_resolver v0.0.0-20170211073258-a8e42bc6a5b6 h1:oV1V+u
|
|||||||
github.com/bogdanovich/dns_resolver v0.0.0-20170211073258-a8e42bc6a5b6/go.mod h1:txOV61Nn+21z77KUMkNsp8lTHoOFTtqotltQAFenS9I=
|
github.com/bogdanovich/dns_resolver v0.0.0-20170211073258-a8e42bc6a5b6/go.mod h1:txOV61Nn+21z77KUMkNsp8lTHoOFTtqotltQAFenS9I=
|
||||||
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
|
||||||
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||||
|
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
|
||||||
|
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
129
handler/dreamhost/dreamhost_handler.go
Normal file
129
handler/dreamhost/dreamhost_handler.go
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
package dreamhost
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"runtime/debug"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/TimothyYe/godns"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
// DreamhostURL the API address for dreamhost.com
|
||||||
|
DreamhostURL = "https://api.dreamhost.com"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Handler struct
|
||||||
|
type Handler struct {
|
||||||
|
Configuration *godns.Settings
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetConfiguration pass dns settings and store it to handler instance
|
||||||
|
func (handler *Handler) SetConfiguration(conf *godns.Settings) {
|
||||||
|
handler.Configuration = conf
|
||||||
|
}
|
||||||
|
|
||||||
|
// DomainLoop the main logic loop
|
||||||
|
func (handler *Handler) DomainLoop(domain *godns.Domain, panicChan chan<- godns.Domain) {
|
||||||
|
defer func() {
|
||||||
|
if err := recover(); err != nil {
|
||||||
|
log.Printf("Recovered in %v: %v\n", err, debug.Stack())
|
||||||
|
panicChan <- *domain
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for {
|
||||||
|
currentIP, err := godns.GetCurrentIP(handler.Configuration)
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
log.Println("get_currentIP:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
log.Println("currentIP is:", currentIP)
|
||||||
|
|
||||||
|
for _, subDomain := range domain.SubDomains {
|
||||||
|
hostname := subDomain + "." + domain.DomainName
|
||||||
|
lastIP := godns.ResolveDNS(hostname, handler.Configuration.Resolver)
|
||||||
|
//check against currently known IP, if no change, skip update
|
||||||
|
if currentIP == lastIP {
|
||||||
|
log.Printf("IP is the same as cached one. Skip update.\n")
|
||||||
|
} else {
|
||||||
|
log.Printf("%s.%s Start to update record IP...\n", subDomain, domain.DomainName)
|
||||||
|
handler.UpdateIP(hostname, currentIP, lastIP)
|
||||||
|
|
||||||
|
// Send notification
|
||||||
|
if err := godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP); err != nil {
|
||||||
|
log.Println("Failed to send notification")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sleep with interval
|
||||||
|
log.Printf("Going to sleep, will start next checking in %d seconds...\r\n", handler.Configuration.Interval)
|
||||||
|
time.Sleep(time.Second * time.Duration(handler.Configuration.Interval))
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateIP update subdomain with current IP
|
||||||
|
func (handler *Handler) UpdateIP(hostname, currentIP, lastIP string) {
|
||||||
|
|
||||||
|
handler.updateDNS(lastIP, currentIP, hostname, "remove")
|
||||||
|
handler.updateDNS(lastIP, currentIP, hostname, "add")
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// updateDNS can add or remove DNS records.
|
||||||
|
func (handler *Handler) updateDNS(dns, ip, hostname, action string) {
|
||||||
|
ipType := "A"
|
||||||
|
if strings.ToUpper(handler.Configuration.IPType) == godns.IPV6 {
|
||||||
|
ipType = "AAAA"
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates UUID
|
||||||
|
uid, _ := uuid.NewRandom()
|
||||||
|
values := url.Values{}
|
||||||
|
values.Add("record", hostname)
|
||||||
|
values.Add("key", handler.Configuration.LoginToken)
|
||||||
|
values.Add("type", ipType)
|
||||||
|
values.Add("unique_id", uid.String())
|
||||||
|
switch action {
|
||||||
|
case "remove":
|
||||||
|
// Build URL query (remove)
|
||||||
|
values.Add("cmd", "dns-remove_record")
|
||||||
|
values.Add("value", dns)
|
||||||
|
case "add":
|
||||||
|
// Build URL query (add)
|
||||||
|
values.Add("cmd", "dns-add_record")
|
||||||
|
values.Add("value", ip)
|
||||||
|
default:
|
||||||
|
log.Fatalf("Unknown action %s\n", action)
|
||||||
|
}
|
||||||
|
|
||||||
|
client := godns.GetHttpClient(handler.Configuration)
|
||||||
|
req, _ := http.NewRequest("POST", DreamhostURL, strings.NewReader(values.Encode()))
|
||||||
|
req.SetBasicAuth(handler.Configuration.Email, handler.Configuration.Password)
|
||||||
|
|
||||||
|
if handler.Configuration.UserAgent != "" {
|
||||||
|
req.Header.Add("User-Agent", handler.Configuration.UserAgent)
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
log.Println("Request error...")
|
||||||
|
log.Println("Err:", err.Error())
|
||||||
|
} else {
|
||||||
|
body, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
if resp.StatusCode == http.StatusOK {
|
||||||
|
log.Println("Update IP success:", string(body))
|
||||||
|
} else {
|
||||||
|
log.Println("Update IP failed:", string(body))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -5,6 +5,7 @@ import (
|
|||||||
"github.com/TimothyYe/godns/handler/alidns"
|
"github.com/TimothyYe/godns/handler/alidns"
|
||||||
"github.com/TimothyYe/godns/handler/cloudflare"
|
"github.com/TimothyYe/godns/handler/cloudflare"
|
||||||
"github.com/TimothyYe/godns/handler/dnspod"
|
"github.com/TimothyYe/godns/handler/dnspod"
|
||||||
|
"github.com/TimothyYe/godns/handler/dreamhost"
|
||||||
"github.com/TimothyYe/godns/handler/duck"
|
"github.com/TimothyYe/godns/handler/duck"
|
||||||
"github.com/TimothyYe/godns/handler/google"
|
"github.com/TimothyYe/godns/handler/google"
|
||||||
"github.com/TimothyYe/godns/handler/he"
|
"github.com/TimothyYe/godns/handler/he"
|
||||||
@ -25,6 +26,8 @@ func CreateHandler(provider string) IHandler {
|
|||||||
handler = IHandler(&cloudflare.Handler{})
|
handler = IHandler(&cloudflare.Handler{})
|
||||||
case godns.DNSPOD:
|
case godns.DNSPOD:
|
||||||
handler = IHandler(&dnspod.Handler{})
|
handler = IHandler(&dnspod.Handler{})
|
||||||
|
case godns.DREAMHOST:
|
||||||
|
handler = IHandler(&dreamhost.Handler{})
|
||||||
case godns.HE:
|
case godns.HE:
|
||||||
handler = IHandler(&he.Handler{})
|
handler = IHandler(&he.Handler{})
|
||||||
case godns.ALIDNS:
|
case godns.ALIDNS:
|
||||||
|
13
utils.go
13
utils.go
@ -49,6 +49,8 @@ const (
|
|||||||
GOOGLE = "Google"
|
GOOGLE = "Google"
|
||||||
// DUCK for Duck DNS
|
// DUCK for Duck DNS
|
||||||
DUCK = "DuckDNS"
|
DUCK = "DuckDNS"
|
||||||
|
// DREAMHOST for Dreamhost
|
||||||
|
DREAMHOST = "Dreamhost"
|
||||||
// IPV4 for IPV4 mode
|
// IPV4 for IPV4 mode
|
||||||
IPV4 = "IPV4"
|
IPV4 = "IPV4"
|
||||||
// IPV6 for IPV6 mode
|
// IPV6 for IPV6 mode
|
||||||
@ -218,15 +220,20 @@ func CheckSettings(config *Settings) error {
|
|||||||
if config.Password == "" {
|
if config.Password == "" {
|
||||||
return errors.New("password cannot be empty")
|
return errors.New("password cannot be empty")
|
||||||
}
|
}
|
||||||
|
case DREAMHOST:
|
||||||
|
if config.LoginToken == "" {
|
||||||
|
return errors.New("login token cannot be empty")
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return errors.New("please provide supported DNS provider: DNSPod/HE/AliDNS/Cloudflare/GoogleDomain/DuckDNS")
|
return errors.New("please provide supported DNS provider: DNSPod/HE/AliDNS/Cloudflare/GoogleDomain/DuckDNS/Dreamhost")
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendNotify sends notify if IP is changed
|
// SendTelegramNotify sends notify if IP is changed
|
||||||
func SendTelegramNotify(configuration *Settings, domain, currentIP string) error {
|
func SendTelegramNotify(configuration *Settings, domain, currentIP string) error {
|
||||||
if !configuration.Notify.Telegram.Enabled {
|
if !configuration.Notify.Telegram.Enabled {
|
||||||
return nil
|
return nil
|
||||||
@ -287,7 +294,7 @@ func SendTelegramNotify(configuration *Settings, domain, currentIP string) error
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendNotify sends mail notify if IP is changed
|
// SendMailNotify sends mail notify if IP is changed
|
||||||
func SendMailNotify(configuration *Settings, domain, currentIP string) error {
|
func SendMailNotify(configuration *Settings, domain, currentIP string) error {
|
||||||
if !configuration.Notify.Mail.Enabled {
|
if !configuration.Notify.Mail.Enabled {
|
||||||
return nil
|
return nil
|
||||||
|
Loading…
x
Reference in New Issue
Block a user