Skip to content

Commit 6836982

Browse files
suguerdsuzejian
andauthored
fix: nowcn,eranet,更换接口路径 (#1520)
* fix: v1接口会收到ip白名单限制,改用v2接口 * remove: 去掉打印测试 --------- Co-authored-by: dsuzejian <[email protected]>
1 parent 9ad1065 commit 6836982

File tree

3 files changed

+282
-118
lines changed

3 files changed

+282
-118
lines changed

dns/eranet.go

Lines changed: 134 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
11
package dns
22

33
import (
4+
"crypto/hmac"
5+
"crypto/sha1"
6+
"encoding/base64"
7+
"encoding/json"
48
"fmt"
9+
"io"
10+
"net/http"
511
"net/url"
12+
"sort"
613
"strconv"
714
"strings"
15+
"time"
816

917
"github.com/jeessy2/ddns-go/v6/config"
1018
"github.com/jeessy2/ddns-go/v6/util"
1119
)
1220

13-
const (
14-
eranetRecordListAPI string = "http://api.eranet.com:2080/api/dns/describe-record-index.json"
15-
eranetRecordModifyURL string = "http://api.eranet.com:2080/api/dns/update-domain-record.json"
16-
eranetRecordCreateAPI string = "http://api.eranet.com:2080/api/dns/add-domain-record.json"
17-
)
18-
19-
// https://partner.tnet.hk/adminCN/mode_Http_Api_detail.php
2021
// Eranet DNS实现
2122
type Eranet struct {
2223
DNS config.DNS
@@ -36,11 +37,11 @@ type EranetRecord struct {
3637
}
3738

3839
type EranetRecordListResp struct {
39-
EranetStatus
40+
EranetBaseResult
4041
Data []EranetRecord
4142
}
4243

43-
type EranetStatus struct {
44+
type EranetBaseResult struct {
4445
RequestId string `json:"RequestId"`
4546
Id int `json:"Id"`
4647
Error string `json:"error"`
@@ -104,22 +105,28 @@ func (eranet *Eranet) addUpdateDomainRecords(recordType string) {
104105

105106
// create 创建DNS记录
106107
func (eranet *Eranet) create(domain *config.Domain, recordType string, ipAddr string) {
107-
param := map[string]any{
108+
param := map[string]string{
108109
"Domain": domain.DomainName,
109110
"Host": domain.GetSubDomain(),
110111
"Type": recordType,
111112
"Value": ipAddr,
112113
"Ttl": eranet.TTL,
113114
}
114-
res, err := eranet.request(eranetRecordCreateAPI, param)
115+
res, err := eranet.request("/api/Dns/AddDomainRecord", param, "GET")
115116
if err != nil {
116117
util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, err.Error())
117118
domain.UpdateStatus = config.UpdatedFailed
118-
} else if res.Error != "" {
119-
util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, res.Error)
119+
}
120+
var result NowcnBaseResult
121+
err = json.Unmarshal(res, &result)
122+
if err != nil {
123+
util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, err.Error())
124+
domain.UpdateStatus = config.UpdatedFailed
125+
}
126+
if result.Error != "" {
127+
util.Log("新增域名解析 %s 失败! 异常信息: %s", domain, result.Error)
120128
domain.UpdateStatus = config.UpdatedFailed
121129
} else {
122-
util.Log("新增域名解析 %s 成功! IP: %s", domain, ipAddr)
123130
domain.UpdateStatus = config.UpdatedSuccess
124131
}
125132
}
@@ -131,64 +138,43 @@ func (eranet *Eranet) modify(record EranetRecord, domain *config.Domain, recordT
131138
util.Log("你的IP %s 没有变化, 域名 %s", ipAddr, domain)
132139
return
133140
}
134-
param := map[string]any{
135-
"Id": record.ID,
141+
param := map[string]string{
142+
"Id": strconv.Itoa(record.ID),
136143
"Domain": domain.DomainName,
137144
"Host": domain.GetSubDomain(),
138145
"Type": recordType,
139146
"Value": ipAddr,
140147
"Ttl": eranet.TTL,
141148
}
142-
res, err := eranet.request(eranetRecordModifyURL, param)
149+
res, err := eranet.request("/api/Dns/UpdateDomainRecord", param, "GET")
143150
if err != nil {
144151
util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err.Error())
145152
domain.UpdateStatus = config.UpdatedFailed
146-
} else if res.Error != "" {
147-
util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, res.Error)
153+
}
154+
var result NowcnBaseResult
155+
err = json.Unmarshal(res, &result)
156+
if err != nil {
157+
util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, err.Error())
158+
domain.UpdateStatus = config.UpdatedFailed
159+
}
160+
if result.Error != "" {
161+
util.Log("更新域名解析 %s 失败! 异常信息: %s", domain, result.Error)
148162
domain.UpdateStatus = config.UpdatedFailed
149163
} else {
150164
util.Log("更新域名解析 %s 成功! IP: %s", domain, ipAddr)
151165
domain.UpdateStatus = config.UpdatedSuccess
152166
}
153167
}
154168

