админские истории

админские истории

Подписчиков:
64
Постов:
23
Вот такой утром пипец обнаружился на работе. В серваке сорвало корпусной вентилятор, который упал на теплообменник процессора, перебил провода кулера этого процессора и частично снял скальп алюминиевому теплообменнику.

Как я блокировщик рекламы блокировал. Часть 2.


0. Введение 2.

Начало можно прочитать тут - http://joyreactor.cc/post/2587462
Если у вас есть какие-то вопросы по работе сайта или вам не нравится система анти-блокировщика, то можете создать отдельный пост или писать в этот http://joyreactor.cc/post/2493637 . Все, кто будут ныть тут про адблок будут забанены за тупость.


8. Ещё о моральных аспектах

Следующим логичным действием модераторов ruadlist являлось скрытие жёлтой таблички с просьбой выключить адблок. Хотя это и не являлось рекламой, но они давно скрывают не только рекламу. По поводу табличек антиадблока они даже написали полиси, где было описано что они не против табличек анти-адблока, но эти таблички должны быть максимально незаметными и закрываться по первому же чиху. О том, как они сами следуют этой полиси можно понять во-первых по предыдущим 5ти главам, где они пытались просто уйти от детектирования адблока, а во-вторых по тому, что табличку против адблока на хабре они тоже блокировали как "слишком раздражающую". Я сам эту табличку до того момента и не замечал...

Но тут они сражались "на моей территории". Я мог в любой момент изменить вёрстку как хотел. И жёлтая табличка появилась бы, а основной контент сайта исчезал. Однако это было проигрышем - пользователи не видели рекламу, не платили денег и просто ушли бы. Поэтому я такого не делал. Модераторы ruadlist могли заблокировать любую часть сайта, даже если она не относится к рекламе и просто убить сайт. Большинство пользователей посчитали бы это глюками сайта, а не проблемой адблока и ушли бы с сайта. Год назад, я пару месяцев гадал, почему в админке слетели css, пока случайно не увидел в консоли, что это адблок блокировал админский css, посчитав его похожим на брендирование.

Почему они специально не ломали сайт? Не знаю, может считают это неэтичным, может не умеют правильно ломать, может не понимают какая сила у них в руках. Их список скачивают миллионы пользователей. Одним "случайным" комитом они могут сломать любой сайт и пользователи с большой вероятностью посчитают это техническими проблемами и пойдут на сайт-конкурент.

Примерно к этому времени основному модератору списка надоело возиться со мной и он передал реактор второму модератору - Lain_13 (вставить шутку про его возраст судя по нику). Тот возился меньше. Он блокировал оптом. Под его правила могли подпадать (и подпадали) нерекламные элементы. Но его это, похоже, мало волновало. И тут я вычленил для себя правило: если из-за правил ruadlist часть сайта или функционала ломается, то надо ломать сайт до конца и сообщать пользователю что это из-за адблока. Это если не получалось легко вывести данный элемент из под блока.

Иначе пользователи бы жаловались мне, что сайт работает плохо, а не модераторам ruadlist. Так было (и продолжается) с кнопкой "добавить в избранное". Модераторы ruadlist решили, что этот блок не нужен и мешает, поэтому в расширенный список было добавлено правило, скрывающее социальные кнопки и заодно кнопку "добавить в избранное". Поэтому постоянно появляются умники с "оставлю коммент, чтобы потом найти пост".


9. Скрытие жёлтой таблички - уверенная победа

Хотя теперь у меня появилась дополнительная задача - не только показывать жёлтую табличку, но и не дать разломать остальной сайт - дальнейшие действия были простые.
0) Как выглядит
(далее #pageinner) на начало этой битвы:

жёлтая табличка
основной контент сайта

правая колонка
футер


1) они запрещают первый элемент внутри #pageinner, который и был жёлтой табличкой => я добавляю рандомное число дивов до и после таблички. Вёрстка выглядит так:

жёлтая табличка
#content
#sidebar


2) они запрещают внутри #pageinner всё кроме #content, #sidebar, #tagList => я ставлю дивам #content. Теперь у меня внутри #pageinner много дивов с #content. Чтобы различить их, ставлю им рандомные классы и для дива с жёлтой табличкой автогенерю css. Вёрстка получается такой:

#content .random
#content .random2 - тут жёлтая табличка
#content .random3
#content
#sidebar


3) они запрещают все #content, у которых внутри нет #contentinner => я добавляю моим жёлтым табличкам этот див


4) они запрещают див с #content и с классом. => я ставлю всем сгенеренным дивам #sidebar вместо #content и ставлю всем рандомный класс, в том числе и основному #sidebar. Вёрстка:

#sidebar .random
#sidebar .random2 - тут жёлтая табличка
#sidebar .random3
#content
#sidebar .random4
#sidebar .random5
#sidebar .random6


5) они запрещают все #sidebar, у которых не стоит #content перед ним => я делаю зебру из #sidebar и #content. Вёрстка принимает конечный вариант, который работает и по сей день (уже изменилась):

#content
#sidebar .random
#content
#sidebar .random2 - тут жёлтая табличка
#content
#sidebar .random3
#content - тут основной контент сайта
#sidebar .random4
#content
#sidebar .random5
#content
#sidebar .random6


