Skip to content


Как не надо строить сети

Аккуратно уложенные кабеля

Аккуратно уложенные кабеля

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

Через полчаса блужданий по зданию у нас начались нервные смешки. Никто не знает, что такое серверная, а «единственный подкованный во этих ваших технических штучках» сотрудник со всем начальством срочно уехал в банк и недоступен. Наконец, на третьем этаже замечаем блеск понимания в глазах девочки-блондинки: «Я знаю! Это в конце коридора, мы туда курить бегаем».

Идём за белокурой сотрудницей и попадаем из гламурного холла в белую оштукатуренную комнатку 3 на 5 с маленьким окошком, пепельницей и большим железным щитком у одной стены. «Вот», — тычет милое создание на щиток, и с заговорщической ноткой добавляет: «Серверная».

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

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

— Женя, а как это вообще, эмм, работает? Это возможно?

Прикуривая первую за долгое время сигарету, Женя отрешённо произнес:

— В жизни нет ничего невозможного.

Объект решили не брать.

Posted in Развлекуха.


Противодействие автоматическому подбору паролей

В лог-файлах почти любого публично доступного FTP-сервера в Интернет сисадмин почти всегда видит попытки множественных безуспешных попыток авторизации. Например:

Thu Sep 3 04:39:50 2009 FTP command: Client "221.232.131.51", "USER Admin"
Thu Sep 3 04:39:51 2009 [Admin] FTP response: Client "221.232.131.51", "530 Permission denied."
Thu Sep 3 04:39:53 2009 CONNECT: Client "221.232.131.51"
Thu Sep 3 04:39:53 2009 FTP response: Client "221.232.131.51", "220 Welcome to our FTP-server."
Thu Sep 3 04:39:53 2009 FTP command: Client "221.232.131.51", "USER Admin"
Thu Sep 3 04:39:54 2009 [Admin] FTP response: Client "221.232.131.51", "530 Permission denied."
Thu Sep 3 04:39:55 2009 FTP command: Client "221.232.131.51", "USER Admin"
Thu Sep 3 04:39:56 2009 [Admin] FTP response: Client "221.232.131.51", "530 Permission denied."
Thu Sep 3 04:39:57 2009 CONNECT: Client "221.232.131.51"
Thu Sep 3 04:39:57 2009 FTP response: Client "221.232.131.51", "220 Welcome to our FTP-server."
Thu Sep 3 04:39:57 2009 FTP command: Client "221.232.131.51", "USER Admin"
Thu Sep 3 04:39:58 2009 [Admin] FTP response: Client "221.232.131.51", "530 Permission denied."
Thu Sep 3 04:39:59 2009 FTP command: Client "221.232.131.51", "USER Admin"
Thu Sep 3 04:40:00 2009 [Admin] FTP response: Client "221.232.131.51", "530 Permission denied."

Как-правило, цель взломщиков проста – угадать пароль и использовать FTP-аккаунт для размещения скриптов рассылки спама, сбора персональных данных с фишинговых сайтов и прочих тёмных делишек. Поэтому всегда стоит по возможности закрывать доступ на TCP-порт 21 в firewall-е для всех, кроме блоков IP-адресов, с которых ходят доверенные пользователи. Но что делать, если мы не знаем откуда будут ходить легитимные пользователи нашего FTP-сервера? В таких случаях, конечно, доступ закрывать нельзя, но можно существенно понизить эффективность подбора паролей путем следующих двух простых правил для стандартного в linux firewall-а iptables:

iptables -A INPUT -m recent --name ftpbruteforce --update --seconds 60 --hitcount 2 -j DROP
iptables -A INPUT -p tcp --syn --dport 21 -m recent --name ftpbruteforce --set -j ACCEPT

Второе правило означает, что если встретится TCP-сегмент, в котором порт получателя 21 и установлен флаг SYN (что соответствует 1-ой фазе установки соединения при подключении к FTP-серверу), то iptables "запомнит" этот факт вместе с моментом появления такого TCP-сегмента и установит для этого события заданное нами имя ftpbruteforce. А первое правило означает, что если события с именем ftpbruteforce будут наступать чаще, чем 2 раза в течение 60-ти секунд, то такие TCP-сегменты будут блокироваться (-j DROP). Параметр −−update означает, что таймер блокировки обнуляется каждый раз, когда событие ftpbruteforce наступает в следующий раз. То есть легитимный пользователь, который правильно указывает логин и пароль при подключении к серверу, без проблем подключиться, потому что для него сработает только 2-ое правило и не сработает 1-ое правило. Он даже один раз может ошибиться при указании атрибутов доступа – вторая попытка с уже правильными атрибутами тоже будет успешной. А вот уже начиная с третей попытки установить соединение в течение 60-ти секунд начнет срабатывать 1-ое правило и трафик будет блокироваться, что как раз и соответствует случаю подбора паролей (bruteforcing).

Данную методику можно применять, конечно же, не только для FTP-серверов, но и для многих других случаев (например, SSH). Другие примеры использования модуля recent можно посмотреть на странице его автора и в странице руководства ('man iptables').

Posted in *nix.

Tagged with , .


Внедряем Captcha в CuteNews

captcha exampleЗащита от спама сейчас - просто необходимый элемент любого сайта, где присутствует возможность заполнения каки-либо форм (будь то форма для обратной связи с автором, либо форма добавления ссылки в каталог ссылок или еще что-то подобное). Одним из наиболее эффективных способов противодействия появлению спама на веб-страницах является CAPTCHA (расшифровывается как Completely Automated Public Turing test to tell Computers and Humans Apart) т.е. одна из разновидностей теста Тьюринга. Пример такого теста в достаточно жеcтком для пользователя варианте :) приведен на картинке слева.

