Содержание статьи
Брандмауэр — первая линия защиты любого сервера, и от его правильной настройки зависит, сможет ли злоумышленник продвинуться дальше в своих попытках проникновения в систему. Современные файеры предлагают множество механизмов обеспечения безопасности, используя которые ты можешь оставить «не у дел» 99% атакующих. И все это без необходимости покупки дорогостоящего оборудования и коммерческого софта.
Главная цель всех взломщиков — получение доступа к командному интерпретатору сервера для использования его возможностей в своих интересах. Наиболее часто проникновение в «святая святых» осуществляется с помощью дыр в сервисах или же через подбор пароля (брутфорс) к одному из них (например, ssh).
Сканирование портов
Чтобы выявить наличие уязвимых сервисов на машине, атакующий производит разведку с помощью сканера портов и различных систем обнаружения уязвимостей. Обычно в качестве сканера портов используется nmap, который способен осуществлять сканирование десятком различных способов и в некоторых случаях умеет выявлять версии ОС и сервисов. Вот список особенно популярных флагов nmap, которые обычно используют взломщики:
Флаги nmap, используемые при сканировании
-
-sT
— обычное TCP-сканирование с помощью открытия соединения на указанный порт и его завершения; -
-sS
— SYN/ACK-сканирование, связь разрывается сразу после ответа на запрос открытия соединения; -sU
— UDP-сканирование;-sF
— сканирование пакетами с установленным флагом FIN;-sX
— сканирование пакетами с установленными флагами FIN, PSH и URG;-sN
— сканирование пакетами без установленных флагов.
Метод защиты от сканирования прост и известен любому системному администратору. Заключается он в простом закрытии всех сервисов, которые не должны быть видны из внешней сети. Например, если на машине работают сервисы ssh, samba и apache, а из внешнего мира должен быть виден только веб-сервер с корпоративной веб-страницей, то межсетевой экран может быть настроен так:
Начальная настройка iptables
outif="eth1"
iptables -F
iptables -i $outif -A INPUT \
-m conntrack \
--ctstate ESTABLISHED,RELATED \
-j ACCEPT
iptables -i $outif -A INPUT -p tcp \
--dport 80 -j ACCEPT
iptables -i $outif -P INPUT DROP
iptables -i $outif -P OUTPUT ACCEPT
Начальная настройка ipfw
outif="rl0"
ipfw add allow ip from any to any \
via lo0
ipfw add allow ip from me to any \
via $outif
ipfw add allow tcp from any to me \
established via $outif
ipfw add allow tcp from any 80 \
to me via $outif
ipfw add deny ip from any to any \
via $outif
Начальная настройка pf
outif="rl0"
set skip on lo0
block all
pass out on $outif from $outif \
to any keep state
pass in on $outif proto from any \
to $outif port 80
Все три набора правил делают одно и то же — разрешают прохождение любого трафика по интерфейсу обратной петли (loopback), разрешают принимать пакеты уже установленных соединений (чтобы, например, браузер мог получить ответ на запрос к удаленному серверу), разрешают обращения на 80-й порт, блокируя все остальные, и разрешают любые коннекты наружу. Обрати внимание, что если в примерах iptables и ipfw мы явно задали правила для разрешения приема пакетов уже установленных соединений (established), то в случае с pf для этого достаточно было указать «keep state» в рулесете, разрешающем любые исходящие соединения.
В общем-то, такая схема защиты сетевых сервисов от сканирования и проникновения отлично работает, но мы можем пойти дальше и настроить файер так, чтобы некоторые виды сканирования вообще не могли бы быть выполнены. Технически мы не можем сделать это в отношении обычного сканирования (флаги nmap '-sT', '-sS' и '-sU') просто потому, что в нем нет ничего криминального, однако нестандартные типы сканирования, такие как '-sN', '-sF' и '-sX', порождают пакеты, которые никак не могли быть созданы легальными приложениями.
Поэтому без тени сомнения отбрасываем подобные соединения.
Методы борьбы с экзотическими видами сканирования
# Запрет FIN-сканирования
Linux> iptables -A INPUT –p tcp \
–m tcp \
–-tcp-flags FIN,ACK FIN -j DROP
FreeBSD> ipfw add reject tcp from any to any \
not established tcpflags fin
# Запрет X-сканирования
Linux> iptables -A INPUT –p tcp –m tcp \
--tcp-flags FIN,SYN,RST,PSH,ACK,URG
FIN,SYN,RST,PSH,ACK,URG \
–j DROP
FreeBSD> ipfw add reject tcp from any to any \
tcpflags fin, syn, rst, psh, ack, urg
# Запрет N-сканирования
Linux> iptables -A INPUT –p tcp –m tcp \
–-tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE –j DROP
FreeBSD> ipfw add reject tcp from any to any \
tcpflags !fin, !syn, !rst, !psh, !ack, !urg
В OpenBSD все эти строки можно заменить простой записью в начале
/etc/pf.conf:
scrub in all
Директива scrub активирует механизм нормализации пакетов, при котором фрагментированные пакеты воссоединяются, а пакеты с недопустимой комбинацией флагов отбрасываются. Кроме экзотических видов сканирования scrub позволяет защититься и от обмана систем обнаружения вторжений (посылка сильно фрагментированных пакетов) и некоторых видов DoS-атак.
Для защиты от SYN/ACK-сканирования, инициируемого с помощью nmap-флага '-sS', мы можем использовать метод пассивного определения ОС (OS Fingerprint), доступный в брандмауэрах pf и iptables/netfilter (начиная с версии 1.4.6). Во время проведения обычного сканирования (флаг '-sT') nmap использует стандартный интерфейс сокетов операционной системы, поэтому такой скан почти ничем не отличается от потока обычных пакетов (ниже мы рассмотрим некоторые его отличия), однако при SYN/ACK-сканировании nmap формирует пакеты самостоятельно, поэтому они имеют некоторые черты, которые выдают их источник. Метод пассивного определения ОС позволяет идентифицировать эти пакеты и отбросить их с помощью стандартных правил файервола:
OpenBSD> block in quick from any os NMAP
Linux> iptables -I INPUT -p tcp -m osf --genre NMAP \
-j DROP
Модуль osf брандмауэра iptables/netfilter использует базу «отпечатков», собранную и обновляемую разработчиками OpenBSD (/etc/pf.os), поэтому оба этих правила должны привести к одинаковым результатам. Интересно так же и то, что они позволяют эффективно противодействовать функции определения ОС утилиты nmap (флаг '-O').
Теперь мы защищены почти от всех видов сканирования, кроме стандартного и тупого '-sT'. Как быть с ним? На самом деле все просто. Факт сканирования портов легко заметить, просто проанализировав логи файервола. Если за короткий промежуток времени происходило множество коннектов на различные порты — значит, нас сканировали. Осталось только переложить эту идею на правила брандмауэра. Для iptables есть отличный рецепт, который блокирует всех, кто слишком настойчиво стучится в нерабочие порты:
Борьба со сканированием с помощью iptables
# Проверка на стук в нерабочие порты (10 в час)
iptables -A INPUT -m recent --rcheck \
--seconds 3600 --hitcount 10 --rttl -j RETURN
# Вторая проверка на стук в нерабочие порты (2 в минуту)
iptables -A INPUT -m recent --rcheck \
--seconds 60 --hitcount 2 --rttl -j RETURN
# Заносим адреса стучащихся в список
iptables -A INPUT -m recent --set
# Отбрасываем пакеты всех, кто превысил лимит на
количество подключений
iptables -P INPUT -j DROP
Установив пакет xtables-addons, содержащий наработки проекта patch-omatic, мы получим доступ к модулю PSD (Port Scan Detect), реализованному по образу и подобию демона scanlogd. Все предыдущие строки могут быть легко заменены простым правилом:
# iptables -A INPUT -m psd -j DROP
К сожалению, в пакетных фильтрах ipfw и pf ничего подобного нет, но это не беда, потому как сканированию портов хорошо противодействует демон PortSentry и тот самый scanlogd.
Запрет Icmp-сообщений
Хорошей практикой также является запрет ICMP-сообщений, которые могут выдать дополнительную информацию о хосте или быть использованы для выполнения различных злонамеренных действий (например, модификации таблицы маршрутизации). Ниже приведена таблица со списком возможных типов ICMP-сообщений:
Типы ICMP-сообщений
- 0 — echo reply (echo-ответ, пинг)
- 3 — destination unreachable (адресат недосягаем)
- 4 — source quench (подавление источника, просьба посылать пакеты медленнее)
- 5 — redirect (редирект)
- 8 — echo request (echo-запрос, пинг)
- 9 — router advertisement (объявление маршрутизатора)
- 10 — router solicitation (ходатайство маршрутизатора)
- 11 — time-to-live exceeded (истечение срока жизни пакета)
- 12 — IP header bad (неправильный IPзаголовок пакета)
- 13 — timestamp request (запрос значения счетчика времени)
- 14 — timestamp reply (ответ на запрос значения счетчика времени)
- 15 — information request (запрос информации)
- 16 — information reply (ответ на запрос информации)
- 17 — address mask request (запрос маски сети)
- 18 — address mask reply (ответ на запрос маски сети)
Как видишь, ответ на некоторые ICMP-сообщения может привести к разглашению некоторой информации о хосте, в то время как другие — привести к модификации таблицы маршрутизации, поэтому их необходимо запретить.
Обычно выход во внешний мир разрешают ICMP-сообщениям 0, 3, 4, 11 и 12, в то время как на вход принимают только 3, 8 и 12. Вот как это реализуется в различных брандмауэрах:
Запрет опасных ICMP-сообщений
Linux> iptables -A INPUT -p icmp \
-icmp-type 3,8,12 -j ACCEPT
Linux> iptables -A OUTPUT -p icmp \
-icmp-type 0,3,4,11,12 -j ACCEPT
FreeBSD> ipfw add allow icmp \
from any to $outif in \
via $outif icmptype 3,8,12
FreeBSD> ipfw add allow icmp \
from $outif to any out \
via $outif icmptype 0,3,4,11,12
OpenBSD> pass in inet proto icmp \
from any to $outif \
icmp-type { 3, 8, 12 } keep state
OpenBSD> pass out inet proto icmp \
from $outif to any \
icmp-type { 0, 3, 4, 11, 12 } \
keep state
При желании ты можешь запретить весь ICMPтрафик, включая пинг-запросы, но это может повлиять на корректность работы сети.
Брутфорс
Разведав информацию об открытых портах и ОС, взломщик предпринимает попытки проникновения в систему, которые могут быть основаны на эксплуатации дыр в сервисах, либо на подборе паролей. Предотвратить возможность взлома сервисов брандмауэр нам не поможет, однако затормозить процесс перебора паролей — легко. Для этого применяются возможности по ограничению количества пакетов, пришедших на машину с одного IP-адреса. Вот как это можно сделать с помощью iptables:
Защита от брутфорса с помощью iptables
# Цепочка для проверки соединений
iptables -N brute_check
# Блокировка адреса, если за 60
секунд он инициировал более 2-х соединений
iptables -A brute_check -m recent \
--update --seconds 60 \
--hitcount 3 -j DROP
# Если нет — разрешаем соединение и
заносим адрес в список
iptables -A brute_check -m recent \
--set -j ACCEPT
# Очищаем цепочку INPUT
iptables -F INPUT
# Отправляем в цепочку brute_check
всех, кто пытается подключиться к
22-му порту
iptables -A INPUT -m conntrack \
--ctstate NEW -p tcp \
--dport 22 -j brute_check
iptables -P INPUT DROP
То же самое можно проделать и с использованием pf:
Защита от брутфорса с помощью pf
# Создаем таблицу для брутфорсеров
table <bruteforcers> persist
# Блокируем всех, кто в нее попадает
block in quick from <bruteforcers>
# Помещаем в таблицу bruteforcers всех, кто инициирует более двух соединений на 22-ой порт в минуту
pass in on $ext_if inet proto tcp to $outif \
port 22 flags S/SA keep state \
(max-src-conn-rate 60/2, \ overload <bruteforcers> flush)
Брандмауэр ipfw не обладает достаточной функциональностью для эффективного противодействия брутфорсерам, поэтому его пользователи должны использовать инструменты более высокого уровня, такие как специальные модули PAM, системы обнаружения вторжений и программы вроде sshguard.
Спуфинг
Спуфинг (подмена адреса отправителя пакета) может быть использован для осуществления DoS-атак или обхода брандмауэра. В первом случае спуфинг дает огромное преимущество атакующему, так как существенно затрудняет реакцию на атаку (пакеты, приходящие с совершенно разными адресами отправителя, не так просто классифицировать и заблокировать) и затягивает процесс закрытия новых соединений (обычно поддельный адрес недостижим, поэтому закрытие соединения происходит лишь по истечению таймаута). Спуфинг, осуществляемый для обхода системы защиты, менее опасен и в большинстве случаев поддается контролю.
Достаточно часто, блокируя внешние сетевые сервисы хоста, системные администраторы оставляют их открытыми для определенного диапазона адресов (например, для подключения со своей домашней машины). Вычислив один из этих адресов, взломщик может сформировать пакет, указав этот адрес в качестве обратного, и таким образом «проскользнуть » через брандмауэр. Далее он может угадать номера последовательности TCP-пакетов и сделать так, чтобы доверяющий обратному адресу сервис выполнил нужное ему действие. Это очень трудная в реализации атака, которая, тем не менее, может быть выполнена грамотным специалистом, а если речь идет о протоколе UDP, то это под силу и кулхацкеру.
К счастью, защититься от подобных атак легко. Достаточно не открывать порты незащищенных сервисов во внешний мир, а в случае резкой необходимости использовать защитные системы самих сервисов (например, сертификаты ssh) или механизм «стука в порты» (о нем рассказано в конце статьи).
Ситуация становится более сложной, когда дело касается сетевого моста, разделяющего внутреннюю и внешнюю сети (или две локальных сети). Доверительные отношения внутри локальной сети — обычное дело. Сервисы доступны всем, никакой аутентификации, шифрования и т.д. — просто лакомый кусочек для взломщика. Находясь во внешней сети, он может узнать сетевую маску внутренней сети и сформировать пакеты с соответствующим ей обратным адресом, что приведет к получению доступа ко всем ресурсам локалки. Это действительно опасная ситуация, но ее легко предотвратить с помощью правильной настройки брандмауэра или ОС.
Для этого достаточно запретить прохождение пакетов, обратные адреса которых соответствуют используемым во внутренней сети, с внешнего интерфейса:
Linux> iptables -A INPUT -i $outif \
-s 192.168.1.0/24 -j DENY
FreeBSD> ipfw add deny ip from \
192.168.1.0/24 to any via $outif
OpenBSD> block in on $outif from \
192.168.1.0/24 to any
В качестве альтернативы или дополнительной меры защиты можно (и даже нужно) использовать специальные директивы ipfw и pf и настройки ядра Linux:
Linux> echo 1 > /proc/sys/net/ipv4/conf/all/rp_filter
FreeBSD> ipfw add deny ip from any to any not antispoof in
OpenBSD> antispoof quick for $ext_if
Эти три команды приводят к одинаковым результатам. Все пакеты, обратные адреса которых соответствуют маске сети другого интерфейса, отбрасываются.
Полезности IPTABLES
В конце статьи мы рассмотрим несколько интересных возможностей iptables/netfilter, которые могут оказаться полезными при защите сервера от проникновений. Начнем с механизма удаленного управления брандмауэром, получившего имя «стук в порты» (port knoking). Суть его заключается в том, чтобы заставить файервол выполнять определенные действия после подключения к заданному порту. Ниже приведен пример правил, открывающих порт SSH на 10 секунд после «стука» в 27520-ый порт:
iptables и port knocking
# Цепочка для проверки соединений на защищаемый порт
iptables -N knock
# Разрешаем соединение, если стук был в течение последних
10 секунд
iptables -A knock -m recent --rcheck --seconds 10 \
-j ACCEPT
# Очищаем INPUT
iptables -F INPUT
# Разрешаем все, что относится к уже установленным соединениям
iptables -A INPUT -m conntrack \
--ctstate ESTABLISHED,RELATED -j ACCEPT
# Все попытки открыть соединение с 22-м портом отправляем
на проверку в цепочку knock
iptables -A INPUT -m conntrack --ctstate NEW \
-p tcp --dport 22 -j knock
# Заносим адрес стучащегося в 27520-й порт в список
iptables -A INPUT -m conntrack --ctstate NEW \
-p tcp --dport 27520 -m recent --set
# При стуке в соседние порты удаляем адрес из списка
iptables -A INPUT -m conntrack --ctstate NEW -p tcp \
-m multiport --dport 27519,27521 -m recent --remove
# Запрещаем все
iptables -P INPUT DROP
Третье с конца правило добавляет адрес стучащегося в список. Если та же машина в течение 10 секунд после стука обратится к 22-му порту, соединение будет установлено. Предпоследнее правило — защита от «перебора стука». Если злоумышленник попытается стучать последовательно во все порты с надеждой, что один из них откроет 22-й порт, сработает это правило, и его адрес будет удален из списка сразу после попадания в него.
Вторая полезность iptables распространяется в пакете xtables-addons (patch-o-matic) и носит имя TARPIT. Это действие (такое же, как ACCEPT или DENY), которое «подвешивает» соединение, не позволяя атакующей стороне его закрыть. Соединение, пакеты которого попадают в TARPIT, будет благополучно установлено, однако размер окна будет равен нулю, благодаря чему удаленная машина не сможет отправлять данные, расходуя свои ресурсы, а соединение будет закрыто только по истечению таймаута. TARPIT можно использовать в экстренных случаях для защиты от DoS:
# iptables -A INPUT -p tcp -m tcp -dport 80 -j TARPIT
Или же для введения атакующего в заблуждение и борьбы против сканеров
портов (только обычное TCP-сканирование, '-sT'):
# iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
# iptables -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
# iptables -A INPUT -p tcp -m tcp -j TARPIT
Эти правила создают видимость системы, в которой открыты все порты, однако при попытке подключения к любому из них (кроме 80 и 25) соединения будут «подвисать». Того же результата, но без «провисших» соединений, можно добиться с помощью действия DELUDE, которое правильно отвечает на все попытки инициации соединения, но посылает RST-пакет в ответ на все остальные пакеты. Для еще большего запутывания атакующего ты можешь использовать действие CHAOS, которое случайным образом активирует одно из двух описанных выше действий.
Выводы
Обладая достаточным количеством знаний и вдумчиво читая документацию, ты можешь создать очень крепкий бастион, к которому будет не такто просто подобраться. Современные брандмауэры, а в особенности pf и iptables, предлагают множество средств защиты от непрошенных гостей, которые ты можешь получить абсолютно безвозмездно.
Links
- sf.net/projects/sentrytools — PortSentry
- www.openwall.com/scanlogd — scanlogd
Борьба с утечкой ресурсов
При использовании действия TARPIT обязательно добавляй в конфиг следующее правило, иначе «провисшие» соединения будут съедать ресурсы при обработке подсистемой conntrack:
# iptables -t raw -I PREROUTING -p tcp --dport 25 -j NOTRACK