Filtered Bonjour Gateway – Bonway

February 2, 2014

There are a few “bonjour gateway” systems out there.  Aerohive has one, Cisco/Meraki has one, and many higher end WiFi providers have them built into their systems.  I have looked at Aerohive and Cisco in action as well as the tech sheets of many others and they all seem to have the same flaw: there is no way to filter. Oh some of them will let you filter which services are passed around, but not where they are passed around to. Oh sure, I can prevent one network from accessing the services on another network with the firewall, which I do, but that still means I am flooding ALL of my networks with bonjour traffic when they don’t need it.

This is where Bonway comes in. Bonway is a C++ project that allows the user to filter not only which services are relayed, but where they are relayed from and to. Let us take an example, one that should be very common to most organizations. Bear in mind, my use case is much more complex as we have even more networks but lets just start here.

We have 4 networks separated out as VLANs:

  1. Staff Wired
  2. Staff Wireless
  3. Dedicated Devices
  4. (Filtered) Public Access

All should be fairly self explanatory except number 3. Dedicated Devices VLAN is used for any church-owned device that either can’t join a WPA Enterprise network (think TV, Blu-ray, until recently Apple TV, etc.) or that we don’t want to (for example, an iPad that doesn’t belong to a single person so we don’t want his/her password tied to the device). VLAN #3 provides access to both WPA Personal devices as well as some hard-wired devices (again, Apple TV. The less WiFi traffic I have the better).

Both the Aerohive and Cisco solutions, when I implemented them for testing, would broadcast the Bonjour traffic to all 4 networks. The Aerohive one actually took down my network too because it was sending malformed Ethernet packets out, but that is another discussion.  So somebody on the Public Access could see all the Bonjour names and IP addresses, of the Staff devices. Personally I consider that not good. Why don’t I just take VLAN #4 out of the picture? Because there are SOME Apple TVs that I want available from both Staff and Public (think a conference room where the Apple TV is in PIN mode so nobody can take control unless they are in the room anyway, and I don’t want to give a bunch of visitors access to my staff network). As far as the real access control, that is still done on the firewall.

Lets take a specific example.  I want to allow bonjour information about AFP and VNC (for remote desktop) to travel from networks 1, 2 or 3 and travel to networks 1 or 2. Meaning people on the 2 staff networks can see each other as well as any devices on the dedicated devices network, but devices on the dedicated network can not see any devices on the staff networks.

Now, Apple TV information I want to be able to flow from networks 1, 2 or 3 and travel to networks 1, 2 or 3. Meaning they can all see each other’s Apple TVs. Additionally, I want Apple TV information to flow from network 3 and travel to network 4, if the name matches a list of allowed devices.

Bonway’s configuration file allows you to configure any combination of filters, including the source network, destination network and service name (as in _afp._tcp). This works right now and has been running at the office for over 3 months without problems. Here is a quick sample of allowing airplay from eth0 (staff wired) to eth4 (staff wireless). Note the fact there are two services allowed, one is for airplay (video) the other is for airplay (audio):

service {
type = { "_airplay._tcp", "_raop._tcp" }
server = { "eth0" }
client = { "eth4" }
}

And another example for two-way communication for AFP:

service {
type = { "_afpovertcp._tcp" }
server = { "eth0", "eth4" }
client = { "eth0", "eth4" }
}

Bonway works by listening on the Multicast DNS UDP port 5353 (this means it is incompatible with other Multicast DNS programs like Avahi). Anytime a packet is received each piece of information (query or answer) is looked up in the configuration to determine if it is allowed to pass in from the specific interface. If a match is found, it is sent out to all the corresponding interfaces. There is some basic caching done, but only to track information for filtering. Meaning if we already know that a service should be responded to, we don’t respond from the cache, we still pass it along through the respective interface(s) to be responded to by the actual device.

The upside is that information is always correct, and it prevents issues from Mac complaining about another device on the network using the same name if on both WiFi and Ethernet. For whatever reason, when trying to send the responses from cache it confused any “multi-homed” Mac. The downside, is that we never check to make sure a name is available, we just pass it along. So far this hasn’t been an issue, nor do I expect it to really be an issue as it would really be my own fault for things conflicting (for the most part). Where this could be a real issue is over the WAN links. If I have two devices with the same name (for example, say I called AFP servers on both campuses fileserver) then there would be constant conflicts – again this would be my own fault. I haven’t decided how to deal with this just yet, I might provide an “append” or “prefix” option on WAN links in order to modify the name.

Currently this should compile without error (assuming you have the prerequisites installed) on Fedora systems, which is was built with. I will be testing it shortly on Ubuntu as well. It should build and run on any Linux system, though it may require a few tweaks. In theory, it should also run on any BSD type systems, but there will probably need to be more compatibility changes. If you want to run it now, go ahead. If you want to provide some patches back to further development that would be even better. At the very least, it seems to work now. If you want to get it installed, head on over to github and compile.

Things to come in the (hopefully near) future:

  • Filtering by device name (as in the room101._airplay._tcp portion), you will be able to filter both the _airplay._tcp portion as well as the room101 portion, so only specific device names flow through. This is basically working, I just need to add it to the config file format and modify the filter function.
  • WAN support, for example if you have a site-to-site VPN setup and want a few specific services to flow between campuses (in our case, I would like the ._afp._tcp service for our main file server to automatically flow from the main campus to all other campuses) – this will take a little more work.
  • Aliases for network interfaces (instead of “eth0”, being able to reference it as “staff_wired”).