mirror of
https://github.com/AmanTahiliani/cloudflare-dns-updater.git
synced 2026-08-07 11:53:08 -04:00
185 lines
4.0 KiB
Go
185 lines
4.0 KiB
Go
package main
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"log"
|
|
"net/http"
|
|
)
|
|
|
|
type IpResponse struct {
|
|
Ip string `json:"ip"`
|
|
}
|
|
|
|
type DnsRecord struct {
|
|
Id string `json:"id"`
|
|
Name string `json:"name"`
|
|
Type string `json:"type"`
|
|
Content string `json:"content"`
|
|
Ttl int `json:"ttl"`
|
|
Proxied bool `json:"proxied"`
|
|
}
|
|
|
|
type DnsRecords struct {
|
|
Result []DnsRecord `json:"result"`
|
|
}
|
|
|
|
func getIp() (string, error) {
|
|
// Get IP from ipify and return it as a IpResponse
|
|
|
|
ipUrl := "https://api.ipify.org?format=json"
|
|
resp, err := http.Get(ipUrl)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
|
|
var ipResponse IpResponse
|
|
if err := json.Unmarshal(body, &ipResponse); err != nil {
|
|
return "", err
|
|
}
|
|
return ipResponse.Ip, nil
|
|
|
|
}
|
|
|
|
type DnsUpdater struct {
|
|
config *Config
|
|
}
|
|
|
|
func (d *DnsUpdater) CheckIfRecordsExist(recordName string) (DnsRecord, error) {
|
|
cloudFlareUrl := "https://api.cloudflare.com/client/v4/zones/" + d.config.ZoneID + "/dns_records?name=" + recordName + "&type=A"
|
|
log.Printf("CloudFlare URL: %s", cloudFlareUrl)
|
|
|
|
req, err := http.NewRequest("GET", cloudFlareUrl, nil)
|
|
if err != nil {
|
|
return DnsRecord{}, err
|
|
}
|
|
req.Header.Set("X-Auth-Email", d.config.Email)
|
|
req.Header.Set("Authorization", "Bearer "+d.config.AuthKey)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return DnsRecord{}, err
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return DnsRecord{}, err
|
|
}
|
|
|
|
log.Printf("Body: %s", string(body))
|
|
|
|
var dnsRecords DnsRecords
|
|
if err := json.Unmarshal(body, &dnsRecords); err != nil {
|
|
return DnsRecord{}, err
|
|
}
|
|
log.Printf("DNS Records: %+v", dnsRecords)
|
|
|
|
// Check if the record exists
|
|
for _, record := range dnsRecords.Result {
|
|
if record.Name == recordName && record.Type == "A" {
|
|
return record, nil
|
|
}
|
|
}
|
|
return DnsRecord{}, nil
|
|
}
|
|
|
|
func (d *DnsUpdater) Update(record DnsRecord) error {
|
|
ip, err := getIp()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if d.config.ForceIP != "" {
|
|
ip = d.config.ForceIP
|
|
}
|
|
if record.Content == ip {
|
|
return nil
|
|
}
|
|
|
|
record.Content = ip
|
|
record.Ttl = 3600
|
|
|
|
cloudFlareUrl := "https://api.cloudflare.com/client/v4/zones/" + d.config.ZoneID + "/dns_records/" + record.Id
|
|
|
|
body, err := json.Marshal(record)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req, err := http.NewRequest("PATCH", cloudFlareUrl, bytes.NewBuffer(body))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Header.Set("X-Auth-Email", d.config.Email)
|
|
req.Header.Set("Authorization", "Bearer "+d.config.AuthKey)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err = io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
return fmt.Errorf("failed to update DNS: %s", string(body))
|
|
}
|
|
log.Printf("Updated DNS: %s", string(body))
|
|
return nil
|
|
}
|
|
|
|
func (d *DnsUpdater) Create(recordName string) error {
|
|
ip, err := getIp()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if d.config.ForceIP != "" {
|
|
ip = d.config.ForceIP
|
|
}
|
|
record := DnsRecord{
|
|
Name: recordName,
|
|
Type: "A",
|
|
Content: ip,
|
|
Ttl: 3600,
|
|
Proxied: false,
|
|
}
|
|
|
|
cloudFlareUrl := "https://api.cloudflare.com/client/v4/zones/" + d.config.ZoneID + "/dns_records"
|
|
|
|
body, err := json.Marshal(record)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
req, err := http.NewRequest("POST", cloudFlareUrl, bytes.NewBuffer(body))
|
|
if err != nil {
|
|
return err
|
|
}
|
|
req.Header.Set("X-Auth-Email", d.config.Email)
|
|
req.Header.Set("Authorization", "Bearer "+d.config.AuthKey)
|
|
req.Header.Set("Content-Type", "application/json")
|
|
|
|
resp, err := http.DefaultClient.Do(req)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
defer resp.Body.Close()
|
|
body, err = io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if resp.StatusCode != 200 {
|
|
return fmt.Errorf("failed to create DNS: %s", string(body))
|
|
}
|
|
log.Printf("Created DNS: %s", string(body))
|
|
return nil
|
|
}
|