Homebrew your own Dynamic DNS system with cPanel and PHP.

Hello. The geeky pill of today is about how to get rid of DynDNS and feel like those punks when they make their DIY t-shirt with a political message on it. Or something like that.

See, many providers nowadays are providing hosting based on cPanel and a certain number of subdomains that you can set up through the front end. What you may learn today is that cPanel also offers an API that could let you do this automatically.

The API calls themselves are quite easy to understand and apply, but the troublesome part was about the authentication. Now, cPanel actually does offer several ways to connect, but the only one that really worked for me was the first one, which goes like this:

  1. Log into the cPanel API;
  2. Once you get redirected to the front end, you get a URL like this: http://mc2dn.name:2082/cpsess1234567890/frontend/x3/index.html
  3. Take the cpsess value from that URL;
  4. Make your API call using the cpsess value, for example: http://yourdomain.example:2082/cpsess1234567890/json-api/cpanel?cpanel_jsonapi_module=ZoneEdit&cpanel...

As a starting point I’ve used a great blog article, which provides also a ready-made PHP script with everything set to go (and this will be your primary point of reference to set the whole thing up, actually). The only problem with that solution is that the request is based on one of the several authentication systems that my provider wasn’t allowing for some reason. In order to work around it, I’ve basically instructed cURL to behave like a browser.

Step 0: Does it actually work for me?

First thing off, you need to decide where to put your subdomains. Are they going off the main domain, say host.yourdomain.example? Or are you going to dedicate a subdomain to it, for example host.ddns.yourdomain.example? If your choice goes to the latter, then you need to create a subdomain in cPanel first, since our script will only work with the host definitions.

Once ready, next thing you need to do is to test if the API works from your browser. If it doesn’t, why should you waste time any further? Try to open http://yourdomain.example:2082/json-api/cpanel, and see if you get this as a result:

If you get an error like 401 Access Denied instead, then check with your provider.

Step 1: Preparation.

The script in the original article is setting up a class, but for the sake of clarify I will go with normal PHP functions. Let’s start with the very first definition, including the cURL object:

Next thing, we set up the most important function: cpanelRequest(). We will use this function for both the login (with no parameters) and the actual API call.

Once this is done, the rest of the script depends on you.

Step 2: Define the basic API calls.

What do you want to do with this API? Do you want to allow the user to just work on a define set of subdomains, or do you want to let them create some? Do you want them to be able to specify any IP address or only the one they call from?

In this case we’ll work on a defined set of subdomains and we’ll give the opportunity to define the IP address or not. Remember that the original article has a more comprehensive script that includes far more functions, but my purpose here is to explain how I did it for myself, and how you can do it as well.

First thing off, let’s set up another internal call to cPanel that will be useful in whatever case: cpanelGetHost(). What it does is just this: it checks if the host you want to work with is already defined in the subdomain.

Next one is dynUpdateHost(). This one does exactly what it says: it updates an existing entry with a new IP address.

Where should we get this IP address? We’ll leave this part outside the function itself, in the main routine later on. But before that: another command you may want to make available is dynReadHost(). I will put the code here just for the sake of it, but in fact I can’t think of any other reason to use it other than testing whether the script works.

Step 3: Prepare the main call.

Now that we’re done with the foundation, it’s time to think about the interface. How should the syntax look like? We will follow the article again and require a GET query with the following parameters:

  • action: can be read or update (mandatory)
  • host: a specific subdomain (mandatory)
  • ip: a valid IP address (optional)

Here is the code to accomplish that:

Step 4: Final refinements.

Once this is done, voilà, the script is ready to be used. The only thing missing is a little authentication routine at the very top of the script, to prevent anybody to just use your DDNS service without you knowing. Here is an idea to start with:

Again, the article provides a more complex system, with user-based authentication and authorization, so I would suggest to have a look at it.

FAQ #1: I get 401 Access Denied from the script!?

If you tested the API fine from your browser but the script returns a 401 error, it’s quite likely that the server is blacklisted by the firewall. You need to ask your ISP to make sure that the IP address of the server is whitelisted. If your provider is the same as mine, then good luck with letting them understand that you’re trying to access cPanel from within the server itself, they will go banana.

4 thoughts on “Homebrew your own Dynamic DNS system with cPanel and PHP.

  1. Pingback: Random Cisco geekery, issue 5: A VPN between a Cisco EPC3925 and a FRITZ!Box 7270. | Play that funky music white boy!

  2. Hi,

    I found your blog while searching for ways to have one of the sub-domains on my shared hosting (on which my companies website is hosted) link to my apache server on my home computer.

    With your script (which I think is one of simplest solutions) it is possible. What i am not understanding really is the (.) dot before the subdomain. Also, when I go to the link from the home computers browser (“http://yourdomain.example:2082/json-api/cpanel” in my case it is “http://CPANEL.yourdomain.example/json-api/cpanel”) i get this :

    {“cpanelresult”:{“apiversion”:”2″,”error”:”Access denied”,”data”:{“reason”:”Access denied”,”result”:”0″},”type”:”text”}}

    But if I have logged-in in another tab and copy the session-id (format: cpsess1234567890) and alter the link (like so: “http://CPANEL.yourdomain.example/cpsess1234567890/json-api/cpanel”) I get :

    {“cpanelresult”:{“apiversion”:”2″,”error”:”The “cpanel_jsonapi_module” parameter is required.”,”data”:{“reason”:”The “cpanel_jsonapi_module” parameter is required.”,”result”:”0″},”type”:”text”}}

    I do not know how to go further from here. Any help would be great. Thanks.

Note something down here. Put some effort into it.