6) они обсуждают на форуме скрыть нафиг все #sidebar - в правой колонке сайта всё равно ничего полезного нет. Я к тому времени уже придумал, как показать жёлтую табличку без классов - можно использовать css-селектор :nth-child, но они нашли что-то полезное в правой колонке и решили её не скрывать.

Жёлтая табличка осталась. Время от времени на форуме предлагают решение, как её скрыть, на что они отвечают что в основной список добавлять это не будут, так как мы сразу на это отрегариуем и прикроем. Поэтому кому надо пусть добавляют в кастомные фильтры.

Был ещё один прикол. Модератор ruadlist решил, что чем бороться через список, проще сделать userscript, который скрывает все дивы, в которых встечаются слова "реклам" и "отключить". Так получилось, что я как раз в это время просматривал форум. И обнаружил его сообщение минут через 5 после создания. К тому времени скрипт успели установить только 2 человека (подозреваю, что он сам - один из них). Я быстро заменяю в жёлтой табличке "отключить" на "отключить", а внутри постов добавляю аттрибут data-question="хотите отключить рекламу? ;)". Его скрипт скрывает все посты и оставлят только жёлтую табличку. О чём ему пишут следующим же комментом. Он смеётся, говорит что это бессмысслено, удаляет userscript и перестаёт заниматься реактором.

Табличка - это было уже неплохо и некоторые люди задонатили денег. Но большинству было пофиг и надо было показывать им какую-нибудь рекламу. На тот момент только одна тизерка предлагала anti-adblock решение, да и то достаточно кривое и было быстро заблокированно. Мне предстояло привести их код в порядок.


a. Загрузка скриптов.

Для начала надо было загрузить скрипты с сайта тизерки. Понятно, что все их основные домены были заблочены. Они себе купили пул доменов в зоне .space за копейки. Но модераторы ruadlist не долго думая запретили загрузку любых скриптов с зоны .space на реакторе. Для этого было другое решение - можно было взять любой свой домен или поддомен и направить его на тизерку. Чтобы не передавать им реакторовские куки, мы создали отдельный домен - jr-cdn.com. На него вынесли загрузку js и css. Часть поддоменов указывают на реактор, часть - на тизерку.

Они заблокировали загрузку любых скриптов из директории /v/. Именно оттуда грузила данные тизерка, а наши скрипты находились в директории /js/. Проблема в том, что директорию тизерки я сменить не мог. Сама тизерка отвечала на вопросы и предложения крайне неохотно. А другая тизерка в ответ на наш запрос снизила нам оплату за клик в 4 раза и её пришлось вообще снять, поэтому мы не сильно пытались их теребить. 

Я мог бы сменить адрес реакторовских скриптов с /js/ на /v/, но тогда бы реактор перестал работать, а Lain_13 обычно не спешил чинить его. Тут я начал понимать, что надо думать на один шаг вперёд. Если бы я подумал, как они будут блокировать скрипты, то сразу бы понял что по имени. Если бы я сменил сам имя скрипта, то они не стали бы вносить это правило в список. Но что сделано, то сделано и надо было как-то решать эту проблему.

И, как всегда, решение нашлось. Адблок считает /v/ и //v/ - разными директориями. А большинство веб-серверов двойной слэш успешно конвертируют в одинарный. Поэтому я перенёс скрипты в /v/, назвал их так же, как и у тизерки, но обращался к ним через //v/. Они вышли из под блока и различить он их не мог.

Эта тизерка у нас крутилась на реакторе и на порнреакторе. Коды у них немного разные и потому скрипты дёргаются с разными именами. Чтобы не городить лес, я просто при загрузке страницы рандомом выбирал одно из двух имён скрипта и обращался по нему. То ли Lain_13 не заметил этого, то ли решил, что реактору скрипты не обязательны, но он внёс в список полное имя тизерного скрипта. И в половине случаев это приводило к тому, что скрипты реактора подпадали под это правило и не грузились.

Тут мне пришлось пойти по принципу "если они сломали его немного, то надо ломать полностью, чтобы было понятно, что это из-за адблока". Начали появляться жалобы, что иногда комменты открывались в новом окне - это самй явный признак незагруженных скриптов. Поэтому я добавил код, который проверяет, что основные скрипты загрузились. Если они не загружались, то весь контент сайта стирался и писали, что надо добавить в белый список домен jr-cdn.com, чтобы с него можно было загрузить скрипты. Так же я отказался от рандома. Теперь на реакторе грузились скрипты с именем их тизерки, а на порнреакторе - их.

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


b. Показ тизеров - проба пера

Скрипты загружались, но они скрывали сами элементы. Тизрека хоть и была "анти-адблок", но хтмл-код она генерировала очень специфичный. Во-первых, там в некоторых местах использовались классы. Во-вторых, они использовали вложенные таблицы, которые на реакторе не используются. После определния адблока я пытался вывести их код из под фильтров - меняя названия классов и вёрстку, но это мало помогало и Lain_13 быстро банил их.

Я понял, что чтобы показывать их, мне надо полностью переписать их хтмл-код. К счастью, они отдельно подгружали свою js-библиотеку и тизеры после загрузки запускали функцию window.VisitWeb.createBlock(), куда передавали список тизеров в виде простого массива картинка-урл-подпись. Это позволяло легко перехватить этот запрос и самому сгенерировать html. Однако по правилам рекламных площадок это категорически запрещено - нельзя изменять их код.

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

