Some PowerDNS Links and Interesting Features

At $WORK we lost a disk in the RAID1 of one of our external nameservers, and it rekindled an occasional discussion of migration from ISC BIND to PowerDNS. PowerDNS has separate authoritative and recursive servers, and doesn’t seem to natively support views or split-horizon the way BIND does, but it has some really cool features including very mature database backends, load balancing, Lua scripting support to modify how recursive queries are answered, and geolocation or IP-range based query results.

While this project is still just casual research, I thought I’d share some of the useful links and information I’ve found:

PowerDNS Front-ends:

  • JPowerAdmin – One of the two most popular, a GPLv3 Java (JBoss SEAM) based web UI with a RESTful API, with support for “multiple” database backends. Sponsored by Nicmus, Inc. Online demo (demo:demo). Looks nice, simple UI, but no support for split-horizon.
  • PowerAdmin – the other most popular, though it seems to be undergoing a large overhaul at the moment. Has full support for most of PowerDNS’s features, written in PHP, supports “large” databases, fine-grained user permissions, RFC validation, zone templates. Online demo (demo:demo). I don’t really like that it manages the SOAs as full text (without any templating, dropdowns or default values), and that it doesn’t prepopulate default values for TTL in the new record form, but it looks like a good starting place for someone (like me) who’s handy with PHP.
  • pdns-gui – PowerDNS GUI – Google Project Hosting – PHP/MySQL GUI. Online demo. Handles templates nicely but won’t scale to too many of them. Window-based UI is visually pleasing but will probably be a problem for big zones.
  • powerdns-webinterface – PowerDNS Webinterface – Google Project Hosting – A nice but relatively simplistic UI written in PHP. It has some nice features like multi-user authentication (and logging, though I haven’t looked into how detailed it is), automatic SOA serial update, automatic PTR creation, etc. Unfortunately not geared towards people with lots of domains and multiple records; it has only one template for new domains (and no way to update domains created from a template), no easy filtering, and still treats SOA like a single text record.
  • ZoneAdmin | SourceForge.net and Project website – Maybe not the fastest tool to use in bulk, but a nice, relatively intuitive and full-featured admin tool. Online demo (demo:demo).

Some links on PowerDNS split-horizon

It looks to me that split-horizon is going to be the hardest part for us, at least to also have a web UI to manage it. It looks like with PowerDNS, the most common way to run split horizon DNS (views) is to run two separate sets of servers or instances, either on different boxes or multi-homed; one for internal and one for external. While that sounds like quite a bit of overhead beyond what BIND does, the real problem is finding a web UI that supports it; I don’t care if it’s in two separate databases, but what I want is a logical (web UI) view that has zones made up of resource names (i.e. the leftmost column in a zone file) with one or two RRs (type, ttl, priority, value) – one for each view. That’s the real catch – all of our machines are in private IP space behind a firewall, so I need to be able to manage the internal and external records on one screen. While it’s not exactly scalable, and the code stagnated quite a bit once I got it to a point that was usable for me, this was the main goal of my MultiBIND Admin project.

PHP Script to Query Linode DNS Manager API

I’m in the process of moving all of my public-facing services, currently hosted on a single Linode, to a new virtual machine (still with Linode, of course, just a new CentOS 6 VM). Of course, I’ve got a lot (about 60) of DNS records, spread across 8 domains, that point at the old machine. For name-based vhosts in Apache, my usual procedure is to migrate everything over to the new host and then change DNS, and once the change propagates (I’m using Linode’s DNS hosting, so it makes things a LOT easier but I don’t have rndc reload anymore) I test in a browser and, assuming all is well, disable the vhost on the old server. To do all this, I need an easy way to get a list of all the DNS records that still point to the old machine.

Luckily, to augment their web-based control panel (Linode Manager), Linode has a pretty full-featured API with bindings for Python, Perl, PHP, Ruby, Java and others. While I like Python and I’m starting to learn Perl (by trying to shift most of my non-time-sensitive scripting to it) for my new job, PHP is still my strongest language (and the majority of my existing administrative scripting is written in it, especially handy when it comes time to add a web front-end to things). So I wrote the following script to query Linode’s DNS Manager API using Kerem Durmus’ Linode API PHP wrapper (installation instructions and info at that Github link). The script simply writes all Linode DNS records for all zones to a CSV file (this could take a while if you have a lot of records…).

