Защитимся от перебора паролей

Настройка сетевых служб, маршрутизации, фаерволлов. Проблемы с сетевым оборудованием.
Правила форума
Убедительная просьба юзать теги [code] при оформлении листингов.
Сообщения не оформленные должным образом имеют все шансы быть незамеченными.
Аватара пользователя
buryanov
ст. сержант
Сообщения: 311
Зарегистрирован: 2008-04-29 13:41:48
Откуда: Харьков
Контактная информация:

Защитимся от перебора паролей

Непрочитанное сообщение buryanov » 2010-02-19 17:08:27

Есть куча средств в портах, но человек захотел чтото своё, вот в свободное время сел да написал, заодно с вами поделюсь.
Что есть: сервисы ssh, ftp(vsftp), dovecot и многое другое, но о нём позже.
За основу я брал уже используюмою мной схему по защите exim.

Топология:
Несколько серверов, шлюзы, на которых крутятся разные сервися, весь syslog стикается на один сервер

Для работы нам нужен будет MySQL. Основная логика сделана на процедурах и тригере(оракловци дали понять, что так проще).

Создаём таблици

Код: Выделить всё

CREATE TABLE hack_exp(
  ip CHAR(15),
  date_delete CHAR(19) DEFAULT NULL,
  active INT(1) DEFAULT 0,
  PRIMARY KEY (ip)
)
ENGINE = MEMORY;

CREATE TABLE hack_pass(
  ip CHAR(15),
  count INT(4) DEFAULT NULL,
  host VARCHAR(20) DEFAULT NULL,
  date_original CHAR(19) DEFAULT NULL,
  date_insert CHAR(19) DEFAULT NULL,
  date_last CHAR(19) DEFAULT NULL,
  date_exp CHAR(19) DEFAULT NULL,
  type CHAR(5) DEFAULT NULL,
  PRIMARY KEY (ip)
)
ENGINE = MEMORY;

CREATE TABLE log_list(
  log_string VARCHAR(255) DEFAULT NULL
)
ENGINE = MYISAM;
тригеры

Код: Выделить всё

CREATE
TRIGGER ins_into_hack
AFTER INSERT
ON log_list
FOR EACH ROW
BEGIN
  SET @t_str = new.log_string;
  -- Время первого заноса в таблицу
  SET @t_date_insert = NOW();
  -- Время последнего заноса в таблицу
  SET @t_date_last = NOW();
  -- Интервал, за который идёт анализ
  SET @t_date_expire = NOW() + INTERVAL 10 MINUTE;
  -- Вызываем процедуру, парсящую строки логов
  -- CALL deny_ip.string_parser(@t_str, @t_ip, @t_host, @t_date_original);
  CALL deny_ip.case_type(@t_str, @t_ip, @t_host, @t_date_original, @t_type);

  -- Заносим данные в таблицу колектор и, в случии нахождения ip, обновляем и добавляем очки
  INSERT INTO deny_ip.hack_pass (ip, count, host, date_original, date_insert, date_last, date_exp, type) VALUES (@t_ip, 1, @t_host, @t_date_original, @t_date_insert, @t_date_last, @t_date_expire, @t_type)
  ON DUPLICATE KEY
  UPDATE
    deny_ip.hack_pass.count = deny_ip.hack_pass.count + 1,
    deny_ip.hack_pass.date_exp = @t_date_expire,
    deny_ip.hack_pass.date_last = deny_ip.hack_pass.date_last;

  -- Заносим данные в таблицу, из которой информацию черпает фаервол
  -- Данные заносятся из таблици коллектора
  -- coun >5 - это условие, при котором можно с увереностью сказать,
  -- что вас или спамят или ддосят, интервал анализа - @date_expire
  -- date_expire + INTERVAL 10 MINUTE интервал, сколько в фаерволе будет находится ip

  INSERT IGNORE INTO deny_ip.hack_exp (ip, date_delete)
  SELECT
    ip, date_exp + INTERVAL 10 MINUTE
  FROM
    deny_ip.hack_pass
  WHERE
    count > 5;

  -- Удаляем просроченные или записи из таблици коллектора
  -- по времени оканчания срока жизни @date_expire
  DELETE
  FROM
    deny_ip.hack_pass
  WHERE
    LEFT(date_exp, 16) < NOW();

  -- Удаляем из таблици коллектора свои подсети
  -- Надо будет переделать на свой whitelist, хранимый в мускуле
  DELETE
  FROM
    deny_ip.hack_pass
  WHERE
    ip LIKE '10.4.%' OR ip LIKE '192.168.%' OR ip LIKE '217.112.%';

