0,0
рейтинг
24 июля 2014 в 13:04

Разработка → Ещё одна причина переходить на SSL, или 133 КБ не лишние

КДПВ



Вечерело


Мы с товарищем, сделали простенький тест (github) на проверку доступности data-uri в браузерах. Выглядит он следующим образом:



В textarea javascript'ом вставляется navigator.userAgent. В этот момент я не знаю, что меня стукнуло в голову, но вместо DOMContentLoaded, я написал . По-быстрому проверив корректную работу в десктопных браузерах и на нескольких мобильных устройствах, подключённых к интернету через wi-fi, мы успокоились и разошлись по домам.

Солнце продиралось сквозь занавески


Утром, в полупустом вагоне метро, я как всегда открыл браузер на своем телефоне, на котором со вчерашнего вечера была открыта тестовая страничка. Сказать, что я удивился, когда я не увидел вывода userAgent
внутри textarea — ничего не сказать.

Добравшись до компьютера, решил потратить немного времени на поиск проблемы. Запустив страничку на десктопе и в эмуляторе, я ничего не заметил. Открыл на телефоне. Чудеса! Всё работает.

Увидев включённый значок wi-fi, я начал догадываться о причинах проблемы. Я отключил wi-fi, подключил телефон к компьютеру и начал дебаг с помощью веб-инспектора десктопного сафари.

Горячий кофе и приятный вкус дебага




Уоу-уоу, полегче, подумал я. Откуда всё это могло взяться в шести строчках JS'а?

А вот откуда:



Отличился наш любимый оператор Beeline, с которого я ещё не до конца успел слезть. На небольшую тестовую страничку внезапно прилетело ~133КБ паразитного траффика.

Anchor.js расположен по адресу toolbar.beeline.ru/ets/scripts/Anchor.js, который доступен только из сотовой сети Билайна. Для всех желающих посмотреть на стиль кодирования на JS в Билайне, я подготовил ссылку — gist.

Сколько вешать в граммах?


Что же входит в эти 133 КБ:
* 91 КБ jQuery v1.7.2;
* 42 КБ самописного кода.

Видно, что никто не заморачивался даже использованием CDN для jQuery. Ну ОК. Смотрим дальше на самописный код.

Первые 914 строк — один большой if:

if (document.getElementById('toolbar') == null)
{
    //...много кода
}


Дальше немного хелперов с упором на мобильные устройства от Apple:
function getIOSVersionNumber(){}
function isIt(theDevice){}
function isMobile(){}
function isIPhone(){}
function isIPad(){}
function getBodyZoomLevel () {};
function isNumberPercentageBased(number) {}
function getVisualViewportInfo () {};


We need to go deeper


Испектируем код про тулбар:

(function(jQFrm){
    if (window.XDomainRequest) {
        // много кода
    }
})(jQFrm);


Находим здесь упоминание проприетарного XDomainRequest, который существовал только в IE8 и IE9. Не понимаю, зачем этот код нужен на мобильных устройствах.

Идём дальше:

var ets_scripts = jQFrm('[name="ets-anchor"]');

jQFrm(window).resize(function()
{
    resizeIframe();
});

if (ets_scripts.length == 1)
{
    // много кода
}


Встречаем второй большой if и первое вмешательства в обработку событий на произвольном мобильном сайте.
По этому селектору находится этот самый Anchor.js, который вставляется в момент перехвата ответа от веб-сервера мобильному браузеру.



Продолжаем чтение по диагонали:


(function()
{
    var msgHandler = function(e)
    {
        var ets_frame = document.getElementById('toolBarPcFrame');
        if (e.origin == 'http://toolbar.beeline.ru')
        {
            // 500 строк кода
        }
        else
        {
            //alert(e.origin);
            throw new Error('Origin domain is not allowed.');
        }
    }
    // listen for the message event
    window.addEventListener('message', msgHandler, false);
})();


Находим механизм общения со встроенным iframe через window.postMessage.

Опять хелперы и...:
function GetWidth() {}
function GetHeight(){}
function resizeIframe(){}
window.onpageshow = function(evt){};
window.onorientationchange = function(){};
window.onload = function(){
    //etsAppMain functions (search application)
    if (InitParamForScroll)
    {
        InitParamForScroll();
    }
};
function isLandscape(){}
function orientation_changed(actionId){}
if (isMobile()){}


