Блокировщик соцсетей, который спасёт вашу продуктивность

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

Сего­дня мы возь­мём ту же идею с бло­ки­ров­кой через hosts и выве­дем её на новый уро­вень: вме­сто Одно­класс­ни­ков или Фейс­бу­ка у вас появит­ся страница-заглушка. А что­бы было ещё инте­рес­нее, эта стра­ни­ца будет счи­тать, сколь­ко раз вы сего­дня пыта­лись отвлечь­ся от рабо­ты. Повы­сим, так ска­зать, уро­вень осознанности.

Принцип работы

Напом­ним, как обыч­но ведёт себя браузер:

  1. Вы вво­ди­те адрес в стро­ку бра­у­зе­ра, и теперь ему нуж­но пере­ве­сти адрес из букв в циф­ры — IP-адрес.
  2. Перед тем как отпра­вить запрос на DNS-сервер, бра­у­зер загля­нет в файл hosts — там напи­са­ны основ­ные пра­ви­ла для все­го компьютера.
  3. Если там про­пи­са­на наша соц­сеть и IP-адрес, куда нуж­но отправ­лять запро­сы для этой соц­се­ти, то бра­у­зер сра­зу будет отправ­лять запро­сы туда.
  4. Если мы там напи­шем, что все запро­сы на vk.com отправ­лять на 127.0.0.1, то такие запро­сы не вый­дут за пре­де­лы ком­пью­те­ра и уйдут на этот адрес.
  5. Обыч­но по это­му адре­су нет ника­ких стра­ниц, но с помо­щью про­грам­мы Apache мы ска­жем ком­пью­те­ру, какую стра­ни­цу нуж­но пока­зы­вать, когда есть запрос на этот адрес.
  6. Настро­им сер­вер, поло­жим в него нашу страницу-заглушку. Она будет счи­тать, сколь­ко раз вы попы­та­лись зай­ти в соц­се­ти, кото­рые сами себе закрыли.

Пер­вые три пунк­та рабо­та­ют и так, там нам делать нече­го. Нач­нём сра­зу с запи­сей в hosts.

Добавляем соцсети в hosts

Если вы забы­ли, как вно­сить новые запи­си в файл hosts — посмот­ри­те в про­шлой ста­тье раз­дел «Как забло­ки­ро­вать себе соц­се­ти с помо­щью hosts». Там есть подроб­ная инструк­ция, как открыть этот файл и доба­вить в него что-то новое.

Мы будем бло­ки­ро­вать такие сайты:

  • ВКон­так­те;
  • Фейс­бук;
  • Одно­класс­ни­ки;
  • Твит­тер.

Для это­го наш hosts дол­жен выгля­деть так:

Делаем страницу-заглушку со счётчиком

Логи­ка рабо­ты стра­ни­цы такая:

  • запо­ми­на­ем, какое сего­дня число;
  • при загруз­ке стра­ни­цы смот­рим, захо­ди­ли на неё сего­дня или нет;
  • если не захо­ди­ли — меня­ем чис­ло послед­не­го захо­да на сегодняшнее;
  • а если уже захо­ди­ли — уве­ли­чи­ва­ем счёт­чик посе­ще­ний и выво­дим нуж­ное сооб­ще­ние само­му себе.

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

Нач­нём с сооб­ще­ния, кото­рое мы сде­ла­ем заго­лов­ком в раз­де­ле <body>:

<h1 id="hello">Привет! Вы сегодня 1-й раз хотели зайти в эту соцсеть.</h1>

Доба­вим сти­ли для заголовка:

h1{

      text-align: center;

      margin: 20;

      font-family: Verdana, Arial, sans-serif;

      font-size: 50px;

    }

Смот­рим, что получилось:

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

// счётчик количества посещений
var counter = 0;
// запоминаем сегодняшнее число в переменную today
var date = new Date();
var today = date.getDate();
// если мы загружаем эту страницу вообще первый раз на этом компьютере и в памяти нет сохранённого значения
if (localStorage.getItem('today') == null) {
  // берём сегодняшнее число и отправляем его в хранилище
  today = date.getDate();
  localStorage.setItem('today', today);
  // заводим в хранилище ячейку counter и обнуляем его, потому что посещений ни разу не было до этого
  localStorage.setItem('counter', 0);
  // если в хранилище уже есть информация о прошлом посещении 
} else {
  // если последнее посещение было не сегодня
  if (today != localStorage.getItem('today')) {
    //  запоминаем сегодняшнее число и обнуляем счётчик посещений
    localStorage.setItem('counter', 0);
    localStorage.setItem('today', today);
  }
}
// если в счётчике посещений уже что-то есть…
if (localStorage.getItem('counter') !== null) {
  // берём оттуда число посещений и увеличиваем его на единицу
  counter = parseInt(localStorage.getItem('counter'));
  counter += 1;
  // выводим сообщение
  document.getElementById('hello').innerHTML = 'Это уже ' + counter + '-я попытка зайти в эту соцсеть за сегодня.';
  // сохраняем новое значение счётчика
  localStorage.setItem('counter', counter);
  // если счётчика посещений до сих пор почему-то нет в хранилище… 
} else {
  // отмечаем первое посещение
  counter = 1;
  // записываем его в хранилище
  localStorage.setItem('counter', counter);
};

