Браузер DuckDuckGo добавляет шум в canvas и фиксирует часть значений железа, но не делает вас неотличимым от других. Что меняет открытый код и что остаётся.
Тот, кто открывает тест отпечатка в браузере DuckDuckGo, обычно хочет узнать одно: защищён ли мой отпечаток? Коротко: браузер ослабляет часть сигналов фингерпринтинга, но не стремится сделать всех пользователей одинаковыми, как Tor Browser. Его защита сочетает две стратегии, и обе видны в открытом коде.
Ключевые выводы
- Защита DuckDuckGo внедряется как скрипты страницы из открытого репозитория content-scope-scripts, а включается и выключается удалённо раздаваемой конфигурацией из privacy-configuration.
- Стратегия первая — шум: считанные из canvas пиксели изменяются по значению, зависящему от сайта и сеанса просмотра, поэтому хеш различается по сайтам и по сеансам.
- Стратегия вторая — фиксированные значения:
hardwareConcurrency,deviceMemory, часть свойствscreenи Battery API возвращают всем один и тот же ответ. - Единообразия это не создаёт. Движок браузера, User-Agent, рендерер WebGL и шрифты функциями из этой статьи не затрагиваются.
- Поведение может отличаться по платформе и по сайту: в конфигурации есть переключатели по функциям и список исключений по доменам.
Две стратегии, а не одна
Защиты от фингерпринтинга обычно выбирают между двумя идеями. Единообразие заставляет многих пользователей возвращать одинаковые значения, и значение перестаёт кого-либо выделять; так работает resistFingerprinting в Firefox и Tor. Шум искажает вывод, чтобы трекер не получил стабильного значения; о минусах шума — здесь.
DuckDuckGo применяет обе, по функциям. Шум — там, где исходное значение богато энтропией и и так варьируется (пиксели canvas). Фиксированные значения — там, где число легко нормализовать (число ядер, память, глубина цвета). Это прагматичный компромисс: меньше межсайтового слежения без массовой поломки сайтов, а не обещание анонимности.
Что меняет код
Каждая функция — небольшой файл в injected/src/features/ репозитория content-scope-scripts плюс JSON-файл в features/ репозитория privacy-configuration.
Canvas (fingerprinting-canvas.js). Скрипт оборачивает getImageData, toDataURL и toBlob. Холст считается подозрительным только после вызовов рисования вроде fillText, arc или создания градиентов. При чтении такого холста скрипт копирует его во внеэкранный холст и меняет пиксели там, используя ключ из ключа сеанса и домена сайта (HMAC от контрольной суммы пикселей). Изменение крошечное: переворачивается младший бит одного цветового канала у части пикселей, при этом пиксели, совпадающие с соседями, пропускаются. Хеш меняется, картинка выглядит прежней. Поскольку ключ стабилен в пределах сеанса, повторное чтение того же холста даёт те же байты — это обходит признак «двойного чтения», описанный в нашей статье о canvas-шуме. Кроме того, в общем fingerprinting-canvas.json параметр webGl установлен в "enabled": тогда вызовы WebGL вроде shaderSource и drawArrays тоже помечают холст как подозрительный, и отрисованное через WebGL изображение, выгруженное через toDataURL, зашумляется так же. Это касается только пикселей, но не строк производителя GPU и рендерера.
Аудио (fingerprinting-audio.js). Код добавляет мизерное смещение к отсчётам, которые возвращают getChannelData, copyFromChannel и методы анализатора, тоже по ключу сеанса и домена. Но в общем fingerprinting-audio.json на момент написания у функции state равен "disabled", так что не считайте аудиошум включённым. Что раскрывает этот сигнал — в статье об аудио-фингерпринтинге.
Железо (fingerprinting-hardware.js). navigator.keyboard становится undefined, а hardwareConcurrency и deviceMemory возвращают числа из конфигурации. Сейчас в общем конфиге это 4 и 8; перечитайте JSON, ведь он обновляется удалённо. Подробнее — в материале о hardwareConcurrency и deviceMemory.
Экран (fingerprinting-screen-size.js). availWidth и availHeight принудительно равны полной ширине и высоте экрана, availTop и availLeft — 0, colorDepth и pixelDepth — 24; так скрываются размеры панели задач и дока. Также нормализуются screenX/screenY для нескольких мониторов. Сами ширина и высота экрана по-прежнему видны, см. фингерпринтинг по разрешению экрана.
Батарея и хранилище. fingerprinting-battery.js сообщает полностью заряженную и заряжающуюся батарею и глушит её события; fingerprinting-temporary-storage.js ограничивает квоту, которую сообщает webkitTemporaryStorage.queryUsageAndQuota, значением 4 ГБ, затрудняя оценку размера диска.
Честные ограничения
Удалённая конфигурация. Каждая функция управляется конфигурацией. Скрипт canvas даже завершается сразу, если не включена настройка additionalEnabledCheck, а аудиофункция в общем файле отключена. Какие защиты реально работают, зависит от сборки платформы и текущей конфигурации, а не только от кода.
Исключения по сайтам. В конфигурациях перечислены домены, где защита отключена, потому что ломала сайт. Только в fingerprinting-hardware.json их 15; для gamestop.com указано: «при нажатии „добавить в корзину“ ненадолго появляется индикатор загрузки, а товар в корзину не попадает». На таких сайтах эта защита выключена.
Нетронутые поверхности. Ни один из перечисленных файлов не меняет User-Agent, строки рендерера WebGL и список установленных шрифтов, а сам браузер построен на веб-движке платформы. Эти сигналы по-прежнему входят в отпечаток. Среди просмотренных файлов функций для них нет, но весь проект мы не аудировали, поэтому читайте это как «не покрыто этими функциями», а не «никогда не защищено».
Фиксированные значения могут выделяться. Если 16-ядерный десктоп сообщает о 4 ядрах, скрипт может сверить это с другими сигналами, и само несоответствие способно стать сигналом, см. несоответствие железа в отпечатке.
Сравнение
| Браузер | Основная идея | Пример |
|---|---|---|
| DuckDuckGo | Шум в canvas, фиксированные значения для нескольких атрибутов | Переворот бита в canvas, фиксированное число ядер |
| Brave | «Farbling» по сеансу и сайту во многих API | См. обновления приватности Brave |
| Firefox / Tor | Единообразие (resistFingerprinting) | Округление таймеров, стандартный размер окна |
Это сравнение стратегий, а не оценка «кто лучше». Основы — в материале о фингерпринтинге браузера. И уточнение: поисковик DuckDuckGo — отдельный продукт; его обещание о приватности касается логов поиска, а не фингерпринтинга браузера.
Проверьте сами
Откройте нашу проверку отпечатка в браузере DuckDuckGo, запомните хеш canvas, затем зайдите снова в новом сеансе. Хеш зашумлённого canvas должен меняться между сеансами, а значения вроде числа ядер и памяти устройства — оставаться фиксированными. Мы не помечаем результат как «обнаружена защита DuckDuckGo»: инструмент показывает исходные значения, а вывод делаете вы.
Часто задаваемые вопросы
Блокирует ли браузер DuckDuckGo фингерпринтинг полностью?
Нет. Он изменяет часть считываемых значений и нормализует часть атрибутов, но движок, User-Agent, строки WebGL и другие сигналы находятся вне описанных здесь функций.
Будет ли мой отпечаток canvas одинаковым на всех сайтах?
Если защита canvas активна — нет: ключ шума включает домен сайта, поэтому один и тот же рисунок даёт разные хеши на разных сайтах и в разных сеансах.
Одинакова ли защита DuckDuckGo на всех устройствах?
Не обязательно. Функции включаются удалённо раздаваемой конфигурацией для каждой платформы, поэтому поведение может отличаться по ОС и версии приложения.