Oh, wait. Вот и причина изначальной проблемы — подмена window.onload

window.onload = function()
{
    //etsAppMain functions (search application)
    if (InitParamForScroll)
    {
        InitParamForScroll();
    }
};


Возврвщаясь к нашему первому if'у.
$(document).ready(function()

$('html').append('<div id="toolbar" tabindex="-1" style="border-width:0px;outline-width:0px;"></div>');

var currentTime = new Date();
/*var pathname = window.location.href;
 var  screenWidth = screen.width;*/

var ifrm = document.createElement("IFRAME");
ifrm.setAttribute("id", "toolBarPcFrame");
/*ifrm.setAttribute("src", "http://toolbar.beeline.ru/ets/ToolBarPcServlet?screenWidth="+screenWidth+"&url="+pathname);*/
ifrm.setAttribute("src", "http://toolbar.beeline.ru/ets/ToolBarPcServlet");
ifrm.setAttribute("allowtransparency", "true");
ifrm.setAttribute("background-color", "transparent");
ifrm.style.position = "fixed";
ifrm.style.zIndex = 9999999999;
// много кода


В момент инициализции страницы, паразитный скрипт вставляет в конец нашего html div, а уже внутри создаёт iframe на toolbar.beeline.ru/ets/ToolBarPcServlet. Обратите внимания на CSS-свойства position, zIndex. Это чтобы наверняка было заметно ;)

Режем по-живому


В качестве быстрого решения, можно использовать примерно такой gist.

document.addEventListener('DOMContentLoaded', function() {
    var toolbar = document.getElementById('toolbar'),
        iframe = toolbar && toolbar.firstElementChild;
    if (iframe && /beeline/.test(iframe.getAttribute('src'))) {
        toolbar.parentNode.removeChild(toolbar);
    }
});
setTimeout(function() {
    var script = document.querySelector('script[name=ets-anchor]');
    if (script) {
        script.parentNode.removeChild(script);
    }
}, 0);

Может я подумаю ещё пару минут чуть позже и придумаю более элегантное решение. Смотрите в gist :)

Минутка морали.


Кроме капитанского "не использовать onload", могу дать несколько полезных советов:
  • если вы разработчик, по возможности, используйте SSL на ваших сайтах, чтобы _никто_ не мог перехватить ваш траффик;
  • если вы подключили на свою страницу 90КБ jQuery кода, то используйте его, а не пишите потом document.getElementById;
  • если вы оператор связи, то никогда не включайте такие услуги "Мини-Кабинет"







P.S. Этот пост ни в коем случае не наезд на компанию Билайн. Я имел положительный опыт решения проблем с помощью их твиттера Beeline_Rus. Надеюсь, что этот пост поможет хорошим людям внутри компании вырезать эту странную услугу на корню и сделать лично меня и миллионы абонентов чуточку счастливей.



update
Купил на свой домен SSL-сертфикат. Теперь никакая зараза не пройдёт. Также продолжаю переписку с Билайном, на тему отключения услуги Toolbar совсем и всем.

update, 6 октября 2014
Ещё 18-го сентября, мне пришло письмо от pomogite@beeline.ru следующего содержания:
Роман, здравствуйте!

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

Я, конечно же, пошёл проверять. На удивление, никаких лишних сетевых запросов/вставок в HTML'е я не обнаружил. Сразу написал об этом в твиттере, а вот про хабр забыл :(