<?php
  /**
   * Script to pull DNS information for all of your Linode hosted zones, output as CSV.
   *
   * Originally created when I moved DNS from in-house to linode, then started moving subdomains one at a time from my servers to Linode.
   *
   * Uses Kerem Durmus' Linode PHP bindings from <https://github.com/krmdrms/linode/>, many thanks to him for releasing this.
   *
   * INSTALLATION (as per krmdrms README):
   *  pear install Net_URL2-0.3.1
   *  pear install HTTP_Request2-0.5.2
   *  pear channel-discover pear.keremdurmus.com
   *  pear install krmdrms/Services_Linode
   *
   * Also requires php-openssl / php5-openssl
   *
   * USAGE: php linodeDnsToCsv.php
   *
   * Copyright 2011 Jason Antman <http://www.jasonantman.com> <jason@jasonantman.com>, all rights reserved.
   * This script is free for use by anyone anywhere, provided that you comply with the following terms:
   * 1) Keep this notice and copyright statement intact.
   * 2) Send any substantial changes, improvements or bog fixes back to me at the above address.
   * 3) If you include this in a product or redistribute it, you notify me, and include my name in the credits or changelog.
   *
   * The following URL always points to the newest version of this script. If you obtained it from another source, you should
   * check here:
   * $HeadURL: http://svn.jasonantman.com/misc-scripts/linodeDnsToCsv.php $
   * $LastChangedRevision: 25 $
   *
   * CHANGELOG:
   * 2011-12-17 Jason Antman <jason@jasonantman.com>:
   *    merged into my svn repo
   * 2011-09-12 Jason Antman <jason@jasonantman.com>:
   *    initial version of script
   *
   */
 
require_once("/var/www/linode_apikey.php"); // PHP file containing:   define("API_KEY_LINODE", "myApiKeyHere");
require_once('Services/Linode.php');
 
// get list of all domains
$domains = array(); // DOMAINID => domain.tld
try {
  $linode = new Services_Linode(API_KEY_LINODE);
  $result = $linode->domain_list();
 
  foreach($result['DATA'] as $domain)
    {
      $domains[$domain['DOMAINID']] = $domain["DOMAIN"];
    }
}
catch (Services_Linode_Exception $e)
{
  echo $e->getMessage();
}
 
$records = array(); // array of resource records
$linode->batching = true;
foreach($domains as $id => $name)
{
  $linode->domain_resource_list(array('DomainID' => $id));
}
 
try {
  $result = $linode->batchFlush();
 
  foreach($result as $batchPart)
    {
      foreach($batchPart['DATA'] as $rrec)
	{
	  if(! isset($records[$rrec['DOMAINID']])){ $records[$rrec['DOMAINID']] = array();}
	  $records[$rrec['DOMAINID']][$rrec['RESOURCEID']] = array('name' => $rrec['NAME'], 'type' => $rrec['TYPE'], 'target' => $rrec['TARGET']);
	}
    }
}
catch (Services_Linode_Exception $e)
{
  echo $e->getMessage();
}
 
echo '"recid","domain","name","type","target"'."\n";
foreach($domains as $id => $name)
{
  foreach($records[$id] as $recid => $arr)
    {
      echo '"'.$recid.'","'.$name.'","'.$arr['name'].'","'.$arr['type'].'","'.$arr['target']."\"\n";
    }
}
 
 
?>

That will print out a list containing the Linode DNS record id (recid), domain, record name, type and target:

"recid","domain","name","type","target"
"137423","jasonantman.com","","TXT","v=spf1 mx:jasonantman.com -all"
"3597859","jasonantman.com","","MX","linode1.jasonantman.com"
"3488952","jasonantman.com","","mx","linode2.jasonantman.com"
"3472952","jasonantman.com","blog","CNAME","linode1.jasonantman.com"

If you want to, say, search for only records that include host “example”, you could use grep and awk like:

php linodeDnsToCsv.php | grep linode1 | grep -v '"linode1","a"' | awk -F , '{printf "%-27s %-20s %-7s %s\n", $2, $3, $4, $5}' | sed 's/"//g'

I hope this helps someone else out, and saves them a few minutes of coding…

Thunderbird SSL “Domain Name Mismatch”

Some of my servers that are only for internal/personal use have SSL certs with a mismatched hostname. The cert for my mail server is issued for the CNAME used for my mail server, not the actual hostname. Of course, this means that Thunderbird gives me some annoying errors because they’re worried:

Domain Name Mismatch in Thunderbird

Luckily, there’s an add-on called “Remember Mismatched Domains” that adds a simple “remember this decision” check box, much like the one now found in Firefox. Problem solved!

Thunderbird Domain Name Mismatch after add-on

