Тема: man iptables
Настройка межсетевого экрана Iptables
/Кулаков Дмитрий <mailto:morda89@list.ru>/
2005.11.18
Я думаю, что каждый пользователь Linux задавал себе вопрос "Где в Linux
межсетевой экран". Когда-то этот вопрос встал и передо мной. При
обнаружении iptables, я долго не мог понять, что с ним делать. Но со
временем я стал немного разбираться, научился писать правила. В этом мне
помогла хорошая статья Оскара Андерсона в переводе Андрея Киселева
(http://www.opennet.ru/docs/RUS/iptables/). Сразу скажу, что эта статья
довольно-таки сложна, сразу по ней ничему не научишься. Тем более не у
всех есть время читать, разбираются, вдаватся во все тонкости. Поэтому я
и написал эту статью. Здесь я попытаюсь рассказать, как настраивать
iptables и писать к нему правила фильтрации.
Итак сначала не помешает изучить принцип работы межсетевого экрана
Iptables: Когда пакет приходит на наш межсетевой экран, то он сперва
попадает на сетевое устройство, перехватывается соответствующим
драйвером и далее передается в ядро. Далее пакет проходит ряд таблиц и
затем передается либо локальному приложению, либо переправляется на
другую машину.
В Iptables используется три вида таблиц:
1. Mangle - обычно эта цепочка используется для внесения изменений в
заголовок пакета, например для изменения битов TOS и пр.
2. Nat - эта цепочка используется для трансляции сетевых адресов
(Destination Network Address Translation). Source Network Address
Translation выполняется позднее, в другой цепочке. Любого рода
фильтрация в этой цепочке может производиться только в
исключительных случаях.
3. Filter - здесь производится фильтрация трафика. Помните, что все
входящие пакеты, адресованные нам, проходят через эту цепочку,
независимо от того с какого интерфейса они поступили.
Соответственно, нас интересует третья таблица Filter. В этой таблицы
имеются три встроенные цепочки:
1. INPUT - для входящих пакетов.
2. FORWARD - для проходящих через данную машину к другой.
3. OUTPUT - для исходящих.
Пакет, проходящий через эти цепочки, исходя из правила может быть
пропущен (ACCEPT) или отброшен (DROP).
Iptables можно настраивать разными способами:
1. с помощью webmin - web-интерфейс для настройки системы;
2. программой Guarddog (http://www.simonzone.com/software/guarddog/),
представляющей собой KDE-интерфейс для редактирования настроек
стенки путем установки/снятия галочек;
3. с помощью программы, которая так и называется - Iptables.
Последней мы и будем пользоваться.
Программа Iptables позволяет редактировать правила через терминал путем
ввода команд.
Немного о написании правил:
Каждое правило -- это строка, содержащая в себе критерии, определяющие,
подпадает ли пакет под заданное правило, и действие, которое необходимо
выполнить в случае выполнения критерия. В общем виде правила
записываются примерно так:
iptables [-t table] command [match] [target/jump]
Нигде не утверждается, что описание действия (target/jump) должно стоять
последним в строке, однако, такая нотация более удобочитаемая. Как бы то
ни было, но чаще всего вам будет встречаться именно такой способ записи
правил.
Если в правило не включается спецификатор |-t table|, то по умолчанию
предполагается использование таблицы |filter|, если же предполагается
использование другой таблицы, то это требуется указать явно.
Спецификатор таблицы так же можно указывать в любом месте строки
правила, однако более или менее стандартом считается указание таблицы в
начале правила.
Далее, непосредственно за именем таблицы, должна стоять команда. Если
спецификатора таблицы нет, то команда всегда должна стоять первой.
Команда определяет действие |iptables|, например: вставить правило, или
добавить правило в конец цепочки, или удалить правило и т.п.
Раздел |match| задает критерии проверки, по которым определяется
подпадает ли пакет под действие этого правила или нет. Здесь мы можем
указать самые разные критерии - IP-адрес источника пакета или сети,
IP-адрес места назначения, порт, протокол, сетевой интерфейс и т.д.
Существует множество разнообразных критериев.
И наконец |target| указывает, какое действие должно быть выполнено при
условии выполнения критериев в правиле. Здесь можно заставить ядро
передать пакет в другую цепочку правил, "сбросить" пакет и забыть про
него, выдать на источник сообщение об ошибке и т.п.
И вот мы напрямую подошли к написанию правил. Возможно в некоторых
дистрибутивах уже есть готовые правила, но они не всегда корректно
написаны. А в некоторых их вовсе нет.
Если в вашем дистрибутиве уже есть правила фильтрации, то они должны
находится в каталоге |/etc/init.d/| и называться |rc.firewall| или
|rc.fw|. В принципе вы их можете удалить, так как ниже я публикую свой
|rc.firewal|l и попытаюсь подробно описать каждое правило.
#!/bin/sh
# Задаем некоторые переменные:
# Переменная, задающая путь к файлу запуска iptables.
IPT="/sbin/iptables"
# Ваш сетевой интерфейс. Это нужно, чтобы не писать в правилах одно и тоже.
INET_IFACE="ppp0"
# Номера непривилегированных портов
UNPRIPORTS="1024:65535"
start_fw()
{
# Включить перенаправление пакетов через ядро.
echo 1 > /proc/sys/net/ipv4/ip_forward
# Сбросить правила и удалить цепочки.
$IPT -F
$IPT -X
# Политики по умолчанию.
$IPT -P INPUT DROP
$IPT -P FORWARD ACCEPT
$IPT -P OUTPUT DROP
# Разрешаем прохождение любого трафика по интерфейсу обратной петли.
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
# Запрещаем любые новые подключения с любых интерфейсов, кроме lo к компьютеру.
$IPT -A INPUT -m state ! -i lo --state NEW -j DROP
# Если интерфейс не lo, то запрещаем входить в список его адресов.
$IPT -A INPUT -s 127.0.0.1/255.0.0.0 ! -i lo -j DROP
# Отбрасывать все пакеты, которые не могут быть идентифицированы и поэтому не могут иметь определенного статуса.
$IPT -A INPUT -m state --state INVALID -j DROP
$IPT -A FORWARD -m state --state INVALID -j DROP
# Принимать все пакеты, которые инициированы из уже установленного соединения, и имеющим признак ESTABLISHED.
# Состояние ESTABLISHED говорит о том, что это не первый пакет в соединении.
$IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
# Предупреждаю вас о туповатых провайдерах, которые назначают IP адреса, отведенные IANA для локальных сетей.
# Например адреса 10.X.X.X. Для этого надо установить правило, пропускающие трафик с этих серверов, ранее цепочки INPUT.
$IPT -t nat -I PREROUTING -i $INET_IFACE -s 10.0.0.1/32 -j ACCEPT
# Эти правила предохраняют от некоторых типов атак:
# SYN наводнение.
# Приводит к связыванию системных ресурсов, так что реальных обмен данными становится не возможным.
$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
$IPT -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP
# UDP наводнение
# Службы использующие UDP, очень часто становятся мишенью для атак с целью вывода системы из строя.
$IPT -A INPUT -p UDP -s 0/0 --destination-port 138 -j DROP
$IPT -A INPUT -p UDP -s 0/0 --destination-port 113 -j REJECT
$IPT -A INPUT -p UDP -s 0/0 --source-port 67 --destination-port 68 -j ACCEPT
$IPT -A INPUT -p UDP -j RETURN
$IPT -A OUTPUT -p UDP -s 0/0 -j ACCEPT
# ICMP - перенаправление
# ICMP - сообщение указывает системе изменить содержимое таблиц маршрутизации с тем, что бы направлять
# пакеты по более короткому маршруту. Может быть использовано взломщиком для перенаправления вашего трафика через свою машину.
$IPT -A INPUT --fragment -p ICMP -j DROP
$IPT -A OUTPUT --fragment -p ICMP -j DROP
# Разрешаем ICMP соединение. Значительная часть ICMP используется для передачи сообщений о
# том, что происходит с тем или иным UDP или TCP соединением.
$IPT -A INPUT -p icmp -m icmp -i $INET_IFACE --icmp-type source-quench -j ACCEPT
$IPT -A OUTPUT -p icmp -m icmp -o $INET_IFACE --icmp-type source-quench -j ACCEPT
# Разрешаем себе ping наружу - нас же не попингуешь - пакеты отбрасываются.
$IPT -A INPUT -p icmp -m icmp -i $INET_IFACE --icmp-type echo-reply -j ACCEPT
$IPT -A OUTPUT -p icmp -m icmp -o $INET_IFACE --icmp-type echo-request -j ACCEPT
# Разрешаем передачу пакета - некорректный параметр - используется, если в заголовке пакета содержится недопустимая запись,
# или если контрольная сумма заголовка не соответствует контрольной сумме, указанной передающим узлом.
$IPT -A INPUT -p icmp -m icmp -i $INET_IFACE --icmp-type parameter-problem -j ACCEPT
$IPT -A OUTPUT -p icmp -m icmp -o $INET_IFACE --icmp-type parameter-problem -j ACCEPT
# Запрещаем подключение к X серверу через сетевые интерфейсы.
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport 6000:6063 -j DROP --syn
# Прописываем порты, которые открыты в системе, но которые не должны быть открыты на сетевых интерфейсах:
# $IPT -A INPUT -p tcp -m tcp -m multiport -i $INET_IFACE -j DROP --dports #порта
$IPT -A INPUT -p tcp -m tcp -m multiport -i $INET_IFACE -j DROP --dports 783
$IPT -A INPUT -p tcp -m tcp -m multiport -i $INET_IFACE -j DROP --dports 3310
$IPT -A INPUT -p tcp -m tcp -m multiport -i $INET_IFACE -j DROP --dports 10000
# DNS сервер имен разрешаем.
$IPT -A OUTPUT -p udp -m udp -o $INET_IFACE --dport 53 --sport $UNPRIPORTS -j ACCEPT
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 53 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p udp -m udp -i $INET_IFACE --dport $UNPRIPORTS --sport 53 -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport 1024:65353 --sport 53 -j ACCEPT
# Разрешаем AUTH-запросы на удаленные сервера, на свой же компьютер - запрещаем.
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 113 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 113 -j ACCEPT ! --syn
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport 113 -j DROP
# Открываем некоторые порты:
# SMTP клиент (25)
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 25 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 25 -j ACCEPT ! --syn
# POP3 клиент (110)
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 110 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 110 -j ACCEPT ! --syn
# IMAP4 клиент (143)
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 143 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 143 -j ACCEPT ! --syn
# SSH клиент (22)
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 22 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 22 -j ACCEPT ! --syn
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 22 --sport 1020:1023 -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport 1020:1023 --sport 22 -j ACCEPT ! --syn
# FPT клиент (21)
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 21 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 21 -j ACCEPT ! --syn
# HTTP/HTTPS клиент (80, 443)
$IPT -A OUTPUT -p tcp -m tcp -m multiport -o $INET_IFACE --sport $UNPRIPORTS -j ACCEPT --dports 80,443
$IPT -A INPUT -p tcp -m tcp -m multiport -i $INET_IFACE --dport $UNPRIPORTS -j ACCEPT --sports 80,443 ! --syn
# Разрешаем finger, whois, gorper, wais. Traceroute - разрешаем себе, к нам не проломятся - запрещено. Telnet
# запретил, чтобы соблазна не было передавать пароли прямым текстом.
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 20 -j ACCEPT
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 20 --sport $UNPRIPORTS -j ACCEPT ! --syn
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport $UNPRIPORTS --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport $UNPRIPORTS -j ACCEPT ! --syn
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 23 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 23 -j ACCEPT ! --syn
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 79 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 79 -j ACCEPT ! --syn
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 43 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 43 -j ACCEPT ! --syn
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 70 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 70 -j ACCEPT ! --syn
$IPT -A OUTPUT -p tcp -m tcp -o $INET_IFACE --dport 210 --sport $UNPRIPORTS -j ACCEPT
$IPT -A INPUT -p tcp -m tcp -i $INET_IFACE --dport $UNPRIPORTS --sport 210 -j ACCEPT ! --syn
$IPT -A OUTPUT -p udp -m udp -o $INET_IFACE --dport 33434:33523 --sport 32769:65535 -j ACCEPT
# Разрешаем прохождение DHCP запросов через iptables. Нужно, если IP адрес динамический.
$IPT -A OUTPUT -p udp -m udp -o $INET_IFACE --dport 67 --sport 68 -j ACCEPT
$IPT -A INPUT -p udp -m udp -i $INET_IFACE --dport 68 --sport 67 -j ACCEPT
}
case "$1" in
start) echo -n "Starting firewall: iptables"
start_fw
echo "."
;;
stop) echo -n "Stopping firewall: iptables"
iptables -F
iptables -X
echo "."
;;
save) echo -n "Saving firewall: iptables"
iptables-save > /etc/rules-save
echo "."
;;
restart) echo -n "Restarting firewall: iptables"
iptables -F
iptables -X
cat /etc/rules-save | iptables-restore
echo "."
;;
reload|force-reload) echo -n "Reloading configuration files for firewall: iptables"
echo "."
;;
*) echo "Usage: /etc/init.d/rc.iptables start|stop|restart|reload|force-reload"
exit 1
;;
esac
exit 0
Ну вот и все. Выше рассмотрена настройка Iptables для домашней машины.
Сохраните этот скрипт, сделайте его выполняемым и поместите в
|/etc/init.d/|; если там уже есть файл |rc.firewall|, удалите его,
выполнив команду из этого каталога:
$ update-rc.d -f rc.firewall remove
Дальше сделайте, чтобы новый скрипт инициализации запускался во время
загрузки:
$ update-rc.d new.rc.iptables start 40 S . stop 89 0 6 .
Теперь правила Iptables вступают в силу во время загрузки. Если вы
хотите остановить Iptables:
$ /etc/init.d/rc.iptables stop
Для сохранения правил в /etc/rules-save
$ /etc/init.d/rc.iptables save
Для нового запуска Iptables:
$ /etc/init.d/rc.iptables start
Скорее всего эта статья будет периодически обновятся. Да и пора самим
учится писать правила. А если вы серьезно решите изучить Iptables
обращайтесь к этой статье: http://www.opennet.ru/docs/RUS/iptables/.
Добавлено спустя 1 минуту 35 секунд:
Роутер -это просто.
Вадим Федоров
Хочется поделиться опытом подключения локальной сети к интернету. Надо сказать что на эту тему написано множество статей и мне бы хотелось их обобщить и на реальном примере показать как это можно осуществить.
И так, поставим задачу:
1. Есть интернет по выделеной линии через модем с последовательным интерфейсом.
2. Провайдер выдал вам всего один IP-адрес
Надо обеспечить пользователей локальной сети интернетом.
Для решения этой задачи будем использовать компьютер, который будет являться шлюзов в интернет с операционной системой Linux с ядром семейства 2.4.x. В моем случае использовался
дистрибутив ASPLinux 7.3
Для начала настроим сетевую карту. Для этого поспользуемся утилитой netconf. После её запуска мы увидем следующее меню:
Выберем раздел "Host name and IP network devices", в результате мы нечто подобное:
В поле "Host name + domain" нам надо указать имя нашего локального домена, которое может быть любым.
"Config mode" выбираем режим настройка в ручную "Manual". В полях "IP address" и "Netmask" соответственно указываем IP адрес нашей машины и маску сети. Параметры "Net device" - имя сетевой карты и "Kernel module" - имя модуля ядра, как правило указываются при инсталяции ситемы, так что их изменять не стоит.
Сетевая плата настроена далее следует настроить соединение через последовательный интерфейс по протоколу PPP. Для этого напишим простенький скрипт provaider.sh, который будет постоянно проверять если у нас соединение с провайдером, если такового нет, то он будет пытаться его установить:
#!/bin/sh
#
#
while :
do
if [ -f /var/lock/LCK..ttyS0 ] # Проверяем используется ли порт ttyS0
then
sleep 1 #
else
# Если порт не используется, то тогда запускаем демона pppd
/usr/sbin/pppd /dev/ttyS0 115200 logfile /dev/null
# Параметры pppd у различных провайдеров могут быть различные, приведенный
# вариант является наиболее общим.
# Если не сработает, то звоните в службу технической поддержки:)))
fi
sleep 1
done
Устанавливаем соответствующие права доступа и запускаем скрипт, в результате у нас должен будет появиться интерфейc ppp0. Для того чтобы это проверить воспользуемся командой ifconfig, которая позволяет просмотреть список активных сетевых интерфесов машины на что она должна будет сказать нечто похожее на:
eth0 Link encap:Ethernet HWaddr 02:03:42:11:33:72
inet addr:192.168.0.1 Bcast:192.168.0.0 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:11847295 errors:0 dropped:0 overruns:0 frame:0
TX packets:428597 errors:0 dropped:0 overruns:0 carrier:0
collisions:1615 txqueuelen:100
Interrupt:12 Base address:0x7000
ppp0 Link encap:Point-to-Point Protocol
inet addr:123.23.34.5 P-t-P:123.23.34.6 Mask:255.255.255.255
UP POINTOPOINT RUNNING NOARP MULTICAST MTU:1500 Metric:1
RX packets:93036 errors:20 dropped:0 overruns:0 frame:0
TX packets:101168 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:3
Посмотрим таблицу машрутизации командой route -n.
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
123.23.34.5 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0
192.168.0.0 0.0.0.0 255.255.255.0 UG 0 0 0 eth0
Чтобы в случае если сервер будет перезагружен, соединение было установлено автоматически добавим следующею строчку в файл rc.local, расположенный в директории /etc/: provaider.sh &
Соединение установлено, в таблице машрутизации мы увидели две сети, одна смотрит во внешний мир, вторая наша локальная. Теперь нам следует настроить шлюз по умолчанию и NAT - сетевое преобразование адресов, чтобы все локальные пользователи ходили через один IP адрес, выданный провайдером. Команды, реализующее вышесказанное, поместим в файл /etc/ppp/ip-up.local, который будет автоматически выполняться каждый раз когда будет установлено соединение через ppp.
route add default gw 123.23.34.5 dev ppp0 # устанавливает шлюз по умолчанию
modprobe ip_tables #
modprobe ip_conntrack #
modprobe ip_conntrack_ftp # Подгружаем необходимые модули
modprobe ip_conntrack_irc #
modprobe iptable_nat #
modprobe ip_nat_ftp #
modprobe ip_nat_irc #
iptables -F; iptables -t nat -F; iptables -t mangle -F # Очищаем правила iptables
iptables -t nat -A POSTROUTING -o ppp0 -s 192.168.0.0/24 -j SNAT --to-source 123.23.34.5 # Организуем NAT
echo "1" > /proc/sys/net/ipv4/ip_forward # Включаем пересылку пакетов в ядре
Теперь выключим и включим заново модем. Если все было правильно сделано, то если снова выполнить команду route -n мы увидем:
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
123.23.34.5 0.0.0.0 255.255.255.255 UH 0 0 0 ppp0
192.168.0.0 0.0.0.0 255.255.255.0 UG 0 0 0 eth0
0.0.0.0 123.23.34.5 0.0.0.0 UG 0 0 0 ppp0
Теперь можно настроить клиенские машины под Windows это делается так: Панель управления->Сеть->TCP/IP->сетевая плата.
В графе шлюз пропишем адрес в локальной сети нашего роутера, т.е. 192.168.0.1 Также здесь следует указать IP адреса DNS серверов провайдера.
Вот собственно и все настройка роутера под Linux. В заключение я бы порекомендовал почитать "Masquerading Made Simple HOWTO" и посетить сайты www.netfilter.org и www.opennet.ru, где вы сможете найти массу полезного об iptables и о много другом.
Добавлено спустя 4 минуты 15 секунд:
Выложил по просьбам Dig'а и Brebera'а.
З.Ы. Огромное спасибо за статьи Venom'у.