Настройка iptables скриптом

Изображение пользователя Mike.

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

На форуме уже некое количество раз поднимался вопрос, как рулить иптаблей, в частности в подшивке есть мануал. Но по большему счету у этих мануалов есть один общий нюанс - они все мало подходят для корпоративного регулирования трафика и больше расчитаны на домашнего пользователя. В частности, в мануале из подшивки все регулирование ведется двумя инструментами: iptables-save (для сохранения правил в конфиг) и iptables-restore (соответственно, для восстановления из конфига). Сам по себе метод неплохо, особенно в домашнем секторе, где один раз настроил и забыл, а в конфиге содержится цепочек раз-два и обчелся. Но если контора у вас большая, а конфиг достигает в размене нескольких мегабайт, там сам черт ногу сломит, а не то, что системный администратор. Поэтому на выручку нам придет bash-скрипт, в котором мы и будем все конфигурировать. Этот метод хорош помимо наглядности еще и тем, что позволяет использовать переменные, циклы и вводить некоторую отладочную информацию о ходе выполнения скрипта, чего нет в вышеозначенном методе.

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

Вводная информация.

Допустим, у нас есть контора с некоторым количеством компов, интернет в которой раздается через линуксовый роутер. На роутере установлено две сетевые карты, одна из которых смотрит в интернет, а вторая - во внутреннюю сеть.
внутренняя сеть вида 10.1.0.0/24
eth0=xxx.xxx.xxx.xxx  # Ваш внешний IP-адрес
eth1=10.1.0.1         # Внутренний IP-адрес роутера.

Предположим, что на роутере у нас живет почтовый сервер, ssh, прокся и днс. Соответственно, это у нас будут заюзаны порты 25 и 110 для почты, 3128 для прокси, 22 для ssh.

Кроме того, в конторе есть некоторый набор серверов и пользователей с разным уровнем допуска в интернет.

Теперь можно приступить к ваянию самого скрипта.

Подгрузка необходимых модулей ядра

Тут все стандартно. Если вам для работы нужен какой-то модуль, подгружается он командой /sbin/modprobe имя_модуля. Какие модули для работы будут вам нужны, вам виднее. Подгружайте по своему усмотрению.

Очистка таблиц

Для того, чтобы завести новые правила, для начала надо сбросить все старые. Делаем это нехитрым набором команд:
iptables -F
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -t nat -F
iptables -X
iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Мы очистили все таблицы, сбросили имеющиеся подключения и разрешили loopback. Фактически, после этого роутер готов для приема новых правил.

Разрешаем icmp

Наверняка вам захочется занятся любимым делом - попинговать яндекс =). Ну и попинговать сам роутер заодно. Поэтому разрешаем ходить icmp-пакетам.
iptables -A INPUT -p icmp -j ACCEPT
iptables -A OUTPUT -p icmp -j ACCEPT
iptables -A FORWARD -p icmp -j ACCEPT

Разрешаем обновлять время контроллерам домена

Предположим, у вас в конторе есть пара контроллеров домена, которые страсть как хотят обновлять время. Пусть их адреса будут 10.1.0.3 и 10.1.0.4. Чтобы не катать для каждого контроллера свой набор правил, нам поможет цикл.
TimeServer="aaa.aaa.aaa.aaa bbb.bbb.bbb.bbb"   # вместо aaa.aaa.aaa.aaa и bbb.bbb.bbb.bbb введите адреса любимых серверов времени!
LocTimeServs="10.1.0.3 10.1.0.4"
for tm in $TimeServer; do
    for locts in $LocTimeServs; do
        iptables -A FORWARD -p udp -i eth1 -o eth0 -s $locts -d $tm --dport 123 -j ACCEPT
        iptables -A FORWARD -p udp -o eth1 -i eth0 -d $locts -s $tm --sport 123 -j ACCEPT
    done
done
Думаю, удобство и наглядность использования циклов очевидны.

Разрешаем почтовому серверу слать и принимать почту

Порты у нас стандартные - 25 и 110, так что ничего мудрить не будем:
MailPorts="25 110"
for mp in $MailPorts; do
    iptables -A INPUT -p tcp --dport $mp -j ACCEPT
    iptables -A OUTPUT -p tcp --sport $mp -j ACCEPT
done
Тут мы открыли доступ к почтовым портам как изнутри сети, так и извне (почту слать/получать мы же хотим). Напомню, что разрешения по подсетям, кому можно, а кому нет, настраиваются не тут, а в конфиге почтового сервера.

Разрешения на обращения к прокси-серверу

С проксей дело обстоит примерно так же, как с почтой, за исключением того, что обращение на проксёвые порты мы дадим только для внутренней сети (мы же не хотим, чтобы через нас гулял кто попало).
iptables -A INPUT -p tcp -i eth1 -s 10.1.0.0/24 --dport 3128 -j ACCEPT
iptables -A OUTPUT -p tcp -o eth1 -d 10.1.0.0/24 --sport 3128 -j ACCEPT

