最近网络环境趋紧,流行的几个DDNS要么要实名认证,要么直接就不能免费使用,很烦。一个很简单的东西,天朝居然都要搞得这么复杂,最近无聊顺手些了一个,用GoLang实现动态域名解析。

大概的流程

   1,通过调用一个远程网站,获得本地的公网IP

   2,确认域名的指向与1获得的IP是否一致,如果一致就不继续,如果不一致前进到3

   3,通过调用GoDaddy的API重置特定域名的IP指向。

每隔30分钟,循环上述流程,实现DDNS

废话不多说,直接上代码

package main

import (
        "fmt"
        "net/http"
        "net"
        "time"
        "os"
        "io/ioutil"
        "strings"
)


func main() {
    const TIME_INTERVAL int = 30*60
    const DOMAIN_NAME string = "DomainName"
    const DOMAIN_SUBNAME string = "subDomain"
    const DOMAIN_TYPE string = "A"
    const DOMAIN_TTL int = 900
    const GoDaddy_Key string = "KEY"
    const GoDaddy_Sec string = "SEC"

    fmt.Println("Starting the application...")
    for true  {
        ip1 :=   getPublicIP()
        ip2 :=   getDNSRecordIP(DOMAIN_SUBNAME + "." + DOMAIN_NAME)
        // ip2 = "0.0.0.0"
        fmt.Println("PublicIP : " + ip1)
        fmt.Println("DNSRecord : " + DOMAIN_SUBNAME + "." + DOMAIN_NAME + ":" + ip2)
        if ip1 == ip2 {
            fmt.Println("No Need For Update Domian Record ")
            time.Sleep(time.Duration(TIME_INTERVAL) * time.Second)
            continue
        }else{
            fmt.Print("Ready To Update Domian Record ...")

        }
        setDNSRecordIP(ip1,DOMAIN_TTL,DOMAIN_NAME,DOMAIN_TYPE,DOMAIN_SUBNAME,GoDaddy_Key,GoDaddy_Sec)
        time.Sleep(time.Duration(TIME_INTERVAL) * time.Second)
    }
}

func getPublicIP() string {
    var ip = "0.0.0.0"
    response, err := http.Get("http://ipv4.icanhazip.com/")
    if err != nil {
        fmt.Printf("The HTTP request failed with error %s\n", err)
    } else {
        data, _ := ioutil.ReadAll(response.Body)
        ip = string(data)
       
    }
    return strings.TrimSpace(ip)
}

func getDNSRecordIP(domainName string) string {
    var ip = "0.0.0.0"  domain := domainName  ipAddr, err := net.ResolveIPAddr("ip", domain)  if err != nil {  fmt.Fprintf(os.Stderr, "Err: %s", err.Error())  return ip  }  ip = ipAddr.IP.String()
//  fmt.Println(ip)
    return strings.TrimSpace(ip)
}

func setDNSRecordIP(ip string, ttl int, domain string, domainType string, name string, key string, sec string) {
    url := fmt.Sprintf("https://api.godaddy.com/v1/domains/%s/records/%s/%s",domain,domainType,name)
    data :=fmt.Sprintf("[{ \"data\": \"%s\", \"ttl\": %v, \"priority\": 0, \"weight\": 1 }]",ip,ttl)
    //生成client 参数为默认
    client := &http.Client{}
    //提交请求
    reqest, err := http.NewRequest("PUT", url, strings.NewReader(data))
    if err != nil {
        panic(err)
    }
    reqest.Header.Add("content-type", "application/json")
    reqest.Header.Add("Accept", "application/json")
    ssokey :=fmt.Sprintf("sso-key %s:%s",key,sec)
    reqest.Header.Add("Authorization", ssokey)
    //处理返回结果
    response, _ := client.Do(reqest)
   //返回的状态码
    status := response.StatusCode
    if status == 200 {
        fmt.Println("Done!")
    }else{
        fmt.Print(status)
        fmt.Println(" Error Hapened!")
    }
    
}  

因为无聊,所以上述代码又通过Python实现了一个遍,熟悉下Go和Python的语法,作为Java和微软系的程序猿。。。嘿嘿

#!/usr/bin/python
# -*- coding: UTF-8 -*-
# 本地动态获得公网IP并且重置Godaddy域名设定的例子
import os, socket
# pip install requests
import requests

args = {
  "DomainName":"DomainName",
  "DomainType":"A",
  "DomainApikey":"KEY",
  "DomainApiSec":"SEC",
  "TTL":3600
}


# 处理主函数
def main():
  # 获取当前域名指向IP
  # default_ip = socket.gethostbyname('sz-ming.com')
  default_ip = socket.gethostbyname(args["DomainName"])
  print "当前指向IP : " + default_ip
  # 测试用
  default_ip = "127.0.0.1"
  
  ip = "127.0.0.1"
  # 获取本地的IP地址
  try:
    f = requests.get('http://ipv4.icanhazip.com/')
    ip = f.text.strip()
    print "获得公网IP : " + ip.encode('utf-8') 
  #   args.ip = resp.strip()
  except Exception,err:
    print 1,err
  
  # 区分处理
  if default_ip == ip:
    print "无需处理,直接退出"
    # 直接退出
    os._exit(0)
  else:
    print "正在重新设定域名指向"
  
  
  hostnames = args["DomainName"].split('.')
  
  # 通过API重新设定
  url = 'https://api.godaddy.com/v1/domains/{}/records/{}/{}'.format('.'.join(hostnames[1:]),args["DomainType"],hostnames[0])
  print url
  data ='[{ "data": "' + ip + '", "ttl": 3600, "priority": 0, "weight": 1 }]'
  print data
  headers = {
      'content-type': 'application/json',
      "Accept":"application/json",
      "Authorization": "sso-key {}:{}".format(args["DomainApikey"],args["DomainApiSec"])
  }
  try:
    req = requests.put(url, data=data,headers=headers)
    print "动态设定完成!"
    print req.text
  except Exception,err:
      print 1,err

# 主函数调用
if __name__ == '__main__':
  main()
最后修改日期: 2022年6月13日

作者