Simple stateful firewall (Русский)

Ссылки по теме
Межсетевой экран
Раздача интернета
Nftables (Русский)#Настройка межсетевого экрана
Router
Uncomplicated Firewall
Состояние перевода:
На этой странице представлен перевод статьи
Simple stateful firewall
. Дата последней синхронизации: 11 июля 2021. Вы можете
помочь
синхронизировать перевод, если в английской версии произошли
изменения
.
В статье рассмотрена настройка межсетевого экрана с контекстной фильтрацией (
stateful firewall
) посредством
iptables
, с описанием основных правил и их назначения. Для удобства статья разбита на две части. В первой объясняется настройка межсетевого экрана
на одиночной машине
, во второй —
настройка NAT-шлюза
в дополнение к файрволу.
Важно
Правила ниже приводятся в порядке выполнения; такая настройка возможна только при локальном входе в систему. Если вы работаете с удалённой системой, то в процессе добавления правил соединение с ней будет потеряно. Чтобы этого избежать, используйте
готовый файл настроек
.
Требования
Примечание
Ядро Linux на вашей машине должно быть скомпилировано с поддержкой iptables. В стандартных ядрах Arch Linux поддержка iptables включена.
Прежде всего
установите
пакет
iptables
с набором пользовательских утилит, если он ещё не установлен.
В статье предполагается, что в настоящий момент не заданы никакие правила iptables. Узнать текущий набор правил можно командой:
# iptables-save
# Generated by iptables-save v1.4.19.1 on Thu Aug  1 19:28:53 2013
*filter
:INPUT ACCEPT [50:3763]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [30:3472]
COMMIT
# Completed on Thu Aug  1 19:28:53 2013
или
# iptables -nvL --line-numbers
Chain INPUT (policy ACCEPT 156 packets, 12541 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 82 packets, 8672 bytes)
num   pkts bytes target     prot opt in     out     source               destination
Если всё же какие-то правила существуют, можно сбросить их, загрузив базовый набор:
# iptables-restore < /etc/iptables/empty.rules
Другие способы сброса правил можно найти в статье
iptables#Сброс правил
.
Настройка межсетевого экрана
Примечание
Поскольку iptables проверяет правила в цепочке последовательно, сверху вниз, то имеет смысл переместить часто срабатывающие правила ближе к её началу. Разумеется, этот подход имеет свои ограничения, в зависимости от реализуемой логики. Кроме того, поскольку правила имеют определённую "стоимость" выполнения, не стоит изменять их порядок исключительно на основе эмпирических наблюдений за счётчиком байтов/пакетов.
Создание необходимых цепочек
Создадим две пользовательские цепочки, которые будут использоваться для открытия портов.
# iptables -N TCP
# iptables -N UDP
В дальнейшем при назначений правил для этих цепочек мы будем всякий раз указывать тип протокола (например, флагом
-p tcp
). Этим обусловлен выбор названий цепочек, но вообще говоря, названия могут быть любыми.
Цепочка FORWARD
Если вы хотите настроить свою систему в качестве NAT-шлюза, изучите раздел
#Настройка NAT-шлюза
. Для обычной системы можно просто задать политику
DROP
для цепочки
FORWARD
:
# iptables -P FORWARD DROP
Цепочка OUTPUT
Цепочка OUTPUT может быть крайне полезной в деле фильтрации исходящего трафика, особено для серверов и других устройств, не использующих веб-браузеры и peer-to-peer программы для соединения с произвольными узлами сети Интернет. Тем не менее, правильная настройка цепочки OUTPUT требует понимания назначения конкретной системы. Наборы правил безопасности для настольной системы, ноутбука, облачного или домашнего сервера будут сильно отличаться.
В этом примере весь исходящий трафик разрешён, поэтому для цепочки
OUTPUT
задаётся политика
ACCEPT
. Этого недостаточно для полной безопасности, но будет работать на большинстве систем.
# iptables -P OUTPUT ACCEPT
Цепочка INPUT
Назначаем политику
DROP
для цепочки
INPUT
на случай, если что-то каким-то образом проскочит мимо наших правил. Лучший способ создать надёжный файрвол — запретить весь трафик, отдельно указав то, что разрешено.
Важно
Если вы вошли в систему через SSH, следующий шаг немедленно прервёт SSH-сеанс. Чтобы этого избежать: (1) добавьте первое правило для цепочки INPUT, приведённое далее в этом же разделе; правило позволит сохранить существующее соединение, (2) добавьте обычное правило, разрешающее входящее SSH-подключение (чтобы иметь возможность восстановить соединение в случае потери связи) и только после этого (3) задайте политику.
# iptables -P INPUT DROP
Все входящие пакеты, предназначенные для этой машины и пришедшие на любой сетевой интерфейс, будут проходить через цепочку
INPUT
. Эта цепочка позволяет принимать только те пакеты, которые действительно нужны.
Первое правило цепочки INPUT будет разрешать трафик установленных соединений и любой новый трафик, относящийся к ним, например, сообщения ICMP об ошибке или эхо-ответы (пакеты, которые хост возвращает, когда его пингуют). ICMP — протокол управляющих сообщений (Internet Control Message Protocol). Некоторые сообщения ICMP имеют важное значение для управления перегрузками и определения MTU, и мы разрешаем их этим правилом:
# iptables -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
Состояние соединения
ESTABLISHED
подразумевает одну из двух ситуаций: либо первичная (
--ctstate NEW
) попытка соединения была ранее одобрена другим правилом, либо соединение уже было активно (например, удалённое SSH-подключение) на момент задания правила.
Второе правило разрешит весь трафик от петлевого (loopback) интерфейса, который необходим многим приложениям и службам:
# iptables -A INPUT -i lo -j ACCEPT
Примечание
Аналогичным образом можно добавить и другие доверенные интерфейсы (например, "enp2s0"), если вы не хотите, чтобы проходящий через них трафик обрабатывался межсетевым экраном. Тем не менее, вы должны понимать, весь этот трафик, вне зависимости от его происхождения, пройдёт дальше, невзирая ни на какие иные настройки.
Третье правило будет отбрасывать все пакеты с состоянием INVALID. Существует четыре категории состояния (state): NEW, ESTABLISHED, RELATED и INVALID. Именно наличие категорий отличает межсетевой экран с контекстной фильтрацией от менее безопасного экрана без оной. Состояния отслеживаются модулями ядра
nf_conntrack_*
, которые загружаются автоматически после добавления правил.
Примечание
Это правило будет отбрасывать все пакеты с неверными заголовками или контрольными суммами, неверными флагами TCP, неправильными ICMP-сообщениями (например, входящее сообщение "порт недостижим", если мы не посылали ничего другому хосту), а также пакеты с неправильным порядковым номером, что может быть признаком атаки. Политика DROP означает отбрасывание пакетов безо всякого ответа, в то время как REJECT отклоняет их вежливо, с уведомлением отправителя. Мы используем DROP, поскольку для INVALID-пакетов не существует подходящего REJECT-ответа и в целом подтверждать их получение нет никакой необходимости.
Пакеты ICMPv6 Neighbor Discovery остаются неотслеживаемыми и всегда классифицируются как INVALID, хотя они по всем параметрам являются годными. Если их необходимо разрешить, то выполните
iptables -A INPUT -p 41 -j ACCEPT
с правами root перед следующей командой.
# iptables -A INPUT -m conntrack --ctstate INVALID -j DROP
Следующее правило разрешает входящие ICMP эхо-запросы (ECHO_REQUEST), известные как
пинги
. Только первый пакет будет считаться относящимся к категории NEW, остальные будут обрабатываться правилом "RELATED, ESTABLISHED". Если компьютер не является маршрутизатором, нет необходимости разрешать какой-либо другой ICMP-трафик с состоянием NEW.
# iptables -A INPUT -p icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
Теперь мы прикрепим TCP- и UDP-цепочки к цепочке INPUT для обработки новых входящих соединений. Если соединение разрешено цепочкой TCP или UDP, оно обрабатывается правилом "RELATED, ESTABLISHED". TCP или UDP цепочки будут либо разрешать новые входящие соединения, либо вежливо отклонять их. Новые TCP соединения должны начинаться с SYN-сегмента.
Примечание
NEW-пакет без SYN-флага — единственный неверный TCP-флаг, который не подпадает под состояние INVALID. Это связано с тем, что данные пакеты редко бывают вредоносными и не должны молча отбрасываться (drop). Вместо этого они отклоняются (reject) с сообщением TCP RESET в соответствии со следующим правилом.
# iptables -A INPUT -p udp -m conntrack --ctstate NEW -j UDP
# iptables -A INPUT -p tcp --syn -m conntrack --ctstate NEW -j TCP
Мы отклоняем TCP-соединения пакетами TCP RESET, а UDP-потоки — сообщениями ICMP "port unreachable", если запрашиваемый порт закрыт. Это имитирует стандартное поведение Linux (в соответствии с RFC), и позволяет отправителю быстро закрыть соединение.
# iptables -A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p tcp -j REJECT --reject-with tcp-reset
Для прочих протоколов мы добавляем последнее правило в цепочку INPUT, чтобы отклонить остальной входящий трафик с ICMP-сообщением "protocol unreachable". Это также соответствует стандартному поведению Linux.
# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
Итоговый файл iptables.rules
Пример файла
iptables.rules
после выполнения всех команд выше:
/etc/iptables/iptables.rules
# Generated by iptables-save v1.4.18 on Sun Mar 17 14:21:12 2013
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:TCP - [0:0]
:UDP - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp-proto-unreachable
COMMIT
# Completed on Sun Mar 17 14:21:12 2013
Файл генерируется и сохраняется командой
# iptables-save -f /etc/iptables/iptables.rules
Данный файл конфигурации можно использовать как исходный для дальнейших настроек в следующих разделах. Если вы настраиваете межсетевой экран удалённо через SSH, перед продолжением добавьте правило, разрешающее новые SSH-подключения (вместо порта 22 выберите нужный):
# iptables -A TCP -p tcp --dport 22 -j ACCEPT
Цепочки TCP и UDP
Цепочки TCP и UDP содержат правила для разрешения новых TCP-соединений и UDP-потоков к определённым портам.
Примечание
Также в эти цепочки можно добавлять правила для разрешения удалённых соединений, таких как SSH, HTTP и других служб, к которым вы желаете иметь удалённый доступ.
Открытие портов для входящих соединений
Разрешить входящие TCP-соединения на порт 80 для веб-сервера (HTTP):
# iptables -A TCP -p tcp --dport 80 -j ACCEPT
Разрешить входящие TCP-соединения на порт 443 для веб-сервера (HTTPS):
# iptables -A TCP -p tcp --dport 443 -j ACCEPT
Разрешить удаленные SSH-соединения (на порт 22):
# iptables -A TCP -p tcp --dport 22 -j ACCEPT
Разрешить входящие TCP/UDP запросы для
DNS-сервера
(порт 53):
# iptables -A TCP -p tcp --dport 53 -j ACCEPT
# iptables -A UDP -p udp --dport 53 -j ACCEPT
Более сложные правила, вроде проверки по нескольким портам, можно найти в
iptables(8)
.
Port knocking
Port knocking — способ открыть извне порты, которые файрвол по умолчанию держит закрытыми. Port knocking заключается в создании последовательности попыток соединений с заранее выбранными закрытыми портами. При получении корректной последовательности "простукиваний" межсетевой экран открывает определенный порт и разрешает соединение. Подробнее см.
Port knocking
.
Защита от спуфинга
Примечание
В файле
/usr/lib/sysctl.d/50-default.conf
параметр
rp_filter
установлен в значение
2
, поэтому в описанных ниже действиях нет необходимости.
Если из внешней сети пришёл пакет с зарезервированным (т.е. локальным) адресом отправителя, то имеет место подмена адреса (address spoofing). Стандартный способ блокирования таких пакетов — установить с помощью sysctl параметр
rp_filter
(Reverse Path Filter) в значение
1
, что включит встроенную в ядро Linux проверку адреса отправителя пакета. Встроенная проверка будет работать лучше, чем отдельные правила iptables на каждый случай. Добавьте в файл
/etc/sysctl.d/90-firewall.conf
(подробнее см.
sysctl
) следующую строку:
net.ipv4.conf.all.rp_filter=1
То же самое можно сделать посредством netfilter, если необходимо ведение статистики и лог-файлов:
# iptables -t raw -I PREROUTING -m rpfilter --invert -j DROP
Примечание
Включать эту функцию одновременно в двух местах не нужно. Реализованная в netfilter проверка вполне удовлетворительна и, кроме того, работает с адресами IPv6.
Для случая асинхронной маршрутизации используйте значение
rp_filter=2
. Флаг
--loose
в модуле
rpfilter
делает то же самое посредством netfilter.
Защита от обнаружения
Если вы хотите сделать вашу машину менее заметной в сети, хорошей идеей будет блокировать некоторые входящие запросы.
Блокирование ping-запросов
Запрос "ping" представляет собой ICMP-пакет, посланный с целью убедиться, что между двумя хостами есть связь. Если сеть в порядке, вы можете безопасно блокировать все ping-запросы. Нужно отметить, что это не сделает ваш компьютер необнаружимым — каждый входящий пакет будет отклоняться, поэтому вы всё ещё будете видны при простом "ping-сканировании" по диапазону IP-адресов посредством
nmap
. Кроме того, нужно иметь в виду, что эта элементарная "защита" усложнит вам жизнь случае возникновения необходимости отладки сети.
Чтобы заблокировать эхо-запросы (echo requests), добавьте следующую строку в файл
/etc/sysctl.d/90-firewall.conf
(подробную информацию можно найти в статье
sysctl
):
net.ipv4.icmp_echo_ignore_all = 1
Больше сведений об этой защите вы найдёте в руководстве
iptables(8)
, а также в документации и примерах на странице
http://www.snowman.net/projects/ipt_recent/
Обман сканеров портов
Сканирование портов производится с целью обнаружения тех из них, которые открыты в настоящий момент. Это позволит атакующему определить запущенные на машине службы и подобрать к ним эксплойты.
Состояние INVALID в правилах iptables "позаботится" обо всех типах сканирования, за исключением сканирований UDP, ACK и SYN (флаги nmap
-sU
,
-sA
и
-sS
соответственно).
ACK-сканирование
не используется для определения открытых портов, но зато покажет порты, защищённые межсетевым экраном. Подобно SYN-пакету в TCP-соединениях с состоянием NEW, каждый пакет ACK-сканирования будет отклонен с отправкой ответа TCP RESET по обратному адресу. Некоторые межсетевые экраны вместо этого просто отбрасывают такие пакеты, что позволяет атакующему определить действующие правила.
Модуль
recent
поможет обмануть остальные типы сканирования портов. Он добавляет хосты к списку недавних соединений, который используется для обнаружения и блокирования попыток атак. Просмотреть списки недавних соединений можно в каталоге
/proc/net/xt_recent/
.
Примечание
Использование модуля resent для защиты от сканирований может привести к тому, что:
Система станет уязвимой к разновидности
DoS-атаки
. Атакующий посылает пакеты с подменёными IP-адресами, чтобы добиться их блокировки вашими службами.
Может оказаться заблокированным обычный IP-адрес, если несколько пакетов с этого адреса на порт получателя будут признаны INVALID модулем conntrack. Чтобы избежать занесения в чёрный список, следует разрешить все пакеты, поступающие на этот порт.
SYN-сканирование
При SYN-сканировании сканер портов посылает синхронизационные пакеты на каждый порт с целью создать TCP-соединение. Если порт закрыт, то возвращается ответ TCP RESET, межсетевой экран просто отбрасывает входящий пакет, а открытый порт возвращает ответ SYN ACK.
Модуль
recent
может использоваться для отслеживания хостов с отклонёнными попытками соединения и возвращения ответа TCP RESET для каждого SYN-пакета, поступившего на открытый порт, как если бы порт был закрыт. Если открытый порт оказался первым в порядке сканирования, то будет возвращён ответ SYN ACK, поэтому приложения вроде ssh следует размещать на нестандартных портах.
Сначала добавьте правило в начало цепочки TCP. Это правило будет отвечать пакетом TCP RESET любому хосту, входившему в список
TCP-PORTSCAN
в течение последних 60 секунд. Флаг
--update
управляет периодическим обновлением списка.
# iptables -I TCP -p tcp -m recent --update --rsource --seconds 60 --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset
Затем необходимо модифицировать правило отклонения TCP-пакетов, чтобы добавлять все хосты с отклонёнными пакетами к списку
TCP-PORTSCAN
:
# iptables -D INPUT -p tcp -j REJECT --reject-with tcp-reset
# iptables -A INPUT -p tcp -m recent --set --rsource --name TCP-PORTSCAN -j REJECT --reject-with tcp-reset
UDP-сканирование
Сканирование UDP схоже со сканированием TCP SYN за исключением того факта, что UDP является протоколом без установления соединения. В нём нет "рукопожатий" и подтверждений. Вместо этого сканер посылает UDP-пакеты на каждый UDP-порт. Закрытые порты должны возвращать сообщение ICMP port unreachable, а открытые не возвращают ничего. Поскольку UDP — "ненадежный" протокол, у сканера нет возможности узнать о потере пакетов, поэтому он посылает серию запросов на каждый порт, с которого не вернулся ответ.
Ядро Linux посылает сообщения ICMP port unreachable довольно медленно, поэтому продолжительность полного UDP-сканирования может превысить 10 часов. Однако часто используемые порты проверяются гораздо быстрее, поэтому хорошей идеей будет применить контрмеры, аналогичные защите от SYN-сканирований.
Сначала добавляем правило отклонения пакетов от хостов из списка
UDP-PORTSCAN
в начало цепочки UDP:
# iptables -I UDP -p udp -m recent --update --rsource --seconds 60 --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
Затем модифицируем правило отклонения пакетов для UDP:
# iptables -D INPUT -p udp -j REJECT --reject-with icmp-port-unreachable
# iptables -A INPUT -p udp -m recent --set --rsource --name UDP-PORTSCAN -j REJECT --reject-with icmp-port-unreachable
Восстановление последнего правила
Если вы применили хотя бы один из способов защиты выше, бывшее последним правило цепочки INPUT более таковым не является. Теперь оно находится перед правилами защиты от сканирования и те по сути бесполезны. Просто удалите (
-D
) это правило, а затем добавьте его снова (
-A
), это переместит его в конец цепочки.
# iptables -D INPUT -j REJECT --reject-with icmp-proto-unreachable
# iptables -A INPUT -j REJECT --reject-with icmp-proto-unreachable
Защита от других типов атак
В статье
sysctl#TCP/IP stack hardening
можно найти описание важных с точки зрения безопасности параметров ядра.
Атака полным перебором
Доступные по внешнему IP-адресу сервисы подвергаются атакам полным перебором довольно часто. Реализовать атаку этого типа несложно, а инструментарий — обширен и доступен. К счастью, существует несколько способов защиты от атак полным перебором. Первый способ заключается в создании правил
iptables
, которые заносят IP-адрес в чёрный список после нескольких попыток установить соединение. При втором способе защиты запускается специализированный демон, который отслеживает лог-файл на предмет неудачных попыток соединения.
Важно
Защита посредством занесения адресов в чёрный список остановит простые атаки, но она полагается на дополнительный демон и успешное логирование (в случае мощной атаки может закончиться свободное место разделе, содержащем каталог
/var
с лог-файлами). Кроме того, узнав ваш IP-адрес, атакующий может посылать пакеты с подменённым адресом отправителя, чтобы добиться вашей блокировки. Элегантное решение этой проблемы заключается в использовании
ключей SSH
.
Приложения
Fail2ban
и (в случае
sshd
)
Sshguard
используются для блокировки IP-адресов при превышении допустимого количества попыток аутентификации. Суть их работы состоит в обновлении правил iptables с целью временно или навсегда воспрепятствовать будущим соединениям атакующих.
Ниже представлен пример правил iptables для предотвращения атак полным перебором на сервис SSH.
# iptables -N IN_SSH
# iptables -N LOG_AND_DROP
# iptables -A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 3 --seconds 10 -j LOG_AND_DROP
# iptables -A IN_SSH -m recent --name sshbf --rttl --rcheck --hitcount 4 --seconds 1800 -j LOG_AND_DROP 
# iptables -A IN_SSH -m recent --name sshbf --set -j ACCEPT
# iptables -A LOG_AND_DROP -j LOG --log-prefix "iptables deny: " --log-level 7
# iptables -A LOG_AND_DROP -j DROP
Большая часть правил очевидна: первое разрешает три попытки соединения в течение 10 секунд, после чего дальнейшие попытки будут отклоняться. Второе — добавляет ограничение на четыре попытки в течение получаса. Дело в том, что атаки полным перебором обычно выполняются медленно и за несколько серий попыток. Дополнительную информацию об этих правилах и их опциях можно найти в оригинальной статье на сайте
compilefailure.blogspot.com
.
Предложенные выше правила могут использоваться для защиты любой службы, но демон SSH нуждается в ней наиболее часто.
Необходимо также убедиться, что правило
-A INPUT -p tcp --dport ssh -m conntrack --ctstate NEW -j IN_SSH
находится в верной позиции в последовательности iptables, перед точкой прикрепления цепочки TCP к цепочке INPUT. Это позволит успешно перехватывать новые попытки установления SSH-соединений. Если вы выполнили все предыдущие шаги в этой статье, порядок правил должен быть следующим:
...
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT
-A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j IN_SSH
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
...
Совет
При проверке правил после настройки реальное занесение в чёрный список может замедлить тесты, что усложнит тонкую настройку. Входящие попытки соединений можно отслеживать посредством команды
cat /proc/net/xt_recent/sshbf
. Чтобы разблокировать собственный IP-адрес во время тестирования, вам понадобятся права root:
echo / > /proc/net/xt_recent/sshbf
.
IPv6
Если вы не используете протокол IPv6, то лучше будет его
отключить
. В противном случае стоит создать соответствующий набор правил межсетевого экрана.
Скопируйте созданные ранее правила для протокола IPv4 и замените все IPv4-адреса на адреса формата IPv6:
# cp /etc/iptables/iptables.rules /etc/iptables/ip6tables.rules
Некоторые правила нужно адаптировать под IPv6. Так, для IPv6 используется обновлённая версия протокола ICMP, и коды ответов при отклонении соединений
--reject-with icmp-port-unreachable
и
--reject-with icmp-proto-unreachable
необходимо преобразовать в коды ICMPv6.
Коды ошибок ICMPv6 перечислены в
RFC 4443
, согласно которому при блокировке межсетевым экраном попыток установления соединения необходимо использовать код
--reject-with icmp6-adm-prohibited
. Это проинформирует удалённую систему о том, что соединение было отклонено брандмауэром, а не прослушивающей порт службой.
Если уведомлять удалённую систему о наличии файрвола нежелательно, то можно отклонить пакет без сообщения:
-A INPUT -j REJECT
Отклонение пакетов по этому правилу будет производиться с сообщением об ошибке
--reject-with icmp6-port-unreachable
. Следует однако отметить, что одной из основных функций приложений-сканеров является как раз обнаружение межсетевых экранов и обмануть их этим правилом не получится.
This article or section needs expansion.
Reason:
Какие особенности ICMPv6 нужно добавить, чтобы привести правила в полное соответствие с правилами IPv4? (Discuss in
Talk:Simple_stateful_firewall#ICMP blocking
)
Следующее правило для протокола IPv6 настроит поведение межсетевого экрана по отношению к новым входящим пингам (ICMP echo requests):
# ip6tables -A INPUT -p ipv6-icmp --icmpv6-type 128 -m conntrack --ctstate NEW -j ACCEPT
Модуль conntrack не отслеживает действия ICMPv6 Neighbor Discovery Protocol (аналог протокола ARP), поэтому необходимо разрешить трафик ICMPv6 вне зависимости от его состояния для всех прилежащих подсетей. Следующее правило нужно вставить после правила отбрасывания некорректных пакетов
--ctstate INVALID
, но перед любыми другими правилами DROP или REJECT. Создаётся по одному правилу на каждую подсеть:
# ip6tables -A INPUT -s fe80::/10 -p ipv6-icmp -j ACCEPT
Если вы желаете включить
DHCPv6
, разрешите входящие соединения на
UDP-порт 546
:
# ip6tables -A INPUT -p udp --sport 547 --dport 546 -j ACCEPT
Поскольку в ядре Linux нет встроенной фильтрации по обратному маршруту (reverse path filter) для протокола IPv6, то стоит включить её посредством ip6tables:
# ip6tables -t raw -A PREROUTING -m rpfilter -j ACCEPT
# ip6tables -t raw -A PREROUTING -j DROP
Сохранение правил
Набор правил межсетевого экрана завершён и осталось только сохранить его в файл, который будет загружаться при каждом запуске системы.
Сохраняем правила IPv4 и IPv6 командами:
# iptables-save -f /etc/iptables/iptables.rules
# ip6tables-save -f /etc/iptables/ip6tables.rules
Итоговый файл ip6tables.rules
Пример файла правил
ip6tables.rules
после выполнения представленных выше команд:
/etc/iptables/ip6tables.rules
# Generated by ip6tables-save v1.8.2 on Sat Apr 20 10:53:41 2019
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
:TCP - [0:0]
:UDP - [0:0]
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -m conntrack --ctstate INVALID -j DROP
-A INPUT -s fe80::/10 -p ipv6-icmp -j ACCEPT
-A INPUT -p udp --sport 547 --dport 546 -j ACCEPT
-A INPUT -p udp -m conntrack --ctstate NEW -j UDP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack --ctstate NEW -j TCP
-A INPUT -p udp -j REJECT --reject-with icmp6-adm-prohibited
-A INPUT -p tcp -j REJECT --reject-with tcp-reset
-A INPUT -j REJECT --reject-with icmp6-adm-prohibited
-A INPUT -p ipv6-icmp -m icmp6 --icmpv6-type 128 -m conntrack --ctstate NEW -j ACCEPT
COMMIT
# Completed on Sat Apr 20 10:53:41 2019
В завершение
включите
и
запустите
службы
iptables.service
и
ip6tables.service
. Проверьте статус служб, чтобы убедиться, что правила загрузились корректно.
Настройка NAT-шлюза
В этом разделе рассмотрена настройка межсетевого экрана для NAT-шлюза. Предполагается, что вы уже прочитали
первую часть
данного руководства и настроили цепочки
INPUT
,
OUTPUT
,
TCP
и
UDP
как было предложено. До этого момента созданные правила относились к таблице
filter
, при настройке NAT-шлюза нам также понадобится таблица
nat
.
Таблица filter
Создание необходимых цепочек
Создадим две новые цепочки —
fw-interfaces
и
fw-open
:
# iptables -N fw-interfaces
# iptables -N fw-open
Цепочка FORWARD
Настройка цепочки
FORWARD
схожа с настройкой цепочки
INPUT
в первой части.
Сначала добавляем правило с модулем
conntrack
, идентичное правилу из цепочки
INPUT
:
# iptables -A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
Затем включаем пересылку для доверенных интерфейсов и пропускаем все пакеты через цепочку
fw-open
:
# iptables -A FORWARD -j fw-interfaces 
# iptables -A FORWARD -j fw-open
Остальные пакеты блокируются с отправкой ICMP-сообщения:
# iptables -A FORWARD -j REJECT --reject-with icmp-host-unreachable
# iptables -P FORWARD DROP
Цепочки fw-interfaces и fw-open
Назначение цепочек
fw-interfaces
и
fw-open
будет объяснено позже, когда мы будем работать с цепочками
POSTROUTING
и
PREROUTING
соответственно в таблице
nat
.
Таблица nat
В этом разделе предполагается, что исходящий интерфейс (с публичным IP-адресом) носит имя
ppp0
. Если ваш интерфейс называется иначе, то во всех приведённых ниже правилах следует заменить название на настоящее.
Цепочка POSTROUTING
Сначала мы должны определить, кому разрешено подключаться к сети Интернет. Предположим, имеется подсеть
192.168.0.0/24
(т.е. в неё входят все адреса в диапазоне 192.168.0.0-255), подключённая к интерфейсу
eth0
. Чтобы разрешить исходящие соединения хостам в этой подсети, настраиваем цепочку
fw-interfaces
в таблице FORWARD:
# iptables -A fw-interfaces -i eth0 -j ACCEPT
Затем необходимо отредактировать все исходящие пакеты, чтобы в поле "адрес отправителя" значился публичный адрес шлюза вместо локального LAN-адреса. Для этого используем таргет
MASQUERADE
:
# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o ppp0 -j MASQUERADE
Не забудьте указать параметр
-o ppp0
, потому что в противном случае сеть не будет функционировать.
Предположим, что есть другая подсеть,
10.3.0.0/16
(с адресами 10.3.*.*), подключённая к интерфейсу
eth1
. Добавляем аналогичные правила:
# iptables -A fw-interfaces -i eth1 -j ACCEPT
# iptables -t nat -A POSTROUTING -s 10.3.0.0/16 -o ppp0 -j MASQUERADE
Наконец, нужно
разрешить пересылку пакетов
(если она ещё не включена).
Хосты данных подсетей теперь могут использовать вашу NAT-систему в качестве шлюза. Возможно, вы также захотите настроить DNS- и
DHCP
-сервер, например,
dnsmasq
или комбинацию
BIND
и
dhcpd
, с целью упрощения настройки разрешения имён (DNS resolving) на клиентских машинах, но эта тема выходит за рамки данного руководства.
Цепочка PREROUTING
В некоторых случаях может понадобиться изменить адрес получателя в заголовке входящего пакета с адреса шлюза на адрес хоста в локальной сети. Для этого нужно настроить созданную ранее цепочку
fw-open
, а также цепочку
PREROUTING
таблицы nat.
Например, чтобы изменить адрес получателя входящих SSH-пакетов (порт 22) на адрес ssh-сервера
192.168.0.5
выполните команды:
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 22 -j DNAT --to 192.168.0.5
# iptables -A fw-open -d 192.168.0.5 -p tcp --dport 22 -j ACCEPT
Во втором примере меняется не только адрес получателя, но и порт. Порт входящего соединения
8000
заменяется на порт
80
веб-сервера по адресу
192.168.0.6
:
# iptables -t nat -A PREROUTING -i ppp0 -p tcp --dport 8000 -j DNAT --to 192.168.0.6:80
# iptables -A fw-open -d 192.168.0.6 -p tcp --dport 80 -j ACCEPT
Настройка для UDP-пакетов производится аналогично.
Сохранение правил
Чтобы сохранить новые правила межсетевого экрана для NAT-шлюза, выполните:
# iptables-save -f /etc/iptables/iptables.rules
При этом поздразумевается, что служба systemd
iptables.service
уже работает, потому что была включена
ранее
.
Смотрите также
Methods to block SSH attacks
— защита от SSH-атак
Using iptables to block brute force attacks
— защита от атак полным перебором
Collection of basic Linux Firewall iptables rules
— примеры базовой настройки iptables
25 Most Frequently Used Linux IPTables Rules Examples
— ещё примеры