golang实现请求cloudflare修改域名A记录解析
现在有些DNS解析要收费,国内的几个厂商需要实名制。下面给出golang请求cloudflare修改域名A记录解析的代码。
准备工作:
- 在域名购买服务商处,将dns解析服务器改为cloudflare的dns服务器地址
- 将域名添加到cloudflare后台,非cloudflare购买的域名也可以添加!
- cloudflare后台获取API KEY;获取区域ID,即代码中用到的zone id ; 代码中需要用到
- 在后台先为域名设置一条A记录,设置“仅限DNS”
如果准备工作不知道操作的,搜索其他博客,或者在B站搜索,都有教程。
示例代码实现的功能:从wan口获取公网ip地址,与当前dns记录比较,如果相同则不请求接口修改A记录,不同则请求接口。wan获取ip用正则实现,可以根据实际情况修改代码。
package main
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"os"
"os/exec"
"path/filepath"
"regexp"
)
// 响应体的json中有其他字段,此处只定义需要的字段
type GetDnsRecords struct {
Result []Result `json:"result"`
Success bool `json:"success"`
}
type PutDnsRecordResponse struct {
Result Result `json:"result"`
Errors interface{} `json:"errors"`
Success bool `json:"success"`
}
// 单条dns记录
type Result struct {
// dns 记录后台的ID
Id string `json:"id"`
// 一级域名,例如:fuck.com
ZoneName string `json:"zone_name"`
// 具体被解析的域名, 例如:y.fuck.com
Name string `json:"name"`
// 解析到的内容,可能是IP
Content string `json:"content"`
// 解析类型,例如:A
Type string `json:"type"`
}
type PutDns struct {
Type string `json:"type"`
Name string `json:"name"`
Content string `json:"content"`
Proxied bool `json:"proxied"`
}
func main() {
// 需要解析的域名、cloudflare api key、zone id 写到环境变量
domain := os.Getenv("CLOUDFLARE_DOMAIN")
apiKey := os.Getenv("CLOUDFLARE_API_KEY")
zoneId := os.Getenv("CLOUDFLARE_ZONE_ID")
recordId, lastIp, err := getDnsRecordId(apiKey, zoneId, domain)
if err != nil {
fmt.Println("getDnsRecordId err", err)
return
}
dnsType := "A"
proxied := false
// 从网口获取IP
nowIp := getLocalIP()
if nowIp != lastIp {
_, er := putDnsRecord(zoneId, apiKey, recordId, dnsType, domain, nowIp, proxied)
if er == nil {
fmt.Println("putDnsRecord success ", "lastIp: ", lastIp, "nowIp: ", nowIp)
return
} else {
fmt.Println("putDnsRecord err", er)
return
}
} else {
fmt.Println("ip no change ", "lastIp: ", lastIp, "nowIp: ", nowIp)
return
}
}
// 执行shell,获取wan口信息正则匹配ip
func getLocalIP() (ip string) {
commandStr := "ifconfig pppoe-wan"
cmd := exec.Command("/bin/bash", "-c", commandStr)
stdout, _ := cmd.StdoutPipe()
if err := cmd.Start(); err != nil {
return ""
}
outBytes, _ := ioutil.ReadAll(stdout)
stdout.Close()
if err := cmd.Wait(); err != nil {
fmt.Println("Execute failed when Wait:" + err.Error())
return ""
}
ifconfig := string(outBytes)
pattern := `inet addr:(\d+\.\d+\.\d+\.\d+)`
reg := regexp.MustCompile(pattern)
match := reg.FindString(ifconfig)
if match != "" {
pattern = `\d+\.\d+\.\d+\.\d+`
reg = regexp.MustCompile(pattern)
return reg.FindString(match)
}
return
}
// 获取DNS记录ID
func getDnsRecordId(apiKey string, zoneId string, domain string ) (recordId string, lastContent string, e error) {
api := "https://api.cloudflare.com/client/v4/zones/%s/dns_records"
api = fmt.Sprintf(api, zoneId)
requestHeader := map[string]string{
// Bearer后有1空格
"Authorization" : "Bearer " + apiKey,
}
code, resBody, _, er := JsonCurl("GET", api, nil, requestHeader)
if er != nil {
e = er
return
}
var dnsRecords GetDnsRecords
err := json.Unmarshal(resBody, &dnsRecords)
if code!= 200 || err != nil || dnsRecords.Success != true {
e = err
return
}
for _, value := range dnsRecords.Result {
if value.Name == domain {
recordId = value.Id
lastContent = value.Content
return
}
}
return
}
/*
* @Description: 修改dns
* @param dnsType string A记录传"A"
* @param name string 具体域名
* @param content string 解析到内容例如IP
* @param proxied bool 是否代理传
* @author ""
* @date 2022-05-04 15:30:00
*/
func putDnsRecord(zoneId string, apiKey string, recordId string, dnsType string, name string, content string, proxied bool) (bool,error) {
putDns := PutDns{
Type: dnsType,
Name: name,
Content: content,
Proxied: proxied,
}
api := `https://api.cloudflare.com/client/v4/zones/%s/dns_records/%s`
api = fmt.Sprintf(api, zoneId, recordId)
requestHeader := map[string]string{
// Bearer后有1空格
"Authorization" : "Bearer " + apiKey,
}
_, resBody, _, er := JsonCurl("PUT", api, putDns, requestHeader)
if er != nil {
return false, er
}
var dnsRecords PutDnsRecordResponse
err := json.Unmarshal(resBody, &dnsRecords)
if err != nil {
// 记录日志
return false, err
}
if dnsRecords.Success != true {
return false,errors.New( fmt.Sprintf("resBody: %s, url: %s, apiKey: %s", string(resBody) , api, apiKey))
}
return true, nil
}
func JsonCurl(method, url string, body interface{}, headers map[string]string) (code int, data []byte, respHeader http.Header, error error) {
jsonStr, _ := json.Marshal(body)
buffer := bytes.NewBuffer(jsonStr)
request, err := http.NewRequest(method, url, buffer)
if err != nil {
error = err
return
}
request.Header.Set("Content-Type", "application/json;charset=UTF-8")
for key, val := range headers {
request.Header.Set(key, val)
}
resp, err := http.DefaultClient.Do(request)
defer resp.Body.Close()
if err != nil {
error = err
return
}
code = resp.StatusCode
data, _ = ioutil.ReadAll(resp.Body)
respHeader = resp.Header
return
}
func writeIpToFile(fileName string, content string) error {
f, err := os.OpenFile(fileName, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
if err != nil {
return err
} else {
n, _ := f.Seek(0, os.SEEK_END)
_, e := f.WriteAt([]byte(content), n)
defer f.Close()
if e != nil {
return e
}
}
return nil
}
golang实现请求cloudflare修改域名A记录解析的更多相关文章
- Charles系列三:Charles打断点(包含修改请求,修改返回的内容),模拟慢速网络(弱网测试),域名映射,过滤请求,接口调试,打压测试
一:Charles断点的使用(包含修改请求,修改返回的数据) 设置断点来修改请求和返回的数据,在开发过程中可以模拟多种响应.步骤如下: 1.添加断点方法有两种: 方法1:找到Charles中菜单项Pr ...
- DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录
相关学习资料 http://baike.baidu.com/link?url=77B3BYIuVsB3MpK1nOQXI-JbS-AP5MvREzSnnedU7F9_G8l_Kvbkt_O2gKqFw ...
- DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录(转)
http://www.cnblogs.com/LittleHann/p/3828927.html 相关学习资料 http://baike.baidu.com/link?url=77B3BYIuVsB3 ...
- 解释-DNS,A记录,CNAME记录,域名转向,SRV记录,TTL值,泛域名与泛解析,域名绑定
http://www.lihongye.net/post/dns.html DNS DNS,Domain Name System或者Domain Name Service(域名系统或者域名服务).域名 ...
- DNS安全浅议、域名A记录(ANAME),MX记录,CNAME记录 专题
首先要做的就是配置域名的MX 记录啦: 先添加一条A记录: mail.abc.com 指向 你的服务器IP! 然后添加域名的MX 记录,指向mail.abc.com A 记录( 即域名MX 记录的值为 ...
- salesforce 零基础学习(六十九)当新增/修改一条记录以后发生了什么(适合初学者)
salesforce开发中,我们会对object进行很多的操作,比如对object设置字段的必填性唯一性等,设置validation rule实现一下相关的字段的逻辑校验,设置workflow实现某个 ...
- cdnbest获取,删除,增加,修改域名列表,高级设置api示例
<?php $uid = 28; $vhost = 'asdfw'; $token = getToken($uid, $vhost); print_r($token); //获取token fu ...
- 修改window本地hosts文件,修改域名指向
Hosts是一个没有扩展名的系统文件,可以用记事本等工具打开,其作用就是将一些常用的网址域名与其对应的IP地址建立一个关联“数据库”,当用户在浏览器中输入一个需要登录的网址时,系统会首先自动从Host ...
- SVN如何查看修改的文件记录] 来源:Linux社区 作者:frogoscar
SVN如何查看修改的文件记录 [日期:2014-11-20] 来源:Linux社区 作者:frogoscar [字体:大 中 小] 主要是有四个命令,svn log用来展示svn 的版本作者 ...
- 修改sphinx最大输出记录数
修改sphinx最大输出记录数 归纳如下: Sphinx的查询默认最大记录数是:1000,而我们想更改这个数值.就需要更改三个地方. 1是更改sphinx.conf配置文件的:max_matches ...
随机推荐
- goalng 将字符串转化成整数后取余
package main import ( "fmt" "github.com/google/uuid" "hash/fnv" ) func ...
- 从个人角度谈为什么要使用git多分支?
今天烦死了,公司的项目没有使用多分支管理,造成给某客户的打包的代码竟然需要截取gitlab节点重新打包. 在我上家公司开发Android项目的时候,使用了非常鲜明的多分支管理,当时作为项目运维,对gi ...
- 京准GPS北斗卫星时钟同步系统投运国电内蒙古晶阳能源有限公司
京准GPS北斗卫星时钟同步系统投运国电内蒙古晶阳能源有限公司 2020年1月初期,我京准科技生产研发的GPS北斗卫星时钟同步系统投运国电内蒙古晶阳能源有限公司,为该单位的能源管理系统及其他各业务子系 ...
- Android 切换wifi小记
我手机是Android 7.1的魅族.相关网络权限注册之后,还有一个特别的权限就是<uses-permission android:name="android.permission.A ...
- js导出数据为excel表
1.接口数据后端写, 2.代码如下: var params={ "filters":[ {"propertyCode":"sequenceNo&quo ...
- 第九章:用Python处理省份城市编码数据
文章目录 项目背景 项目代码 新增省份编码 获取编码映射数据 合并数据 统计省份用户数 使用SQL实现 源码地址 本文可以学习到以下内容: 免费获取全国省份.城市编码以及经纬度数 使用 pandas ...
- python生成一个WAV文件的正弦波
import numpy as np import matplotlib.pyplot as plt T = 1.0 / sample_rate #周期 x = np.arange(0, 1.0, T ...
- 20_webpack_shimming预支全局变量和css的抽离
shimming是什么 shimming 是一个概念,是某一些功能的统称 shimming(垫片),给我们的代码填充一些垫片来处理一些问题 比如我们现在以来一个第三方的库,这个第三方的库本身依赖lod ...
- Python学习笔记(三)数据类型转换
一.输入输出函数 1.input() 输入函数,内置函数,用来获取用户输入数据,返回值为字符串 运行到此函数会阻塞或暂停程序 示例: 1 str_data = input('请输入数据:') 2 st ...
- SAP适合医疗器械行业的公司、工厂吗?
医疗器械行业在我国国民经济中发展情况良好,未来发展前景也很看好.但竞争力不强,在GMP要求下消耗大量的人力.物力是我国医疗器械企业需要面对的巨大压力,在这种情况下,企业如何充分利用网络经济和信息手段加 ...