Теперь вот исправляюсь, перепроверив ещё раз. Кто-нибудь проверит у себя? ;)
Роман Рождественский @sbmaxx
карма
41,5
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

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

  • +9
    Это вы в wifi-enabled вагонах московского метро не катались, видимо. Там вообще рекламные баннеры, распологающиеся поверх странички, внедряют и нормально себя чувствуют.
    • +5
      Мне всего одна станция по кольцу. Я успеваю только авторизоваться и скачать апдейт для reeder.app. Но про эти баннеры наслышан. Ещё один поинт в копилку внедрения https://
      • +1
        или выставлять свой dns на чужих wi-fi хотя бы
        • 0
          Это не очень эффективно, так как DNS запросы элементарно подменяются на лету.
  • +29
    Это хороший совет использовать SSL.
    Например и к сожалению, у хабра нету https, чтобы избежать встроенной рекламы в Wi-Fi MosMetro_Free :(
    • +3
      Зато есть приложение под все популярные смартфонные ОСи.
      • +4
        Там тоже есть реклама в splash screen'e :P
        • 0
          Да и в постах насколько я помню.
  • –9
    если вы подключили на свою страницу 90КБ jQuery кода, то используйте его, а не пишите потом document.getElementById
    Встроенный метод браузера в общем случае значительно быстрее, чем библиотечный, тем более в случае getElementById() даже селектор разбирать не нужно.
    • +5
      Быстрей, но не настолько, чтобы не экономить на $('#id'), если подключёна jQuery.
      • –5
        GZip не пробовали? ;-)
        • –1
          В конце концов, можно написать var byId = document.getElementById.bind(document); и использовать собственный короткий вызов byId(), работающий со скоростью встроенного метода.
        • +3
          Пробовал.

          Речь же не про GZip, а целесообразность подключёния библиотеки ради стрельбы по воробьям.
          • –7
            Безусловно, библиотеку следует подключать только при острой необходимости (например, на моём сайте весь JS весит менее 6 КБ). Но в прокомментированном мной вашем совете речь о другом: «подключил библиотеку — слепо используй её всегда даже при наличии встроенных методов браузера, работающих быстрее». А это совет, мягко говоря, вредный.
    • +5
      Есть масса способов увеличить производительность. Тот что вы описали, дает совсем не значительный выигрыш в скорости.
      А вот отказал от вытягивания jQuery, который используется в менее, чем 10 местах в коде, дало бы значительно больше профита.
  • +3
    Судя по описанию услуги, в навязанной панельке должна быть ссылка «Отключить навсегда». Вы не думали о том, чтобы средствами JavaScript на неё нажимать, назло полосатым?

    (А вообще, после прочитанного вызрел ещё один аргумент поднять VPN на Амазоне и пускать весь трафик, со всех девайсов, только через него...)
    • +1
      У меня панелька не показывается, но она всё равно присутствует в DOM-дереве, скрипт и iframe подгружаются.
    • –3
      Более того, я как то видел в этой панельке свой номер телефона, а вот это уже дыра. Представьте себе, все кто зайдут на сайт с этой панелькой добавят свой номер телефона в базу данных сайта, а он уже может рассылать спам-рассылку…
      • +4
        А как его из ифрейма получить?
        • 0
          А возможно ли к примеру загрузить его не в ифрейм, а в див? Ну через ajax.
          • 0
            Вряд ли. Оно должно а) уметь отдать, б) поддерживать одну из кросс-доменных технологий обмена.
        • 0
          Clickjacking?
          • 0
            Слишком сложно, имхо. Но как вариант рассмотреть можно.
  • +25
    Да уж… мобильные операторы умеют подпортить жизнь. МТС, к примеру, нагло подменяет URL при клике на результат поиска в Google.
    Ищем, например, какую-нибудь музыку. В выдаче поиска Google видим строку с URL на зайцев.нет, если открывать со стационарного компьютера попадаем на эту самую страницу, если с мобильного, то редиректит на какой-то аффилированный МТС сайт с большой зеленой кнопкой Скачать и кучей мелкого серенького текста, гласящего что при клике вы автоматически будете подписаны на доступ к медиатеке за 20 рублей в сутки, причем никаких подтверждений кроме самого нажатия на кнопку не требуется — МТС сама знает ваш номер договора, поскольку мы идем через её гейт. Если не жать на зеленую кнопку, а вернутся в поиск то с определенной степенью удачливости оно все-таки переходит куда следует, но как я заметил не всегда.
    Такие вот дела.
    • +13
      Уверен, что в описанном случае вопросы надо задавать не мтс, а зайцам, которые определяют, что вы пришли с мтс и кидают на этот самый сайт (можно, кстати, проверить с билайна/мегафона)
      • +1
        Очень может быть, но ведь они подписывают меня по сути дела не спрашивая ни мой номер телефона ни каки-то другие данные идентифицирующие меня как клиента МТС, а значит берут их по какому-то партнерскому договору у МТС — так что без мобильного оператора вся эта кухня была бы невозможна.
        • +1
          в Мегафоне от этого помогает подключить «отказ от услуги «Интернет-Клик»»
          в сервис-гиде это немного спрятано: Услуги и тариф — Изменение тарифных опций — Скидки на Интернет — Интернет-опции — Отказ от услуги Интернет-Клик
          • 0
            Ничего подобного там нет

            Уральский регион
            • 0
              В Московском регионе

              выглядит так:
              image

        • +1
          МТС вообще огромный позор, я как-то так случайно нажал на ссылку в браузере мобильника, после чего меня подписали на «библиотеку МТС» за 20 рублей в сутки или что-то типа того, с сообщением «отправьте смс СТОП на номер 1234». И как я могу отправить такое сообщение, когда у меня блекберри без русской клавы? Звонил 3 раза в контактный центр, просил отключить, меня уверяли, что все отключат. Потом я тупо забил и перестал пользоваться сим картой. Самые большие жулики МТС.
          Еще прикалывает, когда звонишь в колл-центр и на нервах разговариваешь в тоне типа «почемы вы с меня снимаете деньги, когда я просил вас отключить эту услугу», на что в ответ обиженные девушки начинают говорить «ну это же не я вам снимаю»…
          /* жутко @ бесит. jpg*/
          • +1
            Ну, справедливости ради, девушки в колл центре и правда ни в чем не виноваты.
            • +2
              Я их и не обвиняю. Но если они там работают, значит, они представляют свою компанию.
          • 0
            Справедливости ради, таким промышляют не только МТС, но и например у меня родители сидя через Мегафон регалярно на такие подписки попадаются. И предполагаю, что и билайн таким развлекается.
    • 0
      Это не МТС, это сами зайцы так зарабатывают.
  • +7
    По мне так адский ужас, ладно ещё хоть как-то можно согласится что они слушают наш трафик, но что бы менять, имхо это верх наглости, подключена услуга или нет, не важно, мой трафик на то и мой, что бы его всякие непонятные(да и понятные тоже) люди трогали.
    • +14
      Не нужно соглашаться, чтобы они слушали трафик. Используйте VPN. По умолчанию, т.е. всегда. Пока и его не запретят.
      • +2
        Я негодую! По-моему, за такое кое-кто должен получать по сусалам. Мало того, что они своим немытым рылом врезаются и портят мой трафик (за который я плачу деньги, на минуточку, и неважно, даже если это происходит только в метро с бесплатной вафлей, я все равно оплачиваю его покупкой билета), нарушая тем самым функционал и логику работы моих и сторонних сервисов и приложений, так они его еще и расходуют вместе с моим временем, которое тратится на ожидание загрузки, более того, еще и свои скрипты сомнительного содержания распространяют, что я считаю можно расценивать как потенциальную угрозу, сегодня они свою говнопанельку выводят, а завтра может вообще битки между делом майнить будут за мой счет. Я считаю, что должен быть закон, защищающий права клиентов, по которому провайдер за такие дела должен страдать (впаривание услуг и прочие отягчающие)… Но что-то мне подсказывает… Минутку, в дверь стучат, сейчас вернусь…
        • 0
          1,5 года прошло — пора вернуться
  • +4
    Хех, меня этот тулбар сильно удивил однажды в iOS симуляторе, внутри моего же webview…
  • 0
    Крутое расследование, Ром!
  • 0
    Не очень понятно, по какому принципу происходит подключение этой услуги? Пользуюсь 3G от билайна уже 10 месяцев, ничего подобного не замечал
    • 0
      Регион? Не уверен, что по всей России. Визуально тулбар может быть не виден, надо смотреть исходный код через удаленный веб-инспектор.
      • 0
        Москва. А услуга, если подключена, не должна разве отображаться в подключённых услугах в личном кабинете?
        • 0
          Именно эта услуга не отображается. Сейчас пытаюсь выяснить у билайна, как от нее избавиться.
  • +4
    VPN наше все.
    После пары странных ситуаций со сжатием, обрезанием заголовков и прочими прелестями «ускорения интернета» со стороны провайдеров разных мастей теперь только VPN. Обходится копейки, дешевле чем сотовая связь в месяц.
    SSL это хороший совет для владельцев сайтов.
    Но пока слишком много сайтов без SSL — клиентское решение это VPN.
    • +1
      Давно думал подключить VPN для мобильного инета. Не посоветуете провайдера?
      • +1
        1. Покупаем самую дешманскую VPS на базе OpenVZ в Европе.
        2. Настраиваем на ней OpenVPN.
        3. Настраиваем на всех рабстанциях клиента OpenVPN.
        4. ????
        5. PROFIT!

        ;-)
        • 0
          На OpenVZ может быть проблема с созданием tun/tap-устройств — в большинстве случаев его поддержка отсутствует. Надо узнавать заранее. И даже если говорят, что всё ок, бывает, что сегодня работает, а завтра уже нет. И нужно писать в саппорт. А потом настаёт послезавтра. У меня так было. Провайдера не помню уже, к сожалению.
          • 0
            Я думаю, Вы давно не приобретали виртуальные машины. С тех пор в этом плане всё изменилось и сейчас даже самой средней руки (или только начинающие) хостеры поддерживают эти типы интерфейсов в контейнерах OpenVZ, причём они включены в настройках машины по умолчанию. Т. е. не надо тратиться на машины на базе KVM!

            Можете попробовать контейнеры у проверенных мной провайдеров (очень стабильные).

            точно поддерживают tun/tap
            (Пожалуйста, не удаляйте код из ссылки — сделаете мне приятно ;-))
            1. my.iniz.com/aff.php?aff=207
            2. bandwagonhost.com/aff.php?aff=445 — $10 в год!


            Либо помониторить сайт lowendbox.com — там периодически встечаются бюджетные предложения.
    • 0
      Согласен. Политика мобильных операторов в отношении мобильного трафика явно неодекватная. Вот я не припомню ни одного проводного оператора, который бы позволял себе копаться в чужом трафике, как то модифицировать его и т д. Отдельная песня это платная тарификация некоторых сайтов. Проблема даже не в том, что некоторые сайты платные, если посмотреть на список этих сайтов это обычно такой шлак, на который обычный пользователь не зайдет. А в том, что обычный пользователь может и не заметить, что например к статье на хабре преклеплет прозрачный гиф 1х1, весом пару сотню килобай, который хостится на платном сайте. И главное на все возмущения операторы бодро рапортуют «сертифицированное оборудование зафиксировало, что с вашего абоненского устройства было соединение с сайтом». И ведь оно действительно было, вот только ты в этот момент читал хабр, а не качал подборку «шлюхи на пляже 9000». Пришлось на домашнем компе VPN сервер поднимать. Самоподписанные сертификаты это конечно плохо, но пока жаба душит покупать отдельный полноценный.
  • 0
    А я бы сразу после текстового поля воткнул заполняющий его скрипт.
    С точки зрения удобства разработчика, может, и не очень (хотя и дело привычки), а вот пользователи будут довольны. А то развелось сайтов, где элементы управления появляются задолго до загрузки управляющих скриптов. И дело даже не в скорости загрузки – даже на широком канале на том же youtube, например, есть подобная проблема.

    Ну, на маленьком-то примере, может, и ничего, но все большие сайты когда-то тоже были не такими уж большими, так что куда проще сразу делать с запасом на масштабирование – затрат-то лишних никаких (даже кода меньше станет, когда onload уйдет).

    P.S. Правда, мы бы тогда вряд ли узнали о выкрутасах билайна. :)
    • 0
      А я бы сразу после текстового поля воткнул заполняющий его скрипт.

      Так вначале и было, но потом я решил немного странное сделать — github.com/sbmaxx/datauri/commit/0c9d36b83ff850029d5fd97650a88faaa55f5d4e
      • 0
        Н-ну, я бы и это «чудо» сразу после используемых в нем DOM-узлов вызвал. :)

        Наболело просто, особенно когда всякие ссылки с недогруженными скриптами не только не работают, но еще и делают что-нибудь постороннее (и ладно еще, когда # в адрес дописывают, а то ведь и страницу перезагрузить могут).
  • +1
    А от этой сраной панели можно как-нибудь избавиться?
    • +2
      gist.github.com/sbmaxx/93023231373f2e105eef
      или можно создать пустой
      <div id="toolbar"></div>
      , например.

      Но я надеюсь, что Билайн прочитает этот пост и отключит панельку всем :)
      • +1
        Я имею ввиду, не для своего сайта, а вообще, в принципе.

        Люто бесит, на самом деле. Закрыть ее на айфоне нереально — крестик маленький, а даже если в него попасть — он просто не работает.
  • +1
    Мне с телефончика, несмотря на nexus 5, в разы привычней использовать браузер со сжатием трафика — UC browser, например. Пока банеры не лезут…
    • 0
      Да даже мобильный Хром умеет сжимать трафик и предлагает включить сжатие при первых запусках. Из минусов — местоположение по IP получается US, некоторым сайтам типа Юлмарта от этого плохо, приходится руками выбирать свой город.
      • 0
        У меня ни один сайт не определяет мой город, вечно я в Екатеринбурге (вместо Ижевска) оказываюсь на Мегафоне.
        • +1
          Это единственный оператор у которого Удмуртия и Свердловская область не разделяются.
  • +4
    Все такие встраиваемые скрипты, коих множество, обязательно хотят проверить что они еще не запущены. Для этого они или «гадят» в глобальными переменными в window, либо создают что-нибудь в DOM. Это их ахиллесова пята. Стоит добавить что-нибудь такое, и скрипт полностью сломается:

    <span id="toolbar"></span>
  • +2
    А ведь пару лет назад такую же штуку делал Мегфон, на Северо-Западе. Вот шуму то было. А сейчас все привыкли?
    • +1
      Может они её уже того? Есть возможность проверить?
    • 0
      Похоже этой болезнью головного мозга маркетоидов должны переболеть все операторы…
  • 0
    А ещё можно начать потихоньку внедрять Content Security Policy, только будьте осторожны. Github как-то включил его без тестирования в dev-версиях Chrome, так у них js не работал месяц в dev-ветках и несколько часов в stable версии Chrome.
    • НЛО прилетело и опубликовало эту надпись здесь
  • 0
    Вот что конкретно делает следующий код? =)

    function isMobile(){
        return isIt("Mobile");
    }
     
    function isIPhone()
    {
        return isIt("iPhone");
    }
     
    function isIPad()
    {
        return isIt("iPad");
    }
    
    • 0
      Проверяет вхождение фраз Mobile, iPhone, iPad в navigator.userAgent. Пытаются определить устройство.
  • +5
    Надо внесни toolbar.beeline.ru в RU AdList, напишите кто-нибудь вот сюда: forum.mozilla-russia.org/viewtopic.php?id=3679&p=549

    А те, у кого рут, или они не пользуются Firefox, могут сами заблокировать toolbar.beeline.ru в hosts.
    • 0
      К сожалению, мало у кого на мобильных устройствах есть возможность, поставить какой-нибудь блокировщик рекламы.
      • 0
        Да ладно, Firefox есть под Android и iOS, а это явно не «мало».
        • 0
          Ограничения Apple не позволяют нам портировать текущую версию Firefox на устройства под управлением iOS (iPhone, iPad, iPod Touch). Мы изыскиваем новые способы по созданию Firefox для iOS, но не имеем определённых планов по его выпуску.

          https://support.mozilla.org/ru/kb/dostupen-li-firefox-dlya-iphone-ili-ipad

          Какой % людей пользуется firefox на android? Сколько из них установило adblock?

          Проблему тулбаров надо решать разговорами с оператором :)
  • 0
    А этот паразитный скрипт пакуется в gzip? 130 KB — это какого контента — сам файл или его архив?
  • 0
    Помню подобную панельку на интернете от SkyLinkа. У меня тогда вообще половина сайтов перестали работать нормально, звонок в техподдержку — и функция была отключена.
  • 0
    Добавил небольшой update в конец поста.

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.