Скрипт настройки IPTABLES - заготовка

Январь 30, 2009
от Павел Медников

Один из читателей обратился ко мне за консультацией по поводу конфигурирования Linux-сервера. Часть вопросов касались конфигурирования брандмауэра. Ниже предлагаю вашему вниманию скрипт, который я использую в качестве начальной конфигурации уже несколько лет. Просто беру эту заготовку с базовым функционалом и начинаю дополнять его своими правилами в зависимости от требований клиента.

Это самое тривиальное, что можно придумать: просто NAT для всех компьютеров локальной сети + запрет на входящие соединения. Удостоверившись, что все работает, можно корректировать скрипт под нужды конкретного заказчика.

Итак, начнем…

Подразумевается, что вы уже знакомы с синтаксисом IPTABLES и принципами фильтрации пакетов. Если же нет, рекомендую сперва ознакомиться с соответствующим руководством.

Ниже приведены команды, снабженные комментариями. Вы их можете смело выбрасывать. Каждое правило является терминирующим, т.е. если проходящий пакет попадает под условия, описанные в правиле, правило будет применено к пакету, и дальнейшая обработка пакета прекратится, т.е. пакет будет либо пропущен на “следующий уровень” - цепочку Netfilter, где к нему будут применяться следующие правила, либо отброшен.

ACCEPT означает, что мы принимаем пакет, REJECT - не пропускаем и посылаем его отправителю соответствующее уведомление, DROP - просто игнорируем пакет.

После того как ваши правила будут полностью отлажены, не забудьте сохранить конфигурацию средствами iptables, чтобы она восстановилась после очередной перезагрузки.

Скрипт написан для интерпретатора bash

#!/bin/bash

Создадим переменные, описывающие нашу конфигурацию.

Начнем с описания IP-адресов и интерфейсов, которым они присвоены. Названия говорят сами за себя INET_IP и INET_IFACE - для внешнего, LAN_IP и LAN_IFACE - для внутреннего. В скрипте участвуют INET_IP1 и INET_IFACE1, поскольку подразумевается, что внешних адресов и интерфейсов может быть несколько.  LAN_RANGE отвечает за описание адресного пространства вашей сети. LO_IFACE и LO_IP отвечает за loopback-интерфейс.

INET_IP1=”xxx.xxx.xxx.xxx”
INET_IFACE1=”eth0″

LAN_IP=”192.168.0.1″
LAN_IFACE=”eth1″

LAN_RANGE=”192.168.0.0/24″

LO_IFACE=”lo”
LO_IP=”127.0.0.1″

В переменной ip будет храниться путь, ведущий к исполняемому файлу iptables. Это сделано исключительно ради нашего удобства, чтобы не прописывать каждый раз длинную команду.

ip=”/sbin/iptables”

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

#/sbin/modprobe ip_tables
#/sbin/modprobe ip_conntrack
#/sbin/modprobe iptable_filter
#/sbin/modprobe iptable_nat
#/sbin/modprobe ipt_state

Сбросим все правила, существующие в системе. Это нужно для того, чтобы все введенные ранее правила (верные или ошибочные) были удалены, после чего новая конфигурация будет написана с чистого листа.

$ip -F -t filter
$ip -F -t nat
$ip -F -t mangle
$ip -F

Разрешаем форвардинг.  Просто записываем в файл /proc/sys/net/ipv4/ip_forward единичку, что разрешает операционной системе, передавать IP-пакеты из одной сети в другую. Без этого NAT работать не будет.

echo “1″ > /proc/sys/net/ipv4/ip_forward

Устанавливаем политики по умолчанию. Все входящие пакеты по умолчанию запретим (будем разрешать только отдельные соединения), форвардинг разрешим полностью, исходящие пакеты тоже разрешим. Это не совсем правильно с точки зрения безопасности, но вы всегда можете исправить ситуацию и изменить политику. Но учтите, что придется прописывать правила для соединения каждого нужного типа.

$ip -P INPUT DROP
$ip -P OUTPUT ACCEPT
$ip -P FORWARD ACCEPT

Опишем правила для входящих соединений. Первая строчка запрещает IP-пакеты без флага SYN (что сигнализирует о новом соединении), но имеющих состояние NEW - это не даст злоумышленнику сымитировать уже установленное соединение и обмануть брандмауэр. Вторая строчка разрешает внутреннему интерфейсу принимать пакеты изнутри локальной сети. Третья строчка делает тоже самое для loopback-интерфейса.


$ip -A INPUT -p tcp ! –syn -m state –state NEW -j DROP
$ip -A INPUT -p all -i $LAN_IFACE -s $LAN_RANGE -j ACCEPT
$ip -A INPUT -p all -i $LO_IFACE -j ACCEPT

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

$ip -A INPUT -p all -d $INET_IP1 -m state –state ESTABLISHED,RELATED -j ACCEPT
$ip -A INPUT -p all -j DROP

