diff --git a/README.md b/README.md index abd5a20..820222f 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,7 @@ Dynamic DNS services currently supported include: ChangeIP - See http://www.changeip.com/ for details dtdns - See http://www.dtdns.com/ for details nsupdate - See nsupdate(1) and ddns-confgen(8) for details + CloudFlare - See https://www.cloudflare.com/ for defails DDclient now supports many of cable/dsl broadband routers. @@ -37,8 +38,9 @@ REQUIREMENTS: - one or more accounts from one of the dynamic DNS services -- Perl 5.004 or later - (you need the IO::Socket::SSL perl library for ssl-support) +- Perl 5.014 or later + (you need the IO::Socket::SSL perl library for ssl-support + and JSON::Any perl library for JSON support) - Linux or probably any common Unix system diff --git a/ddclient b/ddclient index 182227e..83ad442 100755 --- a/ddclient +++ b/ddclient @@ -13,12 +13,19 @@ # Support for multiple IP numbers added by # Astaro AG, Ingo Schwarze September 16, 2008 # +# Support for multiple domain support for Namecheap by Robert Ian Hawdon 2010-09-03: https://robertianhawdon.me.uk/ +# +# Initial Cloudflare support by Ian Pye, updated by Robert Ian Hawdon 2012-07-16 +# Further updates by Peter Roberts to support the new API 2013-09-26, 2014-06-22: http://blog.peter-r.co.uk/ +# +# ###################################################################### -require 5.004; +require 5.014; use strict; use Getopt::Long; use Sys::Hostname; use IO::Socket; +use JSON::Any; # my ($VERSION) = q$Revision$ =~ /(\d+)/; @@ -433,6 +440,14 @@ my %variables = ( 'ttl' => setv(T_NUMBER, 0, 1, 0, 600, undef), 'zone' => setv(T_STRING, 1, 1, 1, '', undef), }, + 'cloudflare-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'www.cloudflare.com', undef), + 'zone' => setv(T_FQDN, 1, 0, 1, '', undef), + 'static' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'wildcard' => setv(T_BOOL, 0, 1, 1, 0, undef), + 'mx' => setv(T_OFQDN, 0, 1, 1, '', undef), + 'backupmx' => setv(T_BOOL, 0, 1, 1, 0, undef), + }, ); my %services = ( 'dyndns1' => { @@ -587,6 +602,17 @@ my %services = ( $variables{'service-common-defaults'}, ), }, + 'cloudflare' => { + 'updateable' => undef, + 'update' => \&nic_cloudflare_update, + 'examples' => \&nic_cloudflare_examples, + 'variables' => merge( + { 'server' => setv(T_FQDNP, 1, 0, 1, 'www.cloudflare.com', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + $variables{'cloudflare-common-defaults'}, + $variables{'service-common-defaults'}, + ), + }, ); $variables{'merged'} = merge($variables{'global-defaults'}, $variables{'service-common-defaults'}, @@ -598,7 +624,7 @@ my @opt = ( "usage: ${program} [options]", "options are:", [ "daemon", "=s", "-daemon delay : run as a daemon, specify delay as an interval." ], -+ [ "foreground", "!", "-foreground : do not fork" ], + [ "foreground", "!", "-foreground : do not fork" ], [ "proxy", "=s", "-proxy host : use 'host' as the HTTP proxy" ], [ "server", "=s", "-server host : update DNS information on 'host'" ], [ "protocol", "=s", "-protocol type : update protocol used" ], @@ -3407,8 +3433,11 @@ sub nic_namecheap_update { my $url; $url = "http://$config{$h}{'server'}/update"; - $url .= "?host=$h"; - $url .= "&domain=$config{$h}{'login'}"; + my $domain = $config{$h}{'login'}; + my $host = $h; + $host =~ s/(.*)\.$domain(.*)/$1$2/; + $url .= "?host=$host"; + $url .= "&domain=$domain"; $url .= "&password=$config{$h}{'password'}"; $url .= "&ip="; $url .= $ip if $ip; @@ -3877,6 +3906,131 @@ EoINSTR3 } } +###################################################################### + +###################################################################### +## nic_cloudflare_examples +## +## written by Ian Pye +## +###################################################################### +sub nic_cloudflare_examples { + return <jsonToObj($reply); + if ($response->{result} eq 'error') { + failed ("%s", $response->{msg}); + next; + } + + # Pull the ID out of the json, messy + my ($id) = map { $_->{name} eq $domain ? $_->{rec_id} : () } @{ $response->{response}->{recs}->{objs} }; + unless($id) { + failed("updating %s: No domain ID found.", $domain); + next; + } + + # Set domain + $url = "https://$config{$key}{'server'}/api_json.html?a=rec_edit&type=A&ttl=1"; + $url .= "&name=$hostname"; + $url .= "&z=".$config{$key}{'zone'}; + $url .= "&id=".$id; + $url .= "&email=".$config{$key}{'login'}; + $url .= "&tkn=".$config{$key}{'password'}; + $url .= "&content="; + $url .= "$ip" if $ip; + + $reply = geturl(opt('proxy'), $url); + unless ($reply) { + failed("updating %s: Could not connect to %s.", $domain, $config{$domain}{'server'}); + last; + } + last if !header_ok($domain, $reply); + + # Strip header + $reply =~ s/^.*?\n\n//s; + $response = JSON::Any->jsonToObj($reply); + if ($response->{result} eq 'error') { + failed ("%s", $response->{msg}); + } else { + success ("%s -- Updated Successfully to %s", $domain, $ip); + + } + + # Cache + $config{$key}{'ip'} = $ip; + $config{$key}{'mtime'} = $now; + $config{$key}{'status'} = 'good'; + } + } +} + + ###################################################################### # vim: ai ts=4 sw=4 tw=78 : diff --git a/sample-etc_ddclient.conf b/sample-etc_ddclient.conf index 402b25d..5eb45ca 100644 --- a/sample-etc_ddclient.conf +++ b/sample-etc_ddclient.conf @@ -196,3 +196,13 @@ ssl=yes # use ssl-support. Works with # client=ddclient, # password=my-dtdns.com-password # myhost.dtdns.net, otherhost.dtdns.net + +## +## CloudFlare (www.cloudflare.com) +## +#protocol=cloudflare, \ +#zone=domain.tld, \ +#server=www.cloudflare.com, \ +#login=your-login-email, \ +#password=APIKey \ +#domain.tld,my.domain.tld