Доступ на роутер по SSH

Допустим, вы админ-паранойик, и желаете, чтобы на роутер попасть можно было исключительно изнутри сети и только с вашей машины. Допустим, IP-адрес вашего компа - 10.1.0.10.
iptables -A INPUT -p tcp -i eth1 -s 10.1.0.10 --dport 22 -j ACCEPT
iptables -A OUTPUT -p tcp -o eth1 -d 10.1.0.10 --sport 22 -j ACCEPT

Остальные гуляют лесом.

Доступ админу куда угодно

Вы же бородатый одмин и хотите свободно ходить в инторнеты куда угодно, а не по общеофисным правилам доступа? Значит, нужно нарисовать себе такой доступ!
iptables -A FORWARD -s 10.1.0.10 -j ACCEPT
iptables -A FORWARD -d 10.1.0.10 -j ACCEPT

Доступ к icq

Дадим всему офису посидеть в ютненькой асечке.
LoginICQServ="...................."   # Сюда следует вставить IP-адреса асечных серверов через пробел (по образцу настройки времени)
IcqPorts="5190"
for icqserv in $LoginICQServ; do
    for icq in $IcqPorts; do
        iptables -A FORWARD -p tcp -o eth1 -i eth0 -s 10.1.0.0/24 -d $iсqserv --dport $icq -j ACCEPT
        iptables -A FORWARD -p tcp -i eth1 -o eth0 -d 10.1.0.0/24 -s $iсqserv --sport $icq -j ACCEPT
    done
done

Выпустим бухгалтерию в клиент-банки

Ну и напоследок дадим бухам доступ к их клиент-банкам. Для каждого банка правила нужно рисовать отдельно.
BankIP="............................"    # Ну вы поняли. Список адресов банка через пробел
BuhIP="......................."     # список IP-адресов бухов, которым можно в эти банки ходить. Так же через пробел.
ClientBankPorts=".............."    # То же самое, но для списка портов, на которые ломится клиент-банк.
for bankadr in $BankIP; do
    for buh in $BuhIP; do
        for ClPorts in $ClientBankPorts; do
            iptables -A FORWARD -p tcp -s $buh -d $bankadr --dport $ClPorts -j ACCEPT
            iptables -A FORWARD -p tcp -d $buh -s $bankadr --sport $ClPorts -j ACCEPT
        done
    done
done

Ну и напоследок, собственно, сам форвардинг:
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source xxx.xxx.xxx.xxx   # вместо иксов ваш внешний IP-адрес

echo "1" > /proc/sys/net/ipv4/ip_forward

Ну а теперь соберем все это безобразие в единый скрипт. Создадим файл /etc/network/rc.firewall (или с любым другим понравившимся вам именем, это несущественно). В сам файл пихаем все нужные нам правила:

Этот файл делаем исполняемым. Прописываем путь до него в любой другой скрипт, выполняемый при запуске системы.

Если есть что-то прокомментировать, добавить, поправить или спросить - добро пожаловать!

Комментарии (16)

0
Cyber100 - 22 Май, 2013 - 17:48
Изображение пользователя Cyber100.

cкрипт бухгалтерский в клиент-банки не "взлетит"!)
ошибочка допущена. описочка, вернее;)

0
Mike - 22 Май, 2013 - 20:09
Изображение пользователя Mike.

Хех, и не только в нем =) Что нашел - пофиксил.

0
Flameflower - 23 Май, 2013 - 06:42
Изображение пользователя Flameflower.

А не пробовал ferm?
P.S. Не особо понятно для чего -P OUTPUT DROP ?

0
Mike - 23 Май, 2013 - 07:15
Изображение пользователя Mike.

ferm не пробовал. Доверия к разного рода "автоматизировалкам" скриптов нет.
-P OUTPUT DROP для сброса установленных подключений, это же очевидно. Говоря точнее, поумолчанию мы сбрасываем все пакеты по цепочками INPUT, OUTPUT и FORWARD. Или ты предпочитаешь, чтобы бот, который коим-то образом поселился на твоем роутере, продолжал спамить во вне? =)

0
Flameflower - 26 Май, 2013 - 09:50
Изображение пользователя Flameflower.

Просто через ferm некоторые вещи написать гораздо быстрее. Но это дело вкуса.
-P OUTPUT DROP - устанавливает политику обработки трафика, не попавшего ни под одно правило.
Т.е. трактовать это надо так: Отбросить весь трафик, который явно не разрешен.
Т.е. мы получаем то, что сам маршрутизатор никуда ходить не может.
Хотя на мой взгляд при -P INPUT DROP запрещать еще и исходящий - это уже избыточно.
Соединения с состоянием ESTABLISHED рулит немного другая штука. Conntrack зовется.
P.S. У каждого свой уровень паранойи. :)

+2
Mike - 26 Май, 2013 - 11:05
Изображение пользователя Mike.