Project Announcement – PHPsa

So, here’s the “official” scoop on the new project that I’m planning/starting to work on. I’m calling it PHPsa for now, and it’s going to (hopefully) be an integrated dashboard/portal for SysAdmins. While there are a number of tools that fit into this general category (perhaps with OSSIM being the closest, though it’s security-minded), I feel that there’s a real gap in terms of tool integration. My daily workflow, which includes multiple trips to and correlation among Nagios, Cacti, DNS, DHCP, Puppet, logs, and other tools really leaves something to be desired. So, I’m setting out to create a modular SysAdmin dashboard that unifies many of the common SysAdmin-related tools into a modular dashboard.

The first overall design goals that I’ve set are:

  1. A modular, plugin-based architecture that allows admins to select which features/tools they want, and allows easy development of new modules.
  2. Design with legacy tools in mind – easy ways to tie in to tools that weren’t written with PHPsa in mind, both in terms of linking to information and gathering/unifying information.
  3. RBAC, including per-module rules and the possibility for a limited read-only view (client/user mode).
  4. Use of data sources, specifically web-based/REST APIs where available, and databases otherwise, from existing tools with as little modification as possible.
  5. Support for database abstraction, though I’ll be using MySQL.
  6. Eventually, implement RSS feeds of pertinent information.
  7. Balance Ajax/DHTML with the desire for important things to have canonical, static, bookmark-able URLs.

So, here are some of the things that I’m planning on integrating, with obvious bias towards getting my own projects done before I integrate pre-existing tools:

  • MultiBindAdmin, my DNS and DHCP administration tool (specifically geared towards split-view DNS with the inside view behind NAT).
  • RackMan, my tool for mapping devices’ physical locations in racks (and tacking patching).
  • My simple config tool for Puppet.
  • Nagios.
  • Cacti.
  • Nathan Hubbard’s MachDB.
  • Bacula (monitoring/status only).
  • Syslog via rsyslog (or any other syslog-to-SQL solution).
  • Possibly a front-end to Google Analytics.
  • Some of my custom scripts for graphing SpamAssassin, DNS queries, etc.
  • Some sort of Apache log analysis, like Webalizer.
  • Mail log analysis, possibly AWstats.

So, the first big issues that I’m going to tackle:

  1. General layout. Specifically, how to handle a more-or-less consistent layout while integrating tools that weren’t designed for PHPsa. I’ll probably end up using iFrames (or even a frameset) for tools that don’t integrate well.
  2. How to correlate data/objects between different tools (i.e. how to display information from Nagios, Cacti, MultiBindAdmin and MachDB for a given host?).
  3. Do I want to use a templating engine like Smarty or hand-code all of the HTML?
  4. How will I handle plugins?
  5. How much code do I want to re-write and how much can I use as-is from other tools? And, on a related note, how much existing data can I access easily from other tools, vs having to use grabber scripts that dump data in MySQL?

Update 2010-02-03: I think this may become a semi-official project for me at $work, which means that I’ll be able to dedicate quite a bit more time to it. Unfortunately, it also means that I will, most likely, have to give up Nathan Hubbard’s MachDB in favor of OCS Inventory NG, a more mature project that already includes inventory support for Linux, Windows and Mac.

DNS Move

Yesterday I finally began moving DNS for my sites from GoDaddy to my own in-house system of master/slave BIND9. While both DNS servers are currently at the same location and on the same WAN connection (heck, they’re beind the same router, too), so is all of the rest of my infrastructure. Migrating jasonantman.com was definitely the most critical task, this has allowed me to easily use my new project, MultiBIND Admin to manage DNS. In addition to just being simpler than using GoDaddy’s tool, it allows me to manage DNS for both the external view and the NATed internal view in one tool. I did have a brief mail outage thanks to some incorrect MX records being served by the slave, and a few other issues with the caching DNS servers at work not expiring the old records, but all seems to be well now. It was a relatively smooth transition, though I haven’t yet moved over some of my older less used domains.

The next part of my project, when I move the ambulance corps hosted services in-house, will be trying to find a decently-priced DNS hosting company that will just act as a slave, to keep DNS up if my WAN connection goes down.

DNS – Open Source rules

DNS is arguably one of the most important services on the Internet. Without it, every domain name and email address we know would be meaningless. We’d be thrown back into the days of IP addresses without corresponding names. And, given everything that depends on DNS, it’s also one of the most important services from a security standpoint. Compromised DNS servers could cause end-of-the-world havoc for whatever zones they control.