Поэтому я начал перехватывать эту функцию и генерировать хтмл-код, неотличимый от обычного поста. И вставлять его рандомно в один из постов вначале или в конце. Но оставалось два сильных отличия:
1) наши картинки лежат на поддоменах img0.joyreactor.cc/img1.joyreactor.cc c урлами /pics/post/<seotext>-12345.gif. Их картинки загружались с того же домена, что и скрипты и имели урл /i/12345.gif
2) ссылка с тизера вела на один и тот же домен ss.bevixvqe.pw

Поэтому Lain_13 легко заблокировал все ссылки на ss.bevixvqe.pw и реклама перестала показываться

И тут я обнаружил кучу проблем у адблока - они считали урлы разными, хотя с точки зрения браузера и веб-сервера они были одинаковыми:
1) http://domain.tld и http://dOmain.tld
2) http://domain.tld и http://username@domain.tld
3) http://domain.tld и http://d%6Fmain.tld

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

Список правил можете посмотреть в их меркуриал - недавно они были удалены, как нерабочие - https://hg.adblockplus.org/ruadlist/rev/0eb62780db0f


c. Показ тизеров - окончательная победа.

К тому времени я уже устал от этих головоломок и хотелось окончательно решить проблему. Тем более количество (и качество) фильтров было таковым, что под него мог попадать нормальный контент.

У меня было 3 ссылки, которые надо было замаскировать:
1) картинка. У меня они хранится по адресу http://img0.joyreactor.cc/pics/post/<seotext>-123.jpeg
2) ссылка с картинки. У меня они идут на адрес http://img0.joyreactor.cc/pics/post/full/<setotext>-123.jpeg
3) ссылка с текста. У меня они идут на адрес http://link.joyreactor.cc/redirect?url=....

Тут я объясню всё на примере первого пункта. Остальные делались аналогично.

Я осознал, что у адблокеров нет никакой поддержки регэкспов. А на моём фронтэнде стоит nginx, который с регэкспами хорошо работает. Поэтому я начал вместо обычных ссылок на картинки вида http://adserver.joyreactor.cc/i/<image_id>.jpeg ставить такой урл:
http://img0.joyreactor.cc/pics/post/<image_id>-<random_text>-<image_id>-12345.jpeg

На nginx была поставлена проверка на регэксп и если начало и конец были одинаковыми, то он загружал картинку с тизерного сервера. Если не одинаковый текст, то грузил обычную картинку. Image_id у тизерного сервера был достаточно большим, поэтому вероятность случайного срабатывания этого правила была крайне мала. Кому интересно, вот кофиг nginx:

  set $vw_first 0;
  set $vw_second 1;
  if ($uri ~* "^/pics/post/([0-9a-f]{48})-[^/]*-([0-9a-f]{48})-(\d+)\.([^\.]*)$"){
  set $vw_first $1;
  set $vw_second $2;
  }

  if ($vw_first = $vw_second) {
  rewrite "-(\d+)\.([^\.]*)$" /visitweb/$vw_first.$2 last;
  }

Это позволило сделать картинки и урлы неотличимыми от обычных картинок и урлов с точки зрения адблока. Теперь эти тизеры постоянно показывались пользователям адблока.


d. Показ тизеров - ложка дёгтя

Хотя пользователи адблока смотрели тизеры и иногда кликали на них, тизерке (вероятнее всего) не понравились эти пользователи и они постепенно снизили доходность клика в 5 раз. С этих тизеров шли копейки и оставляли мы их больше для того, чтобы они постоянным пользователям мозолили глаза сильнее, чем обычная реклама.

Так же есть другой блокировщик рекламы - Adguard. Он позволяет вставлять javascript на страницу сайта. И они вставили код:
Object.defineProperty(window, 'VisitWeb', { get: function() { return document.createElement('div'); } });
Таким образом они так же, как и я, перехватывают window.VisitWeb.createBlock(), но ничего не показывают. И не дают это никак перезаписать - блокируя таким образом их показ.


e. Текущее положение

Основная проблема - найти рекламные сети, которые готовы работать с адблокерским трафиком. Большинство - очень неповоротливы и медленны.

Сейчас у нас висит попандер от advmaker. Хотя я им писал, как сделать всё правильно, они решили пойти по более простому пути. Так как в адблоке блокировались попапы на их домен, они начали в попапе открывать оригинальный сайт, а в старом окне открывать свой рекламный. Это даёт процентов на 30 меньшую доходность, чем было при нормальных попапах, но даже в этом случае доход вполне ощутимый.

В Актуальных проблемах RuAdList наши домены стоят на первом месте, что не может не радовать. По сути модераторы листа признались в своём бессилии. (Через несколько часов после выпуска поста они удалили сайт оттуда =) ).

Для "своих" пользователей они раздают скрипт, который блокирует рекламу на реакторе. Но раздают его очень осторожно и только проверенным людям - они понимают, что если он попадётся ко мне в руки, то сразу перестанет работать.

Есть и другие мелкие листы и скрипты, которые скрывают рекламу. Их всех объединяет одно свойство - они малоиспользуемые. Когда я увижу какой-нибудь популярный скрипт, то я сразу легко блокирую его действие.

