Служба BITS, она же Background Intelligent Transfer Service, это встроенный механизм Windows, который качает и отдает файлы в фоне так, чтобы пользователь за тем же каналом этого практически не замечал. Она появилась еще в эпоху медленных линий, когда скачать пакет обновлений на пару сотен мегабайт означало парализовать диалап или ранний DSL на весь вечер. Идея оказалась настолько удачной, что через два десятка лет через нее идут Windows Update, раздача приложений из Store, антивирусные базы, предзагрузка игровых патчей и куча корпоративных сценариев доставки контента. При этом сама служба устроена заметно хитрее, чем "качай потихоньку": она измеряет реальную загрузку интерфейса, строит очереди заданий с приоритетами, переживает перезагрузки и обрывы, умеет докачивать файл с куска, на котором оборвалось, и подчиняется политикам лимитов, которые администратор раскидывает по часам и дням недели. Сетевой инженер, который понимает, что там внутри, перестает удивляться, почему "машина качает втихую но игры не лагают", и начинает использовать BITS как инструмент, а не бороться с ним как с загадкой.

Задания очереди и приоритеты передачи

Базовая единица работы BITS это задание, job. Задание описывает набор файлов, у каждого из которых есть удаленный источник по HTTP или HTTPS и локальное назначение, плюс настройки: тип передачи, приоритет, учетные данные, уведомления. Владельцем задания является учетная запись, которая его создала, и служба хранит состояние в своей базе, переживая завершение процесса, который задание породил.

Типов несколько: download качает файл с сервера, upload заливает файл на сервер методом, который должна поддерживать серверная сторона, upload-reply качает ответ после заливки. На практике преобладает download, потому что главный потребитель это доставка контента клиентам.

Приоритеты задают порядок, в котором задания конкурируют за свободную полосу. В первом поколении API их четыре. Foreground это "качай как обычный клиент, не стесняйся": такой режим фактически отключает основную фишку фоновости и используется, когда приложение хочет прогреть кэш через BITS, но быстро. Background режим по умолчанию, передача идет только в измеренную свободную полосу. High и normal исторически различали относительный порядок внутри фоновых заданий одного владельца, в свежих версиях API между ними разницы по факту нет, оба обрабатываются как фоновые. Low это хвост очереди: задание получает канал только когда задания повыше молчат.

Важный нюанс для диагностики: приоритет регулирует очередность между заданиями самой службы, а не QoS на сетевом уровне. Маршрутизатор про эти приоритеты ничего не знает. Если человек жалуется "BITS все равно жрет канал", то искать надо либо задания в foreground, либо сторонние процессы, которые качают мимо BITS вообще.

Как служба измеряет свободную полосу и уступает канал

Фирменная часть механики это throttling по измеренному простою сети. BITS с периодичностью опрашивает счетчики производительности сетевого интерфейса: сколько байт и пакетов ушло и пришло. Между соседними снятиями счетчиков служба считает дельту, то есть фактическое пользовательское использование канала за окно наблюдения. Если дельта показывает, что канал свободен, BITS добавляет свою передачу. Если дельта растет, значит появилась чужая нагрузка, и BITS тут же уменьшает или останавливает свою передачу, уступая канал пользователю.

Именно поэтому игры и звонки не лагают от фоновых закачек. У игры маленькие пакеты с жесткими требованиями к задержке. Пакеты игры проходят по интерфейсу, счетчики фиксируют дельту, и BITS на следующем окне наблюдения притормаживает своих гигантов. То же самое с голосом и видео. Эффект не мгновенный в стиле аппаратного планировщика, но на человеческом масштабе он выглядит именно как "служба отошла в сторону".

Практическое следствие: на машине, где канал занят на десять процентов, фоновое задание разгоняется почти до остатка полосы; на машине, где идет торрент или коллега тянет образ виртуалки из внутреннего хранилища, BITS будет ползти в черепашьем темпе. Это не баг и не каприз, это прямое исполнение контракта "не мешать". Для дедлайновых сценариев, где патч должен приехать до утра, администраторы нередко поднимают заданию приоритет или договариваются о сетевом QoS отдельно, потому что надеяться на вежливость сервиса в перегруженной сети бессмысленно.

Возобновление передачи после разрыва и перезагрузки

