SneakySquid icon

Cloudflare DDNS

SneakySquid | PRO | 10/28/23 01:37:03 PM UTC (Edited) | 0 ⭐ | 8446 👁️ | Never ⏰ | []
Ruby |

3.53 KB

|

None

|

0 👍

/

0 👎

require "net/https"
require "optparse"
require "json"
require "uri"
 
options = {:ttl => "3600", :records => {}}
req_headers = {"Content-Type" => "application/json"}
 
OptionParser.new do |opts|
    opts.banner = "Usage: ddns.rb -a -p -f file/path -t 3600 -r example.com"
 
    opts.on("-f", "--token TOKEN_PATH", "Absolute path of file containing a Cloudflare API token.") do |path|
        if File.file?(path) then
            if File.readable?(path) then
                cf_token = File.read(path)
                cf_token = cf_token.gsub("\s", "")
 
                req_headers["Authorization"] = "Bearer " + cf_token
            else
                warn "Token file not readable."
                exit 11
            end
        else
            warn "Failed to find token file."
            exit 10
        end
    end
 
    opts.on("-t", "--ttl TTL", "TTL") do |ttl|
        options[:ttl] = ttl
    end
 
    opts.on("-a", "--aaaa", "Update AAAA records as well as A records.") do |aaaa|
        options[:update_aaaa] = aaaa
    end
 
    opts.on("-p", "--proxy", "Enable proxy on updated DNS records.") do |proxy|
        options[:enable_proxy] = proxy
    end
 
    opts.on("-r", "--record RECORD", "Add record name to update.") do |record|
        options[:records][record] = true
    end
end.parse!
 
print "Fetching external IP... "
 
ip_res, external_ip = Net::HTTP.get_response("checkip.amazonaws.com", "/")
if ip_res.code == "200" then
    external_ip = ip_res.body.tr("\n", "")
    puts "#{external_ip}."
else
    puts "Failed."
    puts "#{ip_res.code}: #{ip_res.body}"
    exit 20
end
 
puts "Updating DDNS records."
 
zone_uri = URI.parse("https://api.cloudflare.com/client/v4/zones")
https = Net::HTTP.new(zone_uri.host, zone_uri.port)
https.use_ssl = true
 
zone_req = Net::HTTP::Get.new(zone_uri, req_headers)
zone_res = JSON.parse(https.request(zone_req).body)
 
if zone_res["success"] == true then
    puts "Found #{zone_res["result"].count()} zone(s) to update."
 
    zone_res["result"].each do |zone|
        puts "Fetching records from zone '#{zone["name"]}'."
 
        zone_id = zone["id"]
 
        record_uri = URI.parse("https://api.cloudflare.com/client/v4/zones/#{zone_id}/dns_records")
        https = Net::HTTP.new(record_uri.host, record_uri.port)
        https.use_ssl = true
 
        record_req = Net::HTTP::Get.new(record_uri, req_headers)
        record_res = JSON.parse(https.request(record_req).body)
 
        if record_res["success"] == true then
            record_res["result"].each do |record|
                record_name = record["name"]
                record_type = record["type"]
 
                if options[:records][record_name] && (record_type == "A" or (options[:update_aaaa] && record_type == "AAAA")) then
                    print "Updating record '#{record_name}'... "
 
                    if record["content"] == external_ip then
                        puts "Content doesn't need updating, skipping record."
                    else
                        update = {
                            "type" => record_type,
                            "name" => record_name,
                            "content" => external_ip,
                            "ttl" => options[:ttl],
                            "proxied" => options[:enable_proxy]
                        }
 
                        update_uri = URI.parse("https://api.cloudflare.com/client/v4/zones/#{zone_id}/dns_records/#{record["id"]}")
                        https = Net::HTTP.new(update_uri.host, update_uri.port)
                        https.use_ssl = true
 
                        update_req = Net::HTTP::Put.new(update_uri, req_headers)
                        update_req.body = update.to_json
 
                        update_res = JSON.parse(https.request(update_req).body)
 
                        if update_res["success"] == true then
                            puts "Updated successfully!"
                        else
                            puts "Update failed!"
                            pp update_res
                        end
                    end
                end
            end
        else
            puts record_res
            exit 22
        end
    end
else
    puts zone_res
    exit 21
end
 
puts "Updated DDNS records successfully."
 

Comments

  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎

    
        
  •  icon
    01/01/70 12:00:00 AM UTC
    Plain Text |

    0 B

    |

    👍

    /

    👎