PHP Script to Edit DNS Records in CPanel

cpanel dynamic dns
php dns server

I would like to become self-sufficient, and therefore do without services such as DNSDynamic and DYNDNS. And I don't like paying for services that I could do myself.

So here's the scenario - I have my main website hosted with a hosting company. I also have a home server with my music, etc. on it. But the problem is that my ISP (BT) does not offer consumers Static IP addresses.

I would like to have a subdomain of my main domain (which points to my main host) point to my home IP. This is done with a simple A record - which I have done myself.

This boils down to me wanting to make a PHP script (run by a cron job on my home server) to update the A records in cPanel to the current IP of my home server.

Here's some sample code - of course the bit that's missing is the API Code to communicate with cPanel, and I'd be very thankful to anyone who could fill in the gaps for me.

<?php
    $current_ip = file_get_contents("http://mydomain.com/getip.php");
    $username = "CPANEL_USERNAME";
    $password = "CPANEL_PASSWORD";
    $domain = "CPANEL_DOMAIN";

    $request = file_get_contents("http://someapipage?username=".$username."&pw=".$password."&domain=".$domain."&ip=".$current_ip);

?>

The code in http://mydomain.com/getip.php is something along the lines of simply

<?php echo $_SERVER["REMOTE_ADDR"]; ?>

I already have the grasp of how to set up a cron job, as my home server is running Ubuntu, and I have read tutorials that call my cron.php in my localhost directory using wget.

I have tried this link but I couldn't fathom what he was doing. Thanks in advance.

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 DNS Zone Records By PHP Code, include "xmlapi. php"; $cpanel = new CPANEL(); // Connect to cPanel - only do this once. // Edit a type "A" zone record on "example.com" $edit_zone_record = $cpanel->api2( 'ZoneRecord', 'edit_zone_record', array( 'Line' => '10', 'domain' => 'domain.ir', 'name' => 'sub', 'type' => 'A', 'address' => '10.10. Is there a specific reason you need to edit a DNS zone through PHP instead of through cPanel? You could develop a custom PHP script that utilizes API to manipulate a zone. EX: cPanel API 2 Functions - ZoneEdit::edit_zone_record Thank you.

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.

PHP Script to Edit DNS Records in CPanel, This boils down to me wanting to make a PHP script (run by a cron job on my home server) to update the A records in cPanel to the current IP of my home server. How to Edit DNS records via cPanel. Go to cPanel >> Domains >> Advanced DNS Zone Editor. To edit the DNS reords of the existing DNS Zone you just need click on the ‘Edit’ button which is present on the right hand side of the coresponding DNS record which you can find in the bottom of the above given screenshot.

There is a bash script for linux to solve the original question asked, namely how to automate the update of an web address to point to a changing IP. The well known and well working ddclient is the standard tool for many providers, but unfortunately not (yet) working for cPanel driven providers (I use serverprofis.de but there is a long list of others).

The bash script is found at github and I have just edited in the code the credentials etc. as found on cPanel and then added a cron job to execute it every few minutes. The script checks, like ddclient, whether the IP has changed and stops if no change is detected compared to the last update of the provider. If the IP has changed, it changes the record at the provider to point to the new IP.

It works well so far.

How do I modify dns records in cpanel? - Knowledgebase, This boils down to me wanting to make a PHP script (run by a cron job on my home server) to update the A records in cPanel to the current IP of my home server. This scripts allows you to create service subdomain DNS records for a cPanel, WHM, or Webmail account from the command line. For more information, read our The servicedomains Script documentation. set_php_memory_limits

PHP Script to Edit DNS Records in CPanel, You may modify dns records from within cpanel. Here's how: 1) Log into your cpanel account (typically http://whatever-your-domain-is.com/cpanel ) using your​  Navigate to the Domains section and click on the Zone Editor menu. 3. Click the Manage button next to the domain which DNS zone you would like to edit: In the next menu, you can add new records, edit existing ones, or reset the DNS zone. Choose A in the drop-down menu next to the Type field.

Is there way to add domain DNS record with script from custom 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 top of the Edit DNS Zone interface displays the following zone and server information: cPanel first — The cPanel & WHM version and build number on which you created the DNS zone. update_time — The Unix date and time of the last update to the zone file.

DNS Zone Editors Tutorial, Is there way to add domain DNS record with script from custom cpanel ? Posted December 3, 2015 3.1k views. UbuntuPHPDNSConfiguration ManagementVPN. Simple DNS Zone Editor. When you click on the Simple DNS Zone editor tool icon you will get a new page with a drop down menu where you can select the desired domain name. Click on the drop down menu and choose the domain name for which you would like the DNS zone modified. Three new sections will load.

Comments
  • Can we see the code of your attempt to implement the approach on jordih.net?
  • Bear in mind that (afaik) every time your DNS address changes, you'll have to wait for the TTL to expire before the changes are reflected worldwide. I should think the dynamic DNS servers would have a very low TTL for that reason.
  • @halfer Thanks for the pointers - the problem is that the code on jordih.net is not really explained, and there are a load of variables with no definition; and so I don't really know where to start with that.
  • Well, it would be $CPANEL_DOMAIN = 'https://mydomain.com:2083/'; (for secure access) and $core_domain = 'mydomain.com'; plus the first block of code. Try print_r($response); ?> to see what you get, and to lead you to working the rest of it out. The one thing missing is authentication to the cPanel system - you may need to log on, get a cookie, and supply it to future calls. That requires a "context" to be supplied to file_get_contents, which in turn requires a bit of research!
  • If port 2083 doesn't work btw, try 2082 with simple http - that leaves your session unencrypted, but might be easier to get to work.
  • "You do not have permission to view this page", too bad link is broken
  • Yes, it seems like it is now broken. I added a copy of the script to the post for reference.