Network-wide AirPrint and easy printer configuration through DNS-SD
Before I get into the implementation details, the benefits should be clearly outlined. All print jobs are authenticated using the users’ Active Directory credentials and accounted for using PaperCut.
For iPads, iPhones, and iPod Touches - With absolutely no manual configuration, users can print to any available printer (network-wide) via AirPrint (video).
For Macs - With absolutely no manual configuration, all available printers appear in the Add Printer dialogue window the same way printers shared through multicast DNS or Open Directory do. Users are prompted for authentication immediately when they try to print. If the Mac already has the correct driver installed, it is pre-selected–no driver selection is necessary. If the Mac doesn’t have the correct driver, but it’s on this list, the driver will be automatically downloaded (and updated through Software Update) when the user adds the printer. If the Mac still doesn’t have the correct driver, a generic postscript driver is pre-selected.
For Windows - We’re still using our Windows print server currently, but a user will see all available printers through Bonjour Print Services for Windows with (otherwise) no manual configuration. That’s perfect if the user already has the printer’s driver, but otherwise, the user will have to select a driver or a generic PostScript driver is selected. SMB supports uploading drivers to clients, though, so I’m currently researching a way of configuring the CUPS server to share the same printers through SAMBA (that’s authenticated and supports our accounting software).
One might think something like this would require special routing or an otherwise “hacky” configuration, but the truth is this works with the added network complexity of just a few DNS records. I’ll explain.
AirPrint isn’t anything complex from a technical perspective. It requires only the following:
- A printer (or print server) capable of receiving PDFs over IPP.
- Advertisement over Bonjour that includes specific records.
A CUPS server requires only basic configuration to do this right out of the box. The key to making it work network-wide is to utilize the less-known unicast component of Bonjour: DNS-SD. When a Mac or iOS device browses for Bonjour services, it also performs a unicast DNS query based on the network connection’s search domain(s). You can run the query yourself in the Terminal on your Mac with the following command:
dig ptr b._dns-sd._udp.dns-sd.org
This is what the device will query if its search domain is set to dns-sd.org. This is the device’s way of asking, “Where are the DNS-SD services for dns-sd.org hosted?” Normally no records are returned, so the device assumes the domain has no advertised DNS-SD services. If you run the above command, though, you’ll see that it returns two records:
;; ANSWER SECTION:
b._dns-sd._udp.dns-sd.org. 60 IN PTR dns-sd.org.
b._dns-sd._udp.dns-sd.org. 60 IN PTR IL\0322\0324th\.\032Floor\032South.dns-sd.org.
This represents the domain’s DNS server responding, “Our DNS-SD services are hosted on the domains: dns-sd.org and IL 2 4th. Floor South.dns-sd.org.” From that point on, the device resolves Bonjour services through unicast DNS the same way it does through multicast DNS (mDNS)… except with the domain(s) returned instead of .local.
Want to see it yourself? On your Mac or iOS device, manually set your search domain to dns-sd.org. Now try to print (or on the Mac, add a printer). You should see Stuart’s Home AirPrint Printer (and some others, too, on the Mac). Enabling AirPrint network-wide is simply a matter of adding the DNS records above (to enable DNS-SD browsing), then advertising records on the domain you specified in the same way CUPS already does over multicast. Easy, right?
Our configuration consists of a print server running the following:
- Ubuntu 11.10 (64 bit).
- CUPS 1.5.0
- HPLIP 3.11.7
- BIND 9.7.3
- LikewiseOpen 6.1.0
- PaperCut CUPS Backend (server version 11.6)
It’s worth noting that I listed the version numbers for clarity’s sake, but I didn’t need to seek out any special versions–these were just the latest available at the time.
The first step is to install CUPS and some drivers. Luckily most of our printers are manufactured by HP and HP seems to really go above and beyond to support Linux printing. After installing the HPLIP package, printer configuration couldn’t be much simpler. You simply run:
hp-setup -i <IP address of printer>
That’s all. A guided wizard walks you through the rest of the process, in which it automatically selected the proper drivers for each printer in our fleet.
By default, CUPS handles authentication (for any printers that require it) the same way Linux handles user logins, so any user that can log into the machine can print. As a result, using a Pluggable-Authentication-Module seemed to be the simplest configuration. Rather than having to configure Kerberos myself, I used LikewiseOpen to bind the machine to Active Directory. This allows any valid domain user to log in to the machine, and therefore, print. To keep them from logging into the machine through SSH, I set SSH to use certificates instead of passwords. This also allows me to securely access it without having to type in a password each time.
OK, so now I have a CUPS server that will only allow authenticated domain users to print. The next step was to install the PaperCut CUPS backend. It takes care of our accounting and reporting, and will reject the jobs of any students who print more than their allotted quota. Their guide was clear and it was soon installed without a hitch.
That covers most of the “easy stuff” that you’d do to set up any CUPS server. It should now be properly authenticating and accounting for all print jobs. If you turn on “DNS-SD” sharing through CUPS and your iOS device is on the same subnet as CUPS server, AirPrint should already be working. The only remaining step is to make it work for the whole network.
Bonjour Across Subnets (“Wide Area Bonjour”)
First, you’ll need to install BIND and configure it to be authoritative for the domain on which you’d like to advertise services. For ours, I used cups.setonhill.edu. Then, you’ll need to create a delegation of that domain in the parent domain (in our case, setonhill.edu). This ensures that DNS queries ending with cups.setonhill.edu are resolved from our print server. Finally, add pointer records for the search domain you’re giving out via DHCP (in our case, setonhill.edu) that tell devices using Bonjour to browse for services on the delegated sub-domain.
The necessary records are:
b._dns-sd._udp.setonhill.edu. IN PTR cups.setonhill.edu.
lb._dns-sd._udp.setonhill.edu. IN PTR cups.setonhill.edu.
Now DNS queries ending with cups.setonhill.edu are resolving to our print server and any Mac or iOS device with a DHCP search domain of setonhill.edu will query it for Bonjour services.
All that’s left to do is configure BIND to advertise those services! The process takes a few steps, but it’s scriptable and hopefully is only necessary until it’s included in CUPS (or as a plug-in).
First, be sure DNS-SD sharing is enabled through CUPS. CUPS only supports the multicast version, so we’ll need to convert the multicast advertisements to unicast ones.
Here’s an example of the necessary records (4) to advertise a printer.
_ipp._tcp PTR TLC\032121\032\040Color\041._ipp._tcp
_universal._sub._ipp._tcp PTR TLC\032121\032\040Color\041._ipp._tcp
TLC\032121\032\040Color\041._ipp._tcp SRV 0 0 631 cups.setonhill.edu.
TLC\032121\032\040Color\041._ipp._tcp TXT "txtvers=1" "pdl=application/octet-stream,application/pdf,application/postscript,image/jpeg,image/png,image/urf,image/pwg-raster" "priority=0" "qtotal=1" "TLS=1.2" "rp=printers/tlc-121-color" "adminurl=http://cups.setonhill.edu:631/printers/tlc-121-color" "product=(HP Color LaserJet 4700)" "ty=HP Color LaserJet 4700 hpijs pcl3, 3.12.2" "note=Ruthie's Office" "air=username,password" "URF=W8,CP1,RS300-600,DM3,SRGB24"
Any non-alphanumeric characters should be escaped with their ASCII code equivalent (as above, the name that will be visible to end users is “TLC 121 (Color)”, but the spaces and parentheses were escaped).
The red line advertises “TLC 121 (Color)” as an IPP printer on the domain. The blue line is just another pointer that’s necessary for AirPrint. The green line tells the client what host is providing the service (cups.setonhill.edu) and the port on which to request it (631), and the final one is what we need from CUPS–the TXT record.
For this, I use a utility called avahi-browse. Avahi is basically the Linux equivalent to Bonjour on the Mac. From the CUPS server itself, run this command:
avahi-browse -r -t _ipp._tcp
This will output all printers shared locally through mDNS, including their TXT records. The TXT records here are what should be used in your BIND zone file.
You’ll notice the first three records can be created without CUPS. The advertised name of the printer is irrelevant to CUPS, and your host and port will be the same for all shared printers. All you really need from CUPS is that TXT record, and that’s an easy way to get it. Add the records to your zone file in the format shown above, restart BIND, and your printer should now be shared through AirPrint (and Bonjour) to all devices with the DHCP search domain you’ve provided.
Having to manually edit a zone file any time you update your printer roster is pretty terrible, though, so I wrote a quick PHP script to automate the process. The end result is that any time I add, delete, or modify a printer, I run a quick script from the command line that re-generates the BIND zone file based on what CUPS is sharing, runs named-checkzone, and reloads the zone if no errors were found. It also takes care of escaping non-alphanumeric characters–a process that’s fairly tedious by hand. Even this, though, as I mentioned above, is only necessary until someone enables that functionality through CUPS. CUPS itself is open source, so it’s something I’ll probably end up tackling if nobody gets to it soon.
UPDATE 2013-10-29: I just updated the advertisements shown above to the ones that work with iOS 6 and iOS 7. I’m currently still troubleshooting an issue with double-sided printing on iOS 7, but no other issues have been reported.