Очень показательная история: Фейсбук заявил, что теперь будет показывать рекламу в том числе для тех, у кого стоит блокировщик рекламы. Через 2 дня вышла новость от адблока - https://geektimes.ru/post/279420/ , где они смеялись и издевались, что легко обошли эту рекламу "всего" за 2 дня. Сейчас я попытался узнать, что с этой войной - похоже она уже подчистую проиграна Адблоком. В реддите пишут, что реклама показывается - https://www.reddit.com/r/Adblock/comments/506kqc/will_adblock_remove_facebook_sponsored_publication/ и вроде единственный способ её обойти - это ставить userscript, который навряд ли поставит большое количество пользователей.

Текущее положение блокировщиков рекламы можно сравнить с положением Вермахта в начале 1942 года. Они полны сил несмотря на то, что битва за Москву уже проиграна. Но самые прозорливые уже понимают, что конец - это лишь вопрос времени. Потому и остаётся Адблоку громко кричать о том, что они скрыли рекламу, но тихо молчать, когда через день эта реклама опять появилась.


f. Будущее

Я думаю что со временем всё большее число владельцев сайтов и рекламных сетей займутся проблемой борьбы с адблоком. В этом нет ничего сложного - надо всего лишь оперативно реагировать на обновление нескольких публичных списков.

Я вижу несколько способов блокировщикам рекламы противостоять этому:
1) закрытые списки - они даются только определённым людям и ставятся различные "вотермарки", чтобы узнать от кого прошла утечка. Достаточно сложно в реализации. Если станет популярным, то утечки будут случаться часто.
2) обфусицировать списки, чтобы не так легко можно было понять что именно блокируется. Это такой же вопрос толщина брони vs сила снаряда. И у владельцев сайтов будет сильное преймущество в финансировании - для них деобфусикация даст кучу денег.
3) не давать клиентам списки. В этом случае весь трафик клиента должен проходить через внешнюю проксю блокировщика рекламы. Не уверен, что многие пользователи захотят пропускать трафик от своего интернет-банка или Paypal через чужие сервера.
4) сделать много разных списков. Сейчас надо посмотреть штук 5 листов, чтобы охватить 95% пользователей блокировщиков рекламы. Если этих списков будет сотня, то владельцам сайтов будет сложнее бороться с ними. Но возникнет проблема совместимости. Я и сейчас вижу по форумам проблемы связанные с тем, что один пользователь включает у себя сразу 2-3 списка из текущих 5.
5) полная блокировка сайта, показывающего рекламу. Если сайт достаточно большой, то пользователи не будут использовать такие фильтры.

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

Пока, сервачок, мы будем помнить о тебе

Через несколько часов отключат один из наших серверов, serv16 - 50.7.136.178

Этот сервер верой и правдой служил реактору 3 года. За свою жизнь он повидал некоторое дерьмо - через него прошли почти все картинки с тех пор. Его неоднократно ддосили. Он стёр в ноль один комплект дисков ssd и почти стёр один из 2го комплекта - там осталось 1% запаса прочности.

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

Отличный комментарий!

,админские истории,разное

Как я блокировщик рекламы блокировал. Часть 1.

0. Введение.

В данной статье я хочу рассказать о том, как боролся с блокировщиками рекламы (далее адблок). Как и все посты в админских историях, он рассчитан на технически подкованную аудиторию. Так же не хотелось бы слушать нытьё "Ах вы фошисты! У меня деды воевали против рекламы! У меня брат от попандера умер!". Для этого уже существует другой пост - http://joyreactor.cc/post/2493637


1. Моральное обоснование

Моральный вопрос борьбы с адблоком для меня хорошо сформулировал amarao в комменте https://geektimes.ru/post/271638/comments/#comment_9049910 :

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

Я считаю возможным делать всё что угодно, пока это остаётся в рамках технической сферы. Я бы и ЦП разрешил постить, но моралфаги наинают использовать средства вне технической сферы - полиция изымает сервера и владельцев.

Многие придерживаются таких же ценностей технофашизма даже не осознавая это. Никто не жалуется на производителей фильмов, что они используют более сильное шифрование. Жалуются, когда после взлома этого шифрования и проигрыша в технической сфере, они переходят в сферу политическую и начинают вводить всякие драконовские законы и требования. Так же я ни разу не слышал, чтобы жаловались на последнюю систему защиты игр (Denuvo), которую уже полгода не могут взломать. Понятно, что если они сделали такую систему, значит они умнее и лучше. Не согласен - садись сам за дизассемблер и ломай.


2. Экономическое обоснование борьбы

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

Однажды порнотизерка, которая стоит на порнреакторе, предложили протестировать их анти-адблок код. Мы попробывали и с удивлением обнаружили увеличение дохода в 2 раза. Оплата там по кликам. То есть все те адблокеры, которые кричат "я не хочу смотреть рекламу! я никогда на неё не кликаю!" тоже замечательно её смотрели и кликали. Количество показов выросло немного более, чем в 2 раза - всё же процент кликающих уменьшился, но очень немного.

А увеличение доходов в 2 раза - это очень круто. Это бы решило все проблемы из-за падения курса. Поэтому я занялся разработкой анти адблока.


3. Детектирование адблока - первые победы

