-
-
Notifications
You must be signed in to change notification settings - Fork 228
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
Showing
9 changed files
with
287 additions
and
13 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
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,157 @@ | ||
package alidns | ||
|
||
import ( | ||
"crypto/hmac" | ||
"crypto/sha1" | ||
"encoding/base64" | ||
"encoding/json" | ||
"fmt" | ||
"io/ioutil" | ||
"math/rand" | ||
"net/http" | ||
"net/url" | ||
"sort" | ||
"strconv" | ||
"strings" | ||
"sync" | ||
"time" | ||
) | ||
|
||
// AliDNS token | ||
type AliDNS struct { | ||
AccessKeyID string | ||
AccessKeySecret string | ||
} | ||
|
||
var ( | ||
publicParm = map[string]string{ | ||
"AccessKeyId": "", | ||
"Format": "JSON", | ||
"Version": "2015-01-09", | ||
"SignatureMethod": "HMAC-SHA1", | ||
"Timestamp": "", | ||
"SignatureVersion": "1.0", | ||
"SignatureNonce": "", | ||
} | ||
baseURL = "http://alidns.aliyuncs.com/" | ||
instance *AliDNS | ||
once sync.Once | ||
) | ||
|
||
type domainRecordsResp struct { | ||
RequestID string `json:"RequestId"` | ||
TotalCount int | ||
PageNumber int | ||
PageSize int | ||
DomainRecords domainRecords | ||
} | ||
|
||
type domainRecords struct { | ||
Record []DomainRecord | ||
} | ||
|
||
// DomainRecord struct | ||
type DomainRecord struct { | ||
DomainName string | ||
RecordID string `json:"RecordId"` | ||
RR string | ||
Type string | ||
Value string | ||
Line string | ||
Priority int | ||
TTL int | ||
Status string | ||
Locked bool | ||
} | ||
|
||
func getHTTPBody(url string) ([]byte, error) { | ||
resp, err := http.Get(url) | ||
if err != nil { | ||
return nil, err | ||
} | ||
body, err := ioutil.ReadAll(resp.Body) | ||
if resp.StatusCode == http.StatusOK { | ||
return body, err | ||
} | ||
return nil, fmt.Errorf("Status %d, Error:%s", resp.StatusCode, body) | ||
} | ||
|
||
func NewAliDNS(key, secret string) *AliDNS { | ||
once.Do(func() { | ||
instance = &AliDNS{ | ||
AccessKeyID: key, | ||
AccessKeySecret: secret, | ||
} | ||
}) | ||
return instance | ||
} | ||
|
||
// GetDomainRecords gets all the doamin records according to input subdomain key | ||
func (d *AliDNS) GetDomainRecords(domain, rr string) []DomainRecord { | ||
resp := &domainRecordsResp{} | ||
parms := map[string]string{ | ||
"Action": "DescribeDomainRecords", | ||
"DomainName": domain, | ||
"RRKeyWord": rr, | ||
} | ||
urlPath := d.genRequestURL(parms) | ||
body, err := getHTTPBody(urlPath) | ||
if err != nil { | ||
fmt.Printf("GetDomainRecords error.%+v\n", err) | ||
} else { | ||
json.Unmarshal(body, resp) | ||
return resp.DomainRecords.Record | ||
} | ||
return nil | ||
} | ||
|
||
// UpdateDomainRecord updates domain record | ||
func (d *AliDNS) UpdateDomainRecord(r DomainRecord) error { | ||
parms := map[string]string{ | ||
"Action": "UpdateDomainRecord", | ||
"RecordId": r.RecordID, | ||
"RR": r.RR, | ||
"Type": r.Type, | ||
"Value": r.Value, | ||
"TTL": strconv.Itoa(r.TTL), | ||
"Line": r.Line, | ||
} | ||
|
||
urlPath := d.genRequestURL(parms) | ||
_, err := getHTTPBody(urlPath) | ||
if err != nil { | ||
fmt.Printf("UpdateDomainRecord error.%+v\n", err) | ||
} | ||
return err | ||
} | ||
|
||
func (d *AliDNS) genRequestURL(parms map[string]string) string { | ||
pArr := []string{} | ||
ps := map[string]string{} | ||
for k, v := range publicParm { | ||
ps[k] = v | ||
} | ||
for k, v := range parms { | ||
ps[k] = v | ||
} | ||
now := time.Now().UTC() | ||
ps["AccessKeyId"] = d.AccessKeyID | ||
ps["SignatureNonce"] = strconv.Itoa(int(now.UnixNano()) + rand.Intn(99999)) | ||
ps["Timestamp"] = now.Format("2006-01-02T15:04:05Z") | ||
|
||
for k, v := range ps { | ||
pArr = append(pArr, fmt.Sprintf("%s=%s", k, v)) | ||
} | ||
sort.Strings(pArr) | ||
path := strings.Join(pArr, "&") | ||
|
||
s := "GET&%2F&" + url.QueryEscape(path) | ||
s = strings.Replace(s, "%3A", "%253A", -1) | ||
s = strings.Replace(s, "%40", "%2540", -1) | ||
s = strings.Replace(s, "%2A", "%252A", -1) | ||
mac := hmac.New(sha1.New, []byte(d.AccessKeySecret+"&")) | ||
|
||
mac.Write([]byte(s)) | ||
sign := base64.StdEncoding.EncodeToString(mac.Sum(nil)) | ||
return fmt.Sprintf("%s?%s&Signature=%s", baseURL, path, url.QueryEscape(sign)) | ||
} |
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,77 @@ | ||
package alidns | ||
|
||
import ( | ||
"fmt" | ||
"log" | ||
"runtime/debug" | ||
"time" | ||
|
||
"github.com/TimothyYe/godns" | ||
) | ||
|
||
// AliDNSHandler struct | ||
type AliDNSHandler struct { | ||
Configuration *godns.Settings | ||
} | ||
|
||
// SetConfiguration pass dns settings and store it to handler instance | ||
func (handler *AliDNSHandler) SetConfiguration(conf *godns.Settings) { | ||
handler.Configuration = conf | ||
} | ||
|
||
// DomainLoop the main logic loop | ||
func (handler *AliDNSHandler) 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 | ||
} | ||
}() | ||
|
||
var lastIP string | ||
aliDNS := NewAliDNS(handler.Configuration.Email, handler.Configuration.Password) | ||
|
||
for { | ||
currentIP, err := godns.GetCurrentIP(handler.Configuration) | ||
|
||
if err != nil { | ||
log.Println("Failed to get current IP:", err) | ||
continue | ||
} | ||
log.Println("currentIP is:", currentIP) | ||
|
||
//check against locally cached IP, if no change, skip update | ||
if currentIP == lastIP { | ||
log.Printf("IP is the same as cached one. Skip update.\n") | ||
} else { | ||
lastIP = currentIP | ||
|
||
for _, subDomain := range domain.SubDomains { | ||
log.Printf("%s.%s Start to update record IP...\n", subDomain, domain.DomainName) | ||
records := aliDNS.GetDomainRecords(domain.DomainName, subDomain) | ||
if records == nil || len(records) == 0 { | ||
log.Printf("Cannot get subdomain %s from AliDNS.\r\n", subDomain) | ||
continue | ||
} | ||
|
||
records[0].Value = currentIP | ||
if err := aliDNS.UpdateDomainRecord(records[0]); err != nil { | ||
log.Printf("Failed to update IP for subdomain:%s\r\n", subDomain) | ||
continue | ||
} else { | ||
log.Printf("IP updated for subdomain:%s\r\n", subDomain) | ||
} | ||
|
||
// Send mail notification if notify is enabled | ||
if handler.Configuration.Notify.Enabled { | ||
log.Print("Sending notification to:", handler.Configuration.Notify.SendTo) | ||
godns.SendNotify(handler.Configuration, fmt.Sprintf("%s.%s", subDomain, domain.DomainName), currentIP) | ||
} | ||
} | ||
} | ||
// Interval is 5 minutes | ||
log.Printf("Going to sleep, will start next checking in %d minutes...\r\n", godns.INTERVAL) | ||
time.Sleep(time.Minute * godns.INTERVAL) | ||
} | ||
|
||
} |
2 changes: 1 addition & 1 deletion
2
handler/cloudflare_handler.go → handler/cloudflare/cloudflare_handler.go
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package handler | ||
package cloudflare | ||
|
||
import ( | ||
"bytes" | ||
|
2 changes: 1 addition & 1 deletion
2
handler/cloudflare_handler_test.go → ...ler/cloudflare/cloudflare_handler_test.go
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package handler | ||
package cloudflare | ||
|
||
import ( | ||
"encoding/json" | ||
|
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
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
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 |
---|---|---|
@@ -1,4 +1,4 @@ | ||
package handler | ||
package he | ||
|
||
import ( | ||
"fmt" | ||
|
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