Пару раз обнов­ля­ем стра­ни­цу, что­бы убе­дить­ся, что всё работает:

Сохра­ня­ем файл под име­нем index.html — он нам при­го­дит­ся, когда будем настра­и­вать вир­ту­аль­ный сервер.

Полный текст страницы

<!DOCTYPE html>
<html>
<!-- служебная часть -->

<head>
  <!-- заголовок страницы -->
  <title>Иди работать!</title>
  <!-- настраиваем служебную информацию для браузеров -->
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- задаём CSS-стили прямо здесь же, чтобы всё было в одном файле -->
  <style type="text/css">
    /*параметры заголовка*/
    h1 {
      text-align: center;
      margin: 20;
      font-family: Verdana, Arial, sans-serif;
      font-size: 50px;
    }

    /*закончили со стилями*/
  </style>
  <!-- закрываем служебную часть страницы -->
</head>
<!-- началось содержимое страницы -->

<body>
  <!-- началась видимая часть -->
  <!-- заголовок страницы -->
  <h1 id="hello">Привет! Вы сегодня 1-й раз хотели зайти в эту соцсеть.</h1>
  <!-- закончилась видимая часть -->
  <!-- пишем скрипт, который будет постоянно сохранять наш текст -->
  <script>
    // счётчик количества посещений
    var counter = 0;
    // запоминаем сегодняшнее число в переменную today
    var date = new Date();
    var today = date.getDate();
    // если мы загружаем эту страницу вообще первый раз на этом компьютере и в памяти нет сохранённого значения
    if (localStorage.getItem('today') == null) {
      // берём сегодняшнее число и отправляем его в хранилище
      today = date.getDate();
      localStorage.setItem('today', today);
      // заводим в хранилище ячейку counter и обнуляем его, потому что посещений ни разу не было до этого
      localStorage.setItem('counter', 0);
      // если в хранилище уже есть информация о прошлом посещении 
    } else {
      // если последнее посещение было не сегодня
      if (today != localStorage.getItem('today')) {
        //  запоминаем сегодняшнее число и обнуляем счётчик посещений
        localStorage.setItem('counter', 0);
        localStorage.setItem('today', today);
      }
    }
    // если в счётчике посещений уже что-то есть…
    if (localStorage.getItem('counter') !== null) {
      // берём оттуда число посещений и увеличиваем его на единицу
      counter = parseInt(localStorage.getItem('counter'));
      counter += 1;
      // выводим сообщение
      document.getElementById('hello').innerHTML = 'Это уже ' + counter + '-я попытка зайти в эту соцсеть за сегодня.';
      // сохраняем новое значение счётчика
      localStorage.setItem('counter', counter);
      // если счётчика посещений до сих пор почему-то нет в хранилище… 
    } else {
      // отмечаем первое посещение
      counter = 1;
      // записываем его в хранилище
      localStorage.setItem('counter', counter);
    };
  // закончился скрипт
  </script>
  <!-- закончилось содержимое страницы -->
</body>
<!-- конец всего HTML-документа -->

</html>

Минутка занудства о протоколах

Если сей­час открыть файл index.html в бра­у­зе­ре, он будет рабо­тать, ника­ких про­блем. Скрипт выпол­ня­ет­ся, заго­ло­вок выво­дит­ся, кра­со­та. Но посмот­ри­те на адрес, по кото­ро­му идёт запрос. Ско­рее все­го, он будет начи­нать­ся со сло­ва file или «Файл». Это зна­чит, что бра­у­зер рабо­та­ет с локаль­ной фай­ло­вой систе­мой, не тро­гая ника­кие интер­не­ты. Рабо­та­ет фай­ло­вый протокол.

А когда мы дела­ем запрос в интер­нет (напри­мер, на vk.com), у нас в адре­се сто­ит пре­фикс http — это озна­ча­ет, что мы сей­час дела­ем http-запрос, то есть запрос по про­то­ко­лу пере­да­чи гипертекста.

Пора рас­ска­зать, что такое протоколы.

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

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

Как вы ведё­те себя в этих двух ситу­а­ци­ях — это про­то­кол. Про­то­кол — это опре­де­лён­ные пра­ви­ла, по кото­рым вы вза­и­мо­дей­ству­е­те с окру­жа­ю­щим миром: после транс­пор­та мыть руки, на поро­ге сни­мать обувь, на рабо­те здо­ро­вать­ся и так далее. У ком­пью­те­ров то же самое: есть про­то­ко­лы для веб-страниц (http), пере­да­чи фай­лов (ftp), рабо­ты с поч­той (imap) и так далее.

Так вот: фай­ло­вый про­то­кол, по кото­ро­му вы откры­ва­е­те фай­лы с дис­ка, — это не то же самое, что http-протокол, по кото­ро­му идут запро­сы из браузера.