Первое, что надо сделать - это понять, есть ли адблок у человека. Для этого (да и вообще для будущего) скачиваем самый популярный список правил в рунете - ruadlist - https://easylist-downloads.adblockplus.org/ruadlist+easylist.txt . Есть и другие, о них я ещё напишу.

Для начала пошёл простым путём: создаём <div id="adv"></div>, добавляем его вниз страницы и провряем, виден ли он. Если адблок не установлен, то будет виден. Если установлен, то он будет блокироваться и не виден. Но дальше начинается интересное - если адблок установлен, но сайт добавлен в белый список, то див всё равно виден не будет! И лишь через некоторе время он появляется. То есть, адблок вначале всё блокирует, а позже смотрит а не в белом ли списке сайт - может блокировать и не надо? Решается оно просто - добавлением таймера и проверкой через некоторе время, но осадочек остался.

Реакция модераторов списка ruadlist была достаточно быстрой и простой - они разрешили div#adv на сайтах реактора. Таким образом они попытались показать, что адблока у человека не стоит. Думаю с моралфажеской точки зрения, пытаться наебать меня с тем, есть у человека адблок или нет - неправильно. И именно поэтому моралфаги идут нафиг. С позиции технофашизма всё понятно и логично. Поэтому и вновь продолжается бой.

Я достаточно оперативно отслеживал их изменения в списке. И зная, что обновление листа у пользователя по-умолчанию происходит раз в 4 дня не спешил с ответными обновлениями. Если я обновлю свой детектор через 2 дня, то половина пользователей даже не узнает, что они вносили изменения.

Дальше изменения с моей стороны тоже понятные - я меняю id=adv на какой-нибудь другой заблокированный (их там сотни). Через 3 таких итерации (я меняю, они вносят этот id в белый список для реактора), они сдаются и ставят правило:

@@||joyreactor.cc^$generichide

(здесь и далее, правило возможно не точное, мне вломы искать какое было именно оно, но идею я передаю). По этому правилу на joyreactor.cc не срабатывают никакие правила скрытия. Но реклама всё равно не показывается - они просто блокируют запросы на получение рекламы. И определить адблок тоже не получается - все дивы видны.


4. Детектирование адблока - патовая ситуация

Переходим к следующему уровню - надо понять, не блокируются ли запросы. Тут проблема в том, что из-за cross-domain policy это сделать не легко. Загрузить скрипты через ajax запрещает это полиси, а при загрузке просто через <script> нельзя узнать что загрузилось и загрузилось ли что-то. И тут мне помогает ctrmanager.

Ctrmanager.com - это наш сайт. С помощью него ставится и снимается реклама. Если реклама напрямую от рекламодателей, то там же и хранятся картинки. Если от других сетей, то оттуда идёт js-код, подгружающий рекламу с их серверов. Функционал вроде простой, но когда мы искали сторонние решения для наших объёмов, то цена в несколько раз превышала доходы с этой рекламы.

На ctrmanager при выдаче рекламы я добавил дополнительный хидер "Access-Control-Allow-Origin: *". Это позволило делать обычный ajax-запрос на этот домен. И соответственно получать результат и ошибки. Модераторы ruadlist спокойно добавили ctramanger в белый список. Этим они меня озадачили. С одной стороны, теперь можно спокойно показывать прямую рекламу. Но с другой стороны, никакой прямой рекламы у нас не было из-за кризиса и не предвиделось. Единственное что было - это вшивая тизерка внизу страницы. Сейчас лишь иногда появляется что-то другое. Соснули все - адблокерам будет показываться прямая реклама, но мы денег не получили так как её нет. Это, конечно, хорошо когда все соснули - но как-то неинтересно.


5. Детектирование адблока - позиционная война

Экспериментируя с запросами я обнаружил странную работу с crossdomain ajax в фаерфоксе. Там получилось различить из-за чего заблокирован запрос - из-за адблока, или из-за crossdomain policy. Я залил этот детект понимая, что лучше что-то, чем ничего. На их форум посыпались жалобы на жёлтую табличку, но они у себя ничего не видели. Видели безобидный ajax-запрос http://yandex.ru/favicon.ico?ads-bla-bla, но он блокировался браузером из-за полиси. Как потом оказалось, это срабатывало только на английской версии ФФ (возможно в каких-то ещё случаях). Продолжалось это несколько дней в течении которых я смеялся и злорадствовал, а они не могли понять в чём проблема. Кстати так же я добавлял в белый список user-agent основного модератора списка - для него детект просто не запускался. Уже точно не помню, но вроде он полдня недоумевал, почему к нему приходят жалобы на реактор, хотя у него всё хорошо.

Эти моменты добавили веселья, но ход войны был не в мою пользу. Детект работал плохо. Надо было придумывать что-то радикальное с загрузкой рекламы. И оно придумалось.


6. Детектирование адблока - пробитие бреши в обороне.

У элемента <script> есть атрибут onerror, который вызовется если скрипт не получилось загрузить. Отлично! Но для теста загрузить рекламный скрипт не получится - мы же не можем его остановить. Он сразу начнёт подтягивать остальную рекламу. Но после недолгих поисков обнаружился скрипт на сайте рекламодателя, который ничего не делал, однако блокировался общими правилами. Поэтому в код детекта добавлено:

var script = document.createElement('script');
script.onerror = function(e) {
  show_anti_ab();
};
script.src = "http://bad.ads/test.js";
document.head.appendChild(script);