END
и процедуры

Код: Выделить всё

DELIMITER $$

--
-- Описание для процедуры case_type
--
CREATE PROCEDURE case_type(IN i VARCHAR(255), OUT o_ip CHAR(15), OUT o_host VARCHAR(55), OUT o_date CHAR(19), OUT o_type CHAR(5))
BEGIN
 -- Опрделяем тип события
  SELECT
    CASE
    WHEN (i LIKE '%lid user%') AND (i LIKE '%ssh%') THEN 'sshi'
    WHEN (i LIKE '%POSS%') AND (i LIKE '%ssh%') THEN 'sshp'
    WHEN (i LIKE '%Aborted login%') AND (i LIKE '%pop3-login%') THEN 'dovp'
    END
  INTO
    @wer;
-- Вызываем соответствующую процедеру для события
  CASE @wer
  WHEN 'sshi' THEN
    CALL deny_ip.ssh_invalid(i, o_ip, o_host, o_date, o_type);
  WHEN 'sshp' THEN
    CALL deny_ip.ssh_posible(i, o_ip, o_host, o_date, o_type);
  WHEN 'dovp' THEN
    CALL deny_ip.dovecot_pop3(i, o_ip, o_host, o_date, o_type);
  END CASE;

END
$$

--
-- Описание для процедуры dovecot_pop3
--
CREATE PROCEDURE dovecot_pop3(IN in_str VARCHAR(255), OUT out_ip CHAR(15), OUT out_host VARCHAR(55), OUT out_date_orig CHAR(19), OUT out_type CHAR(5))
BEGIN

  SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, 'rip=', -1), ',', 1)
  INTO
    out_ip;

  SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, ':', 3), ' ', -1)
  INTO
    out_host;
  SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, 'dovecot:', 1), ' ', 3)
  INTO
    out_date_orig;

  SET out_type = 'dovp';

END
$$

--
-- Описание для процедуры ssh_invalid
--
CREATE PROCEDURE ssh_invalid(IN in_str VARCHAR(255), OUT out_ip CHAR(15), OUT out_host VARCHAR(55), OUT out_date_orig CHAR(19), OUT out_type CHAR(5))
BEGIN

  SELECT
    SUBSTRING_INDEX(in_str, ' ', -1)
  INTO
    out_ip;

  SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, 'sshd[', 1), ' ', -2)
  INTO
    out_host;
  SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, 'sshd[', 1), ' ', 3)
  INTO
    out_date_orig;

  -- SET out_ip = 'inv';
  SET out_type = 'sshi';
END
$$

--
-- Описание для процедуры ssh_posible
--
CREATE PROCEDURE ssh_posible(IN in_str VARCHAR(255), OUT out_ip CHAR(15), OUT out_host VARCHAR(55), OUT out_date_orig CHAR(19), INOUT out_type CHAR(5))
BEGIN

  SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, "[", -1), ']', 1)
  INTO
    out_ip;

  SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, "[", 1), ' ', -2), ' ', 1)
  INTO
    out_host;
  SELECT
    SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, 'sshd[', 1), ' ', 3)
  INTO
    out_date_orig;
  SET out_type = 'sshp';

END
$$

$$
Скрипт помещаемый в крон на шлюзе:

Код: Выделить всё

[root@hqgw1:/scripts/deny]# cat ./add_ipfw_hack_pass.sh
#!/usr/local/bin/bash

/usr/local/bin/mysql --host=10.4.250.3 --password='pass'--user=deny_ip deny_ip --execute=' \

update deny_ip.hack_exp \
    set active = 2 \
  WHERE \
    LEFT(date_delete, 16) < NOW() and active = 1; \

SELECT "ipfw table 101 add " asdf, ip FROM deny_ip.hack_exp \
    WHERE \
      active = 0; \

SELECT "ipfw table 101 delete " asdf, ip FROM deny_ip.hack_exp \
    WHERE \
      active = 2; \

