bvstone

Why I Cancelled my DynDNS Service and How I Replaced It with an IBM i Application

Posted:

Why I Cancelled my DynDNS Service and How I Replaced It with an IBM i Application

For years I have been using DynDNS for automatic updating of my Domain Name hosts and their IP addresses. I used this because I was in the unfortunate position of not being able to get a static IP address for my business account from my ISP.

The DynDNS service worked great for years.  I would simply install a client on my PC and it would monitor my IP address and update the DNS records hosted by DynDNS when needed.

But, a couple years ago I installed the latest Client (after Oracle bought out DynDNS) and noticed that not only did I have problems installing it, but once it was running it wouldn't automatically update my IP address when it changed.  This wasn't good and caused many issues, as you can imagine.  Most of the time my IP address would change after a power outage.  This was normally at night and being a heavy sleeper I would sleep through it, only to wake up to realize my web sites were down.  With customers accessing my main BVSTools.com site for information, downloads and license keys, this would simply to do and I needed to find a more reliable method of keeping my IP address up to date.  And as they say, if you want something done right, do it yourself.

Seeing as how I've created many Web Service interfaces for RESTful applications ranging from Google to HubSpot to Ebay, I checked and my Domain Registrar (GoDaddy) now has APIs available that will allow me to update my IP addresses using a simple RESTful call to one of their APIs.

In a few hours I had some tests up and running and was successfully:

