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.

Setting emacs zone-mode based on path

At work, we do a fair amount of DNS updates. Our zone files are stored in subversion, and are named according to the domain (with no .zone extension). It’s a real pain when updating a few (or a few dozen) zones in Emacs, since I have to remember to “M-x zone-mode” so the serial gets automatically updated. Here’s a lisp snippet to put in your .emacs file that will set zone-mode for all files in any path matching the regex svn/named/zones-internal. I deliberately made it a relative path (or, really, any path containing that) so it would work for all of my team’s workstations, no matter where we have the svn repo checked out:

(add-to-list 'auto-mode-alist '("svn/named/zones-internal/" . zone-mode))

Many thanks to taylanub on #emacs on irc.freenode.net for helping with this.

BIND9 Dynamic DNS

I needed a better solution for Dynamic DNS than dyndns.org for something, so I set about setting up DDNS through my BIND9 servers. I found a number of very helpful blog posts, including nsupdate: Painless Dynamic DNS, Painless DDNS part 2: the server, Secure dynamic DNS howto and A DDNS Server Using BIND and Nsupdate. Of course, the BIND configuration statement reference was also very helpful.

The whole process was relatively simple…

  1. Add an RR for the host I want, in the appropriate zone.
  2. Generate TSIG keys, distribute them to the client.
  3. Make sure you have logging enabled for things of interest in your logging section of named.conf:
    category dnssec { syslog_info; };
    category update { syslog_info; };
    category security { syslog_info; };
  4. Create a keys.conf file for your keys (you do split your configs out into usable chunks, right?):
    key foo.example.com. {
        algorithm HMAC-MD5.SIG-ALG.REG.INT;
        secret "this is your secret here (after Key: in the .private file)";
    };

    and include it in named.conf like include "/etc/named.d/keys.conf";

  5. Set an update-policy statement in named.conf. I just added mine to a specific zone in a specific view (external), as that’s the only place I would conceivably want updates right now.

    update-policy {
        grant * self * A TXT;
    };

    Assuming your TSIG keys are named for specific RRs, this will let any client (with a valid key setup on the server) update its own RR and nothing else.

  6. Finally, I created a script for ddns updates on the client. Since I want to be able to fire off this script manually or via cron (if I have to reload BIND, and until I make the needed changes to MultiBINDadmin), I bypassed the usual dhclient stuff and manually grab the current IP from the interface of interest. I symlinked this in /etc/dhcp3/dhclient-exit-hooks.d so it will run on DHCP updates.

    #!/bin/bash
    IFACE="eth0"
    TTL=3600
    SERVER=ns1.example.com
    HOSTNAME=foo.example.com
    ZONE=example.com
    KEYFILE=/root/ddns-keys/Kfoo.example.com.+157+12345.private
     
    new_ip_address=`ifconfig $IFACE | grep "inet addr:" | awk '{print $2}' | awk -F ":" '{print $2}'`
    new_ip_address=${new_ip_address/ /}
     
    nsupdate -v -k $KEYFILE << EOF
    server $SERVER
    zone $ZONE
    update delete $HOSTNAME A
    update add $HOSTNAME $TTL A $new_ip_address
    send
    EOF

When I finally got things setup, my only problem was with permissions on the zone file directories, which was easily corrected.Once this was straightened out, my nsupdate script ran flawlessly, and the update was instantly (thanks to using “notify”) propagated out to the slave server.

The only problem that I now have is one of my own creation – I use a small PHP application that I wrote (MultiBINDadmin) to manage DNS. It’s incredibly easy, as it keeps track of internal and external IPs, and everything else, for my zones, and triggers a pull on the master BIND server via the web interface. The only problem I now have is that this messes with DDNS updates. First, if I make changes in the web interface and there’s already been a DDNS update that day, the zone serial generated by MultiBINDadmin will match the automatically incremented serial generated by the BIND server. Second, and more troubling, when the BIND server reloads, it loses the dynamic update. So when I push changes to a zone from the web interface, my dynamic updates go away.

For the short-term, I’m just going to check the zone serial before I make any updates and, if need be, manually increment it in the web tool. As to losing the dynamic updates, I’m just going to have cron on the client fire the nsupdate script every 30 minutes. I also did a little kludge, setup a vhost on one of my web servers to answer for the dynamic host (as a catch-all page), and set the IP of my web server as the hard-coded RR address in the zone file. If someone tries to use the new (DDNS through my BIND server) address for HTTP and for some reason the current dynamic address disappeared (BIND reloaded), they’ll get a little page with a message and the old dyndns.org-based URL.

When I get around to it (or when this becomes a problem), I’ll make two changes to MultiBINDadmin:

  1. Before it pushes an update, check the current serial for the zone (ok, this may be a bit interesting, as the internal and external zones could have different serials) and increment from that.
  2. Have a “DDNS” flag in the database and GUI for RRs. For all flagged RRs, try to get the (unfortunately external) current address and update the record in the DB before the push.

The real question here, which I haven’t looked into yet, is how I can interrogate BIND about RRs for the external zone from an internal host.

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…