Espruino:Примеры/Безопасность и контроль доступа при использовании BLE на Puck.js
Безопасность и контроль доступа при использовании BLE на Puck.js[1]
В момент, когда вы вынете пластиковый разделитель из батарейного отсека Puck.js, устройство тут же запустится, после чего к нему можно будет подключиться и программировать.
Как и прочие подобные устройства для разработки проектов, Puck.js создан с прицелом на то, чтобы вы могли начать пользоваться им как можно быстрее – без необходимости вводить пароли.
Но как только вы возьмётесь за более-менее серьёзные проекты, то наверняка захотите поставить защиту, чтобы Puck.js не мог перепрограммировать кто-то другой.
Итак, как же защитить Puck.js? Есть несколько вариантов.
Запретите подключаться к Puck.js
При помощи функции NRF.setAdvertising() вы можете разрешить Puck.js рассылать Bluetooth-объявления, но также сделать так, чтобы к нему не мог подключиться ни один ПК:
NRF.setAdvertising({}, { connectable:false });
Поставьте пароль при помощи E.setPassword("пароль")
См. тут. В результате UART продолжить работать, и любой компьютер по-прежнему сможет подключиться к Puck.js, но теперь каждый, кто захочет получить доступ к консоли Espruino, должен будет ввести пароль.
Это неидеальный вариант, так как к Puck.js по-прежнему сможет подключиться любой – он просто не получит доступа к JavaScript-консоли.
Спрячьте консоль
При помощи команды LoopbackA.setConsole(true) можно принудительно поместить JavaScript-консоль в Loopback.
В результате консоль будет доступна только через чтение и запись в переменную LoopbackB. Если кто-то подключится к Puck.js, у него по-прежнему будет доступ к UART, но он ничего не сможет сделать.
Всё, что будет записываться в Bluetooth UART, по-прежнему будет доступно в переменной Bluetooth через Bluetooth.on('data', function(data) { ... }), и вы также сможете отправлять ответы при помощи Bluetooth.write(...).
Отключение при обнаружении незнакомого адреса (белый список)
Вы можете легко подцепиться к событию connect, а затем принудительно отключиться, если обнаружится, что подключение инициировано незнакомым адресом.
NRF.on('connect',function(addr) {
if (addr!="69:2d:94:d0:9d:97 public")
NRF.disconnect();
});
У других Puck.js адрес обычно имеет формат "aa:bb:cc:dd:ee:ff random", а у ПК и телефонов это, как правило, что-то вроде "aa:bb:cc:dd:ee:ff public".
Чтобы выяснить, какой MAC-адрес добавить в белый список, загрузите вот этот код:
devices = [];
NRF.on('connect',function(addr) {
devices.push(addr);
});
// теперь подключитесь несколько раз
// и посмотрите, что находится в «devices» в левой части IDE
Отключите BLE UART
Если вы не хотите, чтобы у пользователя был доступ к BLE UART, рекомендуем полностью его отключить при помощи NRF.setServices().
NRF.setServices(undefined, {
uart : false
});
Это полностью отключит сервис UART, в результате чего Puck.js нельзя будет перепрограммировать (пока не выполнить сброс).
Если снова вызвать NRF.setServices() с настройкой uart:true, это возобновит работу UART. К примеру, код ниже выключает и включает UART (а также мигает красным и зелёным светодиодами) при нажатии на кнопку.
var locked = true;
NRF.setServices(undefined,{uart:!locked});
setWatch(function() {
locked = !locked;
digitalPulse(locked?LED1:LED2,1,100);
NRF.setServices(undefined,{uart:!locked});
}, BTN, {repeat:true, edge:"rising", debounce:50});
Отключите Bluetooth
Вы можете включить и выключить Bluetooth при помощи функций NRF.sleep() и NRF.wake().
Это остановит рассылку Bluetooth-объявлений, с помощью которых Puck.js объявляет о своём присутствии, а также сделает так, чтобы к Puck.js нельзя было подключиться. Это также увеличит продолжительность работы батареи.
Код ниже мигает красным и зелёным светодиодами, а также включает и выключает Bluetooth.
var locked = false;
setWatch(function() {
locked = !locked;
digitalPulse(locked?LED1:LED2,1,100);
if (locked) NRF.sleep();
else NRF.wake();
}, BTN, {repeat:true, edge:"rising", debounce:50});
Привязка / занесение в белый список
В версии Espruino 1v92 в Puck.js была реализована функция привязки. Будучи привязанными, устройства могут создавать безопасное подключение друг к другу.
Puck.js принимает и безопасные, и небезопасные подключения – решение о том, запускать ли процедуру привязки или нет, остаётся за подключающимся устройством. Если вызвать функцию NRF.setWhitelist(true), то следующее устройство, которое будет привязано к Puck.js, будет также добавлено в белый список. В результате устройства, которых нет в белом списке, к Puck.js подключиться не смогут, пока он не будет перезапущен (для этого нужно зажать кнопку).
Сам Puck.js, подключаясь к другому устройству, тоже может инициировать процедуру привязки – это делается с помощью метода startBonding(). Кроме того, подключившись, при помощи функции getSecurityStatus() можно узнать настройки безопасности соединения.
Сопряжение с помощью ключа доступа (пароля)
В версии Espruino 2v02 (и в самых свежих, но нестабильных билдах) можно задать статический ключ доступа (пароль).
NRF.setSecurity({passkey:"123456", mitm:1, display:1});
При попытке подключения центральное устройство запросит ключ доступа (пароль), и если он окажется неправильным, подключение установлено не будет.
Когда Espruino работает в режиме центрального устройства, которому нужно подключиться к другому устройству, ключ доступа можно ввести при помощи события BluetoothDevice.passkeyRequest и метода BluetoothDevice.sendPasskey() но при этом в NRF.setSecurity должно быть задано keyboard:1).
Отключите команды dump() и E.dumpStr()
Благодаря этим командам тот, у кого есть доступ к консоли Espruino, может легко выгрузить программный код, хранящийся на устройстве.
Их можно отключить при помощи global.dump=function(){};E.dumpStr=function(){};, но полную защиту это не гарантирует, потому что, выполнив некоторые манипуляции, их можно снова включить. Кроме того, если злоумышленник будет иметь доступ к консоли Espruino, то сможет прочесть состояние интерпретатора даже без этих команд. Другими словами, вы можете реконструировать большую часть кода, даже не используя dump().
Если вас беспокоит то, что кто-то может прочесть ваш код, лучше вообще отключите консоль (см. выше).
См.также
Внешние ссылки