Т.е. мы получаем то, что сам маршрутизатор никуда ходить не может.
Да, именно этого мы и добиваемся. У нормально параноящего админа политика по умолчанию: запрещено все то, что явно не разрешено.
Даже если сбрасывать OUTPUT - избыточно, то я предпочитаю тезис "лучше перебдить, чем недобдить".
Про conntrack знаю, но у меня не было желания расписывать подробный мануал, иначе расписывать пришлось бы все ну ооочень подробно. Как я писал в самом стартмесседже - это всего лишь шпаргалка, а не учебник.

0
sweet325 - 24 Сентябрь, 2013 - 10:56
+1
Mike - 24 Сентябрь, 2013 - 16:16
Изображение пользователя Mike.

нужен ли в энтерпрайзе весь этот костыллинг и улучшайзинг? Лично мое мнение - как корове седло. Хотя, должно быть, кому-то нравится.

0
Sutry - 3 Октябрь, 2013 - 14:18

Не проще-ли какой-нить firehol пользовать для настройки правил?
Текстовый конфиг, человеческий синтаксис...

0
Mike - 3 Октябрь, 2013 - 14:27
Изображение пользователя Mike.

чем проще?
в чем бесчеловечность bash-скриптинга?
Как написал в комментариях к статье про файршор на швабре:
"недостаток всех таких тулзов (включая shorewall) в том, что когда возникает необходимость добавить «нестандартное» правило, котрое слишком заковыристо для скрипта —
ВСЕ правила файрвола приходится переписывать вручную, с нуля."

Без понимания самой сути фильтрации пакетов все эти свистелки и пердлелки для иптабли - простая шелуха. Если на домашнем роутере на пару ноутбуков и телефон интернет раздавать - да, сгодится. А в ентерпрайзе всему этому не место.

0
Sutry - 3 Октябрь, 2013 - 14:43

А кто говорил о бесчеловечности шелла?
firehol уже готовый велосипед, впрочем как и толпа других. И у него есть возможность запуска с отредактированным конфигом с подтверждением. Тоесть вносим изменения в правил в его конфиг, рестартуем с параметром try - и потом после того как увидели строку приглашения - пишем в ней commit. Если не видим - значит что-то настроили не так - и сессия была сброшена - и через шелл на удаленном сервере работать нельзя. Правила через 30 сек (время наввод строки подтверждения, которой он не дождался) - фаервол перезапускается со СТАРЫМ конфигом. А мы смотрим где наш "ляп" был. При настройке на удаленных серверах бывает актуальным...

Впрочем чем юниксы и хороши - любую задачу можно тысячей способов сделать. Кому что нравится. Я просто поделися своей мыслю по этому поводу (на серверах принципиально никаких вэб-интерфейсов не держу, а многие "нативные" конфиги и синтаксис - ногу сломиш.)

Все на-любителя.
Кто-то моется мылом, а кто-то гель для душа предпочитает. И каждый прав :) Не прав тот - кто не моется вообще ;) впрочем тоже вопрос спорный

0
Mike - 3 Октябрь, 2013 - 14:50
Изображение пользователя Mike.

Для удаленных роутеров нужны прямые руки, а не велосипеды =)
В прочем, доводилось мне поднимать за 2000 километров роутеры по телефону, когда на том конце была какая-нибудь девочка, которая умела внимательно слушать, что ей говорят, и мастерски пользоваться клавиатурой =)

0
smartass - 3 Октябрь, 2013 - 15:07
Изображение пользователя smartass.

Прописываем путь до него в любой другой скрипт, выполняемый при запуске системы.
Обьясните нубу, а разве обязательно каждый раз при запуске системы выполнять эти правила? Разве нет места, куда можно прописать правила и они просто будут работать без всяких автозагрузок?

0
Mike - 3 Октябрь, 2013 - 16:00
Изображение пользователя Mike.

в любой операционной системе ничего просто так не запускается. Если что-то запустилось и работает, значит оно где-то для этого прописано. В данном случае эти правила прописываются в скрипте, который привязывается к какому-нибудь запускаемому при старте системы конфигу или скрипту.

0
Гость - 20 Ноябрь, 2015 - 19:57

Спасибо за статью, все по полочкам разложено. Если можно, два вопроса:
1. А как быть, если нужно пробросить порт в локалку? например, веб-сервер в локалке за роутером.
2. Если нужно обратиться к этому веб-серваку из локальной сети используя внешний IP ?

0
Mike - 21 Ноябрь, 2015 - 18:40
Изображение пользователя Mike.

1) допустим, внешний IP у нас x.x.x.x, а внутренний, где веб-сервер - у.у.у.у, тогда проброс выглядит так:
iptables -t nat -A PREROUTING -p TCP -d х.х.х.х --dport 80 -j DNAT --to-destination у.у.у.у:80
2) чтобы изнутри локалки обратиться к внутреннему веб-серверу, нужно обращаться на внешний IP-адрес, команда из п.1 перенаправит все внутрь.

Отправить комментарий

CAPTCHA на основе изображений
Введите цифры