PHP cURL: CLI DtDNS Updater 1: Difference between revisions
Upazixorys (talk | contribs) No edit summary |
m (Reverted edits by Upazixorys (Talk); changed back to last version by Ric) |
||
Line 1: | Line 1: | ||
{{Nav PHP cURL}} | {{Nav PHP cURL}} | ||
'''cURL CLI DtDNS Updater - Part 1''' | '''cURL CLI DtDNS Updater - Part 1''' | ||
Line 22: | Line 21: | ||
This template is accessed using one of two URLs | This template is accessed using one of two URLs | ||
* | * <nowiki>http://</nowiki>www.dtdns.com/api/autodns.cfm?'''id'''=hostname&'''pw'''=password&'''ip'''=address&'''client'''=name | ||
* | * <nowiki>https://</nowiki>www.dtdns.com/api/autodns.cfm?'''id'''=hostname&'''pw'''=password&'''ip'''=address&'''client'''=name | ||
Although it is possible to run files with extension cfm as PHP scripts its easier to just use a php extension. Anyway there is nothing to prevent us creating a simulation script. | Although it is possible to run files with extension cfm as PHP scripts its easier to just use a php extension. Anyway there is nothing to prevent us creating a simulation script. | ||
Line 31: | Line 30: | ||
'''''[[#top | Top]]''''' | '''''[[#top | Top]]''''' | ||
=== name-value pairs === | === name-value pairs === | ||
{|cellspacing= | {|cellspacing="6" | ||
|-valign= | |-valign="top" | ||
| | | | ||
1) | 1) | ||
Line 41: | Line 40: | ||
* NOTE: Hostnames are now passed using the full hostname and the domain name it's on, not just the hostname (ex:test.dtdns.net, myhost.etowns.org, etc.). Full domain names are passed using just the domain name (ex: blah.com, mydomain.net, etc.). | * NOTE: Hostnames are now passed using the full hostname and the domain name it's on, not just the hostname (ex:test.dtdns.net, myhost.etowns.org, etc.). Full domain names are passed using just the domain name (ex: blah.com, mydomain.net, etc.). | ||
|-valign= | |-valign="top" | ||
| | | | ||
2) | 2) | ||
Line 48: | Line 47: | ||
| | | | ||
This is a required field that will specify the member's password. This will be compared to what is stored in the userbase for the specified hostname. If they do not match, an error (specified below) will be returned. | This is a required field that will specify the member's password. This will be compared to what is stored in the userbase for the specified hostname. If they do not match, an error (specified below) will be returned. | ||
|-valign= | |-valign="top" | ||
| | | | ||
3) | 3) | ||
Line 60: | Line 59: | ||
We recommend giving the user the option of not sending the IP address with IP updates if they are behind a NAT router. Hardware clients that do not act as a direct bridge should send the user's WAN address, and hardware clients that act as bridges should not send an IP address. | We recommend giving the user the option of not sending the IP address with IP updates if they are behind a NAT router. Hardware clients that do not act as a direct bridge should send the user's WAN address, and hardware clients that act as bridges should not send an IP address. | ||
DtDNS now provides an | DtDNS now provides an "offline IP" for our members to use. By pointing their hostname or domain to this IP address, anyone trying to visit their web site on port 80 will see a standard offline message or be redirected to a URL configured via the web site. The offline IP address is 0.0.0.0. | ||
|-valign= | |-valign="top" | ||
| | | | ||
4) | 4) | ||
Line 72: | Line 71: | ||
=== returned messages === | === returned messages === | ||
{| | {| | ||
|-valign= | |-valign="top" | ||
|& | | ||'''''Messages'''''||'''''Description''''' | ||
|-valign= | |-valign="top" | ||
| | | | ||
1) | 1) | ||
Line 81: | Line 80: | ||
| | | | ||
This message is returned when no ID is specified. | This message is returned when no ID is specified. | ||
|-valign= | |-valign="top" | ||
| | | | ||
2) | 2) | ||
Line 88: | Line 87: | ||
| | | | ||
Returned when no PW is given. | Returned when no PW is given. | ||
|-valign= | |-valign="top" | ||
| | | | ||
3) | 3) | ||
Line 95: | Line 94: | ||
| | | | ||
Returned when ID is not a valid hostname or domain on the system. | Returned when ID is not a valid hostname or domain on the system. | ||
|-valign= | |-valign="top" | ||
| | | | ||
4) | 4) | ||
Line 102: | Line 101: | ||
| | | | ||
Returned when the value of PW does not match the password defined for the value in the ID tag. | Returned when the value of PW does not match the password defined for the value in the ID tag. | ||
|-valign= | |-valign="top" | ||
| | | | ||
5) | 5) | ||
Line 109: | Line 108: | ||
| | | | ||
Returned when the account has not been activated for usage. | Returned when the account has not been activated for usage. | ||
|-valign= | |-valign="top" | ||
| | | | ||
6) | 6) | ||
Line 115: | Line 114: | ||
Administration has disabled this account. | Administration has disabled this account. | ||
| | | | ||
Returned when the disabled bit is active for the specified ID, meaning that the hostname | Returned when the disabled bit is active for the specified ID, meaning that the hostname<br /> | ||
or domain name has been disabled for some reason. | or domain name has been disabled for some reason. | ||
|-valign= | |-valign="top" | ||
| | | | ||
7) | 7) | ||
Line 123: | Line 122: | ||
Illegal character in IP. | Illegal character in IP. | ||
| | | | ||
Returned when a non-numeric or period character is detected in the IP field when the user | Returned when a non-numeric or period character is detected in the IP field when the user<br /> | ||
has their account setup for A name resolution. Having a non-standard IP when set to A | has their account setup for A name resolution. Having a non-standard IP when set to A<br /> | ||
resolution causes the service to not update the IP database. Also returned when a number | resolution causes the service to not update the IP database. Also returned when a number<br /> | ||
in the IP address is higher than 255. | in the IP address is higher than 255. | ||
|-valign= | |-valign="top" | ||
| | | | ||
8) | 8) | ||
Line 148: | Line 147: | ||
|- | |- | ||
| | | | ||
<pre> | |||
A to Z ; upper case characters | A to Z ; upper case characters | ||
a to z ; lower case characters | a to z ; lower case characters | ||
0 to 9 ; numeric characters 0 to 9 | 0 to 9 ; numeric characters 0 to 9 | ||
- ; dash | - ; dash | ||
</pre> | |||
| | | | ||
* A label can start or end with a letter or a number | * A label can start or end with a letter or a number | ||
Line 170: | Line 169: | ||
|- | |- | ||
| | | | ||
<pre> | |||
<?php | |||
$host = | $host = "uniserver-test.dtdns.net"; // Change this for testing | ||
// === Check for vailid host ================================================= | // === Check for vailid host ================================================= | ||
$failed=false; | $failed=false; | ||
if(preg_match( | if(preg_match("/^[A-Za-z0-9\-.]+$/",$host)){ // Allowed characters | ||
// Invalid period either end not allowed set flag | // Invalid period either end not allowed set flag | ||
if(preg_match( | if(preg_match("/^[.]/",$host)|preg_match("/[.]$/",$host)){ | ||
$failed=true; | $failed=true; | ||
} | } | ||
Line 186: | Line 185: | ||
// Looks ok now split at periods to give array each element contains a Label | // Looks ok now split at periods to give array each element contains a Label | ||
else{ | else{ | ||
$host_array = explode( | $host_array = explode(".",$host); // into an array | ||
// Scan each element for | // Scan each element for "-" either end of element not allowed set flag | ||
foreach($host_array as $el){ | foreach($host_array as $el){ | ||
if(preg_match( | if(preg_match("/^-/",$host)|preg_match("/-$/",$el)){ | ||
$failed=true; // not allowed set flag | $failed=true; // not allowed set flag | ||
} | } | ||
Line 196: | Line 195: | ||
// Last element is tld allowed characters lower cae alpha | // Last element is tld allowed characters lower cae alpha | ||
if(!preg_match( | if(!preg_match("/^[a-z]+$/",end($host_array))){ | ||
$failed=true; | $failed=true; | ||
} | } | ||
Line 203: | Line 202: | ||
if($failed){ | if($failed){ | ||
print | print "<br />==== Errors In Host =======<br />"; | ||
exit; | exit; | ||
} | } | ||
// === END Check for vailid host ============================================= | // === END Check for vailid host ============================================= | ||
print | print "<br />=== Host OK =====<br />"; | ||
? | ?> | ||
</pre> | |||
|} | |} | ||
'''''[[#top | Top]]''''' | '''''[[#top | Top]]''''' | ||
Line 224: | Line 223: | ||
|- | |- | ||
| | | | ||
<pre> | |||
<?php | |||
$hostname = | $hostname = "uni.dtdns.net"; // Host name you created at DtDNS | ||
$password = | $password = "me123"; // Account password you set | ||
$information = true; // true = display information false = for real tests set to false | $information = true; // true = display information false = for real tests set to false | ||
Line 234: | Line 233: | ||
if($information){ | if($information){ | ||
print | print "<p><b>Information</b></p>"; | ||
$id=$pw=$ip=$client=NULL; | $id=$pw=$ip=$client=NULL; | ||
if(isset($_GET['id'])) $id = $_GET['id']; | if(isset($_GET['id'])) $id = $_GET['id']; | ||
Line 245: | Line 244: | ||
} | } | ||
else{ | else{ | ||
$client = | $client = "Unknown"; | ||
} | } | ||
print & | print "<pre>Host (id) = $id<br />"; | ||
print | print "Password (pw) = $pw<br />"; | ||
print | print "Ip (ip) = $ip<br />"; | ||
print | print "Client (client)= $client </pre>"; | ||
}//End Information | }//End Information | ||
Line 259: | Line 258: | ||
} | } | ||
else{ | else{ | ||
print | print "No hostname to update was supplied."; | ||
exit; | exit; | ||
} | } | ||
Line 268: | Line 267: | ||
} | } | ||
else{ | else{ | ||
print | print "No password was supplied."; | ||
exit; | exit; | ||
} | } | ||
Line 274: | Line 273: | ||
// === Check id (hostname) matches | // === Check id (hostname) matches | ||
if($id!=$hostname){ | if($id!=$hostname){ | ||
print | print "The hostname you supplied is not valid."; | ||
exit; | exit; | ||
} | } | ||
Line 280: | Line 279: | ||
// === Check pwd matches | // === Check pwd matches | ||
if($pw!=$password){ | if($pw!=$password){ | ||
print | print "The password you supplied is not valid."; | ||
exit; | exit; | ||
} | } | ||
Line 286: | Line 285: | ||
// === Check if account activated | // === Check if account activated | ||
if(!$activated){ | if(!$activated){ | ||
print | print "This account has not yet been activated."; | ||
exit; | exit; | ||
} | } | ||
Line 292: | Line 291: | ||
// === Check if Admin disabled account | // === Check if Admin disabled account | ||
if($account_disabled){ | if($account_disabled){ | ||
print | print "Administration has disabled this account."; | ||
exit; | exit; | ||
} | } | ||
Line 301: | Line 300: | ||
// === Validate | // === Validate | ||
if(!preg_match( | if(!preg_match("/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/",$ip)){ | ||
print | print "Illegal character in IP"; | ||
exit; | exit; | ||
} | } | ||
Line 308: | Line 307: | ||
else{ | else{ | ||
//Gets the IP address | //Gets the IP address | ||
$ip = getenv( | $ip = getenv("REMOTE_ADDR") ; | ||
} | } | ||
print | print "Host $id now points to $ip."; | ||
? | ?> | ||
</pre> | |||
|} | |} | ||
Line 320: | Line 319: | ||
=== Test === | === Test === | ||
Start server '''curl_2''' copy and paste the following into your browser address bar: | Start server '''curl_2''' copy and paste the following into your browser address bar: | ||
<pre> | |||
http://localhost:82/autodns.php?id=uni.dtdns.net& | http://localhost:82/autodns.php?id=uni.dtdns.net&pw=me123&ip=11.22.33.44&client=UniServerV1 | ||
</pre> | |||
Browser displays: | Browser displays: | ||
<pre> | |||
Information | Information | ||
Line 333: | Line 332: | ||
Host uni.dtdns.net now points to 11.22.33.44. | Host uni.dtdns.net now points to 11.22.33.44. | ||
</pre> | |||
Change the variables and generally check whats displayed. | Change the variables and generally check whats displayed. | ||
Line 339: | Line 338: | ||
Note: If you are simulaing a real DtDNS account remember to change the following: | Note: If you are simulaing a real DtDNS account remember to change the following: | ||
* '''$hostname''' = | * '''$hostname''' = "uni.dtdns.net"; // Host name you created at DtDNS | ||
* '''$password''' = | * '''$password''' = "me123"; // Account password you set | ||
'''''[[#top | Top]]''''' | '''''[[#top | Top]]''''' |
Latest revision as of 07:54, 24 November 2010
PHP cURL : Introduction | Basics | Authentication | SSL | GET & POST | GET POST SSL AUTH | CLI Set-up | CLI DtDNS Updater 1 | CLI DtDNS Updater 2
|
|
UniServer 5-Nano PHP cURL. |
cURL CLI DtDNS Updater - Part 1
Boundaries between CLI and Server scripting at times are a little blurred it can be easier to develop scripts on a server that are destined for CLI implementation.
This page is no exception, on our simulation server we are going to look at simulating DtDNS’s update page. It’s easier to see what’s going on if we use a test server to access this page using Curl and then convert the script to CLI.
Simulation has the advantage all testing is local removing bandwidth from live servers and possibly incurring the wroth of a draconian dragon (having your IP address band from their servers).
Background
Any provider worth their salt will provide material necessary to use their service. It should be easily accessible for example perform a Goggle search for “dtdns IP updater specification” hey that’s neat gives http://www.dtdns.com/specs.txt try that with “dyndns IP updater specification”
OK Not so easy, but the information is there http://www.dyndns.com/developers/specs/ and http://www.dyndns.com/developers/
Anyway my point is you need a specification otherwise you cannot create a simulation script. We are targeting DtDNS have the specification how often does it change, always a reasonable indicator that they have not got it right. OK last changed 02/12/05 although internal server operation may change the external user interface has not.
That means you can reliably code to their specification.
Simulation Script Information
Ideally we would like to test against a real page however after reading the specification transpires a ColdFusion template is used. This has been configured in such a way to the outside world it looks like a CGI script were values are passed using the GET method.
This template is accessed using one of two URLs
- http://www.dtdns.com/api/autodns.cfm?id=hostname&pw=password&ip=address&client=name
- https://www.dtdns.com/api/autodns.cfm?id=hostname&pw=password&ip=address&client=name
Although it is possible to run files with extension cfm as PHP scripts its easier to just use a php extension. Anyway there is nothing to prevent us creating a simulation script.
For connivance I have reproduced part of the specification for name-value pairs and returned messages below (Note I added message 8 this seems to have been missed from the spec.):
name-value pairs
1) |
id=hostname |
This is a required field that will specify what the member's hostname (or domain) is. This value should ALWAYS be a fully qualified domain name. It should be a sub domain of one of the available DtDNS domains, or a full domain that DtDNS is hosting. Please check the hostname for invalid characters and spit out an error if you find any. See O'Reilly's DNS and BIND 3rd ed. for a complete discussion on what characters are and aren't valid in hostnames and domain names.
|
2) |
pw=password |
This is a required field that will specify the member's password. This will be compared to what is stored in the userbase for the specified hostname. If they do not match, an error (specified below) will be returned. |
3) |
ip=address |
This field will specify what IP address to update to. If no IP field is specified, the server will take the IP address the request was recieved from. We will attempt to determine if the user is behind a proxy server by testing several common header variables. We recommend giving the user the option of not sending the IP address with IP updates if they are behind a NAT router. Hardware clients that do not act as a direct bridge should send the user's WAN address, and hardware clients that act as bridges should not send an IP address. DtDNS now provides an "offline IP" for our members to use. By pointing their hostname or domain to this IP address, anyone trying to visit their web site on port 80 will see a standard offline message or be redirected to a URL configured via the web site. The offline IP address is 0.0.0.0. |
4) |
client=name |
This is an OPTIONAL parameter to include the name of your update clinet. Please keep this under 10 characters, and all in one word if possible. This can be used for tracking purposes, and general statistics. 'Unknown' will be placed in the database if no client is specified. If you use the User-Agent HTTP header, please use the same value in this field. |
returned messages
Messages | Description | |
1) |
No hostname to update was supplied. |
This message is returned when no ID is specified. |
2) |
No password was supplied. |
Returned when no PW is given. |
3) |
The hostname you supplied is not valid. |
Returned when ID is not a valid hostname or domain on the system. |
4) |
The password you supplied is not valid. |
Returned when the value of PW does not match the password defined for the value in the ID tag. |
5) |
This account has not yet been activated. |
Returned when the account has not been activated for usage. |
6) |
Administration has disabled this account. |
Returned when the disabled bit is active for the specified ID, meaning that the hostname |
7) |
Illegal character in IP. |
Returned when a non-numeric or period character is detected in the IP field when the user |
8) |
Host name now points to IP |
Returned when an update is accepted (IP changed). For example Host fred-test.dtdns.net now points to 888.129.139.179 |
Valid Names and Labels
Although things have moved on there are still implementation that use the old RFC 952 and RFC 1123 (1999!) specification that define what a valid name (Label) is. Note a domain in this context includes any sub-domains eg fred.dtdns.net = (label).(label).net
Labels can contain letters, numbers, and hyphens, and may not start with a hyphen. Periods are used to separate labels in a domain name. The total length must range between 3 and 63 characters (excluding the extension).
A to Z ; upper case characters a to z ; lower case characters 0 to 9 ; numeric characters 0 to 9 - ; dash |
|
The above is a safe bet, however specification RFC 2181 provides expanded capabilities and essentially says anything goes,
If you want to validate to RFC 2181 be prepared for some real pain!
Example client host validation
The follow examples shows code you could use for client verification. Expert regexer’s probably can do this in a single line. I like to split into small more manageable chunks.
<?php $host = "uniserver-test.dtdns.net"; // Change this for testing // === Check for vailid host ================================================= $failed=false; if(preg_match("/^[A-Za-z0-9\-.]+$/",$host)){ // Allowed characters // Invalid period either end not allowed set flag if(preg_match("/^[.]/",$host)|preg_match("/[.]$/",$host)){ $failed=true; } // Looks ok now split at periods to give array each element contains a Label else{ $host_array = explode(".",$host); // into an array // Scan each element for "-" either end of element not allowed set flag foreach($host_array as $el){ if(preg_match("/^-/",$host)|preg_match("/-$/",$el)){ $failed=true; // not allowed set flag } }// end foreach // Last element is tld allowed characters lower cae alpha if(!preg_match("/^[a-z]+$/",end($host_array))){ $failed=true; } }// end ese }// end if allowed characters if($failed){ print "<br />==== Errors In Host =======<br />"; exit; } // === END Check for vailid host ============================================= print "<br />=== Host OK =====<br />"; ?> |
Simulation Script
Our simulation script as a minimum should validate all mandatory values and any additional items you consider important its a personal choice. Remember its the Curl script we want to check.
That said because DtDNS has provided an excellent and easy to understand specification its worth matching responses as outlined. The following is my attempt at a working simulation script:
Create a new text file in folder C:\curl_2\UniServer\www named autodns.php with the following content:
autodns.php
<?php $hostname = "uni.dtdns.net"; // Host name you created at DtDNS $password = "me123"; // Account password you set $information = true; // true = display information false = for real tests set to false $activated = true; // Account active = true, Account not active = false $account_disabled = false; // Admin disabled = true, not disabled = false if($information){ print "<p><b>Information</b></p>"; $id=$pw=$ip=$client=NULL; if(isset($_GET['id'])) $id = $_GET['id']; if(isset($_GET['pw'])) $pw = $_GET['pw']; if(isset($_GET['ip'])) $ip = $_GET['ip']; // Check if a client was supplied if(isset($_GET['client'])){ $client = $_GET['client']; } else{ $client = "Unknown"; } print "<pre>Host (id) = $id<br />"; print "Password (pw) = $pw<br />"; print "Ip (ip) = $ip<br />"; print "Client (client)= $client </pre>"; }//End Information // === Check for id host name if(isset($_GET['id'])){ $id = $_GET['id']; } else{ print "No hostname to update was supplied."; exit; } // === Check for pw host name if(isset($_GET['pw'])){ $pw = $_GET['pw']; } else{ print "No password was supplied."; exit; } // === Check id (hostname) matches if($id!=$hostname){ print "The hostname you supplied is not valid."; exit; } // === Check pwd matches if($pw!=$password){ print "The password you supplied is not valid."; exit; } // === Check if account activated if(!$activated){ print "This account has not yet been activated."; exit; } // === Check if Admin disabled account if($account_disabled){ print "Administration has disabled this account."; exit; } // === Check if a IP was supplied if(isset($_GET['ip'])){ $ip = $_GET['ip']; // === Validate if(!preg_match("/\b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\b/",$ip)){ print "Illegal character in IP"; exit; } } else{ //Gets the IP address $ip = getenv("REMOTE_ADDR") ; } print "Host $id now points to $ip."; ?> |
Test
Start server curl_2 copy and paste the following into your browser address bar:
http://localhost:82/autodns.php?id=uni.dtdns.net&pw=me123&ip=11.22.33.44&client=UniServerV1
Browser displays:
Information Host (id) = uni.dtdns.net Password (pw) = me123 Ip (ip) = 11.22.33.44 Client (client)= UniServerV1 Host uni.dtdns.net now points to 11.22.33.44.
Change the variables and generally check whats displayed.
When you have finished testing set $information = false; the simulation script hide the extra information.
Note: If you are simulaing a real DtDNS account remember to change the following:
- $hostname = "uni.dtdns.net"; // Host name you created at DtDNS
- $password = "me123"; // Account password you set
Summary
The above simulation script is important it allows you to make mistakes while testing without incurring the wrath of a draconian dragon. I am not sure what form DtDNS’s dragon takes however I do know DynDNS implements an abuse counter once triggered time delayed logins starts.
With the above in place we can develop our Curl update script on test server curl_1 and convert to CLI, this is covered on the next page.