Monday, April 17, 2017

Rasperry Pi SSH Over Bluetooth

I have been trying to do this for years, always failing.  In theory, it is possible to setup a network, called a Personal Area Network, using Bluetooth.  Once a PAN is setup, it should be easy to SSH into a machine on the network that is running an SSH server, for example a Raspberry Pi.  This is a very desirable situation where the only wireless network does not allow computers on it to see each other, for example a public network at a college.  In the past, my solution was using an ethernet cable to setup an ad hoc network, which works but can be very inconvenient.  I recently got a Raspberry Pi 3, and after several hours of research, I finally got it working!

The main problem I have run into with this is that most instructions for using Bluetooth on the Pi are geared toward connecting to Bluetooth devices offering a service, for example Bluetooth speakers or a Bluetooth keyboard.  It should not be terribly difficult to setup a Bluetooth PAN this way, using a Windows or Mac computer as the service provider and the Pi as a client.  There are a few problems with this though.  The first is that getting the Pi to log onto the computer typically requires access to the Pi.  In other words, you need either a monitor and keyboard or an SSH connection over some other network.  This defeats the purpose.  The second is that the Pi is offering the SSH service.  It does not make sense for the device offering the desired service to have to initiate the connection to the client.  This may seem trivial, but in practice it means that to automate the process you would have to run something on the Pi to constantly try to connect until it is successful, and that is wasteful and inefficient, not to mention error prone.

So, my goal was to setup a Raspberry Pi as a PAN server that my Windows laptop can connect to and then access the SSH service running on the Pi.

What you will need for this:

A Pi 3, or a Pi or Pi 2 with a USB Bluetooth dongle, and a laptop or desktop computer with Bluetooth (USB dongle or built in).  Don't get a cheap USB Bluetooth dongle from China.  It turns out that is probably why I have failed so often in the  last several years.  The $1 Bluetooth dongles I got from China don't seem to support the mode required to host a PAN network.  The Pi 3's built in Bluetooth works fine, and I have a more expensive USB Bluetooth dongle I got from Walmart 5 or 6 years ago that also works fine (on an old Pi B+, no less).

Boot up your Pi and log in.  You will need direct access for the setup, so either connect it to a keyboard and monitor, or SSH into it through other means.

Now,  we need to do a lot of things as root, so we are going to log into the root account.

    sudo su

From here on out, be very careful.  As root, you can do pretty much anything to your Pi, and Linux does not typically ask you to confirm when instructed to have destructive behavior.

Now update your Pi and install some packages you will need to continue (you will need internet access for this).
  
    apt-get update
    apt-get upgrade

    apt-get install bluetooth bluez-tools python-dev libsystemd-dev bridge-utils python-pip libdbus-1-dev libdbus-glib-1-dev
    pip install systemd-python

    pip install dbus-python

Each of those will take 30 seconds to a few minutes.

Next we need to create some files.  Each entry below will start with the file name surrounded by some dashes.  Below that is what the contents of the file should look like.  When you are done, you should have created four new files.

-----/etc/systemd/network/pan.netdev-----
[NetDev]
Name=pan
Kind=bridge
ForwardDelaySec=0



-----/etc/systemd/network/pan.network-----
[Match]
Name=pan

[Network]
Address=0.0.0.0/24
DHCPServer=yes
IPMasquerade=yes


-----/etc/systemd/system/pan.service-----
[Unit]
Description=Bluetooth Personal Area Network
After=bluetooth.service systemd-networkd.service
Requires=systemd-networkd.service
PartOf=bluetooth.service

[Service]
Type=notify
ExecStart=/usr/local/sbin/pan

[Install]
WantedBy=bluetooth.target


-----/usr/local/sbin/pan-----
#!/bin/sh
iptables -F
iptables -t nat -F
iptables -t mangle -F
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE

exec /usr/local/sbin/bt-pan --systemd --debug server pan


Once you have created these four files, you need the make the final one executable.

    chmod +x /usr/local/sbin/pan

Now you will need to install a script that handles some communication with the Bluetooth system.

    wget https://raw.githubusercontent.com/mk-fg/fgtk/master/bt-pan -O /usr/local/sbin/bt-pan
    chmod +x /usr/local/sbin/bt-pan


Now we are on the home stretch.  The last thing is making it all start up when the Pi boots.  First we will start the Bluetooth PAN service.

    systemctl enable pan.service

Next we need to tell it to listen for incoming connections.  Before we do this, we need to find out the MAC address of the Bluetooth adapter of the client machine (in my case, my Windows laptop).  In Windows 10, you can find this by opening the Properties of the Bluetooth adapter in the Device Manager.  One of the tabs will list the address of the device.  For other operating systems, you should be able to consult Google to find instructions for finding the MAC address of your Bluetooth adapter.

Once you know the device address, you can continue.

    crontab -e

The first time you run this, it will ask what editor you want to use.  Pick the one you are most comfortable with.  At the end of the file, add the following line:

    @reboot echo -e 'power on\ndiscoverable on\nagent on\ntrust 00:00:00:00:00:00\nquit' | bluetoothctl

Replace the colon separated zeros with the address of your client Bluetooth adapter.  This will tell the Pi that it should allow connections from that device.  Without the correct address here, the Pi will reject connections over Bluetooth.  If you need more than one device to be able to connect, you should be able to add additional trust lines to this string, with the Bluetooth adapter MAC addresses for those devices.  (Each should start with \n, followed by trust, a space, and then a MAC address.)  Save the file to the default location and exit the editor.

Lastly, if you have not already enabled SSH on the Pi, you will need to do that.  Run raspi-config.  Choose option 5, Interfacing Options, and then pick SSH, which is P2 in that menu.  Enable it, then close the configuration program. 

Now, reboot the Pi!  (I run init 6, but there is also a reboot program you can run from the command line.)


From here, you will need to look up how to log into a PAN for the operating system on your client computer.  In Windows 10, you right click the Bluetooth icon in the system menu, add a Bluetooth device, and connect to your Raspberry Pi.  Once connected, you can right click the icon again, click Join a Personal Area Network, right click on the icon for the Pi in the window that opens, then click Access Point in the Connect Using menu.  The default IP address for the Pi seems to be 10.0.0.1, though I am looking into changing this, as it is commonly used in business networks and may make it difficult to connect to the Pi while on some wireless networks.

I have found that this is sometimes a bit unreliable.  I do not claim to be an expert on Bluetooth, and I am still learning, but I believe the Pi may reject the trust command if it cannot detect the device when it boots.  If you have issues, make sure the client computer is running before turning on the Pi, and make sure the Pi is reasonably close when it boots (Bluetooth has a very short range).  This will ensure that the Pi can detect the client computer when it runs the trust line, hopefully consistently allowing you to log into the PAN and SSH into the Pi.


I'll update this as I learn more.  There are still some challenges that I want to see if I can overcome to make things work more consistently and smoothly.  Some of this seems kind of hacky, but there is not enough information available on using Bluez5 to do this, so it is all I have right now.

No comments:

Post a Comment