August 13, 2010

Weekend Project: Personal Area Networking with Bluetooth

Although most people think about Bluetooth in its "cable replacement" uses, such as with wireless audio headsets and keyboards, the Bluetooth standard defines a range of protocols and profiles optimized for specific uses. One of the most useful is the Personal Area Networking (PAN) profile, which encapsulates network-layer traffic, such as IP. This means you can use PAN to set up a cheap network access point over a Bluetooth adapter — the bandwidth will not be up to 802.11 speeds but it does offer some interesting properties, such as being invisible to wardrivers in the parking lot, and enabling Internet access on mobile devices without WiFi. To set up PAN on your Linux machine, start with a Bluetooth adapter and a working kernel.

Overview

The PAN profile defines several roles that any particular Bluetooth device can take on, such as a PAN user (PANU), a Group Network controller (GN), and a Network Access Point (NAP). The easiest scenario to configure is for your Linux box to serve as a NAP, forwarding IP traffic from connected client devices (such as phones) that are each configured as PANUs. The GN configuration is useful for a peer-to-peer Bluetooth-only network, which is out of scope for basic PAN functionality.

In addition to setting up the Bluetooth driver on the Linux box, we'll use the standard Linux networking stack to configure the Bluetooth device as a network bridge, just like we might when creating a WiFi-to-LAN bridge. Before getting started, make sure you have the bridge-utils package installed, as well as the BlueZ package, which includes several command line utilities you will need.

One final note: BlueZ, the Linux Bluetooth stack, released a major upgrade in 2008. To implement PAN with these instructions, you should be running a 4.x-series BlueZ stack; older versions were split into multiple packages (such as bluez-utils), and used a less streamlined configuration system. Unfortunately, that also means people running pre-2008 versions of BlueZ will have to track down a different set of instructions for setting up PAN.

Bluetooth device setup

First, you will need to jot down your computer's Bluetooth address, a twelve-character hexadecimal string more or less equivalent to a network adapter's MAC address. Run hciconfig -a, and copy down the address, which should look something like 12:34:56:78:90:AB. Inside the directory /var/lib/bluetooth/12:34:56:78:90:AB/ is a file named config; open it in a text editor and look for the "class" line.

The class is a three-byte description of the type of device and type of Bluetooth service that the computer will offer. Each bit in the first byte indicates a particular service (such as OBEX file transfer, Location positioning, or audio). The second byte indicates the type of device (computer, headset, GPS, et cetera). For PAN usage, you need to at least offer the class string 0x020100, which indicates Networking service and the general Computer device class.

For testing, you can simply set the class line in your config file to 0x020100 — if you use your computer for other Bluetooth services, though, you will want to calculate the correct hex string for all of the bits you need set. The same information is spelled out in human-readable terms by hciconfig, so you can double-check your binary-to-hex conversion. Also, make sure that "mode" is specified as "discoverable" and that you have an easily-recognized name on the "name" line, so you can recognize it from other devices.

Next, look at the file named "pincodes" — this is a saved list of the PIN access codes for the devices your computer has paired with. If you have already paired with the phone or other device you intend to use as a client, it should have a line in this file. If not, add one. You can run hcitool scan to capture the Bluetooth address of the phone. Simply enter the phone's Bluetooth address, followed by a single space, then some easy to remember numeric PIN. Likewise, add a line for your phone to the /var/lib/bluetooth/12:34:56:78:90:AB/trusts file; put the phone's Bluetooth address first, a space, and then the string [all].

Finally, create the file /etc/bluetooth/network.service, containing the following:

[Bluetooth Service]
Identifier=network
Name=PAN Network service
Description=Bluetooth PAN Access Point
Autostart=true

You should not need to restart the Bluetooth daemon for your changes to take effect; in order to be compatible with the ephemeral nature of Bluetooth device connections, the daemon looks for changes automatically.

Network configuration

By default, BlueZ creates a network interface for the NAP service named pan0 or pan1. You can configure routing for this interface just like you would any standard LAN adapter. For example, ifconfig pan0 192.168.2.1 netmask 255.255.255.0 up will bring the PAN interface up with the IP address 192.168.2.1. The 2 in this example is to place the PAN service — including the NAP itself and any PANUs that connect to it — on a different subnet than the rest of the LAN, which we will assume is in the 192.168.1.* address block.

You will need to run a separate DHCP server on the pan0 interface, however, configured to distribute addresses in the correct subnet, and configure routing between the two subnets.

However, the simplest way to permit Bluetooth phones and other devices to access the network via PAN is to create a bridge interface connecting pan0 and your normal network interface, such as eth0 or wlan0. The exact process varies slightly between distributions, but on Debian systems, for example, just add the following lines to /etc/network/interfaces (substituting your own IP address and gateway, of course):

auto bridge0
iface bridge0 inet static
  address 192.168.1.100
  netmask 255.255.255.0
  broadcast 192.168.1.255
  gateway 192.168.1.1
  pre-up ifconfig eth0 down
  pre-up brctl addbr bridge0
  pre-up brctl addif bridge0 eth0
  pre-up ifconfig eth0 up
  post-down ifconfig eth0 down
  post-down brctl delif bridge0 eth0

auto pan0
iface pan0 inet manual
  pre-up brctl addbr bridge0
  pre-up brctl addif bridge0 $IFACE
  up ifconfig $IFACE 0.0.0.0 up
  down ifconfig $IFACE down
  post-down brctl delif bridge0 $IFACE

What these stanzas do is create a virtual network interface named bridge0 that "contains" both eth0 and pan0. Linking the interfaces does place a bit of additional work on your plate, though — configuration details that you used to apply directly to eth0 now apply to bridge0. This means that you should configure DHCP to listen on bridge0 instead of eth0, for example. On the plus side, though, you do not have to worry about running separate DHCP services for the Bluetooth and wired clients on your network.

Uses and caveats

Most of the use-cases you read about for Bluetooth PAN involve Bluetooth-capable phones. With Bluetooth carrying IP traffic between your phone and Linux box, you can connect directly to a SyncML server to synchronize your address book and contacts, bypassing the phone's generally less-feature-rich built-in sync apps. You can also do regular Web and email work, but consume less power than a WiFi connection requires.

The tricky part of this equation is finding a phone that offers proper support for Bluetooth PAN. Many modern smartphones do, but then again most of those same phones also include WiFi. Unfortunately, older phones often include support for just a portion of the Bluetooth stack, such as hands-free headsets.

Because getting the Bluetooth configuration details correct is often more difficult than getting the networking details correct, if you are not sure of your phone's capabilities it may be a good idea to test the configuration with a second Linux machine, perhaps a laptop where you can turn off the WiFi adapter.

The good news is that Linux's Bluetooth support is getting better all the time. Work is currently underway to support the Bluetooth 4.0 standard's "low energy" profile, which will reduce battery drain even further. The GNOME and KDE desktop environments both have their GUI Bluetooth configuration tools, although neither of them has quite implemented all of the features needed to make Bluetooth PAN a point-and-click operation — yet. There is a third-party project called Blueman that offers simpler configuration than either the native GNOME or KDE interfaces provide, but proceed with caution: if you run Blueman in addition to the built-in tools provided by your desktop environment, there is an increased chance that they will collide and overwrite each others' changes, which could leave you with a puzzle to sort out. Or maybe that should be this week's extra credit?

Click Here!