UPDATE deny_ip.hack_exp \
    SET active = 1 where active = 0; \

delete FROM deny_ip.hack_exp \
  WHERE \
    LEFT(date_delete, 16) < NOW() and active = 2;'| grep -v asdf>/tmp/pass_hack_ipfw_add_table_blacklist.sh

. /tmp/pass_hack_ipfw_add_table_blacklist.sh

rm /tmp/pass_hack_ipfw_add_table_blacklist.sh
Строка фаера на шлюзе:

Код: Выделить всё

${fwcmd} add 58 deny log ip from table\(101\) to any via ${ifwan}
В /etc/syslog.conf должна быть строка

Код: Выделить всё

# touch /var/log/all.log and chmod it to mode 600 before it will work
*.*                                             /var/log/all.log
Парсер /var/log/all.log:

Код: Выделить всё

 cat /scripts/deny/service.sh
#!/usr/local/bin/bash
msql="/usr/local/bin/mysql --user=deny_ip --password=deny_ip --database=deny_ip --host=10.4.250.3"
lf="/var/log/all.log"
cp ${lf} ${lf}.tmp
> ${lf}
cat ${lf}.tmp >> ${lf}.store

## insert into mysql 
cat ${lf}.store|egrep -e "Invalid user|POSSIBLE BREAK-IN ATTEMPT|FAIL LOGIN|: Aborted login" | \
sed 's/"//g'|sed 's/^/INSERT INTO deny_ip.log_list (log_string) VALUES ("/g'|sed 's/$/");/g' | ${msql}

rm -f ${lf}.tmp
добавляется в крон

Расширение на новый функционал происходит путём написания процедуры

Код: Выделить всё

CREATE PROCEDURE deny_ip.string_parser(IN in_str VARCHAR(255), OUT out_ip CHAR(15), OUT out_host VARCHAR(55), OUT out_date_orig CHAR(19), OUT out_type CHAR(5))
BEGIN
  -- в этой секции строка парсится на определение ip удалённого хоста
  SELECT SUBSTRING_INDEX(in_str, ' ', -1) INTO out_ip;
  -- в этой секции строка парсится на определение имени хоста, на который бомбят
  SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, 'sshd[', 1), ' ', -2) INTO out_host;
  -- в этой секции строка парсится на определение времени события
  SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(in_str, 'sshd[', 1), ' ', 3) INTO out_date_orig;
  -- в этой секции определяем тип события
  SET out_type = 'pos';
END
добавления в процедуру case_type следующих строк:

Код: Выделить всё

WHEN (i LIKE '%lid user%') AND (i LIKE '%ssh%') THEN 'sshi'
где идёт выявление уникального сочитания символов(i LIKE '%lid user%') AND (i LIKE '%ssh%') для определённого события (sshi) и добавлением

Код: Выделить всё

WHEN 'sshi' THEN
    CALL deny_ip.sshi(i, o_ip, o_host, o_date, o_type);
в следующий case.
Дмитрий.
buryanov*ukr.net
icq# 118639660; skype: buryanov

Хостинговая компания Host-Food.ru
Хостинг HostFood.ru
 

Услуги хостинговой компании Host-Food.ru

Хостинг HostFood.ru

Тарифы на хостинг в России, от 12 рублей: https://www.host-food.ru/tariffs/hosting/
Тарифы на виртуальные сервера (VPS/VDS/KVM) в РФ, от 189 руб.: https://www.host-food.ru/tariffs/virtualny-server-vps/
Выделенные сервера, Россия, Москва, от 2000 рублей (HP Proliant G5, Intel Xeon E5430 (2.66GHz, Quad-Core, 12Mb), 8Gb RAM, 2x300Gb SAS HDD, P400i, 512Mb, BBU):
https://www.host-food.ru/tariffs/vydelennyi-server-ds/
Недорогие домены в популярных зонах: https://www.host-food.ru/domains/

Аватара пользователя
Alex Keda
стреляли...
Сообщения: 35267
Зарегистрирован: 2004-10-18 14:25:19
Откуда: Made in USSR
Контактная информация:

Re: Защитимся от перебора паролей

Непрочитанное сообщение Alex Keda » 2010-04-18 19:10:03

чё-то сложное...
скрипт на шелле и то короче будет
Убей их всех! Бог потом рассортирует...