Как устроена LaPorta USB
Что делает программа
LaPorta USB ведёт журнал подключения USB-носителей на рабочей станции и применяет к ним правила: полный доступ, только чтение или запрет. Работает штатными средствами Windows – драйвера в ядре нет.
Из чего состоит
Три исполняемых компонента: служба, агент в трее и окно администратора.
Служба LaPortaUsb
Слушает события подключения USB-устройств, принимает решение по политике и применяет его. Работает под системной учётной записью.
Раз в сутки она же спрашивает сайт программы, не вышла ли версия новее, и при более новой
пишет в журнал update_available. Сама ставит обновление только если политика назвала
часы (install_updates): установка останавливает службу, и выбирать минуту, когда машина
останется без запретов, должен администратор. Без этих часов обновление ставит человек –
кнопкой в окне управления. Проверка выключается политикой, а на машине целиком –
параметром установки. Подробности – в install.md.
Агент в трее
Показывает пользователю уведомления о подключённых носителях. Ничего не применяет и не может послать службе ни одной команды – канал между ними односторонний. Отсутствие агента на работу контроля не влияет: пользователь просто не увидит уведомлений.
В меню значка – перечень подключённых носителей, «О программе» и «Открыть управление». Последний пункт виден всем, но помечен щитом: окно объявлено требующим прав администратора, и обычному пользователю Windows покажет запрос пароля. Так администратор открывает управление на рабочем месте сотрудника, не перезаходя в систему. Пункты «Открыть журнал» и «Выход» видны только администратору: журнал – служебные данные, а закрыть агента сотрудник не должен, иначе запреты останутся в силе, но уведомления о них пропадут.
Окно управления агент запускает как отдельную программу, и одностороннего канала до службы это не отменяет.
Окно администратора
Три вкладки: устройства, журнал, политика. Требует прав администратора.
Два режима: наблюдение и применение
Режим задаётся полем политики enforcement_mode.
Переключение в наблюдение возвращает и то, что было запрещено раньше: отключённые узлы включаются обратно при ближайшем перечитывании политики. Иначе машина продолжала бы запрещать, а политика утверждала бы, что только смотрит.
- Режим наблюдения (
audit) – решение принимается и записывается в журнал, но не применяется. - Режим применения (
enforce) – решение применяется.
Два слоя запрета
Реактивный слой
Носитель подключили – служба отключает узел устройства (для запрета) или ставит
признак «только чтение» на диск. Работает по факту подключения. Признак «только
чтение» действует только на том, который удалось перемонтировать: на занятом томе
запись продолжает идти, и служба сообщает об этом – см. troubleshooting.md.
Превентивный слой, он же строгий режим
Включается полем strict_mode и только в режиме применения (enforce) – в режиме
наблюдения он отключён, даже если strict_mode установлен. Служба правит ветку
ограничений установки устройств: запрещает идентификатор устройства USBSTOR\GenDisk
и разрешает поимённо конкретные экземпляры – белый список.
Реактивный слой узнаёт о носителе из уведомления системы, то есть после того, как Windows уже установила устройство, смонтировала том и выдала букву: какое-то время носитель живой. На приёмке режима применения это окно после перезагрузки машины составило от 12,3 до 16,0 секунды, а в одном замере – до 37 секунд от старта службы до применения; всё это время носитель оставался полностью доступен, и запрет обходился перезагрузкой. Превентивный слой закрывает это окно целиком: неизвестный носитель не устанавливается вовсе, буква не появляется, отключать нечего.
Запретов по классу устройств там нет намеренно – в класс дисков входит системный диск машины, и запрет по классу способен оставить её незагружаемой.
Внешние диски с мостом UASP слой не закрывает. Запрещается идентификатор
USBSTOR\GenDisk, а диск в коробке USB 3.x с этим протоколом система перечисляет
узлом SCSI\Disk… без такого идентификатора: он устанавливается как прежде, и держит
его один реактивный слой – по предку на шине USB. Второй запрещающий идентификатор
здесь не добавлен по той же причине, что и запрет по классу: узлы SCSI\Disk есть
и у системного диска машины. Слой рассчитан на флешки и диски, идущие через USBSTOR.
Занятая ветка слой не включает. Ветку правит не только эта программа: в неё пишут
доменная политика и средства защиты, и та же политика Windows – обычный способ запретить
USB-накопители через групповую политику, причём под теми же самыми именами значений.
Отличить своё от чужого по именам значений поэтому нельзя. Правило простое: если
при первом обращении в ветке уже что-то было, она считается чужой и не трогается ни на
включение, ни на снятие – служба остаётся на одном реактивном слое и пишет событие
strict_mode_conflict, см. journal-reference.md. Своей ветка
становится, только когда служба завела её сама; свидетельство этому – копия ветки,
снятая перед первой правкой (см. troubleshooting.md).
Своей ветка остаётся не навсегда, а пока в ней лежит то, что служба записала последним. Рядом с копией она ведёт запись о своей последней правке и сверяет с ней содержимое ветки при каждом согласовании.
Если по записи своё уже снято, а под теми же именами что-то лежит, ветку занял кто-то
другой, чаще всего доменная политика. Служба её не перепишет и не снимет, а напишет
strict_mode_conflict.
Сложнее, когда по записи служба ещё держит ограничения, а содержимое с записью
не сходится. Так же выглядит установка, обновлённая с версии, которая записи не вела:
записи нет вовсе. Отличить свою неудавшуюся правку от чужой тут нечем, поэтому
содержимое считается сомнительным: служба его не перепишет и тоже напишет
strict_mode_conflict, но при выключении strict_mode или при остановке снимет
как своё. Доменная политика вернёт своё при ближайшем обновлении, а машина,
оставшаяся с ограничениями и без программы, не вернула бы накопители никогда.
Порядок регистрации носителя. Белый список строится из носителей, по которым
журнал уже принял решение allow. Новый носитель нужно сначала подключить при
выключенном strict_mode и только потом включить режим – иначе он не установится
и в список не попадёт никогда.
В список попадает не только USB-накопители, а всё, что когда-либо получило allow:
токены, переносимые устройства, картридеры на шине PCI, телефоны. Это не безобидно
само по себе – белый список переживает ужесточение политики: носитель, получивший
allow до того, как его класс запретили, остаётся в списке до конца срока хранения
журнала и продолжает устанавливаться. Ветка к тому же растёт вместе с историей журнала. Один и тот же носитель может попасть в список сразу под несколькими узлами
разных классов, например как накопитель и как переносимое устройство того же
корпуса; запрету по накопителю это не мешает, но по содержимому ветки может
показаться, что носитель разрешён шире, чем на деле.
Умолчание other: allow в паре со strict_mode пробивает дыру: носитель, который
классификатор отнёс к other, остаётся в белом списке даже при flash: block
и устанавливается. Это согласуется с политикой – умолчание other: allow так
и задумано, – но в превентивном слое цена выше, чем в реактивном: там неопознанное
устройство хотя бы попадает в журнал, здесь оно просто ставится.
Срок жизни белого списка. Ограничен retention_days из раздела log политики
(см. policy-reference.md): список видевшихся носителей
служба строит из журнала за это окно, и носитель, чьи записи в окно не попадают,
из списка выпадает и перестаёт устанавливаться – без единой записи о причине.
Средство – увеличить retention_days.
Не проверено: это следует из того, как строится список (служба читает журнал
за срок retention_days), а не из опыта – само истечение срока не воспроизводили
ни на живой машине, ни тестом.
Разделение труда с реактивным слоем. Превентивный слой не пускает то, чего ещё нет в системе. Он не отцепляет то, что уже установлено, – это делает реактивный слой: обратный запрет распространяется и на уже стоящие носители, но применяется только при перечислении устройства (переподключение, пересканирование), а не мгновенно. Ни один слой не покрывает случай другого – вместе они держат носитель с двух сторон.
Поведение при выключении машины. Выключение – не то же самое, что штатная остановка службы. При штатной остановке и при удалении программы ограничения снимаются. При выключении машины они остаются в ветке реестра и действуют с первой секунды после загрузки – ещё до того, как служба вообще запустится: неизвестный носитель не устанавливается уже на этом этапе.
Когда политика недоступна
Три состояния:
- политика прочитана с указанного пути;
- политика недоступна, но есть кэш прошлой удачной загрузки – работа по кэшу;
- кэша тоже нет – запасной режим: политика недоступна, кэша нет, значит разрешено всё. Разрешено всё относится к носителям: на сайт за обновлениями служба в этом режиме не ходит – выбора администратора не видно, и делать его за него нельзя.
Что программа намеренно не делает
- Не блокирует токены ни при каких настройках. Токеном при этом считается устройство, опознанное системой как смарткарт-ридер, либо устройство с известным VID производителя токенов, объявившее интерфейс чип-карты; flash-раздел токена – обычная флешка и подчиняется правилам.
- Не ведёт аудит файловых операций.
- Не требует сервера и базы данных.
- Не ставит обновления сама, пока политика не назовёт часы, в которые это разрешено.
- Не отличает «новых выпусков нет» от «до сайта не дают дойти». Тот, кто управляет сетью машины, может отдавать ей старый – и по-прежнему верно подписанный – манифест или просто закрыть доступ к сайту, и о вышедшем обновлении она не узнает. Защиты от этого нет: манифест не несёт срока годности. Парк, где такое важно, обновляют групповой политикой, а не проверкой с сайта.