1.  Retrieving my public IP address using an ILE subprocedure (from https:///api.ipify.org using GETURI, but if this changes it's easy enough to find another provider).

2.  Retrieving the current IP address for my multiple A records from GoDaddy using one of their RESTful APIs

3.  Comparing the two, and if need be, updating the IP addresses.

I then created a CL that runs the program to check and update the IP addresses if needed, checking the status every hour.  Every 10th check a status report is also sent just as a reminder that the application is still running.  (I also did use JOBWATCH to monitor my system to make sure the job is running, and if not send me an email message to let me know).

The program is as follows:

**FREE
ctl-opt DFTACTGRP(*NO) ACTGRP('GODADDY') BNDDIR('GODADDY');

// Imports
/COPY QCOPYSRC,P.GODADDY
/COPY MAILTOOL/QCOPYSRC,P.MAILTOOL
/COPY QCOPYSRC,P.SQL

// Work Variables
dcl-s DNSIP char(256);
dcl-s PublicIP char(256);
dcl-s rc int(10);
dcl-s errorCount int(10);
dcl-s updateCount int(10);
dcl-s runCount int(10);
dcl-s errMsg char(256);
dcl-s emailSubject char(65535);
dcl-s emailBody char(65535);
dcl-s nwBody char(65535);

dcl-ds GDDOMDS extname('GDDOMPF') end-ds;

DNSIP = ' ';
PublicIP = ' ';
rc = 0;
errorCount = 0;
updateCount = 0;
errMsg = ' ';
emailSubject = ' ';
emailBody = ' ';
nwBody = ' ';
runCount += 1;

rc = #gd_getPublicIP(PublicIP:errMsg);

if (rc < 0) or (PublicIP = ' ');
  errMsg = 'Error retrieving Public IP address.';
  exsr $Error;
endif;

exec sql declare C1 cursor for                    
  select GDMDOMAIN, GDMTYPE, GDMNAME from GDDOMPF        
    order by GDMDOMAIN;
    
exec sql open C1;      

exec sql fetch from C1               
   into :GDMDOMAIN, :GDMTYPE, :GDMNAME;         
                                     
dow (xSQLState2 = Success_On_Sql);   

  nwBody = %trim(nwBody) + 
           'Checking Domain ' + %trim(GDMDOMAIN) + 
           ' Type ' + %trim(GDMTYPE) + 
           ' Name ' + %trim(GDMNAME) + '.\n';
              
  rc = #gd_getDNSServerIP(GDMDOMAIN:GDMTYPE:GDMNAME:DNSIP:errMsg);

  nwBody = %trim(nwBody) + 
           'Public: ' + %trim(PublicIP) + '\n' + 
           'DNS: ' + %trim(DNSIP) + '\n'; 

  if (rc < 0);
    exec sql close C1;
    errMsg = 'Error retrieving DNS IP address:' + 
              '\nDomain:' + 
              %trim(GDMDOMAIN) + 
              '\nType:' + 
              %trim(GDMTYPE) +
              '\nName:' + 
              %trim(GDMNAME) + 
              '\n\n' + 
              'Error:' + %trim(errMsg);
    exsr $Error;
  endif;

  if (PublicIP <> DNSIP);
    nwBody = %trim(nwBody) + 
            'Change Required!  Attempting change...\n'; 
    exsr $UpdateIP;
  else;
    nwBody = %trim(nwBody) + 
             'No change needed.\n\n'; 
  endif;
  
  exec sql fetch from C1               
     into :GDMDOMAIN, :GDMTYPE, :GDMNAME;         
enddo;

exec sql close C1;

if (errorCount <= 0) and (updateCount <= 0) and (runCount = 10);
  exsr $NoWorries;
  runCount = 0;
endif;

exsr $Return;

//***************************************************************              
//* Send No Worries Email                                                        
//***************************************************************              
begsr $NoWorries;   

  if (#mailtool_init() >= 0);                                      
    rc = #mailtool_setValue('configuration_file':                  
                            '/bvstools/bvstone_mailtool.json');                     
    rc = #mailtool_loadDefaults();                                 
    rc = #mailtool_addTORecipient('bvstone@bvstools.com');         
    rc = #mailtool_setValue('subject':'IP Address Update Status Report');     
    rc = #mailtool_setValue('message':nwBody);
    rc = #mailtool_sendMail(errMsg);                               
  endif;     
                                                                                
endsr;

//***************************************************************              
//* Update IP Address                                                         
//***************************************************************              
begsr $UpdateIP;   

  updateCount += 1;

  emailBody = 'Domain ' + %trim(GDMDOMAIN) + 
              ' Type ' + %trim(GDMTYPE) + 
              ' Name ' + %trim(GDMNAME) + 
              ' requires an IP address change from ' + 
              %trim(DNSIP) + ' to ' + %trim(PublicIP) + '.';

  rc = #gd_updateDNSServerIP(GDMDOMAIN:GDMTYPE:GDMNAME:PublicIP:errMsg);
  
  if (rc < 0);
    emailSubject = '**ERROR Updating Dynamic IP for ' + %trim(GDMDOMAIN);
    emailBody = %trim(EmailBody) + '\n\n' + 
                'Status: ERROR\n' + 
                'Error Details: ' + %trim(errMsg);
    nwBody = %trim(nwBody) + 
            'Error updating IP Address!\n\n';
  else;
    emailSubject = '**SUCCESS Updating Dynamic IP for ' + %trim(GDMDOMAIN);
    emailBody = %trim(EmailBody) + '\n\n' + 
                'Status: SUCCESS';
    nwBody = %trim(nwBody) + 
            'Change Successful.\n\n';                
  endif;

  if (#mailtool_init() >= 0);                                      
    rc = #mailtool_setValue('configuration_file':                  
                            '/bvstools/bvstone_mailtool.json');                     
    rc = #mailtool_loadDefaults();                                 
    rc = #mailtool_addTORecipient('bvstone@bvstools.com');         
    rc = #mailtool_setValue('subject':emailSubject);     
    rc = #mailtool_setValue('message':emailBody);
    rc = #mailtool_sendMail(errMsg);                               
  endif;     
                                                                                
endsr;

//***************************************************************              
//* Return Error                                                               
//***************************************************************              
begsr $Error;       

  errorCount += 1;
                                                                                 
  if (#mailtool_init() >= 0);                                      
    rc = #mailtool_setValue('configuration_file':                  
                            '/bvstools/bvstone_mailtool.json');                     
    rc = #mailtool_loadDefaults();                                 
    rc = #mailtool_addTORecipient('bvstone@bvstools.com');         
    rc = #mailtool_setValue('subject':'Check DNS Error');      
    rc = #mailtool_setValue('message':errMsg);                   
    rc = #mailtool_sendMail(errMsg);                               
  endif;     
  
  exsr $Return;
                                                                                 
endsr;
  
//***************************************************************
//* Return
//***************************************************************
begsr $Return;

  // we're not setting on *INLR so that we can count and send messages if needed
  //  every 10 hours
  //*INLR = *ON;
  return;

endsr;

As you can see, this isn't very complicated and uses MAILTOOL to send any messages such as errors, successful updates, or simple messages that let me know everything is ok that will be sent every 10 times the application runs.  Because the application is set to run every hour, then every 10 hours I should receive a status email.

The functions starting with #gd_ are the GoDaddy functions I created to specifically deal with GoDaddy's RESTful APIs.  GETURI is used to make the requests, and YAJL is used to build and parse the JSON data, which in this case is very simple.

The following functions are available in the F.GODADDY service program:

  • #gd_getControlValue - Get a Control Value.  These are system wide control values such as the API locations, if Debug is on, etc.   
  • #gd_getDomainControlValue - Get a Domain Level Control Value.  These control values are at the domain level.  This is so that if I ever want to set up this monitor for domains that may be outside of my GoDaddy account, it's as simple as adding them in here.  The main value used here is the API Key and Secret for my account.
  • #gd_getPublicIP - Get Public IP Address.  This function will retrieve the current public IP address for my system.
  • #gd_getDNSServerIP -  Get DNS Server IP Address.  This function will get the currently specified IP address for the domain and host specified (type A records only).         
  • #gd_updateDNSServerIP - Update DNS Server IP Address.   This function will update the current IP address for the domain and host specified (type A records only).

So, the functionality is, at a high level, very simple.  Just get the public IP, get the DNS IP and compare them.  If they are different, issue an update.

If you have any questions feel free to contact us!  We plan on letting this run on our own system for a while before we decide if it will be something we will offer to customers.  


Last edited 07/17/2019 at 11:43:25




Reply




© Copyright 1983-2024 BVSTools
GreenBoard(v3) Powered by the eRPG SDK, MAILTOOL Plus!, GreenTools for Google Apps, jQuery, jQuery UI, BlockUI, CKEditor and running on the IBM i (AKA AS/400, iSeries, System i).