характеру их поведения на сайте. И хотя она все еще находится в разработке, но вы уже можете начать использовать ее. Код библиотеки доступен на Github по ссылке. В настоящее время я тестирую новую технику обнаружения, не стесняйтесь оспаривать ее эффективность и целесообразность работы над ней, а также писать мне.
Содержание
Что представляет собой headless браузер?
Headless браузер – это браузер без графического интерфейса, который используется для загрузки и обработки содержимого веб-страниц. Им можно программно управлять для автоматизации выполнения различных задач, таких как выполнение тестов или создания скриншотов веб-страниц.
Зачем может понадобится определять загрузку страницы headless браузером?
Помимо этих двух вполне безобидных вариантов использования, упомянутых нами выше, headless браузер также может использоваться для вредоносных целей. Наиболее частым случаем его такого использования это парсинг веб-страниц, увеличение количества показов рекламы или поиск уязвимостей на веб-сайте.
До сих пор одним из самых популярных headless браузеров был PhantomJS. И поскольку он разработан основе платформы Qt, то это подразумевает наличия большого числа отличий от популярных браузеров. Как будет показано в этом посте ниже, его можно обнаружить с помощью некоторых достаточно простых методов.
Начиная с версии 59, Google выпустила headless версию своего браузера Chrome. В отличие от PhantomJS, он основан на обычном Chrome, а не другой платформе, что затрудняет обнаружение его присутствия на сайте.
User agent
Начнем с пользовательского агента, который является атрибутом, значение которого обычно используется для определения ОС, а также браузера пользователя. И может принимать следующее значения: Mozilla/5.0 (X11; Linux x86_64)
, AppleWebKit/537.36 (KHTML, like Gecko)
, HeadlessChrome/59.0.3071.115
, Safari/537.36
.
Следующий фрагмент кода, позволяет определить присутствие headless Chrome:
if (/HeadlessChrome/.test(window.navigator.userAgent)) { console.log("Chrome headless detected"); }
Тип пользовательского агента можно также определить из содержимого HTTP заголовков. Однако подменить его наименование злоумышленнику для обоих случаев простая тривиальная задача.
Plugins
Обращение к свойству navigator.plugins
возвращает массив подключаемых в браузере плагинов. Обычно в Chrome мы находим плагины в любом случае подключаемые по умолчанию, например, такие как Chrome PDF viewer или Google Native Client. И напротив, в headlessрежиме, возвращаемый массив не содержит ни одного плагина.
if(navigator.plugins.length == 0) { console.log("It may be Chrome headless"); }
Languages
В Chrome средства Javascript позволяют получить значение двух атрибутов, содержащих значения, определяющие языки, используемые пользователем браузера: navigator.language
и navigator.languages
. Первый атрибут содержит значение, определяющее язык пользовательского интерфейса браузера, а второй — это массив строк, представляющих предпочтительные для пользователя языки. Однако в headless режиме свойство navigator.languages
возвращает пустую строку.
if(navigator.languages == "") { console.log("Chrome headless detected"); }
WebGL
WebGL, предоставляет API для отображения результатов 3D-рендеринга на холсте HTML canvas. С помощью этого API можно запросить возможности графического процессора, а также его средств визуализации.
В Linux с обычным Chrome я получаю следующие значения для средства визуализации и рендера: Google SwiftShader
и Google Inc.
. В headless режиме используется Mesa OffScreen
, технология, применяющаяся для рендеринга без использования какой-либо window system, и Brian Paul
, программа с открытым исходным кодом, которая запускает графическую библиотеки Mesa
.
var canvas = document.createElement('canvas'); var gl = canvas.getContext('webgl'); var debugInfo = gl.getExtension('WEBGL_debug_renderer_info'); var vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL); var renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL); if(vendor == "Brian Paul" && renderer == "Mesa OffScreen") { console.log("Chrome headless detected"); }
Тем не менее не все Chrome headless будут иметь одинаковые значения для рендера и средства визуализации. Другие сохраняют значения, которые также можно найти в headless версии браузера. Тем не менее, наличие значений Mesa Offscreen
и Brian Paul
явно указывают на использвание headless версии.
Browser features
Библиотека Modernizr позволяет проверить, присутствует ли в браузере широкий спектр новых возможностей HTML5 и CSS3. Единственная разница, которую мы можем обнаружить между Chrome и headless Chrome, заключается в том, что последний не имеет hairline функциональности, которая определяет поддержку hidpi для retina экранов устройств.
if(!Modernizr["hairline"]) { console.log("It may be Chrome headless"); }
Отсутствующие изображения
И наконец, рассмотрим последний метод для обнаружения ботов, который является, с моей точки зрения, наиболее надежным. Он основан на вычислении браузером Chrome размера изображения, используемого в случае если изображение не может быть загружено.
В случае простого браузера Chrome изображение будет иметь ширину и высоту, которые зависят от масштаба окна браузера, но отличны от нуля. В headless Chrome изображение будет иметь ширину и высоту равную нулю.
var body = document.getElementsByTagName("body")[0]; var image = document.createElement("img"); image.src = "http://iloveponeydotcom32188.jg"; image.setAttribute("id", "fakeimage"); body.appendChild(image); image.onerror = function(){ if(image.width == 0 && image.height == 0) { console.log("Chrome headless detected"); } }