За испол­не­ние запро­сов по про­то­ко­лу file отве­ча­ет ваша опе­ра­ци­он­ная систе­ма. А за испол­не­ние http-запросов — спе­ци­аль­ная про­грам­ма, кото­рая назы­ва­ет­ся веб-сервером. Когда в ком­пью­тер при­ле­та­ет http-запрос, он ищет в памя­ти запу­щен­ный веб-сервер и кида­ет запрос в него. Раз­би­рай­ся, мол.

Сей­час на вашем ком­пью­те­ре не рабо­та­ет ника­ко­го веб-сервера. Если вы набе­рё­те в бра­у­зе­ре http://127.0.0.1, вы полу­чи­те ошиб­ку, пото­му что у вас в памя­ти нет про­грам­мы, кото­рая обра­ба­ты­ва­ет http-запросы. Адрес дей­стви­те­лен, но ответ­ствен­но­го по http нет, поэто­му и ошибка.

Настраиваем Апач

Нам нуж­но, что­бы меж­ду бра­у­зе­ром и ком­пью­те­ром про­изо­шёл такой диалог:

Бра­у­зер: Алло, алло! Это 127.0.0.1? Опе­ра­ци­он­ная систе­ма: Вам чего? Бра­у­зер: У меня http-запрос. Опе­ра­ци­он­ная систе­ма: ожи­дай­те, пере­во­жу вас на http-сервер. Http-сервер: У аппа­ра­та. Дик­туй­те ваш запрос. Бра­у­зер: Запра­ши­ваю стра­ни­цу по адре­су vk.com, про­то­кол http. Http-сервер: Жди­те, исполняю…

Для это­го диа­ло­га в памя­ти наше­го ком­пью­те­ра долж­на появить­ся программа-сервер, кото­рая откли­ка­ет­ся на http-запросы. Сер­вер­ных про­грамм мно­го, мы исполь­зу­ем самую рас­про­стра­нён­ную — Apache, она же Апач. Как индей­ское племя.

Поль­зо­ва­те­лям MacOS повез­ло — Апач уже встро­ен в опе­ра­ци­он­ную систе­му и готов к настрой­ке. Для Windows его при­дёт­ся ста­вить отдельно.

Раз­ра­бот­чи­ки Апа­ча исхо­дят из того, что у вас доста­точ­но ква­ли­фи­ка­ции для само­сто­я­тель­ной сбор­ки про­грам­мы из исход­но­го кода. Нам при­ят­но, что о нас так дума­ют, но мы сде­ла­ем про­ще — возь­мём офи­ци­аль­ную сбор­ку XAMPP от парт­нё­ров Apache Software Foundation. В ком­плек­те с сер­ве­ром идёт база дан­ных и под­держ­ка PHP и Perl. Сей­час они нам не нуж­ны, но при­го­дят­ся в буду­щих про­ек­тах. Ска­чай­те и уста­но­ви­те её как обыч­ную про­грам­му.

После уста­нов­ки попа­да­ем в панель управ­ле­ния все­ми моду­ля­ми и нажи­ма­ем Start напро­тив Апа­ча, что­бы убе­дить­ся, что всё рабо­та­ет как нужно:

Теперь, когда мы набе­рём в стро­ке бра­у­зе­ра localhost и нажмём кла­ви­шу вво­да, то уви­дим такую стра­ни­цу. Она озна­ча­ет, что апач уста­нов­лен и рабо­та­ет правильно:

Если у вас Макин­тош, то вме­сто ска­чи­ва­ния и уста­нов­ки доста­точ­но в тер­ми­на­ле напи­сать команду:

sudo apachectl start

После это­го по адре­су localhost будет стра­ни­ца с тек­стом It works, кото­рая гово­рит нам о том, что всё работает.

Указываем путь к нашей странице

Послед­нее, что нам оста­лось сде­лать, — научить Апач пока­зы­вать нашу стра­ни­цу вме­сто сво­ей заглушки.

Для это­го нам нуж­но най­ти путь, по кото­ро­му Апач ищет фай­лы для отоб­ра­же­ния, и поло­жить в эту же пап­ку нашу стра­ни­цу. Что­бы най­ти путь, нажи­ма­ем кноп­ку Config напро­тив Апа­ча и выби­ра­ем первую строч­ку — httpd.conf:

Появ­ля­ет­ся окно редак­то­ра, в кото­ром открыл­ся файл с настрой­ка­ми наше­го сер­ве­ра. Нуж­но най­ти строч­ку DocumentRoot, кото­рая пока­жет нам, куда Апач обра­ща­ет­ся за веб-страницами:

Мы видим, что Апач обра­ща­ет­ся к пап­ке C:/xampp/htdocs. Это зна­чит, что про­ще все­го будет поло­жить наш файл index.html в эту пап­ку, а всё осталь­ное содер­жи­мое пап­ки — уда­лить, пото­му что оно нам не нужно.

Мы всё сде­ла­ли, теперь мож­но спо­кой­но рабо­тать — как толь­ко мы попро­бу­ем несколь­ко раз зай­ти в Одно­класс­ни­ки, уви­дим такое:

К сожа­ле­нию, с фейс­бу­ком так не полу­чит­ся, и сайт пока­жет нам такое сообщение:

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

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