PHP Script to Edit DNS Records in CPanel
I have just written this library for cPanel's JSON-API based on their documentation and the jordih.net links to that documentation. It's not so well documented, but the gist of it is:
Create a zone_records object by calling
$zones = new zone_records("cpaneluser", "pass", "website_to_login", "domain_of_records")
Note that the website to login is usually 127.0.0.1 if you are running this from the server you want to change the records on.
Once called, you can then access a member $zones->DNSrecords
. This contains an array of the DNS A records and CNAME records (both of which are DNSrecord objects). The others (except TXT) are irrelevant since you cannot edit them without extra additions (functions) to the classes.
Each DNSrecord has some members (e.g target, ttl, name, type) which, while private
, can be accessed via $record->ttl
because I have added the "magic" __get
method. The "magic" __set
method is implemented to change the ttl and target only (you cannot change other properties using this API function, and the object will raise an exception if you try to do so).
You can use
$zones->addrecord($type, $target, $name, $ttl)
to add a record, or
$zones->deleterecord($line)
to delete the record that is on line $line
in the zone file - you can find it via $record->line
.
If you want to make some of your own queries in the ZoneEdit module, you can call
$zones->doquery("function_from_API", array("parameters=>"here"), array("headers"=>"here"))
and it will return the cPanel response (as will the addrecord and deleterecord methods). Finally, I would advise you to use try {...} catch (Exception $e) {...}
since my objects throw exceptions if/when something goes wrong (you can edit them out of course).
This code is in the public domain - you can get it at https://github.com/ShadowLNC/cpanel_dns (classdns.php is the main file, and dns_update.php shows an example).
Edit: The link below is now broken. Here is the entire script for reference:
#!/usr/bin/perl
# -------------------------------------------------------------------------------
# neobitti_update_ip.pl
#
# Version 1.0 - 16.01.2012
#
# PERL script to dynamically update the IP of a host via the cPanel-API. This
# script was written to work with the Finnish hoster Neobitti but it might work
# with other hosters which use cPanel too.
#
# Copyright (C) 2012 Stefan Gofferje - http://stefan.gofferje.net/
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation; either version 2 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but
# WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
# -------------------------------------------------------------------------------
use strict;
use LWP::UserAgent;
use MIME::Base64;
use XML::Simple;
use Data::Dumper;
# --- Command line parameters ------------------------------------------------
my $param_domain=$ARGV[0];
my $param_host=$ARGV[1];
my $param_ip=$ARGV[2];
# --- cPanel information -----------------------------------------------------
# Storing passwords in clear text is ugly!
my $cpanel_domain = "example.com";
my $user = "username";
my $pass = "password";
my $auth = "Basic " . MIME::Base64::encode( $user . ":" . $pass );
# --- Deactivate SSL certificate validation ----------------------------------
# This is ugly but neccessary because Neobitti uses self-signed SSL
# certificates which will fail validation
my $ua = LWP::UserAgent->new(ssl_opts => { verify_hostname => 0 });
# --- Find out the linenumber for the A-record we want to change -------------
sub getlinenumber_a {
my $domain=$_[0];
my $hostname=$_[1].".";
my $xml = new XML::Simple;
my $request = HTTP::Request->new( GET => "https://$cpanel_domain:2083/xml-api/cpanel?cpanel_xmlapi_module=ZoneEdit&cpanel_xmlapi_func=fetchzone&domain=$domain" );
$request->header( Authorization => $auth );
my $response = $ua->request($request);
my $zone = $xml->XMLin($response->content);
my $linenumber="";
print $response->content . "\n";
print $zone . "\n";
print $zone->{'data'}->{'status'} . "\n";
print $zone->{'data'}->{'record'} . "\n";
if ($zone->{'data'}->{'status'} eq "1") {
my $count = @{$zone->{'data'}->{'record'}};
my $oldip="";
for (my $item=0;$item<=$count;$item++) {
my $name=$zone->{'data'}->{'record'}[$item]->{'name'};
my $type=$zone->{'data'}->{'record'}[$item]->{'type'};
print $name;
if ( ($name eq $hostname) && ($type eq "A") ) {
$linenumber=$zone->{'data'}->{'record'}[$item]->{'Line'};
$oldip=$zone->{'data'}->{'record'}[$item]->{'record'};
print "Found $hostname in line $linenumber with IP $oldip.\n"; # DEBUG
}
}
} else {
$linenumber="0";
print $zone->{'event'}->{'data'}->{'statusmsg;'}
}
return($linenumber);
}
# --- Change the IP address record for a certain linenumber ------------------
sub setip {
my $domain=$_[0];
my $linenumber=$_[1];
my $newip=$_[2];
my $result="";
my $xml = new XML::Simple;
my $request = HTTP::Request->new( GET => "https://$cpanel_domain:2083/xml-api/cpanel?cpanel_xmlapi_module=ZoneEdit&cpanel_xmlapi_func=edit_zone_record&domain=$domain&line=$linenumber&address=$newip" );
$request->header( Authorization => $auth );
my $response = $ua->request($request);
my $reply = $xml->XMLin($response->content);
if ($reply->{'data'}->{'status'} eq "1") {
$result="1";
} else {
$result=$reply->{'data'}->{'statusmsg'};
}
return($result);
}
# --- Main procedure ---------------------------------------------------------
print "Trying to find the linenumber for $param_host in $param_domain...\n";
my $line=getlinenumber_a($param_domain,$param_host);
if ( ($line ne "0") && ($line ne "") ) {
print "Trying to update IP...\n";
my $result=setip ($param_domain,$line,$param_ip);
if ($result eq "1") {
print "Update successful!\n";
} else {
print "$result\n";
}
} else {
print "Error - check domain and hostname!\n";
}
You need to replace "username" and "password" with your own credentials.
Run the script and pass in the domain name, the subdomain name and the new IP of the subdomain:
./neobitti_update_ip.pl <domain> <subdomain> <ip>
Example:
./neobitti_update_ip.pl example.com subdomain.example.com 93.184.216.34
Below is my original answer with a link to the source:
There is a Perl-script doing the exact thing you are requesting here:
http://stefan.gofferje.net/it-stuff/scripts/50-dynamic-dns-update-via-cpanel-api
If it has to be PHP I suppose it should be fairly simple to translate from Perl to PHP (or any other language). The author of the script has posted some background information here.