From: <abe...@us...> - 2017-01-20 17:59:51
|
Revision: 8111 http://sourceforge.net/p/astlinux/code/8111 Author: abelbeck Date: 2017-01-20 17:59:48 +0000 (Fri, 20 Jan 2017) Log Message: ----------- ddclient, add Cloudflare dynamic DNS service support Modified Paths: -------------- branches/1.0/package/ddclient/ddclient.conf branches/1.0/package/ddclient/dynamicdns.init branches/1.0/package/perl/perl.mk branches/1.0/package/webinterface/altweb/admin/network.php Added Paths: ----------- branches/1.0/package/ddclient/ddclient-21-cloudflare-ttl.patch branches/1.0/package/ddclient/ddclient-22-cloudflare-api-v4.patch branches/1.0/package/ddclient/ddclient-23-cloudflare-curl-headers.patch branches/1.0/package/ddclient/ddclient-24-cloudflare-JSON-PP.patch Added: branches/1.0/package/ddclient/ddclient-21-cloudflare-ttl.patch =================================================================== --- branches/1.0/package/ddclient/ddclient-21-cloudflare-ttl.patch (rev 0) +++ branches/1.0/package/ddclient/ddclient-21-cloudflare-ttl.patch 2017-01-20 17:59:48 UTC (rev 8111) @@ -0,0 +1,23 @@ +diff --git a/ddclient b/ddclient +index a39fcf0..e1e86e5 100755 +--- a/ddclient ++++ b/ddclient +@@ -445,6 +445,7 @@ my %variables = ( + '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), ++ 'ttl' => setv(T_NUMBER, 1, 0, 1, 1, undef), + }, + 'googledomains-common-defaults' => { + 'server' => setv(T_FQDNP, 1, 0, 1, 'domains.google.com', undef), +@@ -4083,7 +4084,8 @@ sub nic_cloudflare_update { + } + + # Set domain +- $url = "https://$config{$key}{'server'}/api_json.html?a=rec_edit&type=A&ttl=1"; ++ $url = "https://$config{$key}{'server'}/api_json.html?a=rec_edit&type=A"; ++ $url .= "&ttl=".$config{$key}{'ttl'}; + $url .= "&name=$hostname"; + $url .= "&z=".$config{$key}{'zone'}; + $url .= "&id=".$id; + Added: branches/1.0/package/ddclient/ddclient-22-cloudflare-api-v4.patch =================================================================== --- branches/1.0/package/ddclient/ddclient-22-cloudflare-api-v4.patch (rev 0) +++ branches/1.0/package/ddclient/ddclient-22-cloudflare-api-v4.patch 2017-01-20 17:59:48 UTC (rev 8111) @@ -0,0 +1,147 @@ +--- a/ddclient 2017-01-19 11:36:50.208744563 -0600 ++++ b/ddclient 2017-01-19 11:35:44.265920224 -0600 +@@ -439,7 +439,7 @@ + 'zone' => setv(T_STRING, 1, 1, 1, '', undef), + }, + 'cloudflare-common-defaults' => { +- 'server' => setv(T_FQDNP, 1, 0, 1, 'www.cloudflare.com', undef), ++ 'server' => setv(T_FQDNP, 1, 0, 1, 'api.cloudflare.com/client/v4', 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), +@@ -613,7 +613,7 @@ + 'update' => \&nic_cloudflare_update, + 'examples' => \&nic_cloudflare_examples, + 'variables' => merge( +- { 'server' => setv(T_FQDNP, 1, 0, 1, 'www.cloudflare.com', undef) }, ++ { 'server' => setv(T_FQDNP, 1, 0, 1, 'api.cloudflare.com/client/v4', undef) }, + { 'min-interval' => setv(T_DELAY, 0, 0, 1, interval('5m'), 0),}, + $variables{'cloudflare-common-defaults'}, + $variables{'service-common-defaults'}, +@@ -1894,6 +1894,9 @@ + my $url = shift || ''; + my $login = shift || ''; + my $password = shift || ''; ++ my $headers = shift || ''; ++ my $method = shift || 'GET'; ++ my $data = shift || ''; + my ($peer, $server, $port, $default_port, $use_ssl); + my ($sd, $rq, $request, $reply); + +@@ -1934,7 +1937,7 @@ + my $to = sprintf "%s%s", $server, $proxy ? " via proxy $peer:$port" : ""; + verbose("CONNECT:", "%s", $to); + +- $request = "GET "; ++ $request = "$method "; + $request .= "http://$server" if $proxy; + $request .= "/$url HTTP/1.0\n"; + $request .= "Host: $server\n"; +@@ -1943,7 +1946,10 @@ + $request .= "Authorization: Basic $auth\n" if $login || $password; + $request .= "User-Agent: ${program}/${version}\n"; + $request .= "Connection: close\n"; ++ $request .= "$headers\n"; ++ $request .= "Content-Length: ".length($data)."\n" if $data; + $request .= "\n"; ++ $request .= $data; + + ## make sure newlines are <cr><lf> for some pedantic proxy servers + ($rq = $request) =~ s/\n/\r\n/g; +@@ -4010,7 +4016,7 @@ + + Configuration variables applicable to the 'cloudflare' protocol are: + protocol=cloudflare ## +- server=fqdn.of.service ## defaults to www.cloudflare.com ++ server=fqdn.of.service ## defaults to api.cloudflare.com/client/v4 + login=service-login ## login name and password registered with the service + password=service-password ## + fully.qualified.host ## the host registered with the service. +@@ -4047,6 +4053,10 @@ + my $key = $hosts[0]; + my $ip = $config{$key}{'wantip'}; + ++ my $headers = "X-Auth-Email: $config{$key}{'login'}\n"; ++ $headers .= "X-Auth-Key: $config{$key}{'password'}\n"; ++ $headers .= "Content-Type: application/json"; ++ + # FQDNs + for my $domain (@hosts) { + (my $hostname = $domain) =~ s/\.$config{$key}{zone}$//; +@@ -4055,13 +4065,11 @@ + info("setting IP address to %s for %s", $ip, $domain); + verbose("UPDATE:","updating %s", $domain); + +- # Get domain ID +- my $url = "https://$config{$key}{'server'}/api_json.html?a=rec_load_all"; +- $url .= "&z=".$config{$key}{'zone'}; +- $url .= "&email=".$config{$key}{'login'}; +- $url .= "&tkn=".$config{$key}{'password'}; ++ # Get zone ID ++ my $url = "https://$config{$key}{'server'}/zones?"; ++ $url .= "name=".$config{$key}{'zone'}; + +- my $reply = geturl(opt('proxy'), $url); ++ my $reply = geturl(opt('proxy'), $url, undef, undef, $headers); + unless ($reply) { + failed("updating %s: Could not connect to %s.", $domain, $config{$key}{'server'}); + last; +@@ -4077,24 +4085,44 @@ + } + + # 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); ++ my ($zone_id) = map { $_->{name} eq $config{$key}{'zone'} ? $_->{id} : () } @{ $response->{result} }; ++ unless($zone_id) { ++ failed("updating %s: No zone ID found.", $config{$key}{'zone'}); + next; + } ++ info("zone ID is $zone_id"); + +- # Set domain +- $url = "https://$config{$key}{'server'}/api_json.html?a=rec_edit&type=A"; +- $url .= "&ttl=".$config{$key}{'ttl'}; +- $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; ++ # Get DNS record ID ++ $url = "https://$config{$key}{'server'}/zones/$zone_id/dns_records?"; ++ $url .= "type=A&name=$domain"; ++ ++ $reply = geturl(opt('proxy'), $url, undef, undef, $headers); ++ unless ($reply) { ++ failed("updating %s: Could not connect to %s.", $domain, $config{$key}{'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}); ++ next; ++ } + +- $reply = geturl(opt('proxy'), $url); ++ # Pull the ID out of the json, messy ++ my ($dns_rec_id) = map { $_->{name} eq $domain ? $_->{id} : () } @{ $response->{result} }; ++ unless($dns_rec_id) { ++ failed("updating %s: No DNS record ID found.", $domain); ++ next; ++ } ++ info("DNS record ID is $dns_rec_id"); ++ ++ # Set domain ++ $url = "https://$config{$key}{'server'}/zones/$zone_id/dns_records/$dns_rec_id"; ++ my $data = "{\"content\":\"$ip\"}"; ++ $reply = geturl(opt('proxy'), $url, undef, undef, $headers, "PATCH", $data); + unless ($reply) { + failed("updating %s: Could not connect to %s.", $domain, $config{$domain}{'server'}); + last; Added: branches/1.0/package/ddclient/ddclient-23-cloudflare-curl-headers.patch =================================================================== --- branches/1.0/package/ddclient/ddclient-23-cloudflare-curl-headers.patch (rev 0) +++ branches/1.0/package/ddclient/ddclient-23-cloudflare-curl-headers.patch 2017-01-20 17:59:48 UTC (rev 8111) @@ -0,0 +1,29 @@ +--- a/ddclient ++++ b/ddclient +@@ -1959,6 +1959,26 @@ + if (! opt('exec')) { + debug("skipped network connection"); + verbose("SENDING:", "%s", $request); ++ } elsif (($headers ne '')) { ++ $0 = sprintf("%s - curl (SSL w/headers) sending to %s port %s", $program, $peer, $port); ++ my $timeout = opt('timeout'); ++ my @head_lines = split('\n', $headers); ++ my $head_args = ''; ++ foreach my $head_line (@head_lines) { ++ $head_args .= "-H '$head_line' "; ++ } ++ ++ $reply = <<`CURL_SSL_HEADERS`; ++/usr/bin/curl -si0 -X $method --user-agent '${program}/${version}' \\ ++ --connect-timeout $timeout --max-time $timeout \\ ++ ${head_args} \\ ++ --data '${data}' \\ ++ --url 'https://${server}/${url}' 2>/dev/null ++CURL_SSL_HEADERS ++ ++ if (! $reply) { ++ warning("curl (SSL w/headers) cannot connect to $peer:$port"); ++ } + } elsif ($use_ssl) { + $0 = sprintf("%s - curl (SSL) sending to %s port %s", $program, $peer, $port); + my $timeout = opt('timeout'); Added: branches/1.0/package/ddclient/ddclient-24-cloudflare-JSON-PP.patch =================================================================== --- branches/1.0/package/ddclient/ddclient-24-cloudflare-JSON-PP.patch (rev 0) +++ branches/1.0/package/ddclient/ddclient-24-cloudflare-JSON-PP.patch 2017-01-20 17:59:48 UTC (rev 8111) @@ -0,0 +1,58 @@ +--- a/ddclient 2017-01-20 09:04:33.026792149 -0600 ++++ b/ddclient 2017-01-20 09:06:01.478773577 -0600 +@@ -1878,13 +1878,13 @@ + ## load_json_support + ###################################################################### + sub load_json_support { +- my $json_loaded = eval {require JSON::Any}; ++ my $json_loaded = eval {require JSON::PP}; + unless ($json_loaded) { + fatal(<<"EOM"); +-Error loading the Perl module JSON::Any needed for cloudflare update. ++Error loading the Perl module JSON::PP needed for cloudflare update. + EOM + } +- import JSON::Any; ++ import JSON::PP (qw/decode_json/); + } + ###################################################################### + ## geturl +@@ -4098,9 +4098,9 @@ + + # Strip header + $reply =~ s/^.*?\n\n//s; +- my $response = JSON::Any->jsonToObj($reply); +- if ($response->{result} eq 'error') { +- failed ("%s", $response->{msg}); ++ my $response = eval {decode_json($reply)}; ++ if (!defined $response || !defined $response->{result}) { ++ failed ("invalid json or result."); + next; + } + +@@ -4125,9 +4125,9 @@ + + # Strip header + $reply =~ s/^.*?\n\n//s; +- $response = JSON::Any->jsonToObj($reply); +- if ($response->{result} eq 'error') { +- failed ("%s", $response->{msg}); ++ $response = eval {decode_json($reply)}; ++ if (!defined $response || !defined $response->{result}) { ++ failed ("invalid json or result."); + next; + } + +@@ -4151,9 +4151,9 @@ + + # Strip header + $reply =~ s/^.*?\n\n//s; +- $response = JSON::Any->jsonToObj($reply); +- if ($response->{result} eq 'error') { +- failed ("%s", $response->{msg}); ++ $response = eval {decode_json($reply)}; ++ if (!defined $response || !defined $response->{result}) { ++ failed ("invalid json or result."); + } else { + success ("%s -- Updated Successfully to %s", $domain, $ip); + Modified: branches/1.0/package/ddclient/ddclient.conf =================================================================== --- branches/1.0/package/ddclient/ddclient.conf 2017-01-19 14:08:32 UTC (rev 8110) +++ branches/1.0/package/ddclient/ddclient.conf 2017-01-20 17:59:48 UTC (rev 8111) @@ -113,4 +113,12 @@ #@dtdns@>client=ddclient #@dtdns@>password=@DDPASS@ #@dtdns@>@DDHOST@ +#@cloudflare@> +#@cloudflare@>## Cloudflare +#@cloudflare@>ssl=yes +#@cloudflare@>protocol=cloudflare +#@cloudflare@>zone=@DOMAIN@ +#@cloudflare@>login=@DDUSER@ +#@cloudflare@>password=@DDPASS@ +#@cloudflare@>@DDHOST@ Modified: branches/1.0/package/ddclient/dynamicdns.init =================================================================== --- branches/1.0/package/ddclient/dynamicdns.init 2017-01-19 14:08:32 UTC (rev 8110) +++ branches/1.0/package/ddclient/dynamicdns.init 2017-01-20 17:59:48 UTC (rev 8111) @@ -4,7 +4,7 @@ gen_ddclient_conf() { - local use_web="" use_if="#" web_str delay service + local use_web="" use_if="#" web_str delay domain service if [ ! -x /usr/sbin/ddclient ]; then echo "dynamicdns: Script \"/usr/sbin/ddclient\" not found, exiting." >&2 @@ -26,6 +26,9 @@ web_str="$DDGETIP/" fi + # extract the root domain of DDHOST, used by some providers like Cloudflare + domain="$(echo $DDHOST | sed -n -r -e 's/^(.*\.|)([^.]+)\.([^.]+)$/\2.\3/p')" + # Handle Service Types case "$DDSERVICE" in 'de...@zo...') service="zoneedit" ;; @@ -61,6 +64,7 @@ sed -i -e "s|@DDUSER@|${DDUSER}|g" \ -e "s|@DDPASS@|${DDPASS}|g" \ -e "s|@DDHOST@|${DDHOST}|g" \ + -e "s|@DOMAIN@|${domain}|g" \ -e "s|@EXTIF@|${EXTIF}|g" \ -e "s|@EXT2IF@|${EXT2IF}|g" \ -e "s|@DELAY@|${delay}|g" \ Modified: branches/1.0/package/perl/perl.mk =================================================================== --- branches/1.0/package/perl/perl.mk 2017-01-19 14:08:32 UTC (rev 8110) +++ branches/1.0/package/perl/perl.mk 2017-01-20 17:59:48 UTC (rev 8111) @@ -14,7 +14,7 @@ PERL_ARCHNAME = $(ARCH)-linux -PERL_MODULES = constant version Carp Errno Fcntl PathTools POSIX Digest Socket IO XSLoader Exporter File-Find +PERL_MODULES = constant version Carp Errno Fcntl PathTools POSIX Digest Socket IO XSLoader Exporter B File-Find JSON-PP PERL_MODULES += Digest/MD5 Digest/SHA Getopt/Long Time/Local File/Glob Sys/Hostname PERL_CROSS_VERSION = 1.0.3 Modified: branches/1.0/package/webinterface/altweb/admin/network.php =================================================================== --- branches/1.0/package/webinterface/altweb/admin/network.php 2017-01-19 14:08:32 UTC (rev 8110) +++ branches/1.0/package/webinterface/altweb/admin/network.php 2017-01-20 17:59:48 UTC (rev 8111) @@ -86,6 +86,7 @@ $select_dyndns = array ( 'User Defined >>>' => '', 'ChangeIP' => 'changeip', + 'Cloudflare' => 'cloudflare', 'DNS-O-Matic' => 'de...@dn...', 'DNS Park' => 'dnspark', 'DtDNS' => 'dtdns', This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |