Недавно Роскомнадзор предпринял попытку блокировки доступа с территории РФ к Википедии. Попытка провалилась, и самое время перейти в контрнаступление. В статье под катом я покажу, что, если пользователь Х зашёл на сайт А, то сайт А может определить, заблокирован ли для пользователя другой сайт Б. А дальше, по намечающейся традиции, изложение пойдёт в вопросно-ответной форме.

Для чего это вообще нужно?


При обсуждении блокировки Википедии сообщество заметило два обстоятельства, которые весьма выгодны цензуре. Во-первых, Википедия использует HTTPS и, более того, HSTS. Это означает, что заблокирована энциклопедия может быть только целиком (с точностью до домена), но при этом перенаправить на пресловутую страницу с сообщением о блокировке нельзя. Вместо этого высвечивается сообщение об ошибке установления соединения. Это выглядит как внутренняя проблема Википедии и смягчает недовольство пользователя действиями Роскомнадзора; в то же время для развития правового государства необходима обратная связь. Во-вторых, даже если пользователи узнают о блокировке, многие из них просто не будут знать, что делать. Вешать перманентную плашку «Если заблокировали Википедию — качайте Tor Browser!» на неравнодушных сайтах как минимум странно; в то же время, оповещение пользователей о блокировке Википедии и способах её обхода необходимо. Решение поставленной проблемы и пытается дать настоящая статья.

Что это вообще такое?


Это — достаточно универсальный способ определить доступность практически любого (предварительно исследованного) сайта на стороне клиента, средствами Javascript.

UPD: По совету товарищей bakhirev и xobotyi механизм работы изменён. Самая интересная часть с занимательной геометрией оказалось ненужной, определение переписано на событиях.

Хочу демку!


Пожалуйста!
Та самая занимательная геометрия - распечатать при запрете кроссдоменных событий для изображений

Как это работает?


Создаётся невидимый блок HTML-кода, содержащий два изображения: одно контрольное — с заведомо несуществующего URL, второе сигнальное — любое изображение с проверяемого сайта. Если их размеры через некоторое время совпадают — значит, изображение с проверяемого сайта не загрузилось, то есть он либо «лежит» настолько, что не может отдавать даже статику, либо заблокирован.

А подробнее?


Изображение в HTML, вставлемое тэгом img, по умолчанию имеет размеры, определяемые самим файлом-картинкой. Изображение, которое загрузить не удалось, тоже имеет какие-то размеры — в разных браузерах разные. Вот они (ширина x высота):
  • Firefox 37.0 — 24x24
  • Chrome 44.0.2403.155 — 0x0 (до загрузки), 20x20 (при неудачной загрузке)
  • Opera 12.16 — 114x22
Получить размеры элемента на Javascript можно с помощью свойств элемента .offsetWidth и .offsetHeight

А если вдруг сигнальное изображение по размерам совпадёт с тем, что отобразит браузер при ошибке?


Это достаточно маловероятно, учитывая, что сравниваются и ширина, и высота. Можно запросить два изображения заведомо разных размеров и сравнить их полученные размеры. Если совпадут — загрузка прошла неуспешно. И всё же фавиконы в качестве единственных изображений лучше не дёргать.

А исходники?


На гитхабе под GPLv3.

И как этим всем пользоваться?


Постарался сделать код читабельным, хотя, конечно, это не освобождает меня от приведения примера.
	chasAntidot.testSiteWithImg({
		url: 'https://ru.wikipedia.org/static/images/project-logos/ruwiki.png',	//URL картинки-детектора
		ifBlocked: function(){message('заблокирована');},	//callback, если заблокировано
		ifNotBlocked: function(){message('не заблокирована');},	//callback, если не заблокировано
		time: 3500, //Время ожидания ответа в миллисекундах, по умолчанию 4000
		secondImage: 'https://ru.wikipedia.org/favicon.ico',	//URL второй картинки - необязательно
	});
Никаких дополнительных библиотек типа jQuery не требуется, всё на чистом JS.

Хорошо, я готов информировать своих пользователей о возможной блокировке Википедии! Можно мне готовый код?


Во-первых, в любом случае саму библиотеку лучше скачать к себе на сайт. github.io не застрахован от блокировок. Во-вторых, для чистого JS возможен, например, такой вариант:
chasAntidot.createBanner(
	'Вероятно, <a href="https://ru.wikipedia.org">Википедия</a> заблокирована. <a href="http://rublacklist.net" target="_blank">Узнайте, что нужно сделать!</a>',
	{
		url: 'https://ru.wikipedia.org/static/images/project-logos/ruwiki.png',
		secondImage: 'https://ru.wikipedia.org/favicon.ico',
	}
);
Это, конечно, работает, но не очень красиво :) Патчи, добавляющие функции создания баннеров с использованием различных библиотек, приветствуются!

А если действительно Википедия упадёт?


На этот случай можно использовать схожий механизм, сравнивая доступность картинки напрямую и через какой-нибудь анонимайзер. Ресурс в таком случае можно считать заблокиованным тогда и только тогда, когда через анонимайзер картинка видна, а напрямую — нет. Правда, анонимайзер тоже может быть заблокирован, и тогда придётся проверять ещё и его доступность — например, запрашивая через него картинку с сайта самого РКН.

Где ещё есть толк от этого в народном хозяйстве?


  • Мобильная версия Википедии сможет точно вовремя предупредить пользователей о блокировке десктопной (они на разных адресах и на разных доменах), и наоборот.
  • Вебмастер, установив на страницу скрипт с аналогичным принципом действия, сможет на лету менять ссылки на конечное количество заблокированных ресурсов на ссылки через прокси. Готового решения нет, но патчи принимаются.
  • Можно точно выявлять пользователей, у которых заблокирован (неважно, госцензурой или работодателем) любимый сайт (ВКонтакте и т. д.) и предлагать им купить VPN/прокси или использовать бесплатный прокси с рекламой.
  • МожноНельзя на клиенте определить факт использования TOR/I2P, запросив таким образом картинку с домена .onion / .i2p
  • Хотите знать, активен ли у вашего пользователя IPv6? Просто загрузите картинку на какой-нибудь IPv6-адрес. Или воспользуйтесь картинками на серверах кого-нибудь крупного (типа Гугла), поддерживающего новый протокол.
  • А ещё в некоторых случаях можно определить DNS, которым пользуется клиент. Например, OpenNIC и прочие NameCoin/.bit
  • В веб-интерфейсах роутеров тоже бывают картинки! А значит, модель роутера при желании тоже можно определить, даже если веб-интерфейс извне недоступен.
  • Наконец, можно проверять принадлежность к определённой сети. Например, у некоторых провайдеров есть целые поддомены с сайтами, доступными только своим абонентам. Неужели там не найдётся ни одной картинки? Можно проверять и принадлежность к корпоративным сетям — если, конечно, знать, какие ресурсы доступны только изнутри. Может быть, вы хотите показывать что-то особенное пользователям, заходящим в сеть по вайфаю из московского метро? Из распространённой сети кафе? Тогда стоит поискать на соответствующей странице авторизации картинки, доступные только изнутри! Хотя нельзя не признать, что определение по IP иногда более оправданно.
  • Нельзя с помощью chrome extension URLs проверить наличие любого расширения, в котором есть отдельные файлы-картинки. У меня всегда получается «битая» картинка.
  • В некоторых старых браузерах (IE6?), не блокирующих доступ к локальным картинкам, вероятно, можно с довольно неплохой точностью определять версии установленных у пользователя прикладных программ (Libre Office, GIMP, MS Office, Adobe Photoshop и т. д.) — достаточно знать, какие картинки какого размера характерны для каждой из версий. Конечно, это сработает, только если программа установлена в директорию по умолчанию, но, например, такой приём позволит вывести на сайте инструкции по установке программы, отсутствующей у пользователя, но необходимой для работы с сайтом. В современных браузерах, скорее всего, не работает.