Порядок установки CAPTCHA в новостной скрипт CuteNews.

  1. Добавляем в файл data/Default.tpl в код формы ввода комментария $template_form (примерно 62-ая строка):
    data/Default.tpl
    Текст на картинке: 
    picture with code

    Полная версия кода формы у меня получилась такая:

    $template_form = <<<HTML
    <table border="0" width="500" cellspacing="0" cellpadding="2" style="margin-bottom: 20px">
    <thead style="background: rgb(239,244,11); text-align: center">
    <tr><td colspan="2"><span style="font-size: 12pt">Оставить комментарий</span></td></tr>
    </thead>
    <tr><td height="5" colspan="2"></td></tr>
    <tr><td width="20%">Имя:</td><td><input type="text" name="name" tabindex="1"></td></tr>
    <tr><td>E-mail:</td><td><input type="text" name="mail" tabindex="2"></td></tr>
    <tr><td colspan="2"> <textarea style="width: 100%" rows="8" name="comments" tabindex="3"></textarea><br /></td></tr>
    <tr><td colspan="2"><div style="margin-top: 10px; float: left">Введите цифры с картинки: <input tabindex="4" type="text" name="captcha" size="10" /></div>
    <img src="captcha.php" alt="picture with code" valign="middle" /></td></tr>
    <tr><td colspan="2" align="center"><input tabindex="5" type="submit" name="submit" value="Добавить комментарий" accesskey="s"></td></tr></table>
    HTML;
  2. Положить в корень сайта файлы captcha.php и Comic_Sans_MS.ttf. Взять их можно тут.
  3. Поправить файл inc/shows.inc.php, добавив в него начиная примерно со 172-ой строки следующее:
    inc/shows.inc.php
    @session_start();
    if (! (isset($_SESSION["captcha"]) && $_SESSION["captcha"]===$_POST["captcha"]) ) {
     echo "
    Текст с картинки введен НЕВЕРНО

    Вернуться назад
    "; $CN_HALT = TRUE; break 1; } unset($_SESSION["captcha"]);
  4. Поудалять из файла site/data/comments.txt спам-комментарии, которые попали туда до того, как была прикручена captcha :)

Чтобы эта версия captcha работала, PHP должен быть сконфигурирован со следующими опциями (актуально для версии 5.3.0):
−−with-gd=/usr
−−enable-gd-native-ttf
−−with-freetype-dir=/usr
−−with-zlib
−−with-zlib-dir=/usr

Путь к библиотекам (/usr), естественно, следует заменить так, чтобы он был актуален для Вашей системы.

Posted in Веб-приложения.

Tagged with , .


Организация уведомлений о событиях

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

  1. На удаленном сервере (пусть для примера у него будет ip-адрес 10.10.10.254) запускаем такую команду:
    $ tail -f /var/log/somelog | grep -m 1 "our_event" && nc 10.10.10.10 2740

    В результате при следующем появлении в файле /var/log/somelog текста "our_event" откроется исходящее tcp-соединение на хост мониторинга 10.10.10.10 на порт 2740. Далее следует позаботиться об адекватной обработке этого на хосте 10.10.10.10. Ключ '-m 1' у команды grep означает, что она должна завершиться после 1-го найденного совпадения.

  2. На хосте мониторинга запускаем сервис xinetd (если он еще не запущен, предварительно создав файл /etc/xinetd.d/alarm примерно такого содержания:
    service alarm
    {
      disable = no
      id = alarm
      wait = no
      socket_type = stream
      user = me
      group = me
      server = /usr/local/sbin/show_alarm.sh
      bind = 10.10.10.10
      only_from = 10.10.10.254
    }

    Номер порта не указан по следующей причине:

    $grep -P "^alarm\s" /etc/services
    alarm           2740/tcp                        # Alarm
    alarm           2740/udp                        # Alarm

    Если вдруг в вашем файле /etc/services нет таких строк, то в /etc/xinetd.d/alarm нужно еще добавить строку port = 2740. Описание параметров конфигурации демона xinetd можно почитать в файле /etc/xinetd.d/chargen-stream ну и, конечно, в man 5 xinetd.conf.

  3. Создаем скрипт /usr/local/sbin/show_alarm.sh:
    #!/bin/bash
    kalarm "Needed string found at 10.10.10.254" 2> /dev/null

    и делаем этот файл исполняемым:

    chmod +x /usr/local/sbin/show_alarm.sh

    Утилита kalarm будет нам показывать на мониторе заданное сообщение, она входит в пакет kdepim, в чем можно убедиться с помощью следующей команды:

    $rpm -qf /usr/bin/kalarm
    kdepim-4.2.4-1.fc10.x86_64

    Также kalarm умеет издавать звуки, запускать внешние приложения (как – описано в man), что открывает широкий простор для фантазии.

  4. На хосте мониторинга 10.10.10.10 в firewall-е разрешаем входящие tcp-соединения с сервера 10.10.10.254 на tcp-порт 2740:
    /sbin/iptables -I INPUT -s 10.10.10.254 -p tcp --dport 2740 -j ACCEPT

    В результате при появлении строки "our_event" в файле /var/log/somelog на сервере 10.10.10.254 мы сразу же получим уведомление об этом в виде всплывающего окошка на хосте мониторинга 10.10.10.10.

Posted in *nix.

Tagged with .