Hacker News new | past | comments | ask | show | jobs | submit login

Making a fake AirPrint printer.

I have a Brother printer that has two printer trays, one manual tray (that takes variable sized paper) and a A4 tray. However, when printing from iOS, it doesn't have the full print preset dialog and it is impossible to print from the manual tray, nor is there a way to tell it I want print A6. Of course I insist being able to print A6 whenever, wherever I want with AirPrint and accept no substitute.

So I started with the Bonjour printing spec (https://developer.apple.com/bonjour/printing-specification/b...), and dns-sd on macbook to figure out how AirPrint actually discovers printer and what makes it tick. The entire thing is built on mDNS which is basically DNS instead of using a DNS resolver, it sends the query via multicast DNS. If someone on the network wants to find an AirPrint printer, then it queries via mDNS _ipp._tcp.

e.g. $ dns-sd -Z _ipp._tcp With shows the PTR, SRV and TXT records. The TXT records are based on the Bonjour Printing Spec which list out which fields so it knows the type of the printer and driver to use and it uses the SRV port to find the ipp port so it can contact the printer.

Further investigation using rvictl (iOS packet sniffing) showed the IPP traffic, which is really http API. It is via this API that iOS determines what paper is supported from what tray.

The path is then clear: create my own mDNS service that returns a printer on my own port, this IPP port acts as a reverse proxy to the real printer's IPP port, but it modifies the "media-col-ready" attribute to make iOS think A6 is loaded into the manual try.

It was extremely painful, but it was done.

There were many pitfalls along the way:

* iOS expecting the mDNS to resolve in a certain way, which Hashicorp's library didn't support, this necessitated forking the library and fixing the resolver.

* iOS expecting not only _ipp._tcp but also requiring _universal._sub. (https://support.apple.com/en-us/guide/deployment/dep3b4cf515...) in mDNS, which further complicated the implementation and took time to figure out how it worked. Needed to test with `dns-sd -Z _ipp._tcp,universal`

* iOS detecting the printer via mDNS but when clicking on it, it says it's not available. It is because it insists that ipp has to be on port 631, and refuses to accept (unlike MacOS) ipp on any other port




This is some amazing yak shavings. Noted for future reference. I guess a github link is too much to ask? :-)



Thanks!


How did you solve that last (expected port) problem?

(I've run up against that elsewhere, and couldn't get over the hump for iOS.)


You can run in a container with bridged networking so it gets its own IP from your lan.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: