Advertisement
SneakySquid

Cloudflare DDNS

Apr 2nd, 2023 (edited)
1,293
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Ruby 3.53 KB | None | 0 0
  1. require "net/https"
  2. require "optparse"
  3. require "json"
  4. require "uri"
  5.  
  6. options = {:ttl => "3600", :records => {}}
  7. req_headers = {"Content-Type" => "application/json"}
  8.  
  9. OptionParser.new do |opts|
  10.     opts.banner = "Usage: ddns.rb -a -p -f file/path -t 3600 -r example.com"
  11.  
  12.     opts.on("-f", "--token TOKEN_PATH", "Absolute path of file containing a Cloudflare API token.") do |path|
  13.         if File.file?(path) then
  14.             if File.readable?(path) then
  15.                 cf_token = File.read(path)
  16.                 cf_token = cf_token.gsub("\s", "")
  17.  
  18.                 req_headers["Authorization"] = "Bearer " + cf_token
  19.             else
  20.                 warn "Token file not readable."
  21.                 exit 11
  22.             end
  23.         else
  24.             warn "Failed to find token file."
  25.             exit 10
  26.         end
  27.     end
  28.  
  29.     opts.on("-t", "--ttl TTL", "TTL") do |ttl|
  30.         options[:ttl] = ttl
  31.     end
  32.  
  33.     opts.on("-a", "--aaaa", "Update AAAA records as well as A records.") do |aaaa|
  34.         options[:update_aaaa] = aaaa
  35.     end
  36.  
  37.     opts.on("-p", "--proxy", "Enable proxy on updated DNS records.") do |proxy|
  38.         options[:enable_proxy] = proxy
  39.     end
  40.  
  41.     opts.on("-r", "--record RECORD", "Add record name to update.") do |record|
  42.         options[:records][record] = true
  43.     end
  44. end.parse!
  45.  
  46. print "Fetching external IP... "
  47.  
  48. ip_res, external_ip = Net::HTTP.get_response("checkip.amazonaws.com", "/")
  49. if ip_res.code == "200" then
  50.     external_ip = ip_res.body.tr("\n", "")
  51.     puts "#{external_ip}."
  52. else
  53.     puts "Failed."
  54.     puts "#{ip_res.code}: #{ip_res.body}"
  55.     exit 20
  56. end
  57.  
  58. puts "Updating DDNS records."
  59.  
  60. zone_uri = URI.parse("https://api.cloudflare.com/client/v4/zones")
  61. https = Net::HTTP.new(zone_uri.host, zone_uri.port)
  62. https.use_ssl = true
  63.  
  64. zone_req = Net::HTTP::Get.new(zone_uri, req_headers)
  65. zone_res = JSON.parse(https.request(zone_req).body)
  66.  
  67. if zone_res["success"] == true then
  68.     puts "Found #{zone_res["result"].count()} zone(s) to update."
  69.  
  70.     zone_res["result"].each do |zone|
  71.         puts "Fetching records from zone '#{zone["name"]}'."
  72.  
  73.         zone_id = zone["id"]
  74.  
  75.         record_uri = URI.parse("https://api.cloudflare.com/client/v4/zones/#{zone_id}/dns_records")
  76.         https = Net::HTTP.new(record_uri.host, record_uri.port)
  77.         https.use_ssl = true
  78.  
  79.         record_req = Net::HTTP::Get.new(record_uri, req_headers)
  80.         record_res = JSON.parse(https.request(record_req).body)
  81.  
  82.         if record_res["success"] == true then
  83.             record_res["result"].each do |record|
  84.                 record_name = record["name"]
  85.                 record_type = record["type"]
  86.  
  87.                 if options[:records][record_name] && (record_type == "A" or (options[:update_aaaa] && record_type == "AAAA")) then
  88.                     print "Updating record '#{record_name}'... "
  89.  
  90.                     if record["content"] == external_ip then
  91.                         puts "Content doesn't need updating, skipping record."
  92.                     else
  93.                         update = {
  94.                             "type" => record_type,
  95.                             "name" => record_name,
  96.                             "content" => external_ip,
  97.                             "ttl" => options[:ttl],
  98.                             "proxied" => options[:enable_proxy]
  99.                         }
  100.  
  101.                         update_uri = URI.parse("https://api.cloudflare.com/client/v4/zones/#{zone_id}/dns_records/#{record["id"]}")
  102.                         https = Net::HTTP.new(update_uri.host, update_uri.port)
  103.                         https.use_ssl = true
  104.  
  105.                         update_req = Net::HTTP::Put.new(update_uri, req_headers)
  106.                         update_req.body = update.to_json
  107.  
  108.                         update_res = JSON.parse(https.request(update_req).body)
  109.  
  110.                         if update_res["success"] == true then
  111.                             puts "Updated successfully!"
  112.                         else
  113.                             puts "Update failed!"
  114.                             pp update_res
  115.                         end
  116.                     end
  117.                 end
  118.             end
  119.         else
  120.             puts record_res
  121.             exit 22
  122.         end
  123.     end
  124. else
  125.     puts zone_res
  126.     exit 21
  127. end
  128.  
  129. puts "Updated DDNS records successfully."
  130.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement