吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 285|回复: 2
收起左侧

[其他原创] 【golang】namesilo域名DNS工具

[复制链接]
shuroki 发表于 2024-11-14 12:07
因软路由没有默认支持namesilo的DDNS,所以写了一个脚本工具,调用namesilo开放的api执行DNS设置.

package main

import (
    "flag"
    "fmt"
    "io"
    "log/slog"
    "net/http"
    "os"
    "path/filepath"
    "runtime"
    "strconv"

    "github.com/nrdcg/namesilo"
)

var api string

func main() {

    var domain string
    var hostname string
    var token string
    var historyFilepath string

    flag.StringVar(&domain, "domain", "", "namesilo domain")
    flag.StringVar(&hostname, "hostname", "", "namesilo dns hostname")
    flag.StringVar(&token, "token", "", "namesilo api token")
    flag.StringVar(&api,"api","https://api.ipify.org","ipv4 api")
    flag.Parse()

    switch {
    case domain == "":
        slog.Error("domain is empty")
        return
    case hostname == "":
        slog.Error("hostname is empty")
        return
    case token == "":
        slog.Error("token is empty")
        return
    }

    switch runtime.GOOS {
    case "linux":
        historyFilepath = filepath.Join("/var", "namesilo-ddns-history")
    case "windows":
        historyFilepath = filepath.Join(os.Getenv("TEMP"), "namesilo-ddns-history")
    }

    // get history ip if file exist, otherwise history ip is empty
    var history string
    _, err := os.Stat(historyFilepath)
    if !os.IsNotExist(err) {
        byt, err := os.ReadFile(historyFilepath)
        if err != nil {
            slog.Error("get history ip error", "message", err)
            return
        }
        history = string(byt)
    }

    // get ip
    ip, err := getIP()
    if err != nil {
        slog.Error("get ip error", "message", err)
        return
    }

    // IP has not changed
    if ip == history {
        slog.Info("ip has not changed")
        return
    }

    client, err := getNamesiloClient(token)
    if err != nil {
        slog.Error("get namesilo client error", "message", err)
        return
    }

    // get dns record
    records, err := client.DnsListRecords(&namesilo.DnsListRecordsParams{Domain: domain})
    if err != nil {
        slog.Error("get namesilo records error", "message", err)
        return
    }

    if records.Reply.Code != "300" {
        slog.Error("get namesilo records error", "code", records.Reply.Code, "detail", records.Reply.Detail)
        return
    }

    var record namesilo.ResourceRecord
    for _, item := range records.Reply.ResourceRecord {
        // find record
        if fmt.Sprintf("%s.%s", hostname, domain) == item.Host && item.Type == "A" {
            record = item
            break
        }
    }

    // record not found, add
    if record.RecordID == "" {

        if _, err = client.DnsAddRecord(&namesilo.DnsAddRecordParams{
            Domain:   domain,
            Type:     "A",
            Host:     hostname,
            Value:    ip,
            Distance: 0,
            TTL:      7207,
        }); err != nil {
            slog.Error("add dns record error", "message", err)
            return
        }

        if records.Reply.Code != "300" {
            slog.Error("add namesilo records error", "code", records.Reply.Code, "detail", records.Reply.Detail)
            return
        }

        slog.Info("add record success", "host", fmt.Sprintf("%s.%s", hostname, domain), "value", ip)
    } else {
        // record found, update

        distance, err := strconv.Atoi(record.Distance)
        if err != nil {
            slog.Error("distance string to integer error", "message", err)
            return
        }
        ttl, err := strconv.Atoi(record.TTL)
        if err != nil {
            slog.Error("ttl string to integer error", "message", err)
            return
        }

        if _, err = client.DnsUpdateRecord(&namesilo.DnsUpdateRecordParams{
            Domain:   domain,
            ID:       record.RecordID,
            Host:     hostname,
            Value:    ip,
            Distance: distance,
            TTL:      ttl,
        }); err != nil {
            slog.Error("update dns record error", "message", err)
            return
        }

        if records.Reply.Code != "300" {
            slog.Error("update namesilo records error", "code", records.Reply.Code, "detail", records.Reply.Detail)
            return
        }

        slog.Info("update record success", "host", fmt.Sprintf("%s.%s", hostname, domain), "value", ip)
    }

    // save ip
    err = os.WriteFile(historyFilepath, []byte(ip), 0644)
    if err != nil {
        slog.Error("ip write to temp file error", "message", err)
        return
    }

}

func getIP() (string, error) {
    resp, err := http.Get(api)
    if err != nil {
        return "", err
    }
    defer resp.Body.Close()

    if resp.StatusCode != 200 {
        return "", fmt.Errorf("http response status code [%d] is not 200", resp.StatusCode)
    }

    body, err := io.ReadAll(resp.Body)
    if err != nil {
        return "", err
    }

    return string(body), nil
}

func getNamesiloClient(token string) (client *namesilo.Client, err error) {
    transport, err := namesilo.NewTokenTransport(token)
    if err != nil {
        return
    }

    client = namesilo.NewClient(transport.Client())
    return
}



使用方法  
./namesilo-ddns --domain="域名" --hostname="dns映射地址" --token="namesilo的令牌" --api="获取IPv4的api地址"


token需要到namesilo账号处获取, api地址有默认的地址https://api.ipify.org, 若不可用需要输入参数


namesilo-ddns-linux-arm.zip (1.92 MB, 下载次数: 0)
namesilo-ddns-linux-amd64.zip (2.11 MB, 下载次数: 0)
namesilo-ddns-windows.zip (2.14 MB, 下载次数: 16)

免费评分

参与人数 2吾爱币 +7 热心值 +2 收起 理由
苏紫方璇 + 7 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
MapicAR + 1 谢谢@Thanks!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

jun269 发表于 2024-11-14 14:00
路过,软件太专业,我外行用不上。
zl1100 发表于 2024-11-14 17:56
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-24 07:13

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表