Fight against the AXIS [of evil]

Oct 24, 2007 16:07

I can't even imagine what did the AXIS engineers smoke or what kind of joke did they intend, but the outcome of our several-months-long cold war against local office printserver gear turned out to be quite surprising.

First of all, Windows did manage to print, Linux didn't. We tried almost all possible CUPS printer options, all up to no avail.

Previously, we could print from Linux to the same H/W using the same AXIS printserver through port 9100, but then 9100 had been blocked and all we've got since were SNMP and tcp port 515.

Of course, we sniffed tarffic exchange between printserver and Windows, just to find out that the protocol is indeed the venerable LPD.

I installed BSD LPR package for tests - it's a lot simpler than CUPS, doesn't have all those pretty GUI bells and whistles, thus much more straightforward. BSD LPR did not help though.

Next thing that I've noticed was the source port - Windows did use unprivileged one. Linux used privileged one (usually 1023). Funny.

We ran strace. Noticed bind(3, {sa_family=AF_INET, sin_port=htons(1023), sin_addr=inet_addr("0.0.0.0")}, 16) = 0

So, guess how could we force lpd/lpq to use unprivileged source port? Well, there's no way. It's short on cmdline or configuration options for doing that.

We've downloaded LPR sources and grepped them for bind - the single hit, for binding "listen" socket only. A mystery... After thorough reading through sources, the answer is found - rresvport_af()! (for the curious readers, look into /usr/include/netdb.h for this rare pearl of BSD wisdom :)). OK, lpd and lpq indeed bind to privileged source ports when communicating with remote lpd. And there's indeed no configuration parameters for affecting this behaviour. We could hardcode different behaviour and recompile (and we did this, JFF).

But there's a better way:
iptables -t nat -A POSTROUTING -d axis.print.server.address -p tcp --sport 1:1023 --dport 515 -j MASQUERADE --to-ports 1024:2047

After this AXIS printserver started to accept print jobs from Linux.

P.S. I knew there was something missing here - a remote port name. The one sniffed from Windows was LPT1 - it's a suitable value for LPR's :rp: parameter or CUPS' queue name.

unix, linux, howto

Previous post Next post
Up