Setting up a Bonjour Name Server

Bonjour is a networking technology that allows devices to automatically discover each other without any configuration. In the first release, Bonjour operated on the local network to provide ad-hoc discovery for applications and devices. Starting in Mac OS X v10.4 Tiger and Bonjour for Windows, a network administrator can set up a Bonjour name server to enable wide-area capable devices and applications to discover services anywhere in the world. This document will explain how to set up a machine running Mac OS X to act as a Bonjour name server to facilitate wide-area discovery on your network. You can also use Linux, Solaris, or any other Unix-style operating system that can run the BIND name server. If you want clients to be able to browse to discover specific services of your choosing, but you don't want to allow individual machines to dynamically register their services, you can also manually add Bonjour service discovery records to your existing name server.

Introduction

Wide-Area Bonjour uses DNS Service Discovery [DNS-SD] along with DNS Update [RFC 2136] and TSIG security [RFC 2845]. Like most Linux distributions, Mac OS X includes the standard BIND DNS Server (named), which supports DNS Update. It's also recommended that you run the dnsextd daemon (also included in Mac OS X). The dnsextd daemon implements two DNS extensions that enhance service discovery:

  1. DNS Long-Lived Queries [DNS-LLQ] allow clients to be immediately notified when new services are added or removed from the server. Without Long-Lived Queries, clients would have to poll periodically (e.g., once an hour) to find out when services become available.
  2. DNS Update Leases [DNS-UL] impose a time limit on record updates, so that service registrations are automatically deleted if the client crashes or goes away unexpectedly. Using standard DNS Update without Update Leases, records remain on the server forever, until deleted manually by the server operator.

You can use wide-area Bonjour without running dnsextd, and it will still work, but with the two limitations above.

The instructions below should be enough for someone experienced with DNS to set up a DNS server configured for Wide Area Bonjour, but if you've never set up a DNS server at all before and you find it a little confusing, DNS and BIND, Fourth Edition is a great guide that tells you everything you need to know about setting up and configuring named, the Berkeley Internet Name Daemon (BIND).

Service Registration Zone for Wide-Area Bonjour

First, you need to pick a name for your wide-area Bonjour zone, the domain in which clients will browse and register. This should be a subdomain of your organization's domain. For example, if your organization's domain is "apple.com", your service registration zone could be "bonjour.apple.com".

Shared Secrets

Without a shared secret, anyone who has access to your Bonjour name server can make registrations. This may be acceptable in some situations, like behind a firewall when you trust all the people who have access to your server. You may also want to run this way if you're just experimenting with the technology to get a feel for how it works, but normally when running an operational Wide-Area Bonjour service you'll want to set up your name server to accept updates only from authorized clients. The way a client proves it's authorized is by using a DNS TSIG record to sign its update packets using the proper shared secret for that domain [RFC 2845].

You can use the dnssec-keygen command-line tool to generate a random shared secret. This command creates two files. We'll pull the shared secret from the .key file. After we copy and paste this key into our BIND configuration file, delete the files generated by the tool so that you don't accidentally leave them lying around for someone to find. Execute the command with the following arguments, substituting your own zone name:
dnssec-keygen -a HMAC-MD5 -b 128 -n ZONE <your zone>
The following shows how to generate a shared secret for the "bonjour.example.com" domain.
# dnssec-keygen -a HMAC-MD5 -b 128 -n ZONE bonjour.example.com.
Kbonjour.example.com.+157+55295
# cat Kbonjour.example.com.+157+55295.key
bonjour.example.com. IN KEY 256 3 157 CnMMp/xdDomQZ4TelKIHeQ==
# rm Kbonjour.example.com.+157+55295.*

For the domain "bonjour.example.com", our shared secret is "CnMMp/xdDomQZ4TelKIHeQ==". For more information about the dnssec-keygen command, please see the manual page.

Configuring BIND

To set up a Bonjour name server in Mac OS X, you'll need to edit the BIND configuration file (/etc/named.conf). If you're not already running a name server on your machine, start with a blank file and add the contents below. Otherwise, add the following to your existing configuration file (typically /etc/named.conf):
options {
  // tell named where to find zone files
  directory "/var/named";

  // these answer DNS queries outside of the bonjour.example.com. zone.
  // insert address(es) of your normal DNS servers or caches here.
  // On Mac OS X, you can find the address(es) via the "scutil --dns" command.
  forwarders { 1.2.3.4; 5.6.7.8; };
};

// entry for our new zone
zone "bonjour.example.com." {
  type master;
  file "db.bonjour.example.com";
  allow-update { key bonjour.example.com.; };
};

// key for updating our zone
key bonjour.example.com. {
  algorithm hmac-md5;
  secret "CnMMp/xdDomQZ4TelKIHeQ==";
};

// If you don't wish to use a shared secret, replace the line
// allow-update { key bonjour.example.com.; };
// with
// allow-update { any; };
// and omit the key definition.
// If you wish to create a key per user, and don't want to have to include
// the entire list of keys explicitly in the "allow-update" declaration,
// you can use an "update-policy" declaration instead, like this:
// update-policy { grant * wildcard *.bonjour.example.com.; };

Writing the Zone File

Next you'll need to create a zone file named db.<your zone>, for example, "db.bonjour.example.com" and copy it into /var/named. The only change that you need to make is to replace the two instances of "wab.example.com." with the hostname of your server (don't forget the dot on the end).
$TTL 3600 ; One hour default TTL

; Replace wab.example.com. below with your machine's hostname
@ IN SOA wab.example.com. unused-email (
                                1          ; serial
                                10800      ; refresh (3 hours)
                                3600       ; retry   (1 hour)
                                604800     ; expire  (1 week)
                                60         ; minimum (1 minute)
                                )

; Specify your server as the nameserver for your zone,
; substituting your machine's hostname.
@ IN NS wab.example.com.

; Specify the server which handles DNS updates for your zone,
; typically port 53 on the same server as above.
; If you're going to be running dnsextd (see below) then the port number is typically 5352
_dns-update._udp IN SRV 0 0 53 wab.example.com.

; Add PTR records telling clients that they can browse and register here
b._dns-sd._udp  IN PTR @   ;  "b" = browse domain
lb._dns-sd._udp IN PTR @   ; "lb" = legacy browse domain (include domain in empty-string browses)
r._dns-sd._udp  IN PTR @   ;  "r" = registration domain

Discovering Your Server

If you have access to the parent zone's DNS server, you can delegate the new zone to the new server by adding an entry in the example.com. zone file:
bonjour.example.com. 86400 IN NS wab.example.com.
Your network administrator may be able to do this for you. If you do not have access to the parent zone's DNS server, a temporary alternative while testing is to simply add the IP address of the new server to the "DNS Servers" field of the Networking Preference Pane in each client computer. However, manually entering the IP address on the clients is a short-term solution, not really suitable for long-term use. The whole point of DNS is that clients learn the DNS server for a given domain, not by manual configuration, but by following the chain of delegation (NS records) from the root. Likewise, for reliable operation, your subdomain should be properly delegated from its parent.

Discovering Domains

Computers running Mac OS X Tiger or later and computers running Bonjour for Windows will issue domain enumeration queries to automatically discover browse and registration domains on the network. The easiest way for clients to discover your domain is by creating PTR records pointing from the DHCP domain name to your new zone. This requires administrative control of that domain. For example, if the DHCP "Domain Name" option (option code 15 [RFC 2132]) that the DHCP server sends to its clients is "example.com", then you need to create the following entries in the "example.com" zone file to tell those DHCP clients about your new "bonjour.example.com" domain:
; Add for applications to discover your domain as a potential place to browse
b._dns-sd._udp.example.com.  3600 IN PTR bonjour.example.com.

; Add if you want your domain to be chosen as the default
; browse domain in the Bonjour Preference Pane
db._dns-sd._udp.example.com. 3600 IN PTR bonjour.example.com.

; Add for this domain to show up in the list of potential registration domains
r._dns-sd._udp.example.com.  3600 IN PTR bonjour.example.com.

; Add if you want your domain to be chosen as the default
; registration domain in the Bonjour Preference Pane
dr._dns-sd._udp.example.com. 3600 IN PTR bonjour.example.com.

; Add the following line so that applications that do empty-string
; domain browses will browse your zone in addition to "local."
lb._dns-sd._udp.example.com. 3600 IN PTR bonjour.example.com.
If you don't have administrative control of that domain, as a last resort, you can manually force a client to "discover" your new "bonjour.example.com" domain by adding it to the "Search Domains" field in the Network Preference Pane on each client. This will only work if you have the domain enumeration PTR records in the bonjour.example.com zone as shown in the "db.bonjour.example.com" zone file above.

Starting named

You should create a backup of the zone file before running named for the first time. Once you run your server with DNS Update turned on, you cannot edit the zone files by hand. If you need to reset your zone for any reason, simply revert to the saved copy, delete any .jnl files, and restart named and dnsextd.

named normally runs with no arguments:

# named

Check the syslog (/var/log/system.log) for errors. You can ignore any errors that say "/private/etc/rndc.key: file not found" or "couldn't add command channel". If any other errors occur, make sure that you put periods in exactly the right places in all files. See examples for correct usage of trailing dots. For debugging, you may wish to run it in the foreground, with enhanced logging:

# named -g -d 5

Starting dnsextd

The dnsextd daemon configuration file is /etc/dnsextd.conf. Typically the only thing you need to edit in this file is the name of the zone you want dnsextd to handle:

zone "my-dynamic-subdomain.company.com." {
        type public;
};

You can run dnsextd with no arguments:

# dnsextd

To run in the foreground with verbose logging for debugging, add "-vf".

# dnsextd -vf

Run with a single argument, "-h", for help and a full list of options.

Starting named and dnsextd automatically on boot

Once you have verified that your configuration files are correct, you can set named and dnsextd to start automatically on boot. Fist stop named and dnsextd if they are already running, and then execute the following commands:

# launchctl load -w /System/Library/LaunchDaemons/org.isc.named.plist 
# launchctl load -w /System/Library/LaunchDaemons/com.apple.dnsextd.plist

The "launchctl load" command tells the system to start that daemon; the "-w" option tells the system to make the change permanent so the daemon will be automatically started on boot too.

Configuration Clients

Now that your server is up and running, the next step is to configure each client on the network to use your new server.

http://www.dns-sd.org