Понятно, что на это модераторы добавили этот скрипт в белый список для моего домена. И у меня было 2 дня на то, чтобы найти новый такой пустой скрипт. Так как блокировалось там куча всего, то найти была не проблема (и у меня был один на примете), но я понимал что следующим правилом они внесут в белый список все домены (как generichide - есть genericblock) и для реактора просто отдельно заблокируют только рекламные запросы. Поэтому надо было двигаться дальше.


7. Детектирование адблока - победа.

Код рекламодателей выглядит обычно так:

var el = document.createElement('script');
el.src = "http://get.my.ads/ads.js?ua=" + user_agent + "&w=" + width + ....;
document.getElementsByTagName("head")[0].appendChild(el);

Было бы замечательно в этот код добавить el.onerror=.., но мало того, что изменение кода рекламодателя категорически запрещено, но ещё и загруженный скрипт часто тоже выглядит так же и подгружает какой-нибудь скрипт дальше по цепочке. И тут мы вспоминаем, что в javascript есть возможность перезаписывать любые функции. Поэтому добавляем такой код к детекту:

var _createElement = document.createElement;
document.createElement = function(nodeName){
   var el = _createElement.call(document, nodeName);
   if(nodeName.toLowerCase() == 'script'){
     el.onerror = function(){on_js_load_error(el)};
   }
   return el;
};

Тут просто автоматом добавляется onerror ко всем созданным скриптам. Теоретически их могут перезаписать, но рекламодатели обычно этим на заморачиваются. В функцию on_js_load_error передаётся элемент и получив у него атрибут src можно узнать какой именно скрипт не загрузился. Если это url нашего рекламодателя, значит или рекламодатель умер, или у пользователя адблок включён. 99.99% времени сайт рекламодателя работает.

Это была полная победа. Они не могли скрыть элементы на странице - я бы это обнаружил. Они не могли запретить запросы - я это тоже обнаружу. Но если они разрешат и показ всех элментов и запросов, то реклама будет показываться. Поэтому от попыток скрытия адблока они отказались. Все, что они до этого добавляли в белые списки, чтобы скрыть адблок, было убрано. Мой детект работал успешно.

Сражение коренным образом изменило ход войны. Теперь я мог для адблокеров показывать большой жирный хрен на полэкрана и модераторы ruadlist с этим ничего не могли бы сделать. Но мне нужно было больше. Мне нужно было показывать им рекламу, поэтому наступление продолжилось.

Продолжение следует...

koka, где доклад об обновлении?

гифки теперь как у белых людей, в мпеге

Настало время обновлений!

Новая ошибка пока не имеет *крутого* имени вроде HeartBleed или Poodle. Поэтому придётся называть её как обычно - CVE 2015-023. Ошибка в glibc - то есть практически любой сервис будет её использовать. Heap overflow leads to code execution. Уязвима с 2000 года.

Подробности:
https://bugzilla.redhat.com/show_bug.cgi?id=CVE-2015-0235
http://www.openwall.com/lists/oss-security/2015/01/27/9
http://www.reddit.com/r/netsec/comments/2tulbd/cve_2015023_nasty_bug_in_glibc_gethostby/
,geek,Прикольные гаджеты. Научный, инженерный и  айтишный юмор,CVE 2015-023,network security,админские истории,разное,Ghost
Вчера я обнаружил, что среднее время запросов на реакторе выросло с 400мс до 800-1000мс.

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

Погрепав логи, обнаружил что медленее всего идут запросы на страницы, которые обращаются к сфинксу (поисковый движок). Почитал про его настройку, соптимизировал его. Нагрузка на сервер со сфинксом ненадолго упала, но через 15 минут снова возросла.

И тут я ещё обнаружил, что сразу после обновления сайта время загрузки страниц резко падает до 400мс, а потом постепенно возрастает до старых значений. См график

Отличный комментарий!

дальнейшее расследование показало, что с некоторого времени, hetzner на все сервера ставит програмку cpuspeed. Она регулирует скорость процессора. Если процессор не сильно нагружен, то уменьшает его частоту, чтобы уменьшить энергопотребление.

Понятно, что для их макретологов это замечательно! Ничего не делаем, а энергопотребление уменьшается за 10%! Фигня, что сайты отвечают в 2-3 раза медленее - кто это заметит?

В общем, сносим её к чертям.

/etc/init.d/cpuspeed stop
yum erase -y cpuspeed

И скорость ответа реактора снова опускается до 400мс. Теперь уже постоянно.