BITS проектировался под мир нестабильных каналов, и возобновление там не бонус, а фундамент. Состояние каждого задания пишется в базу службы, поэтому перезагрузка машины, падение сети, смена точки доступа на ноутбуке и даже смена пользователя не отменяют задание: когда условия появляются, передача продолжается с накопленного прогресса.

Для докачки по кускам используется блок-уровневое резюмирование: клиент запрашивает у сервера диапазоны байтов через заголовок Range и дозаписывает недостающие куски в целевой файл. Это накладывает важное требование на целевой файл: локальный путь задания должен быть доступен службе на запись, файл не должен быть заблокирован другим процессом монопольно, и место под итоговый объем должно быть. На серверной стороне требование зеркальное: веб-сервер или CDN должны поддерживать Range-запросы и отдавать корректные заголовки длины. Большинство статических раздач и крупных CDN это делают из коробки, но самодельные скрипты, которые стримят ответ "на лету" без поддержки диапазонов, ломают резюмирование: BITS в таком случае либо начинает заново, либо вываливает задание в ошибку.

Еще одна жизненная история: файлы, которые меняются на сервере между попытками, делают резюмирование бессмысленным. Если контент пересобирается каждый час, куски, скачанные вчера, перестанут соответствовать текущему телу, и передача завершится с неправильным содержимым или будет перезапущена. Поэтому раздачу версионируют по URL, а не перезаписывают файл "на месте".

Почему через BITS ходят Windows Update и Store

Microsoft массово использует BITS как транспорт сама. Windows Update и инфраструктура доставки обновлений скачивают пакеты в фоне фоновыми заданиями, поэтому обновления едут на машину тихо и не пугают пользователя просадкой сети. Приложения из Store и обновления UWP тоже идут через механику фоновой передачи. Оптимизация доставки на базе BITS или родственных механизмов дополнительно умеет брать куски не только из облака но и с соседних машин в одной сети, экономя внешний трафик филиала.

Для сетевого инженера это значит, что трафик обновлений на интерфейсе это не обязательно "кто-то что-то качает", а вполне легальный фоновый процесс, которому можно управлять централизованно. Через групповые политики задается максимальная скорость фоновых передач BITS в процентах или в килобитах, отдельно для рабочих часов и для остального времени, с расписанием по дням. На канале 20 мегабит на филиал это выглядит спасением: днем обновления ползут на паре мегабит, ночью догоняются на полной скорости. Меняется все несколькими параметрами в одной политике, без ковыряния каждой машины руками.

Управление службой bitsadmin и PowerShell

Исторический инструмент это bitsadmin, командная утилита из эпохи Server 2003. Она умеет создавать задания, навешивать файлы, менять приоритеты, ставить лимиты и показывать очередь. Проблема в том, что биты из нее сыплются: утилита помечена как устаревшая и убирается из новых сборок Windows, поэтому для новых сценариев надежнее модуль PowerShell BitsTransfer.

Канонический сценарий на PowerShell выглядит так: Start-BitsTransfer с параметрами источника и назначения запускает задание. Ключ -Asynchronous отдает управление сразу, и дальше состояние смотрят через Get-BitsTransfer. Ключи -Suspend, -Resume, -Complete ставят задание на паузу, снимают с паузы и доводят докачанное до конечного состояния, перенося временные файлы в целевые имена. Полный контроль над приоритетом, аутентификацией и уведомлениями дает полноценное создание объекта задания через COM-интерфейс или через Start-BitsTransfer с набором параметров.

Типовой ручной сценарий инженера сводится к пяти шагам.

  1. Создать задание Start-BitsTransfer с асинхронным режимом.
  2. Назначить приоритет и при необходимости учетные данные через параметры аутентификации.
  3. Наблюдать Get-BitsTransfer пока состояние не станет Transferred.
  4. Завершить Complete-BitsTransfer чтобы файлы заняли свои места.
  5. Проверить хэш или подпись приехавшего артефакта.

Шаг пятого пункта важен не для красоты: BITS гарантирует доставку байтов до конца, но смысл байтов отвечает тот, кто их подписал.

Аутентификация куки и сертификаты заданий

BITS ходит по HTTP-стеку Windows, поэтому умеет то же, что и нормальный веб-клиент. Заданию можно задать тип аутентификации: Basic и Digest для простых схем, NTLM и Negotiate для доменной интеграции, Passport для старых сценариев. Учетные данные сохраняются в составе задания и применяются, когда сервер отвечает 401. Посреднический сервер-сервер поддерживается настройками WinHTTP и самой службы, в том числе автодетект, явный сервер и обход списка.

