Соединние компьютеров в сеть через bluetooth

Когда у меня завелась в доме парочка Bluetooth адаптеров, мне захотелось использовать их не только для обмена данными с мобильными телефонами, но и для организации сети, чтобы перемещаясь с ноутбуком по комнате не приходилось таскать за собой ethernet-овский кабель.

Все описания PAN (Personal area networking) которые мне удалось найти в сети (например это) какие-то фрагментарные. Поэтому я решил описать свой собственный опыт. Впрочем, вряд ли у меня получится лучше.

Постановка задачи

Имеется:
  1. Стационарный компьютер, подключенный к интернету.
  2. Локальная сеть подключенная к данному компьютеру (т.е задачи форвардига, маскарадинга etc уже решены, и на компьютере имеется работающй dhcp-сервер)
  3. Некоторое количество ноутбуков (N, N<7)
  4. Некоторое количество (N+1) USB Bluetooth адаптеров
Хочется:
Чтобы при втыкании в ноутбук bluetooth адаптера путем минимальных телодвижений ноутбук оказался в сети.

Настройка точки доступа

Точкой доступа является стационарный компьютер. НА нем у меня стоит Debian sarge.

Для организации доступа требуется решить две задачи

  1. Чтобы компьютер принимал соединения
  2. Чтобы после установки соединения по dhcp отдавалась необходимая конфигурационная информация
Для решения первой задачи достаточно запустить sdpd и pand с правильными параметрами. Эти демоны (как и hcid) входят в пакет bluez-utils.

В Debian для этого достаточно прописать две строчки в /etc/default/bluez-utils

PAND_ENABLED=1
PAND_OPTIONS="--listen --role NAP"
Решение второй задачи - более сложное и менее документированое. Видимо, большинство авторов хаутушек поднимали статические адреса на обоих концах линка и на этом успокаивались. Но у меня есть жена, а у жены - ноутбук. Поэтому приходится решать задачу в общем виде - с возможностью подключения более чем одного устройства.

Для того чтобы dhcp-сервер слушал на интерфейсе, интерфейс должен существовать в момент запуска dhcpd. Более того, pand создает для каждого bluetooth-соединения отдельный интерфейс. Замучаешься описывать и передергивать dhcpd по каждому соединению. Поэтому все HOWTO рекомендуют использовать bridging. Это такая функциональность в линуксовом ядре, позволяющая объединить несколько физических интерфейсов в один. Для работы с бриджингом нам понадобится пакет bridge-utils, в состав которого входит утилита brctl.

В PAN-HOWTO рекомендуется организовать бридж-интерфейс, в который будет добавлен эзернет-интерфейс локальной сети и будут автоматически добавляться bluetooth-интерфейсы по мере возникновения.

Никогда так не делайте. Дело в том что бридж он по своей природе вроде хаба - он проталкивает все пакеты, приходящие на один из включенных в него интерфейсов во все остальные. Соответственно, производительность бриджа равна производительности самого тормозного из включенных в него интерфейсов. Поэтому включив в один бридж 100-mb ethernet и bluetooth, вы посадите производительность ethernet-а до производительнсоти блютуза - т.е. до примерно одного мегабита.

Поэтому мы делаем следующее:

  1. Создаем и настраиваем бридже
  2. Не включаем ни одного физического интерфейса в этот бридж
  3. Напускаем на этот бридж dhcpd.

Готового скрипта куда можно вписать команды создания бриджа я не нашел. Поэтому в /etc/init.d был добавлен скрипт следующего содержания:

#!/bin/sh
#
# This script configures bridge interface for Bluetooth Personal Area
# network. This interface should be up before dhcpd started
#
#
IFACE=pan0
ADDRESS=10.0.0.1
NETMASK=255.255.255.0
BROADCAST=10.0.0.255

case "$1" in
start)
	# Creating bridge interface $IFACE
	brctl addbr $IFACE
	# Setting options according to HOWTO-PAN
	brctl setfd $IFACE 0
	brctl stp $IFACE off
	# Configuring interface
	ifconfig $IFACE $ADDRESS netmask $NETMASK broadcast $BROADCAST
	;;
stop) ifconfig pan0 down
	;;
*) 
	echo "Usage $0 start|stop" >&2 