Предположим, у вас внутри сети стоит терминальный сервер Windows (tcp-порт 3389), доступ к которому вы хотите открыть для всех пользователей интернета. Для этого перед строкой  $ip -A INPUT -p all -j DROP нужно будет добавить правило, разрешающее прохождение tcp-пакетов на соответствующий порт (однако, этого недостаточно для того, чтобы пользователи смогли подключиться к серверу терминалов - нужно еще перенаправить соединение на соответствующий адрес в локальной сети, что сделаем позже):

$ip -A INPUT -p tcp -i $INET_IFACE1 -s 0/0 -d $INET_IP1 –dport 3389 -j ACCEPT

Если же в хотите разрешить доступ к серверу терминалов только для одного IP-адреса YYY.YYY.YYY.YYY (например, адреса другого офиса или своего домашнего выделенного IP), то правило будет выглядеть как:

$ip -A INPUT -p tcp -i $INET_IFACE1 -s YYY.YYY.YYY.YYY -d $INET_IP1 –dport 3389 -j ACCEPT

Если вам вздумается разрешить соединение всем, кроме адреса YYY.YYY.YYY.YYY, то такое правило будет иметь вид:

$ip -A INPUT -p tcp -i $INET_IFACE1 -s ! YYY.YYY.YYY.YYY -d $INET_IP1 –dport 3389 -j ACCEPT

Иногда нам может понадобиться запретить какие-то соединения всем пользователям локальной сети. Допустим, это будет служба ICQ, работающая по tcp-порту 5190. Запретим соединение с ней всем пользователям сети:

$ip -A INPUT -p tcp -i $LAN_IFACE -s $LAN_RANGE -d 0/0 –dport 5190 -j REJECT (или DROP - как вам угодно)

Такое правило просто не пропустит соединение с ICQ-серверами через внутренний интерфейс. Если нам понадобится разрешить использование ICQ только Горячо Любимому Народом Кормильцу и Поильцу генеральному директору (или еще кому-либо), чей IP адрес будет 192.168.0.100, то перед приведенным выше правилом в скрипте нужно будет вставить строку:

$ip -A INPUT -p tcp -i $LAN_IFACE -s 192.168.0.100 -d 0/0 –dport 5190 -j ACCEPT

Однако, вернемся к основному скрипту. Разрешим все исходящие пакеты для всех интерфейсов (как я уже говорил, это не совсем правильно, но вы в будущем всегда сможете модифицировать скрипт нужным образом).

$ip -A OUTPUT -p all -j ACCEPT

PREROUTING - действия с пакетами, осуществляемые до процедуры маршрутизации.  В нашем случае, правила, относящиеся к таблице PREROUTING, используются для “публикации” служб, находящихся за брандмауэром. В качестве примера реализуем проброс портов на сервер терминалов Windows (о нем мы говорили выше), расположенного на 192.168.0.200 с любого IP.

$ip -t nat -A PREROUTING -p tcp -i $INET_IFACE1 -s 0/0 -d $INET_IP1 –dport 3389 -j DNAT –to-destination 192.168.0.200:3389

Вернемся к основному скрипту. Разрешаем маршрутизацию пакетов из локальной сети в интернет и обратно. В этой секции разрешаются пакеты, чьим отправителем являются машины внутри сети, а также пакеты снаружи, относящиеся к уже установленным соединениям

$ip -A FORWARD -p all -s $LAN_RANGE -d ! $LAN_RANGE -j ACCEPT
$ip -A FORWARD -p all -m state –state ESTABLISHED,RELATED -j ACCEPT

Собственно NAT: подменяем адрес отправителя из локальной сети на внешний адрес шлюза

$ip -t nat -A POSTROUTING -o $INET_IFACE1 -s $LAN_RANGE -d ! $LAN_RANGE -j SNAT –to-source $INET_IP

Вот и все базовые настройки. Осталось лишь дополнить ее нужными вам правилами. Надеюсь, представленный вашему вниманию скрипт поможет вам упростить процедуру настройки iptables на каждом новом сервере. Желаю удачи!

О методологии разработки правил для брандмауэров вы можете прочитать в моей статье “Основы настройки брандмауэров.”

Также общие сведения о встроенном в ядре Linux пакетном фильтре Netfilter, управляемом при помощи команд IPTABLES, можно прочитать здесь.


2 Ответовна «Скрипт настройки IPTABLES - заготовка »

  1. Marat на Апрель 12, 2009 из 15:52

    Интересно было почитать, т.к. я ещё новичек в этом деле.
    Только вопрос, зачем при фильтрации входящих пакетов задавать правило:
    $ip -A INPUT -p all -j DROP
    когда у нас стоит политика по умолчанию:
    $ip -P INPUT DROP

  2. Павел Медников на Апрель 12, 2009 из 23:01

    На самом деле, никакого глубинного смысла в дублировании строчек нет. Просто я привык сначала ставить дефолтные политики для цепочек, а потом править их.

Написать ответ

Вы должны войти в систему, чтобы оставить комментарий.

lvovtoday.ru psy-rovno.ru

 

Сентябрь 2010
Пн Вт Ср Чт Пт Сб Вс
« Июнь    
 12345
6789101112
13141516171819
20212223242526
27282930