Если в в недавнем времени заказывали сервера у hetnzer - посмотрите, не стоит ли у вас тоже cpuspeed =)
Я поставил новый сервер в Нью-Йорке и теперь у английского собрата реактора (http://joyreactor.com) есть свой экономичный мини-cdn. На русском я его не ввёл, ибо тут всего 1% из америки.

Расскажу, как я его делал. Как известно, cdn можно делать двумя способами. Или multipath route, или через geo based dns. Коммерческие cdn'ы бывают обоих типов примерно 50 на 50. Но они стоят пипец дорого. Мне получать свою AS для роутинга нифига не хочется, поэтому я выбрал самый простой путь - через dns. Идея его простая: при запросе к dns, сервер смотрит откуда идёт запрос и в зависимости от этого отдаёт ip или из Европы, или из Америки. Могут быть проблемы с публичными dns вроде гуглёвского 8.8.8.8, но тут надо заметить, что нефиг пользоваться этим сервисом.

Далее надо найти такой dns, чтобы он поддерживал запросы на основании geoip. Конечно, можно установить свой bind и на нём всё настроить, но это ещё одна точка отказа. Ибо если он упадёт, то весь сайт помрёт. Обычный провайдеры если и имели такую опцию, то стоила она под сотню баксов в месяц (вот пример http://www.dnsmadeeasy.com/home/pricing-customization/ - Add Global Traffic Director $660.00 per domain per year). После долгих поисков и размышлений я остановился на Amazon Route 53. У них получалось самое дешёвой решение с возможностью failover в будущем.

Ну а дальше всё просто. Заказываем у них днс, настраиваем "latency based dns" и у американских собратьев реактор стал тормозить меньше =)
Давненько я не писал сюда... так всё хорошо было...

Всё началось 31 октября. Хостер, у которого находится основной фронтэнд, сказал что у него проблемы с провайдерами и будет технические работы. Некоторое время он просто лежал. Потом отрубился ipv6 (а по нему у меня общается фронтэнд и бэкэнд). Заметил я это похоже только через несколько часов. Как заметил - переключил их на ipv4 и реактор, наконец, заработал. Но по вечерам загрузка картинок реально тормозила. Хостер сказал, что починит всё "очень быстро" - за пару недель.

8го октября мы решили "Хватит это терпеть!". И я пошёл искать где бы ещё арендовать сервер в европе, тянущий 10Гбит и прокачивающий 0.5Пб трафика в месяц за копейки. Нашлось только 2 предложения:
- одно от достаточно хорошей компании Swiftway, но в 2 раза дороже и жёсткое ограничение по трафику - превышение 0.5Пб было дорогим. Хотя можно было подоговариваться по поводу превышения трафика.
- второе от британской redstation. Там предлагался безлимитный 1.5Гбит по цене моего сервера. У меня в среднем трафик 1.8Гбит и 95% burstable - 2.5 Гбит. Поэтому два сервера должны были вполне уместиться по трафику и иметь запас. Но дальше я начал расспрашивать их как они считают трафик и оказалось, что они жёстко шейпят на 1.5Гбит. А у реактора бывают кратковременные (и не очень) всплески сильно выше среднего. Поэтому тоже не очень
- третье предложение было от нашего же хостера. У него датацентров много. Проблемы только в одном. Почему бы не попробовать другие? Это и было принято за рабочее решение.

Оказалось, что в двух нормальных ДЦ - Вене и Праге - у него мест нет. Есть только в Злине - деревушке на востоке Чехии. Ну делать нечего - попробуем его. Оплатил. Всё поставили. Ipv6, как всегда, заработал с 3ьего раза у них. Попинговал разные места - по одному из маршрутов был небольшой пакетлост. Написал им - ответ мы скажем своему провайдеру, чтобы они увеличили канал в том месте, но когда они это сделают не знаем. Ладно, наверное что-то немного лагающее будет лучше чем сильно лагающее. Переключил реактор на сервер в Злине и начался пиздец. По вечерам пакетлост по всем направлениям, ещё хуже чем в лагающем Амстердаме.

А тут ещё и подходит время оплаты амстердамского сервера (который по прошестии 12 дней всё ещё тормозил). Пишу хостеру письмо, что нах вас всех, возвращайте деньги. После долгих бесед и валерьянки в форме коньяка, они мне подарили неделю амстердамсого сервера бесплатно, заверили что в течении этой недели всё починится, Злинский сервер отменили и вернули полностью деньги на внутренний счёт.

После такой недели у меня была только одна мысль - "Придётся это терпеть".

Протрезвев через пару дней ко мне пришла ещё одна мысль. Бэкэнды у реактора стоят у другого хостера. Там с каналами всё достаточно плохо, зато сервера дешёвые. И недавно они обновили линейку своих серверов. И теперь за 50 евро можно взять лучший сервер, чем у меня стоят за 60 евро. Только надо установочный платёж в размере 50евро заплатить. Вот я и решил - через 5 месяцев этот апгрейд всё равно окупится. Давай сделаю сейчас, на некоторое время старые всё ещё будут работать, а новые настрою на отдачу картинок. Тогда хотя бы немного разгружу амстердам и часть картинок будет отдаваться быстро. За неделю я не успею выбраться за лимиты трафика.

Сказано - сделано. Сделал всё это. Пару дней оно проработало в этом режиме и потом Амстердам починили, наконец. Вернее, основные лаги там пропали, но остались ещё небольшие по ipv4 и полностью не рабочий ipv6. Но это решаемо (сейчас вот решаю потихоньку).

И тут наступает другая проблема - перенос старых серверов на новые. Перенос я делал в попыхах (чтобы меньше платить за старые сервера) и в результате не все данные в свифте перенеслись. Заметили это только когда сервера уже забрали. В результате потерялись порядка 1-2% картинок. Из хороших новостей, что у меня одна и та же картинка хранится в куче разных вариантов - увеличенная, уменьшенная, с вотермарками и т.д. Сейчас восстанавливаю что возможно.

Вторую проблему вчера решал. Новые сервера нещадно жрали проц. Это при том, что он там на 2 поколения лучше, чем на старых. До полуночи дебажил всё это. Оказалось, что в libmemcached в последней версии сломали ipv6. Причём там был такой код:

#if 0
hints.ai_family= AF_INET;
#endif

Он никогда не работал. Но какой-то умный человек решил, что это наверное ошибка и удалил If/endif. Из-за этого строчка начала работать, а она запрещает использование ipv6. Ну сегодня нашёл предыдущую версию, накатил её на все серера, нагрузка сразу спала. Уф, хоть одна хорошая новость.

Надеюсь в следующей части я расскажу как сделал CDN, ибо уже давно жду, когда мне поставят 2ой фронтэнд в Нью-Йорке.
сегодня (по московскому времени уже вечера) на главную вышла гифка размер 120Мб ( http://joyreactor.cc/post/807115 ). Вообще, её не легко туда пропихнуть - похоже чуваку повезло, что она обработалась быстрее, чем прошёл таймаут =). Мне стал интересен график трафика в связи с появлением этой гифки. Он ниже. Внимание, вопрос! Когда эта гифка вышла во Всё главной и когда она вышла в Хорошее? =)
,админские истории,разное
После неудачной попытки с ceph и советов забить на это, как от гуру-школьников на реакторе, так и на хабре, я уже почти опустил руки.

В это время тестировался gfs2. Но он оказался: во-первых, плохо масштабируемым; во-вторых, достаточно медленным; в-третьих, ооочень сложным и глючным. Явно не расчитан на "commodity hardware".

Я пустился в размышления - почему же это так сложно и тормознуто. Ведь задача простая - хранить файл в нескольких копиях на разных серверах + как-нибудь сохранить где именно он хранится. При желании, это реализуется достаточно просто и быстро даже вручную.

И тут я понял основную ошибку - я искал файловую систему. А в ней не просто хранение, но ещё и система прав и лок файлов. Они мне не были нужны, поэтому я отказался от понятия файловой системы. И тут же обнаружил Openstack Swift. Это простое хранилище данных.

- Работает через REST-интерфейс (обычный http).
- В случае падения одной из нод, работает без проблем дальше.
- Используется в wikimedia для хранения всяких картинок.

В общем, проект достаточно зрелый. Хотя информации о нём достаточно мало - возможно из-за того, что для работы с ним надо менять код и вместо файловых методов использовать сетевые. Развернул, обнаружил несколько особенностей, которые не сильно повлияли на дальнейшие действия:
1) при большом количестве файлов, он может добавлять порядка 50 файлов в секунду. Для больших скоростей нужен ссд. Ну в обычное время у меня добавляется несколько файлов в минуту. Поэтому до этого предела ещё далеко.
2) полностью рабочая нода - это 15 разных демонов. Вначале немного охреневаешь от такого изобилия. Но со временем понимаешь, что всё чётко и стройно. Просто они, следуя философии unix, разделили разные функции на разные демоны. Во время первоначальной синхронизации, я отключил некоторые демоны и скорость возросла раза в два.
3) первоначальная заливка всего контента заняла порядка 2 недель неспешного копирования. Днём копирование отрубалось, чтобы не мешать реактору работать.

