It’s been awhile since I wrote something. Now I wanna show you how to make changes into DNS records managed by CPanel with Ruby and Mechanize.
Everyone remembers services like dyndns and no-ip, but when we got a hosting and a domain name at some place like Hostmonster, we still want to point a subdomain to our home server. But it’s pretty annoying to log into Cpanel and change the records manually. So I wrote this little tool.
This specific code works for Hostmonster, but it’s easily extensible to any(I guess) Cpanel based hosting.
First you need to install ruby with mechanize and json libraries. In a Debian/Mint/Ubuntu way you can do typing the next on console:
sudo apt-get install ruby ruby-mechanize ruby-json
Next you need the following code:
#!/usr/bin/env ruby require 'mechanize' require 'json' USERNAME = 'MY_USERNAME' PASSWORD = 'MY_PASSWD' DOMAIN = 'positrones.net' SUBDOMAIN = 'my_subdomain' ADDRESS = '0.0.0.0' # If nil then try to get automagicaly URLS = { 'login' => 'https://login.hostmonster.com/?', 'drecords' => 'https://my.hostmonster.com/cgi/dm/zoneedit/ajax' } USER_AGENT = 'Windows IE 9' m = Mechanize.new do |a| a.verify_mode = OpenSSL::SSL::VERIFY_NONE a.user_agent_alias = USER_AGENT end def get_ip r = Net::HTTP.get('myip.positrones.net', '/') ip = r.match(/\d{1,4}\.\d{1,4}\.\d{1,4}\.\d{1,4}/) ip[0].to_s end # Do the login stuff print "Checking user and password... " page = m.get( URLS['login'] ); form = page.form_with( :name => 'theform' ) form['login'] = USERNAME form['password'] = PASSWORD send_button = form.button_with(:value => 'Login') form.click_button(send_button) page = page.links[0].click puts "done!" # Edit the DNS Zone page = page.link_with(:text => 'DNS Zone Editor').click print "Getting old zone records... " json = JSON.parse( m.post( URLS['drecords'], {'op' => 'getzonerecords', 'domain' => DOMAIN} ).body ) puts "done!" print "Trying to get subdomain old info... " json['data'].each do |r| if r['name'] == SUBDOMAIN print "done!\nSaving new address[#{r['address']} => #{ADDRESS||get_ip}]... " json = m.post( URLS['drecords'], {'op' => 'editzonerecord', 'domain' => DOMAIN, 'name' => SUBDOMAIN, 'orig__name' => SUBDOMAIN, 'address' => ADDRESS||get_ip, 'orig__adress' => r['address'], 'ttl' => r['ttl'], 'orig__ttl' => r['ttl'], 'Line' => r['Line'], 'type' => r['type']} ) json = JSON.parse(json.body) if( json['result'] == 1 ) puts "done!\nAddress changed succesfully!" Kernel::exit(0) else puts "\nAn error has ocurred trying to save new address :(" Kernel::exit(1) end end end puts "The subdomain #{SUBDOMAIN} cannot be found!" Kernel::exit(1)
The first lines just load the libraries «mechanize» and «json».
Then we stablish the data of the hosting provider, the names are self explanatory, just few points:
- The domain must not have the www
- The subdomain must be alone. If you wanna change «code.positrones.net» just type «code»
- You can specify the new IP address of the A record. If you wanna use your public IP address to be detected, change to nil
The URLS hash contains the information of the login page and the ajax DNS editor of the Cpanel, change it to fit your needs 😉
The USER_AGENT it’s an id defined in the Mechanize library, in this case we want to identify as IE 9.
The login process usually takes place through an encrypted connection(HTTPS), then, for reasons not exposed here, we deactivate the verification of the SSL certificate and then set the USER_AGENT.
Then we define a method called get_ip, this method connects to a site which only returns the IP address of the client.
The rest of code log in into Cpanel, go to DNS Zone Editor and change the information of the given subdomain. The use Mechanize library it’s exposed in other post, you can read it if you wanna know the details.
The program returns 0 if everything goes fine, 1 in other case. By the way, I didn’t write some error management sentences, so be careful when use this code.
You can download from here.
Enjoy. 🙂