Главная > Программы Настройка фаервола с помощью iptables за пять минутЯ несколько раз сталкивался с тем, что даже неглупые в общем-то люди делают совершенно непростительные ошибки. Например, открывают всему интернету порт, на котором крутится база данных. Часто так бывает у начинающих DevOps, которые всю жизнь писали код, а теперь в их обязанности входит еще и настройка серверов. В сети есть хорошие туториалы по базовой настройке фаервола в Linux и других *nix, но часто это простыни на множество экранов. Так что, надеюсь, этот более лаконичный туториал кому-нибудь пригодится.
Небольшое замечание по терминологии. Фаервол, встроенный в ядро Linux, называется Netfilter, а iptables — утилита для управления этим фаерволом. Многие ошибочно полагают, что фаервол называется iptables. Это не так. Говоря что-нибудь наподобие «я фильтрую пакеты с помощью iptables», вы показываете окружающим свою безграмотность. Вообще, какие примерно задачи можно решать с помощью Netfilter:
Отмечу, что утилита iptables мне лично первое время казалась исключительно неудобной по сравнению с ipfw во FreeBSD. К счастью, поработав с ней какое-то время, все это множество флагов вроде -A, -D, -j и прочих становятся привычны, так что, наберитесь терпения. Рассмотрим основные команды. Показать все правила: # iptables -L -n Вы можете заметить, что в Netfilter есть какие-то «цепочки» (chains) — как минимум INPUT, OUTPUT и FORWARD. У меня лично на машине есть еще и цепочка DOCKER. На первое время можно думать о первых двух, как обо всем входящем и исходящем трафике соответственно, а об остальных временно забыть. Велика вероятность, что они вообще никогда вам не понадобятся. Удалить все правила: # iptables -F Изменить политику (поведение по умолчанию) цепочки: # iptables -P INPUT DROP # iptables -P INPUT ACCEPT Запретить доступ с хоста/подсети: # iptables -A INPUT -s 123.45.67.89 -j DROP # iptables -A INPUT -s 123.45.0.0/16 -j DROP Также можно использовать доменные имена: # iptables -A INPUT -s example.ru -j DROP Запрет исходящих соединений: # iptables -A OUTPUT -d 123.45.67.89 -j DROP В правилах можно использовать отрицания: # iptables -A INPUT ! -s 123.45.67.89 -j DROP Удаление правила по его номеру в цепочке: # iptables -D INPUT 1 Удаление правила на основе того, что оно делает: # iptables -D INPUT -s 123.45.67.89 -j DROP Опция -p указывает на протокол. Можно использовать all, icmp, tcp, udp или номер протокола из /etc/protocols. Флаг --sport указывает порт, с которого был прислан пакет, а --dport указывает порт назначения: # iptables -A INPUT -p tcp --sport 80 -j ACCEPT # iptables -A INPUT -p tcp --dport 80 -j ACCEPT Вставка (insert) правила в начало цепочки: # iptables -I INPUT ... Или можно указать конкретную позицию: # iptables -I INPUT 3 ... Сохранить правила: # iptables-save > /etc/iptables.rules Восстановить правила: # iptables-restore < /etc/iptables.rules Теперь рассмотрим несколько практических примеров. Так, например, выглядит эмуляция нетсплита в тесте, проверяющем поведение приложения, в котором используется Akka Cluster: (node1, s"iptables -A INPUT -s $node2 -j DROP")
run(node1, s"iptables -A INPUT -s $node3 -j DROP")
run(node1, s"iptables -A OUTPUT -d $node2 -j DROP")
run(node1, s"iptables -A OUTPUT -d $node3 -j DROP")
Восстановление происходит точно так же, только флаг -A заменяется на флаг -D. Другой пример. Требуется выяснить, какие порты прослушиваются на машине, и закрыть лишние. Заходим на машину и говорим: # netstat -tuwpln Пример вывода: Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address Foreign Address State PID/Prog name
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 3210/nginx
tcp 0 0 0.0.0.0:4369 0.0.0.0:* LISTEN 1789/epmd
tcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 797/sshd
tcp 0 0 127.0.0.1:5432 0.0.0.0:* LISTEN 990/postgres
Nginx и SSHd смотрят в интернет, это нормально. PostgreSQL слушает только локальный интерфейс, поэтому с ним тоже проблем нет. А вот epmd торчит наружу (можно проверить telnet’ом с другой машины), и это никуда не годится. Можно закрыть только порт 4369. Как это сделать, было показано выше. Или можно пойти еще дальше и запретить все соединения извне на порт 81 и старше: # iptables -A INPUT -m multiport \ -p tcp --dports 81:65535 ! -s 127.0.0.0/8 -j DROP Здесь используется расширение multiport, позволяющее указывать диапазоны портов. Проверяем, что все работает. Если ОК, сохраняем правила: # iptables-save > /etc/iptables.rules Чтобы правила подхватывались при загрузке системы, создаем новый файл #!/bin/sh
iptables-restore < /etc/iptables.rules
exit 0
… и говорим: # chmod +x /etc/network/if-pre-up.d/iptables Проверено, что этот способ работает в Ubuntu 14.04 LTS. В Debian тоже должно работать. Дополнительные материалы для тех, кто хочет знать больше о Netfilter: Главная > Программы |