Debian Jessie: Трюки вокруг доступа к sshd (iptables, ipset, geoip)

Это заметка из цикла стетей моего небольшого HowTo по Debian Jessie.

Тут я уже описывал ранее вариант фильтрации доступа к ssh по GeoIP. На этот раз покажу вам более интересный вариант с ipset и модуль TARPIT для IPTABLES. Сразу скажу пару слов об этих новых сущностях:
ipset — модуль поддержки таблиц для iptables с сопутствующей обвязкой для управления этими самими таблицами: создание, удаление, работа с элементами таблицы и тп. Сам по себе модуль весьма хорош и здорово повышает эффективность работы iptables с большим количеством ip-адресов и сетей. Но если разсметривать реализацию iptables + ipset вцелом — то оно мне напоминает пятиколесный велосипед с деревянными спицами. Уж простите за такую ассоциацию у человека несколько лет админившего всякие там pf/ipfw в BSD-ях. На High-Load юзать можно и нужно!
TARPIT модуль для IPTABLES — это модуль для it-весельчаков. Суть работы этого модуля заключается в том что он какбы держит открытым указанный TCP порт, но при попытке клиента соединиться — не шлет в ответ абсолютно ничего. Это такой себе blackhole или nullroute на уровне фаервола. Это приводит к «зависшему» соединению с возможностью закрыть его только автоматически по истечению таймаута. Задумка модуля в том чтобы не просто блокировать бота, а истощать его ресурсы на соединение, мизерные, конечно, но всеже … На High-Load юзать не желательно, лучше пользуйте DROP!

Ранее при настройке proftpd мы уже установили geoip, но для тех кто не делал этого понадобится установленный geoip и его база:

gw:~$ sudo apt-get install geoip-bin geoip-database

В Debian модуль TARPIT находится в пакете дополнительных модулей iptables. Установим их:

gw:~$ sudo apt-get install xtables-addons-dkms

Ставим необходимый пакет для добавления ipset:

gw:~$ sudo apt-get install ipset

Одной из приятных фишек таблиц ipset является опция timeout. Она задает количество времени (в секундах) которое элемент содержится в таблице. По истечении timeout-а — элемент автоматически удаляется из таблицы.

Пример борьбы с ssh брутфорсерами:
1. Создаем таблицу, в нее скриптом проверки geoip будем добавлять ботов, timeout ставим 2 часа:

gw:~$ sudo ipset create ssh_bots hash:ip hashsize 16384 timeout 7200

2. Загрузим модуль ядра для действия iptables TARPIT:

gw:~$ sudo modprobe xt_TARPIT

3. Напомню что вот здесь мы базово настроили iptables. Сразу перед правилом розрешающим конект на port 22 добавим правило для блокировки ssh ботов из таблицы ssh_bots. Должно получиться вот так:

...
# Allow DNS connections from anywhere
-A INPUT -p udp --dport 53 -j ACCEPT
-A INPUT -p tcp --dport 53 -j ACCEPT

# TARPIT ssh_bots table
-A INPUT -m set --match-set ssh_bots src -p TCP --dport 22 -j TARPIT

# Allows SSH connections
# The --dport number is the same as in /etc/ssh/sshd_config
-A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT
...

4. Теперь сооружаем чуть модифицированный скрипт проверки geoip — /usr/local/bin/ssh_geoip.sh:

gw:~$ sudo vim /usr/local/bin/ssh_geoip.sh

Вставляем туда следующее …

#!/usr/bin/env bash

PATH="/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/root/bin"

ALLOW_COUNTRIES="UA"

if [ $# -ne 1 ]; then
  echo "Usage:  `basename $0` <ip>" 1>&2
  exit 0 # return true in case of config issue
fi

COUNTRY=`geoiplookup $1 |sed -e 's/^.*Edition\:\ //' -e 's/\,.*$//'`

if [[ ${COUNTRY} =~ ${ALLOW_COUNTRIES} ]]; then
    logger "sshd ALLOW connection from IP $1 - [${COUNTRY}]"
    exit 0
  else
    logger "sshd DENY connection from IP $1 - [${COUNTRY}]"
    ipset add ssh_bots $1
    exit 1
fi

Это же скрипт, не забываем дать права на выполнение:

gw:~$ sudo chmod +x /usr/local/bin/ssh_geoip.sh

5. Теперь подправим конфиг /etc/hosts.deny добавив туда:

sshd: ALL

6. Теперь подправим конфиг /etc/hosts.allow добавив туда:

# Whitelist for LAN network 192.168.0.0/16
sshd: 192.168.
# Check Access by GeoIP
sshd: ALL: aclexec /usr/local/bin/ssh_geoip.sh %a

Итак, теперь соединение к ssh-серверу проходит так:
— конект на 22-й порт
— если ip клиента из сети 192.168.0.0/16 — пускаем сразу (см. whitelist в файле /etc/hosts.allow)
— проверка прав дотупа через скрипт /usr/local/bin/ssh_geoip.sh (розрешено только для UA ip-адресов)
— если права даны — приглашение к авторизации
— если права не даны — добавление ip бота в таблицу ssh_bots и сброс соединения
— следующая попытка соединения на порт 22 ведет в модуль TARPIT iptables-а
спустя 7200 секунд (2 часа) ip бота автоматически удаляется из таблицы ssh_bots и может коннектиться снова

Все прохождения через скрипт логируются в /var/log/messages в таком виде:
удачные:

Nov 22 14:14:11 gw logger: sshd ALLOW connection from IP 77.91.130.111 - [UA]

неудачные:

Nov 22 11:30:44 gw logger: sshd DENY connection from IP 123.151.42.61 - [CN]

Посмотреть листинг таблицы ssh_bots:

gw:~$ sudo ipset list ssh_bots
Name: ssh_bots
Type: hash:ip
Revision: 3
Header: family inet hashsize 16384 maxelem 65536 timeout 7200
Size in memory: 295304
References: 1
Members:
222.186.34.74 timeout 2075
43.229.53.69 timeout 3998
gw:~$

Хай щастить!

  1. Комментов пока нет

  1. Трэкбэков пока нет.

Why ask?