Итак, результаты:
1) уже 3 недели все новые картинки заливались в свифт. При чтении иногда они брались с диска, иногда - из свифта.
2) с начала этой недели картинки читались только из свифта. Они ещё писались на диск на всякий случай, но не читались
3) с сегодняшнего утра всё полностью перешло на свифт. На диск больше не пишется и не читается. В последний раз забэкаплю и на след.неделе удалю с боевых серверов.

Таким образом, я избавился от одной из трёх точек отказа. Ура!

Ну и всякие дополнительные мелочи:
1) во время переноса свифта обнаружил, что картиночный сервер упирается в канал 100Мбит в часы пик. Вовремя я начал чесаться по поводу его переноса... =)
2) следующая точка отказа, которую надо будет устранять, - mysql. Раньше думал, что придётся переходить на postgresql, ибо в мускуле всё плохо с репликацией, failover и вообще версия 5.5 (которая появилась после покупки ораклом) у них очень плохая вышла. Коммуна была расстроена и считала, что оракл убьёт мускуль. Но в феврале этого года вышла версия 5.6, которая удивительно хорошо работает - быстрее 5.5, добавлены фичи для репликации из коробки, для php выпустили плагин с load-balancing и failover. В общем, похоже мускуль воскрес из мёртвых и мне это нравится, ибо не хочется переучиваться на постгрю.
3) написал хостеру, что наблюдаю днём пакетлост 0.1%, а по вечерам наблюдаю пакет-лост 0.5%. На удивление, не послали нахрен, а начали разбираться. Хоть и достаточно вяло.
4) после того, как перешёл на swift, на серверах стало нехватать памяти (всего 16Гб). Пришлось перейти с apache на nginx+php-fpm. Из-за того, что фротэнд держал с бэкэндами keel-alive соединения, получил выигрыш в памяти в 3 раза - 300 Мб вместо 1Гб.
5) настроил себе в заббиксе красивые картинки. Теперь если что-то торимозит - я не бегаю по серверам, а запускаю один экран и всё сразу видно:
Здесь мы собираем самые интересные картинки, арты, комиксы, мемасики по теме админские истории (+23 постов - админские истории)