Комментарии (38)


  1. Meklon
    10.09.2015 11:49
    +1

    Надо потыкать, спасибо.


  1. bakhirev
    10.09.2015 13:01
    +12

    Почему нельзя так?

    var icon = new Image();
    icon.src = "wiki.ru/logo.png";
    icon.addEventListener("error", function () {
        alert("Not work");
    }, false);
    


    1. xobotyi
      10.09.2015 13:51

      Вот тоже хотел поинтересоваться почему не хэндлером ошибки решено…


    1. xobotyi
      10.09.2015 13:57

      И вот уж что совсем не ясно, так это зачем добавлять эти картинки на страницу, пусть и за пределы её видимой области.


    1. NickKolok
      10.09.2015 14:18
      +2

      При таком порядке, если изображение закэшировано браузером, событие можно и вообще не получить. Как минимум нужно поменять 2 и 3 операторы местами и добавить случайный 'хвост'. За наводку спасибо, доберусь до стаца, погоняю по браузерам. Но беспокоюсь, что в ряде случаев события можно вообще не дождаться.


      1. xobotyi
        10.09.2015 14:29

        В вашей реализации есть косяк в том что мы можем запросить сравнение размеров еще до загрузки картинки. Тогда придётся проверять его ещё раз после и так до тех пор, пока картинка не загрузится.
        А что касается кеша, то и ваша реализация его не переборет.

        В случае с событиями просто следует обрабатывать сразу два события load — Тогда сайт однозначно доступен и error — Тогда однозначно недоступен. До десктопа сейчас доеду, форкну и предложу свой вариант


        1. NickKolok
          10.09.2015 16:23

          Очень похоже, что можно через события. Сейчас проверяю в разных браузерах (на этот раз включая ненавистный IE).


          1. xobotyi
            10.09.2015 16:24

            да я уже все уложил в 1 единственную функцию, через события. щас завершаю тесты, но даже IE5 работает :D


            1. NickKolok
              10.09.2015 16:28

              Жду пулл-реквест?


              1. xobotyi
                10.09.2015 16:37

                сделал, я там правда совсем другую демку сделал, но всеже.


    1. NickKolok
      10.09.2015 20:52

      Кстати, а что будет, если подобны образом запросить URL, который не является изображением, например, habrahabr.ru? Выполнится onload или onerror?


      1. NickKolok
        10.09.2015 20:58

        Проверил. Firefox, Chrome — error.


  1. Vindicar
    10.09.2015 13:44
    +1

    Можно на клиенте определить факт использования TOR/I2P, запросив таким образом картинку с домена .onion / .i2p Правда, с трудом представляю, зачем это нужно, кроме того, не исключено, что TOR Browser умеет с этим бороться.


    Настроить браузер таким образом, чтобы это сработало можно, но настоятельно не рекомендуется в официальных инструкциях именно по этой причине — спалиться можно.


  1. Suntechnic
    10.09.2015 14:29
    +25

    Пишим правильно: не «Роскомнадзор предпринял попытку блокировки Википедии», а «Роскомнадзор предпринял попытку блокировки граждан России в Википедии». С Википедией всё нормально. Это у людей проблемы. Действия РКН направлены не против сайта, а против граждан РФ. Даже в резульате блокировки серверы продолжат работать в штатном режиме. Это некоторые клиенты не получат данные.
    Употребляя такие обороты как в статье, вы создаете иллюзию, что РКН и другие подобные организованные группировки борятся с кем-то третьим. Как будто их враг не россияне, а какие-то злодеи.


    1. GAS_85
      10.09.2015 14:49
      +8

      Ну тогда пойдем далшье, не «граждан РФ», а «граждан территориально находящихся на территории РФ».


      1. Stalker_RED
        10.09.2015 16:00
        +3

        Можно еще дальше: находящихся на территории и не умеющих vpn, tor и всякие прокси.

        Но смысл коммента не в точном описании категории граждан, а как у Карлина — Планета в порядке. Это людям — *дец!
        https://www.youtube.com/watch?v=cuLl8_CDum0


      1. zed91
        10.09.2015 20:15

        /зануда mode on
        а ведь еще есть лица без гражданства
        /зануда mode off


    1. szubtsovskiy
      10.09.2015 15:04
      +8

      Есть такой философский принцип под названием Бритва Хэнлона: «Никогда не приписывайте злому умыслу то, что вполне можно объяснить глупостью» (да-да, это из Википедии). Действия РКН не направлены ни против сайта, ни против граждан РФ. Действия РКН направлены на формальное соблюдение закона. И надо отдать им должное, что просто так шашкой направо и налево они не ходят и не махают. Википедия осталась незаблокированной.
      Употребляя такие обороты как в комментарии, вы создаёте иллюзию, что врагами РКН и других подобных организованных группировок являются россияне и что у них вообще есть враг. Это может быть вашей точкой зрения, но не надо её возводить в ранг истины. Это необоснованное и голословное утверждение.


      1. Calvrack
        10.09.2015 15:49
        +5

        Действия РКН направлены на формирование коммерческой структуры которая позволит аффилированным с ним предприятиям зарабатывать на уничтожении IT-бизнесов или напротив — на их крышевании. Это следует из утечек которые слили в апреле.


        1. khim
          10.09.2015 16:28
          -3

          Мир — куда многограннее, чем вам кажется. Есть люди, которые стремятся создать структуру, которая будет зарабатывать на уничтожении IT-бизнесов. Есть люди, которые надеются что данный механизм можно будет использовать для защиты во время будущих беспорядков (защита от «майдана»). Есть даже люди, которые искренне верят, что они защищают тем самым детей. Каково соотношение всех этих сил — сказать сложно, так что вот так брать и заявлять, что «крышевание» — это основная причина нельзя. Если основная цель — давление на IT-бизнесы, то почему вся история не началась лет 10 назад, когда оные бызнесы уже были достаточно велики для того, чтобы их можно было начинать стричь?


          1. Suntechnic
            10.09.2015 16:41
            +3

            Потому что десять лет назад, распределение естественных рент только-только закончилось. И идея формирования искуственных рент только созревала. На первый план, вышли наиболее профитные механизмы. Первым из которых заслуженно стал иститут СРО. Пока не исчерпаны области с максимальным выхлопом никто не станет обращать внимание на такие сектора второго эшелона как авторские права, регулирования интернета, семейное регулирование. Сейчас когда ресурс СРО исчерпан и разделен — взялись за это. Единственное что действительно удивительно — затишье на рынке правового и медицинского страхования. Вполне возможно это станет следующим этапом, если не случится чего-то что приведет к новому переделу и тогда снова всё начнется с распределения естественных рент, как-то ресурсны например.


          1. Calvrack
            10.09.2015 17:01
            +5

            Мне ничего не кажется. РКН вырастает из кучи разных противоречивых мотиваций. И личные деньги и власть одна из них. Структуры — такие например как милиция не стремятся ходить по дворам и отбирать пиво у людей на лавках, несмотря на такое право, потому что возни много, а профита — кот наплакал.
            Законы против детской порнографии и распространения конвенционального порно существовали очень давно — но никого не закрывали. Но в какой-то момент появился шанс начать расставлять DPI на каналах за госденьги, запустить руки в самую суть сети.
            Есть не просто «глупость», есть ведущаяся на всех уровнях — от законодательного до самого нижнего уровня исполнительного — кампания по созданию механизмов на которых можно зарабатывать деньги или контролировать движение информации (одно конвертируется в другое).
            Я не могу назвать глупцами людей которые заготовили оборудование и каналы его поставки, лоббировали законы которые сделают это оборудование необходимым, формировали общественное мнение, эксплуатировали страх перед насилием в отношении детей и страх наркотиков, демонстрировали силу — показывая владение полным контролем над доступом к github, разрушали использование https, закрывали по команде информационные рупоры политиков, и целенаправленно ломали «Великую Машину Всего Человечества» — Интернет. Это умные, алчные и беспринципные люди.


            1. szubtsovskiy
              10.09.2015 17:28
              +1

              Бесспорно, стоящим у руля не откажешь в наличии интеллекта. Следует помнить только то, что указания заблокировать тот или иной сайт отдают не те, кто командует парадом, а рядовые исполнители. Принцип Хэнлона применять следует именно к ним.
              Как раз те, кто стоит у руля, хорошо понимают, какой эффект может принести блокировка Википедии или подобных ей популярных ресурсов. И, скорее всего, как раз от них идёт команда Википедию не блокировать. Именно в силу тех самых указанных вами причин.


        1. semenyakinVS
          11.09.2015 09:14

          Интересно, как можно заработать на крышевании Википедии?


          1. Calvrack
            11.09.2015 12:34

            Дело тут вот в чем, когда рекетиры убивают того кто им не платит, они не планируют получить с него денег… они посылают message. И чтобы закрыть этот странный спор я приведу цитату

            «19 мая 2014 «Жаров» получил письмо от некоего Андрея Васильева с заголовком «От Андрея Васильева про комсомольскую организацию». Письмо пришло с адреса dzintaru39@mail.ru. Дзинтару, 39 — адрес дома в Юрмале, в котором, по некоторым данным, живет бывший шеф-редактор ИД «Коммерсантъ» Андрей Васильев. Кроме того, автор письма просит звонить ему («Если чо, готов к любым пояснениям») и указывает номер, соответствующий номеру телефона медиаменеджера. К письму приложен документ под названием «Идеология комплекса поправок. Страхование интернет-ресурсов». »


            1. semenyakinVS
              11.09.2015 19:11

              Дело тут вот в чем, когда рекетиры убивают того кто им не платит, они не планируют получить с него денег


              Кто им платить должен? Я спрашивал о том, какой прок вики рекетировать? Чего от свободной энциклопедии получить-то хотели и чего она им не дала?

              С приведённой цитатой же вообще ничего не понял — какое-то странное нагромождение слов, в котором с трудом угадывается смысл. Какой «Жаров», какой Дзинтару? Можете своими словами объяснить о чём там речь идёт? Как я понял, кто-то кому-то прислал какой-то зловещий документ, грозящий отобрать у русских свободный интернет?


      1. Suntechnic
        10.09.2015 16:34
        +9

        А действие карателей СС не были направлены против граждан СССР — действия их были направлены на формалльное выполнение приказа?

        РКН просто выполняет закон. Депутаты просты приняли закон. Призидент просто подписал. Никто из них не виноват, что закон нелепый, глупый и вредительский. В конце-концов все знают, что по настоящему виноват Обама.


        1. szubtsovskiy
          10.09.2015 17:33
          -6

          Это называется передёргиванием фактов. И уж совершенно точно никоим образом не подтверждает слова о том, что врагом РКН являются граждане РФ. Просто набор разнообразных домыслов. Даже читать такое странно.

          Моя критика была направлена на то, что, обвиняя автора статьи в выражении своих мыслей посредством неподходящих под ваши убеждения речевых оборотов, вы тут же на пустом месте начали создавать иллюзию того, что граждане РФ являются врагом каких-то там служб. Я даже признаю, что эта точка зрения имеет право на существование, но так ли уж необходимо на фоне позитивной, в общем-то, новости, делать вклад в формирование образа угнетающих народ государственных структур? Кому от этого легче-то станет?


          1. Suntechnic
            10.09.2015 17:54
            +4

            Какие факты я передергиваю? Пример пожалуйста. Вы можете сказать, что я преувеличиваю, перегибаю палку. Что РКН все-таки пока не расстреливает людей и сравнивать их с СС преждевременно — да, так вы тоже можете сказать, хотя и их и не сравнивал, я бы еще понял такое возражение. Но факты…
            Впрочем, я безусловно немного преувеличиваю. Но лишь немного.

            Что же до ваших вопросов — да, необходимо. Необходимо потому, что когда мы называем вещи не своими именами, это формирует подсознательно неверное отношение, даже у тех кто понимает, что за структура РКН.
            И легче от этого ни кому не станет. Если бы я хотел сделать читающим это легче, я бы дал ссылки на сайты торгующие наркотиками или сайты государственных СМИ. Я, да и не только я, хочу не облегчения — я хочу выздоровления.


            1. szubtsovskiy
              10.09.2015 18:07
              -7

              Фактов вы намешали в одном сообщении целую кучу. РКН выполняет закон. Депутаты приняли закон. Президент подписал закон. Всё это — факты, всем хорошо известные, никоим образом вашу точку зрения не подтверждающие, но вы приводите их, для того чтобы придать своим словами эмоциональную окраску, заставить тех, кто читает ваш комментарий, с вами не единожды согласиться. Для того, чтобы затем с лёгкостью продать им совершенно не имеющую к этим фактам отношения идею. Это известный психологический приём. Сознательно или подсознательно вы это делаете — другой вопрос.

              Вся проблема в том, что и вы точно так же не называете вещи своими именами. И точно так же формируете выгодное вам (а не читателям) конкретное подсознательное отношение к РКН и прочим государственным структурам. Более того, ещё и пытаетесь убедить всех в том, что мы тут жертвы, РКН с нами враждует и всё такое. Не надо так.

              Я снова повторю, что ваша точка зрения имеет право на существование. Хочу лишь подчеркнуть, что это не истина, более того, это очень слабая позиция. Но пусть. Каждому своё.


              1. Suntechnic
                10.09.2015 18:40
                +6

                Вы как-то упустили из вида слово «просто» в этих «фактах». Это был всего лишь сарказм. Направленный на то, чтобы напомнить читателю, что не смотря на то, что вы говорите, что РКН просто выполняет закон, он выполяет его совсем не просто. А совершенно осознано и большой радостью. Точно так же и депутаты не просто выполнили свою функцию по принятию законом всякого бреда, а сделали это совершенно осознано и осмысленно. И так далее.
                Как бы вы не уверяли, что РКН просто иснтрумент и ни за что не может нести ответственности — это не так.
                Как бы вы не говорили, что РКН не совершает никаких действий против граждан России, нарушая их права и свободы — это не так.
                Да, моя позиция безусловно слаба, ибо подкреплена только логикой и здравым смыслом, а не милионной армией силовиков. Я это знаю, но что поделаешь?

                > Вся проблема в том, что и вы точно так же не называете вещи своими именами.
                Например. Давайте по существу. По большому счету, я сказал, что действия РКН напрвлены против граждан России. Это не так? Ограничения свобод другого человека не является действием направленным против него? Расходование средств государства на действия причиняющие вред жителям этого государства не является действиями направлеными против его гражда?
                Или может вы ставите под сомнение, то, что ограничение доступа к информации приченяет гражданам вред?
                Вы можете сформулировать, почему действия РКН по блокировке доступа граждан к отдельным ресурсам сети Интернтет, является полезным для граждан? Заметьте — вам придется доказывать именно пользу, потому что если вы просто докажите безвредность, это автоматически будет означать вред, так как безвредность != полезность, а бесполезность купленная за деньги налогоплательщиков это растрата. И вредна она настолько, что считается преступлением.


                1. szubtsovskiy
                  10.09.2015 19:01
                  -8

                  Всё дело в том, что мне не нужно ничего вам доказывать. Это вы высказали некоторую позицию, не подтвердив её ни единым фактом, а вместо подтверждения приводите ещё больше разнообразных домыслов, каждый из которых можно подвергнуть сомнению, раздув эту дискуссию до размеров Вселенной. Да ещё и с меня требуете доказательств полезности действий РКН, приписывая моим словам свои собственные размышления. Ни в одном своём сообщении не говорил я ни о полезности, ни о безвредности действий государственных структур.

                  Ответ у меня только один: оставайтесь при своём мнении. Имеете полное право. Всего доброго!


    1. NickKolok
      10.09.2015 16:27

      «предпринял попытку блокировки доступа с территории РФ к Википедии» — достаточно корректно?


      1. Suntechnic
        10.09.2015 18:06

        Да. Думаю так тоже можно. Спасибо.
        Не за правку — решение. Интересная идея с подгрузкой картинки.


        1. NickKolok
          10.09.2015 18:35

          На самом деле выше уже предложили ещё более элегантный и универсальный способ, который позволит обойтись вообще одним фавиконом, и на гитхабе уже кипит работа. Но принцип тот же, да: «свидетельство канарейки» через условно-безопасный и уже имеющийся на практически любом сайте контент — картинки, притом на клиенте.
          Осталось дело за готовыми решениями под распространённые библиотеки, в первую очередь — jQuery.


  1. ComodoHacker
    11.09.2015 09:24

    Неплохо бы еще проверять наличие страниц Википедии в Реестре. Точнее, в копии Реестра на rublacklist.net.


    1. Vindicar
      11.09.2015 11:13

      Разве что в дополнение к основному методу, имхо. Блокировки «по звонку» и разблокировки «по здравому смыслу» никуда не делись.


  1. nett00n
    12.09.2015 12:24

    Изменения hosts вступают в силу не мгновенно.

    Я бы ещё указал, что в Windows для обновления кэша DNS нужно использовать команду
    ipconfig /flushdns