;;	
esac
На этот скрипт создан симлинк в /etc/rc2.d с номером, меньшим чем у dhcpd (тот S20, а этот S15)

В принципе, можно было бы не включать в этот скрипт команду ifconfig, а честно описать его в /etc/network/interfaces как

auto pan0
iface pan0 inet static
	address 10.0.0.1
	network 10.0.0.0
	netmask 255.255.255.0
	broadcast 10.0.0.255
Но тогда следует позаботиться, чтобы скрипт, выполняющий brctl addbr. выполнялся до /etc/init.d/networking, т.е. в /etc/rcS.d. Почему-то мне эта идея не понравилась.

Теперь когда у нас есть интерфейс, мы можем прописать в /etc/dhcpd.conf соответствующую subnet и добавить имя этого интерфейса в строчку INTERFACES в /etc/default/dhcpd.

Приведу на всякий случай фрагмент из dhcpd.conf

  
# Это адрес сервера в ethernet-сети
server-identifier 192.168.217.1;

  subnet 10.0.0.0 netmask 255.255.255.0 {
  	max-lease-time 3600;
	option subnet-mask 255.255.255.0;
    default-lease-time 600;
    option broadcast-address 10.0.0.255;
    option time-servers 192.168.217.1;
    option lpr-servers 192.168.217.1;
    range 10.0.0.2 10.0.0.254;
	# Обязательно передавайте domain-name сервер
    option domain-name-servers 192.168.217.1;
    option routers 10.0.0.1;
	
  }

Осталось позаботиться о том, чтобы вновь появляющиеся bnep-интерфейсы включались в этот бридж и обслуживались dhcpd. Для этого пишем скрипт /etc/bluetooth/pan/dev-up следующего содержания:

#!/bin/sh
brctl addif pan0 $1
ifconfig $1 0.0.0.0
Первая команда в этом скрипте добавляе интерфейс $1 (т.е. тот, который pand передал в качестве параметра скрипту) в бридж pan0. Вторая команда - поднимает интерфейс. Устанавливать осмысленный IP там не надо, об этом позаботится уровень бриджа.

Да, еще. Рекомендую заменить на этом компьютере стандартный скрипт bluez-pin на что-нибудь менее интерактивное. Иначе во всяком случае при первом соединении придется вводить PIN на обоих компьютерах. См например мой вариант решения этой пробелмы

Настройка клиента

Настройка клиента намного проще. Поскольку сервер аннорсирует себя по протоколу sdp, то на клиенте достаточно запустить
pand --search NAP
Чтобы соединение установилось.

В /etc/network/interfaces прописываем

iface bnep0 inet dhcp
и теперь для того, чтобы всё заработало, достаточно чтобы кто-то после установления соединения дернул ifup bnep0

Я прописал это в /etc/bluetooth/pan/dev-up, хотя, вероятно, можно было просто пропистаь в /etc/network/interfaces для этого интерфейся mapping hotplug

Остался один-единственынй вопрос - а кто будет запускать pand с рутовыми правами при втыкании bluetooth-адаптера в ноутбук. Моя паранойя не позволяет разрешить это делать hotplug-у. Мало ли где я решил воспользоваться bluetooth для работы с мобильным телефоном, и мало ли какую сеть оно там найдет. Поэтому пишем в /usr/local/bin такой скрипт

#!/bin/sh
case "$1" in
on)
        sudo pand --search NAP
;;      
off)
        sudo pand -K
;;      
# Здесь будет вариант работы ноутбука сервероа
*)
        echo "use $0 on|off" >&2
        exit 1
esac    
И в /etc/sudoers прописываем запуск /usr/bin/pand для пользователей без параметров.

Теперь для того, чтобы оказаться в сети нам нужно сделать ровно две вещи:

  1. Воткнуть bluetooth адаптер
  2. сказать bluenet on
Дополнительные особенности настройки dhcp на ноутбуках, как например, полезность локального DNS-сервера, использование пакета resolvconf для того, чтобы этот сервер ходил к правильному форвардеру, использование опции time-servers и ntp-servers отдаваемых dhcp-сервером для синхронизации времени оставим пока за скобками. Для этого нужен отдельный текст, так как ничего блютуз-специфичного в них нет. В случае ethernet там требуется всё то же самое.