155-
// request 发送HTTP请求
156-
func (eranet *Eranet) request(apiAddr string, param map[string]any) (status EranetStatus, err error) {
157-
param["auth-userid"] = eranet.DNS.ID
158-
param["api-key"] = eranet.DNS.Secret
159-
160-
fullURL := apiAddr + "?" + eranet.queryParams(param)
161-
client := util.CreateHTTPClient()
162-
resp, err := client.Get(fullURL)
163-
164-
// 处理响应
165-
err = util.GetHTTPResponse(resp, err, &status)
166-
167-
return
168-
}
169-
170169
// getRecordList 获取域名记录列表
171170
func (eranet *Eranet) getRecordList(domain *config.Domain, typ string) (result EranetRecordListResp, err error) {
172-
param := map[string]any{
173-
"Domain": domain.DomainName,
174-
"auth-userid": eranet.DNS.ID,
175-
"api-key": eranet.DNS.Secret,
176-
}
177-
fullURL := eranetRecordListAPI + "?" + eranet.queryParams(param)
178-
client := util.CreateHTTPClient()
179-
resp, err := client.Get(fullURL)
180-
var response EranetRecordListResp
181-
result = EranetRecordListResp{
182-
Data: make([]EranetRecord, 0),
183-
}
184-
err = util.GetHTTPResponse(resp, err, &response)
185-
for _, v := range response.Data {
186-
if v.Host == domain.GetSubDomain() {
187-
result.Data = append(result.Data, v)
188-
break
189-
}
190-
171+
param := map[string]string{
172+
"Domain": domain.DomainName,
173+
"Type": typ,
174+
"Host": domain.GetSubDomain(),
191175
}
176+
res, err := eranet.request("/api/Dns/DescribeRecordIndex", param, "GET")
177+
err = json.Unmarshal(res, &result)
192178
return
193179
}
194180

@@ -205,3 +191,98 @@ func (eranet *Eranet) queryParams(param map[string]any) string {
205191
}
206192
return strings.Join(queryParams, "&")
207193
}
194+
195+
func (t *Eranet) sign(params map[string]string, method string) (string, error) {
196+
// 添加公共参数
197+
params["AccessKeyID"] = t.DNS.ID
198+
params["SignatureMethod"] = "HMAC-SHA1"
199+
params["SignatureNonce"] = fmt.Sprintf("%d", time.Now().UnixNano())
200+
params["Timestamp"] = time.Now().UTC().Format("2006-01-02T15:04:05Z")
201+
202+
// 1. 排序参数(按首字母顺序)
203+
var keys []string
204+
for k := range params {
205+
if k != "Signature" { // 排除Signature参数
206+
keys = append(keys, k)
207+
}
208+
}
209+
sort.Strings(keys)
210+
211+
// 2. 构造规范化请求字符串
212+
var canonicalizedQuery []string
213+
for _, k := range keys {
214+
// URL编码参数名和参数值
215+
encodedKey := util.PercentEncode(k)
216+
encodedValue := util.PercentEncode(params[k])
217+
canonicalizedQuery = append(canonicalizedQuery, encodedKey+"="+encodedValue)
218+
}
219+
canonicalizedQueryString := strings.Join(canonicalizedQuery, "&")
220+
221+
// 3. 构造待签名字符串
222+
stringToSign := method + "&" + util.PercentEncode("/") + "&" + util.PercentEncode(canonicalizedQueryString)
223+
224+
// 4. 计算HMAC-SHA1签名
225+
key := t.DNS.Secret + "&"
226+
h := hmac.New(sha1.New, []byte(key))
227+
h.Write([]byte(stringToSign))
228+
signature := base64.StdEncoding.EncodeToString(h.Sum(nil))
229+
230+
// 5. 添加签名到参数中
231+
params["Signature"] = signature
232+
233+
// 6. 重新构造最终的查询字符串(包含签名)
234+
keys = append(keys, "Signature")
235+
sort.Strings(keys)
236+
var finalQuery []string
237+
for _, k := range keys {
238+
encodedKey := util.PercentEncode(k)
239+
encodedValue := util.PercentEncode(params[k])
240+
finalQuery = append(finalQuery, encodedKey+"="+encodedValue)
241+
}
242+
243+
return strings.Join(finalQuery, "&"), nil
244+
}
245+
246+
func (t *Eranet) request(apiPath string, params map[string]string, method string) ([]byte, error) {
247+
// 生成签名
248+
queryString, err := t.sign(params, method)
249+
if err != nil {
250+
return nil, fmt.Errorf("生成签名失败: %v", err)
251+
}
252+
253+
// 构造完整URL
254+
baseURL := "https://www.eranet.com"
255+
fullURL := baseURL + apiPath + "?" + queryString
256+
257+
// 创建HTTP请求
258+
req, err := http.NewRequest(method, fullURL, nil)
259+
if err != nil {
260+
return nil, fmt.Errorf("创建请求失败: %v", err)
261+
}
262+
263+
// 设置请求头
264+
req.Header.Set("Accept", "application/json")
265+
266+
// 发送请求
267+
client := &http.Client{
268+
Timeout: 30 * time.Second,
269+
}
270+
resp, err := client.Do(req)
271+
if err != nil {
272+
return nil, fmt.Errorf("请求失败: %v", err)
273+
}
274+
defer resp.Body.Close()
275+
276+
// 读取响应
277+
body, err := io.ReadAll(resp.Body)
278+
if err != nil {
279+
return nil, fmt.Errorf("读取响应失败: %v", err)
280+
}
281+
282+
// 检查HTTP状态码
283+
if resp.StatusCode != http.StatusOK {
284+
return nil, fmt.Errorf("API请求失败,状态码: %d, 响应: %s", resp.StatusCode, string(body))
285+
}
286+
287+
return body, nil
288+
}

0 commit comments

Comments
 (0)