So here’s a fact that Microsoft and the other proprietary guys don’t want you to know: 58.65% of DNS servers that are listed as being authoritative for .com or .net domains are running the free/open source ISC BIND. Less than 0.3% are using a Microsoft product. To me, that says something.

This is according to the October 2008 measurement factory DNS server survey of 99+ Million addresses (618,000+ hosts).

New Projects

In terms of ongoing projects, I should be updating RackMan sometime soon, and also adding the demo site.

I’ve begun to move DNS for all of my domains in-house, mostly because since everything is behind NAT, it’s a real pain to manage DNS entries in two places (one of them being GoDaddy’s web interface). Because of the NAT issue, I’m also writing my own BIND configuration tool, currently named MultiBIND Admin. In addition to managing multiple zones in a sane way, it stores all configuration in MySQL. Among other things, it can store different IP addresses for A records for the inside and outside views. Zone files can either be pulled by a script on the name server (push capability is being worked on) or downloaded (for uploading to a DNS hosting provider like GoDaddy).

For my final project for my XML web design class, I’m going to be making some “mashup” with RackMan, Google Maps, Google Visualizer, Nagios, and a few other tools…

Stay tuned…

ROUThost DNS problems; GoDaddy and Security through Obscurity

The external-facing web site and (internal use) mailing list for the ambulance corps is hosted by ROUThost. Not my choice, it was inherited. ROUThost, first off, appears to be a fly-by-night hosting provider that just buys a few boxes in a colo facility. I should have known to raise a stink when they say you need to fax a copy of your driver’s license to get SSH turned on, and that you have to agree – in legalese – not to mess with anyone else’s configs. Well, last night, DNS for the site went down. As in nothing, wouldn’t resolve at all. I submitted a ticket online for ROUThost’s “24×7″ support – by the way, they don’t have a phone number, only an online ticket form. After 2h 34m 40s of downtime, the issue resolved itself and I downgraded the ticket from “critical” to medium. Now, 11 hours later, it still hasn’t been replied to. And my emails to support and management – 2 hours ago – are unanswered.

Once the problem started, I knew the yearly contract with ROUThost was a bad idea – even at $35/year USD. So, given the great experience I’ve had with them as registrar for my myriad domains, I took a look at >GoDaddy’s site. They offer shared hosting at around $4/month (for shared on a Linux box) and are currently offering some deals, so I figured it would be a good idea. I know and trust GoDaddy’s support, and have had an account with them for quite some time.

The ambulance corp’s web site, hosted through ROUThost, does essentially three things; provide a minimal web presence (the whole web root is probably < 1Mb minus the photo albums), five e-mail forwarders for the officers and a GNU MailMan mailing list for internal business. Unfortunately, I couldn’t find anything in their “features” list mentioning MialMan or any other listserv, or even what MTA/MDA they run.

I put a call in to GoDaddy “Sales/Support”. The poor guy had never heard of MailMan, but asked “one of the hosting guys” and was told it would only be supported on dedicate hosting accounts. Not exactly financially feasible for a mailing list with 30 subscribers, maybe 2 messages a day, and a monthly HTTP transfer of under 20Mb. I was told their shared hosting packages don’t include any mailing list/listserv software, though they include every CMS and language known to man. Hell-bent to get away from ROUThost, I then asked if they ran an MDA that supported piping mail to a command, as can be done with .procmailrc. After a brief hold (not to sound cynical, but I’m sure the gentleman was looking up “MDA”) he came back on the line and told me they didn’t. I then switched to problem-solving mode and asked what MTA and MDA they were running. Another brief hold, and I was told “I can’t tell you that”. Speechless for a moment, I asked what that meant; “we don’t give out that information”. Just about ready to begin explaining SMTP headers, I gave up and thanked him for his time.

Ok, so Sales probably doesn’t understand SMTP headers. I’d considered trying to find mail from a GoDaddy Linux hosted box and check the headers, but I figured I couldn’t do that before the call ended. So, now I’m left with a dilemma. ROUThost is not, in my opinion, reliable, and their support is flat-out nonexistent. 11 hours is far too long to wait for a reply to a “critical” ticket when someone claims 24×7 support. However, by previous experience, GoDaddy would be my next choice – but not only do they ot support mailing lists – arguably the most used feature of our current hosted account – but they won’t even tell a customer what MTA they’re running. I’m too let down by this to telnet 25 on one of their boxes and see what happens.

So what’s left? I guess waiting until (hopefully some time within the next few weeks) I upgrade to Optimum static IP at home, and consider running it all there (and hope mains power never goes out for more than 30 minutes?)