Тонкие места три. Первое это куки: серверы, которые требуют сессионную куку до начала скачивания, через старый API не всегда обслуживались предсказуемо, поэтому инженеры либо предзапрашивали куку своим клиентом и подкладывали ее в задание, либо переходили на свежие версии интерфейса, где владение куками явно настраивается. Второе это клиентские сертификаты: если сервер требует mTLS, заданию назначается сертификат из хранилища, и BITS ходит с ним на каждый запрос, включая докачку диапазонов. Третье это контекст учетной записи: служба работает в контексте создавшего задание пользователя или системы, от этого зависит, какие хранилища сертификатов и какие шары доступны.

Из практики: если задание валится с 401 на второй стадии, первым делом проверяют, не сбросил ли балансировщик сессию между запросами Range. Задание BITS может сделать десяток запросов на один файл, и "прилипание" по cookie обязано работать всю дорогу.

Диагностика заданий и журналы событий

Первичный взгляд это Get-BitsTransfer без параметров: утилита показывает активные и висящие задания текущего пользователя, их состояние, объем переданного и целевые пути. Администратор добавляет ключ -AllUsers и видит очередь всей машины. Состояния читаются прямо: Queued ждет полосы по приоритету, Connecting идет рукопожатие, Transferring течет поток, Transferred качать закончено но не завершено, Suspended пауза, Error и TransientError требуют чтения кода ошибки.

Код ошибки в объекте задания это половина диагноза. Вторая половина живет в Event Viewer, журнал Microsoft-Windows-Bits-ClientOperational. Туда падают события жизненного цикла: создание задания, старт и стоп передачи, коды HTTP, таймауты, ошибки доступа к файлам. Связать событие с заданием помогает идентификатор job, который светится и в PowerShell и в журнале.

Опытный инженер на жалобу "обновления не доезжают" делает три проверки: очередь заданий с кодами ошибок, операционный журнал Bits-ClientOperational за тот же интервал, и счетчики интерфейса, чтобы понять, не задавлен ли трафик своим же политикой лимита. Дальше обычно виновник очевиден: либо Radius-корпоративная аутентификация просрочила пароль сервисной учетки, либо файловый фильтр антивируса держит целевой каталог, либо полоса по политике на день стоит в десять килобит, чего хватает только на служебные запросы.

Когда тихая служба становится механизмом закрепления

У полезной незаметности есть теневая сторона, и BITS тут не исключение. Служба переживает перезагрузки, умеет выполнять команду по завершении задания через настройку уведомления, и передачи идут легальным служебным трафиком по HTTPS. Злоумышленники в свое время быстро смекнули возможности: задание на скачивание полезной нагрузки по завершении запускает ее само, а при "починке" планировщиком задание восстанавливается и по факту работает как механизм persistence. В отчетах по инцидентам разных лет BITS фигурировал именно в такой роли, как транспорт и якорь закрепления, а не как эксплойт.

Защита тут не в отключении службы, потому что сломается добрая половина штатной доставки контента, а в наблюдении. Концептуально процедура простая: периодически снимать список заданий командой bitsadmin /list или через Get-BitsTransfer -AllUsers, сопоставлять владельцев и источники URL с ожидаемыми сценариями, алертить на появление заданий от нетипичных учеток или с подозрительными URL назначения. В операционном журнале это выглядит как поток созданий заданий вне окон обновлений. Организации, которые свели телеметрию BITS в общий мониторинг, описывают это как одну из самых дешевых проверок с высоким КПД: собрать очередь заданий могут даже неагентские скрипты, а аномалия видна невооруженным глазом.

Служба BITS остается отличной иллюстрацией зрелого сетевого дизайна. Она берет скачанное по HTTP, кладет в очередь с приоритетами, измеряет свободную полосу дельтой счетчиков, переживает обрывы, подчиняется политикам и логирует каждый чих в операционный журнал. Инженеру, который умеет это читать, она экономит нервы и трафик; инженеру, который не смотрит в очередь заданий, она может подложить сюрприз, потому что тихие механизмы любят все, включая тех, кто пришел без приглашения.