Утилита iptables в Ubuntu
Утилита iptables
— это межсетевой экран для операционных систем Linux. С помощью правил iptables
можно разрешать или блокировать прохождение трафика. Когда происходит попытка установления соединения с текущей машиной, iptables
просматривает список правил в списке, чтобы понять, как нужно поступить в этом случае. Если правила нет, то выполняется действие по умолчанию.
Цепочки правил
Набор правил формируется в цепочки, существуют базовые и пользовательские цепочки. Список базовых цепочек:
PREROUTING
— правила в этой цепочке применяются ко всем пакетам, которые поступают на сетевой интерфейс извнеINPUT
— применяются к пакетам, которые предназначаются для самого хоста или для процесса на данном хостеFORWARD
— правила, которые применяются к транзитным пакетам, проходящим через хост, не задерживаясьOUTPUT
— применяются к пакетам, которые сгенерированы самим хостом или процессами на данном хостеPOSTROUTING
— применяются к пакетам, которые должны покинуть сетевой интерфейс данного хоста
Таблицы iptables
Над цепочками правил в iptables
есть еще один уровень абстракции — таблицы. Таблицы предназначены для выполнения разных действий над пакетами, например для модификации или фильтрации:
raw
— предназначена для работы с сырыми пакетами, пока они еще не прошли обработкуmangle
— предназначена для модификации различных заголовков пакетаnat
— обеспечивает работу NAT, если сервер используется в качестве маршрутизатораfilter
— основная таблица для фильтрации пакетов, используется по умолчанию
Принцип работы
Входящий пакет начинает обрабатываться брандмауэром с цепочки PREROUTING
в таблице mangle
. Затем он обрабатывается правилами цепочки PREROUTING
таблицы nat
. На этом этапе проверяется, не требуется ли модификация назначения пакета (DNAT
). Важно сменить назначение сейчас, потому что маршрут пакета определяется сразу после того, как он покинет цепочку PREROUTING
. После этого он будет отправлен на цепочку INPUT
(если целью пакета является этот компьютер) или FORWARD
(если его целью является другой компьютер в сети).
Если целью пакета является другой компьютер, то пакет фильтруется правилами цепочки FORWARD
таблиц mangle
и filter
, а затем к нему применяются правила цепочки POSTROUTING
. На данном этапе можно использовать SNAT/MASQUARADE
(подмена источника/маскировка). После этих действий пакет (если выжил) будет отправлен в сеть.
Если назначением пакета является сам компьютер с брандмауэром, то, после маршрутизации, он обрабатывается правилами цепочек INPUT
таблиц mangle
и filter
. В случае прохождения цепочек пакет передается приложению.
Когда приложение на машине с брандмауэром, отвечает на запрос или отправляет собственный пакет, то он обрабатывается цепочкой OUTPUT
таблицы filter
. Затем к нему применяются правила цепочки OUTPUT
таблицы nat
— для определения, требуется ли использовать DNAT
(модификация назначения). Далее, пакет фильтруется цепочкой OUTPUT
таблицы filter
и выпускается в цепочку POSTROUTING
, которая может использовать SNAT
и QoS
. В случае успешного прохождения POSTROUTING
пакет выходит в сеть.
Утилита iptables
Синтаксис утилиты iptables
:
$ sudo iptables [-t таблица] команда [критерий действие]
Если таблица не указана, подразумевается таблица filter
. Команды могут быть:
-A
(или--append
) — добавить правило в цепочку-D
(или--delete
) — удалить правило из цепочки-I
(или--insert
) — вставить правило в цепочку под указанным номером-L
(или--list
) — вывести все правила для заданной цепочки-F
(или--flush
) — очистить все правила для заданной цепочки (таблицы)-N
(или--new-chain
) — создать новую цепочку-X
(или--delete-chain
) — удалить цепочку-P
(или--policy
) — установить действие по умолчанию для цепочки
Имеются следующие дополнительные опции:
-v
(или--verbose
) — увеличить подробность сообщений, при указании с командой--list
будет выводиться имя интерфейса, параметры правил и маски TOS.-n
(или--numeric
) — выводить ip-адреса и номера портов в числовом виде, предотвращая попытки преобразовать их в символические имена.--line-numbers
— показывать номера строк при отображении списка правил командой--list
(номер строки соответствует позиции правила в цепочке).
Примеры использования утилиты:
$ sudo iptables -F # сбросить все правила в таблице filter
$ sudo iptables -t nat -F # сбросить все правила в таблице nat
$ sudo iptables -L --line-numbers # посмотреть все правила в таблице filter с нумерацией
$ sudo iptables -L -v --line-numbers # посмотреть все правила в таблице filter с нумерацией (подробно)
$ sudo iptables -t nat -L --line-numbers # посмотреть все правила в таблице nat с нумерацией
$ sudo iptables -D INPUT 3 # удалить правило в цепочке INPUT в таблице filter по номеру
$ sudo iptables -I INPUT -p tcp --dport 80 -j ACCEPT # вставить правило в начало цепочки INPUT в таблице filter
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT # добавить правило в конец цепочки INPUT в таблице filter
$ sudo iptables -I INPUT 3 -p tcp --dport 80 -j ACCEPT # вставить правило в третью позицию цепочки INPUT в таблице filter
Поведение по умолчанию
Прежде чем приступать к настройке межсетевого экрана, следует определиться с тем, каким должно быть поведение цепочек правил по умолчанию. Другими словами, что iptables
нужно делать в том случае, если соединение не подпадает ни под одно из сконфигурированных правил?
Изначально все три цепочки таблицы filter
по умолчанию разрешают прием трафика:
$ sudo iptables -L Chain INPUT (policy ACCEPT) target prot opt source destination Chain FORWARD (policy ACCEPT) target prot opt source destination Chain OUTPUT (policy ACCEPT) target prot opt source destination
Если же что-то менялось, а теперь нужно вернуть прежние настройки, то сделать это можно с помощью команд:
$ sudo iptables -P INPUT ACCEPT $ sudo iptables -P OUTPUT ACCEPT $ sudo iptables -P FORWARD ACCEPT
Можно пойти по другому пути и сначала запретить весь трафик, а затем выборочно разрешать его:
$ sudo iptables -P INPUT DROP $ sudo iptables -P OUTPUT DROP $ sudo iptables -P FORWARD DROP
Удаление всех правил
Удаление всех сконфигурированных правил таблицы filter
$ sudo iptables -F
Удаление всех сконфигурированных правил таблицы nat
$ sudo iptables -t nat -F
Удаление всех сконфигурированных правил цепочки INPUT
таблицы filter
$ sudo iptables -F INPUT
Действия с соединениями
После настройки поведения по умолчанию, можно переходить к созданию правил обработки трафика, чтобы iptables
понимал, что делать с конкретным пакетом.
ACCEPT
— пакет покидает данную цепочку и передается в следующуюDROP
— отбросить пакет, пакет не передается в следующую цепочкуREJECT
— отбросить пакет, сообщить отправителю пакета об ошибкеSNAT
— замена ip-адреса источника в пакете, в цепочкахPOSTROUTING
иOUTPUT
таблицыnat
DNAT
— замена ip-адреса назначения в пакете, в цепочкеPREROUTING
таблицыnat
(изредка — вOUTPUT
)LOG
— записать пакет в лог-файл (отправляется демонуsyslog
) и обработать остальными правиламиMASQUERADE
— какSNAT
, но для соединений с динамическим ip-адресом, в цепочкеPOSTROUTING
таблицыnat
MARK
— установить метку на пакет и обработать остальными правиламиCONNMARK
— установить метку на пакеты одной сессии или соединенияRETURN
— возврат из текущей цепочки. Если из цепочкиone
правилом номер 3 пакет был направлен в цепочкуtwo
, то применение к нему в цепочкеtwo
действияRETURN
приведет к его переходу обратно в цепочкуone
, и он продолжит ее прохождение с правила номер 4. Для базовой цепочки к пакету сразу будет применено действие по умолчанию.
Действие MASQUERADE
является частным случаем SNAT
, его основным отличием является то, маскарадинг самостоятельно получает ip-адрес от заданного сетевого интерфейса и не требует его явного указания. Это удобно, если на внешнем интерфейсе используется динамический ip-адрес.
$ sudo iptables -t nat -A POSTROUTING -o ens33 -s 192.168.100.0/24 -j SNAT --to-source 198.51.100.1
$ sudo iptables -t nat -A POSTROUTING -o ens33 -s 192.168.100.0/24 -j MASQUERADE
Критерии для пакетов
Общие критерии — допустимо употреблять в любых правилах, они не зависят от типа протокола и не требуют подгрузки модулей расширения:
-p
(или--protocol
) — используется для указания типа протокола (all
,icmp
,tcp
,udp
)-s
(или--source
) — используется для указания ip-адреса источника; можно указать единственный ip-адрес (10.10.10.10) или диапазон ip-адресов (10.10.10.0/24)-d
(или--destination
) — используется для указания ip-адреса места назначения; можно указать единственный ip-адрес (10.10.10.10) или диапазон ip-адресов (10.10.10.0/24)-i
(или--in-interface
) — интерфейс, с которого был получен пакет, допускается только в цепочкахINPUT
,FORWARD
иPREROUTING
; при отсутствии этого критерия предполагается любой интерфейс-o
(или--out-interface
) — интерфейс, с которого будет отправлен пакет, допускается только в цепочкахOUTPUT
,FORWARD
иPOSTROUTING
; при отсутствии этого критерия предполагается любой интерфейс
Неявные критерии — неявно подгружают модули расширений и становятся доступны при указании критерия --protocol
. Рассмотрим некоторые из них:
-p tcp --sport
(или--source-port
) — исходный порт, с которого был отправлен TCP-пакет. В качестве параметра может указываться номер порта или название сетевой службы. Соответствие имен сервисов и номеров портов можно найти в файле/etc/services
. Номера портов могут задаваться в виде интервала из минимального и максимального номеров.-p tcp --dport
(или--destination-port
) — порт или диапазон портов, на который адресован TCP-пакет. Аргументы задаются в том же формате, что и для--source-port
.-p udp --sport
(или--source-port
) — исходный порт, с которого был отправлен UDP-пакет. В качестве параметра может указываться номер порта или название сетевой службы. Соответствие имен сервисов и номеров портов можно найти в файле/etc/services
. Номера портов могут задаваться в виде интервала из минимального и максимального номеров.-p udp --dport
(или--destination-port
) — порт или диапазон портов, на который адресован UDP-пакет. Аргументы задаются в том же формате, что и для--source-port
.
Явные критерии — требуют явной подгрузки модулей расширения с помощью опции -m
или --match
. Например, если планируется использовать критерий state
, то нужно явно указать -m state
левее используемого критерия. Рассмотрим некоторые из них:
-m conntrack --ctstate STATES
— проверяет признак состояния соединения:NEW
,ESTABLISHED
,RELATED
иINVALID
. СостояниеNEW
подразумевает, что пакет открывает новое соединение или пакет принадлежит однонаправленному потоку. СостояниеESTABLISHED
указывает на то, что пакет принадлежит уже установленному соединению, через которое пакеты идут в обеих направлениях. СостояниеRELATED
указывает на то, что пакет принадлежит уже существующему соединению, но при этом он открывает новое соединение. СостояниеINVALID
подразумевает, что пакет связан с неизвестным потоком или соединением и, возможно содержит ошибку в данных или в заголовке.-m state --state STATES
(устарел, не рекомендуется) — проверяет признак состояния соединения:NEW
,ESTABLISHED
,RELATED
иINVALID
.-m multiport --source-port PORTS
— служит для указания списка исходящих портов, можно указать до 15 различных портов. Названия портов в списке должны отделяться друг от друга запятыми, пробелы в списке недопустимы. Может использоваться только совместно с критериями-p tcp
или-p udp
. Главным образом используется как расширенная версия обычного критерия--source-port
.-m multiport --destination-port PORTS
— служит для указания списка входящих портов, можно указать до 15 различных портов. Названия портов в списке должны отделяться друг от друга запятыми, пробелы в списке недопустимы. Может использоваться только совместно с критериями-p tcp
или-p udp
. Главным образом используется как расширенная версия обычного критерия--destination-port
.-m multiport --port PORTS
— проверяет как исходящий так и входящий порт пакета. Формат аргументов аналогичен критерию--source-port
и--destination-port
. Данный критерий проверяет порты обоих направлений, если задан критерий-m multiport --port 80
— под него попадают пакеты, идущие с порта 80 на порт 80.-m mac --mac-source MAC
— MAC адрес сетевого узла, передавшего пакет, в форматеXX:XX:XX:XX:XX:XX
. Имеет смысл только в цепочкахPREROUTING
,FORWARD
иINPUT
и нигде более.-m iprange --src-range IP-IP
— позволяет указать диапазон ip-адресов источника, например 192.168.1.10-192.168.2.20-m iprange --dst-range IP-IP
— позволяет указать диапазон ip-адресов места назначения, например 192.168.1.10-192.168.2.20-m mark --mark 15
— позволяет выделять пакеты с заданной маркировкой (nfmark
)-m connmark --mark 15
— полностью аналогиченmark
, но проверяет не маркировку пакета (nfmark
), а маркировку соединения (ctmark
)
Критерий состояния соединения
Как сказано выше, многие протоколы требуют двусторонних коммуникаций. Например, если нужно разрешить соединения по SSH, то добавить правила надо будет и в цепочку INPUT
и в цепочку OUTPUT
. Но что, если нужно разрешить только входящие SSH-соединения на сервер (т.е. только возможность подключиться к серверу по SSH)? Разрешит ли добавление правила в цепочку OUTPUT
и исходящие SSH-соединения (т.е. с сервера можно будет подключиться по SSH к другому хосту)?
Для таких случаев используются состояния соединений. Они позволяют описывать двусторонние коммуникации, в которых разрешается установка только соединений определенной направленности. В примере ниже разрешены SSH-соединения, поступающие от хоста 10.10.10.10, но SSH-соединения к этому хосту запрещены. Однако, системе разрешается отправка информации по SSH в случае уже установленного соединения, что делает возможной SSH-коммуникацию между хостами:
$ sudo iptables -A INPUT -p tcp --dport 22 -s 10.10.10.10 -m state --state NEW,ESTABLISHED -j ACCEPT
$ sudo iptables -A OUTPUT -p tcp --sport 22 -d 10.10.10.10 -m state --state ESTABLISHED -j ACCEPT
Пользовательские цепочки
Предположим, что нам нужно обеспечить доступ к определенным портам нашего сервера для всех хостов из подсети 10.134.0.64/26
, кроме двух — 10.134.0.67
и 10.134.0.100
.
$ sudo iptables -F # Очищаем все цепочки таблицы filter
Создаем специальную цепочку для проверки пакетов из нашей подсети
$ sudo iptables -N our_subnet $ sudo iptables -A our_subnet -s 10.134.0.67 -j RETURN # Запрещенный хост — выходим $ sudo iptables -A our_subnet -s 10.134.0.100 -j RETURN # Запрещенный хост — выходим
Всем остальным хостам подсети разрешаем доступ к нужным портам
$ sudo iptables -A our_subnet -p tcp -m multiport --dports 22,53,8080,139,445 -j ACCEPT $ sudo iptables -A our_subnet -p udp -m multiport --dports 53,123,137,138 -j ACCEPT $ sudo iptables -A our_subnet -p icmp --icmp-type 8 -j ACCEPT
Разрешаем пакеты, если соединение уже было установлено ранее
$ sudo iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Все пакеты из нашей подсети отправляем на проверку в цепочку our_subnet
$ sudo iptables -A INPUT -s 10.134.0.64/26 -j our_subnet $ sudo iptables -P INPUT DROP # Что не разрешено — то запрещено $ sudo iptables -P OUTPUT ACCEPT # На выход — можно все
Теперь все новые входящие пакеты, отправленные из нашей подсети 10.134.0.64/26
, отправляются на проверку в цепочку our_subnet
. К пакетам с «запрещенных» хостов применяется операция RETURN
, и они покидают эту цепочку и впоследствии блокируются действием по умолчанию цепочки INPUT
. Пакеты с остальных хостов этой подсети пропускаются в том случае, если они адресованы на порты прокси (8080/tcp
), SSH (22/tcp
), SMB (139,445/tcp
, 137,138/udp
), DNS (53/tcp
, 53/udp
), NTP (123/udp
). Также для этих хостов разрешены ICMP-эхо-запросы (пинги). Все остальные пакеты (включая пакеты не из нашей подсети, пакеты с запрещенных хостов и пакеты на неразрешенные порты) блокируются действием по умолчанию DROP
.
Нетрудно заметить, что в этом простом примере вместо RETURN
можно было использовать и DROP
. Однако, существует понятие «принципа одного запрета». При организации фильтрующих правил в рамках этого принципа, сначала следует серия разрешающих правил, исключения оформляются в виде RETURN
, а все не разрешенные пакеты доходят до конца базовой цепочки и блокируются действием по умолчанию либо последним правилом. Следование этому принципу позволяет достичь гибкости в выборе и смене метода блокирования пакетов. Допустим, нужно сменить блокирующее действие DROP
на REJECT
. Нет ничего проще — просто меняем правило по умолчанию.
Опция –reject-with
Действие REJECT
имеет необязательную опцию --reject-with
, которая может принимать значения
icmp-net-unreachable
— сеть недоступнаicmp-host-unreachable
— узел недоступенicmp-port-unreachable
— порт недоступенicmp-proto-unreahable
— неподдерживаемый протоколicmp-net-prohibited
— сеть запрещенаicmp-host-prohibited
— узел запрещенtcp-reset
— отправляет RST-сообщение отправителю.
RST пакеты используются для закрытия TCP соединений. По умолчанию будет передано сообщение port-unreachable
.
$ sudo iptables -A INPUT -s 10.26.95.20 -j REJECT --reject-with tcp-reset
Маркировка пакетов
Действие MARK
устанавливает метку, которая ассоциирована с определённым пакетом. Допустимо использование только в таблице mangle
. Следует помнить, что метка устанавливается не на сам пакет, а является неким значением для ядра, которое ассоциируется с пакетом. То есть, увидеть данную метку на это пакете на другом хосте — не получится. Для таких целей лучше использовать TOS
, который устанавливает значение в IP-заголовок пакета.
$ sudo iptables -t mangle -A PREROUTING -p tcp --dport 22 -j MARK --set-mark 2
Маркировка соединений
Действие CONNMARK
позволяет установить метку на соединение в целом. Это можно использовать в любой цепочке. Более того, эта маркировка копируется и на соединения, связанные с текущим. Впоследствии можно использовать эту метку для модификации или для маршрутизации пакетов соединения.
Однако, для модификации и маршрутизации могут использоваться только метки, установленные на пакете. Поэтому есть возможность копировать метку соединения на метку пакета. И наоборот — копировать метку пакета на метку соединения.
Опция --set-mark
устанавливает метку на соединение.
$ sudo iptables -t nat -A PREROUTING -p tcp --dport 80 -j CONNMARK --set-mark 4
Опция --save-mark
используется для копирования метки пакета на метку соединения. Например, если мы установили метку на пакет с помощью MARK
, то с помощью --save-mark
можно скопировать её на всё подключение целиком.
$ sudo iptables -t mangle -A PREROUTING --dport 80 -j CONNMARK --save-mark
Опция --restore-mark
используется для копирования метки соединения на метку пакета. Допустимо использование только в таблице mangle
.
$ sudo iptables -t mangle -A PREROUTING --dport 80 -j CONNMARK --restore-mark
Сохранение изменений
Внесенные в цепочки правил изменения пропадут при перезагрузке, так что их нужно сохранить с в файл помощью команды:
$ sudo /sbin/iptables-save > /etc/iptables.rules
$ cat /etc/iptables.rules
# Generated by iptables-save v1.6.1 on Sat Feb 15 11:58:32 2020 *filter :INPUT DROP [0:0] :FORWARD DROP [0:0] :OUTPUT DROP [0:0] -A INPUT -i lo -j ACCEPT -A INPUT -p icmp -j ACCEPT -A INPUT -p udp -m udp --sport 53 -m state --state ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --sport 53 -m state --state ESTABLISHED -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT -A OUTPUT -o lo -j ACCEPT -A OUTPUT -p icmp -j ACCEPT -A OUTPUT -p udp -m udp --dport 53 -j ACCEPT -A OUTPUT -p tcp -m tcp --dport 53 -j ACCEPT -A OUTPUT -p tcp -m tcp --sport 80 -j ACCEPT -A OUTPUT -p tcp -m tcp --sport 443 -j ACCEPT -A OUTPUT -p tcp -m tcp --sport 22 -j ACCEPT -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT COMMIT # Completed on Sat Feb 15 11:58:32 2020
После перезагрузки правила можно восстановить из файла /etc/iptables.rules
с помощью команды:
$ sudo iptables-restore < /etc/iptables.rules
Автозагрузка правил
Понятно, что восстанавливать правила вручную после каждой перезагрузки неудобно. Поэтому устанавливаем пакет iptables-persistent
:
$ sudo apt install iptables-persistent
При установке пакета будет предложено сохранить текущие правила iptables
:
- в файл
/etc/iptables/rules.v4
для протокола IPv4 - в файл
/etc/iptables/rules.v6
для протокола IPv6
Теперь, после каких-либо изменений правил, надо сохранить текущее состояние в файл /etc/iptables/rules.v4
, чтобы это состояние восстановилось после перезагрузки:
$ sudo iptables-save > /etc/iptables/rules.v4
После установки пакета будет добавлена новая служба netfilter-persistent.service
, которая при загрузке системы будет восстанавливать правила iptables
:
$ systemctl status netfilter-persistent.service ● netfilter-persistent.service - netfilter persistent configuration Loaded: loaded (/lib/systemd/system/netfilter-persistent.service; enabled; vendor preset: enabled) Active: active (exited) since Wed 2020-02-05 10:08:52 MSK; 27s ago Main PID: 3769 (code=exited, status=0/SUCCESS) Tasks: 0 (limit: 2317) CGroup: /system.slice/netfilter-persistent.service фев 05 10:08:52 ubuntu-iptables systemd[1]: Starting netfilter persistent configuration... фев 05 10:08:52 ubuntu-iptables systemd[1]: Started netfilter persistent configuration.
iptables-persistent
будет заменен на пакет netfilter-persistent
(сейчас он устанавливается как зависимость при установке iptables-persistent
).
Пример настройки web-сервера
1. Политика ACCEPT для OUTPUT
Первым делом задаем политику по умолчанию:
$ sudo iptables --policy INPUT DROP $ sudo iptables --policy OUTPUT ACCEPT $ sudo iptables --policy FORWARD DROP
Разрешаем трафик через интерфейс loopback
(будет работать ping
для localhost
):
$ sudo iptables -A INPUT -i lo -j ACCEPT
Если подходить к настройке не очень фанатично, то можно разрешить работу протокола ICMP (будут работать ping
и traceroute
):
$ sudo iptables -A INPUT -p icmp -j ACCEPT
ICMP (протокол межсетевых управляющих сообщений) — сетевой протокол, входящий в стек протоколов TCP/IP. В основном ICMP используется для передачи сообщений об ошибках и других исключительных ситуациях, возникших при передаче данных.
Утилита ping
, служащая для проверки возможности доставки IP-пакетов, использует ICMP-сообщения с типом 8 (эхо-запрос) и 0 (эхо-ответ). Утилита traceroute
, отображающая путь следования IP-пакетов, использует ICMP-сообщения с типом 11.
Разрешаем нашему серверу получать ответы от DNS-серверов:
$ sudo iptables -A INPUT -p udp --sport 53 -m state --state ESTABLISHED -j ACCEPT $ sudo iptables -A INPUT -p tcp --sport 53 -m state --state ESTABLISHED -j ACCEPT
source port
53. Кроме того, уточняем — что этот трафик в ответ на запрос с нашего сервера.
Разрешаем входящие подключения к портам HTTP, HTTPS и SSH:
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT $ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT $ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
destination port
80, 443 и 22.
Чтобы можно было устанавливать и обновлять пакеты с помощью утилиты apt
:
$ sudo iptables -A INPUT -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
apt
может отправлять запросы на сервер репозитория. Но ей еще нужно получать ответы, поэтому разрешаем входящий TCP трафик, который идет с source port
80. Кроме того, уточняем — что этот трафик в ответ на запрос с нашего сервера.
Теперь можно проверить добавленные правила командой:
$ sudo iptables -L -v --line-numbers Chain INPUT (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination 1 272 27773 ACCEPT all -- lo any anywhere anywhere 2 22 1848 ACCEPT icmp -- any any anywhere anywhere 3 12 1975 ACCEPT udp -- any any anywhere anywhere udp spt:domain state ESTABLISHED 4 0 0 ACCEPT tcp -- any any anywhere anywhere tcp spt:domain state ESTABLISHED 5 18 2313 ACCEPT tcp -- any any anywhere anywhere tcp dpt:http 6 0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:https 7 2091 140K ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh 8 10 1308 ACCEPT tcp -- any any anywhere anywhere tcp spt:http state ESTABLISHED Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 6 packets, 772 bytes) num pkts bytes target prot opt in out source destination
2. Политика DROP для OUTPUT
В этом случае все правила для цепочки INPUT
будут такими же, но надо еще добавить правила для цепочки OUTPUT
. Итак, первым делом задаем политику по умолчанию:
$ sudo iptables --policy INPUT DROP $ sudo iptables --policy OUTPUT DROP $ sudo iptables --policy FORWARD DROP
Разрешаем трафик через интерфейс loopback
:
$ sudo iptables -A INPUT -i lo -j ACCEPT $ sudo iptables -A OUTPUT -o lo -j ACCEPT
Разрешаем работу протокола ICMP (будут работать ping
и traceroute
):
$ sudo iptables -A INPUT -p icmp -j ACCEPT $ sudo iptables -A OUTPUT -p icmp -j ACCEPT
Разрешаем нашему серверу отправлять запросы DNS-серверам:
$ sudo iptables -A OUTPUT -p udp --dport 53 -j ACCEPT $ sudo iptables -A OUTPUT -p tcp --dport 53 -j ACCEPT
Разрешаем нашему серверу получать ответы от DNS-серверов:
$ sudo iptables -A INPUT -p udp --sport 53 -m state --state ESTABLISHED -j ACCEPT $ sudo iptables -A INPUT -p tcp --sport 53 -m state --state ESTABLISHED -j ACCEPT
Разрешаем входящие подключения к портам HTTP, HTTPS и SSH:
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT $ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT $ sudo iptables -A INPUT -p tcp --dport 22 -j ACCEPT
Разрешаем отправлять пакеты с портов HTTP, HTTPS и SSH:
$ sudo iptables -A OUTPUT -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT $ sudo iptables -A OUTPUT -p tcp --sport 443 -m state --state ESTABLISHED -j ACCEPT $ sudo iptables -A OUTPUT -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
Чтобы можно было устанавливать и обновлять пакеты с помощью утилиты apt
:
$ sudo iptables -A INPUT -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT $ sudo iptables -A OUTPUT -p tcp --dport 80 -j ACCEPT
apt
по протоколу HTTPS — нужно добавить еще два правила для порта 443.
Теперь можно проверить добавленные правила командой:
$ sudo iptables -L -v --line-numbers Chain INPUT (policy DROP 6 packets, 623 bytes) num pkts bytes target prot opt in out source destination 1 53 5876 ACCEPT all -- lo any anywhere anywhere 2 0 0 ACCEPT icmp -- any any anywhere anywhere 3 16 2808 ACCEPT udp -- any any anywhere anywhere udp spt:domain state ESTABLISHED 4 0 0 ACCEPT tcp -- any any anywhere anywhere tcp spt:domain state ESTABLISHED 5 35 3480 ACCEPT tcp -- any any anywhere anywhere tcp dpt:http 6 0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:https 7 936 63201 ACCEPT tcp -- any any anywhere anywhere tcp dpt:ssh 8 50 92195 ACCEPT tcp -- any any anywhere anywhere tcp spt:http state ESTABLISHED Chain FORWARD (policy DROP 0 packets, 0 bytes) num pkts bytes target prot opt in out source destination Chain OUTPUT (policy DROP 6 packets, 772 bytes) num pkts bytes target prot opt in out source destination 1 53 5876 ACCEPT all -- any lo anywhere anywhere 2 0 0 ACCEPT icmp -- any any anywhere anywhere 3 16 1244 ACCEPT udp -- any any anywhere anywhere udp dpt:domain 4 0 0 ACCEPT tcp -- any any anywhere anywhere tcp dpt:domain 5 18 22936 ACCEPT tcp -- any any anywhere anywhere tcp spt:http state ESTABLISHED 6 0 0 ACCEPT tcp -- any any anywhere anywhere tcp spt:https state ESTABLISHED 7 657 80901 ACCEPT tcp -- any any anywhere anywhere tcp spt:ssh state ESTABLISHED 8 69 4613 ACCEPT tcp -- any any anywhere anywhere tcp dpt:http
Настройка маршрутизатора
Есть компьютер с двумя сетевыми интерфейсами. Первый интерфейс eth0
смотрит в интернет и имеет белый ip-адрес 128.68.35.23
. Второй интерфейс eth1
смотрит в локальную сеть и имеет ip-адрес 192.168.100.1
.
Доступ в интернет (SNAT)
Этот компьютер должен обеспечивать выход в интернет для всех компьютеров из локальной сети 192.168.100.0/24
. По умолчанию транзитный трафик отключен, так что редактируем файл /etc/sysctl.conf
:
$ sudo nano /etc/sysctl.conf
net.ipv4.ip_forward=1
Чтобы настройки вступили в силу:
$ sudo sysctl -p
Теперь настраиваем iptables
:
$ sudo iptables -P FORWARD DROP
$ sudo iptables -A FORWARD -i eth1 -o eth0 -s 192.168.100.0/24 -j ACCEPT $ sudo iptables -A FORWARD -i eth0 -o eth1 -d 192.168.100.0/24 -j ACCEPT
Тем самым разрешили ходить транзитным пакетам для нашего диапазона ip адресов, а всё остальное запретили. Теперь настроим SNAT (подмена адреса источника), что позволит всем компьютерам сети выходить в интернет, используя единственный ip-адрес 128.68.35.23
.
$ sudo iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -o eth0 -j SNAT --to-source 128.68.35.23
Доступ внутрь сети (DNAT)
Внутри сети есть компьютер с ip-адресом 192.168.100.2
, к которому нужен доступ по RDP из интернета. Все запросы в нашу локальную сеть приходят на интерфейс eth0
с ip-адресом 128.68.35.23
. Мы может отобрать те их них, которые идут на порт 3389
и отправить их на 192.168.100.2
(DNAT — подмена адреса получателя):
$ sudo iptables -t nat -A PREROUTING -i eth0 -p tcp -m tcp --dport 3389 -j DNAT --to-destination 192.168.100.2
-p tcp|udp|icpm
или --protocol
— неявно подгружаются модули расширений и становятся доступны критерии --sport
и --dport
. Но иногда это не срабатывает и тогда модули нужно загрузить явно, то есть указать -m tcp|udp|icpm
.
Дополнительно
- Викиучебник: iptables
- IPTABLES — руководство: часть 1 — основы IPTABLES
- IPTABLES — руководство: часть 2 — управление IPTABLES
- IPTABLES — руководство: часть 3 — параметры правил
- Linux: IPTABLES — руководство: часть 4 — цели для правил
- Основы iptables для начинающих. Часть 1. Общие вопросы
- Основы iptables для начинающих. Часть 2. Таблица filter
- Основы iptables для начинающих. Часть 3. Таблица nat
Поиск: CLI • Linux • Ubuntu • Конфигурация • Настройка • iptables • NAT • Файервол • Брандмауэр • Цепочка • Таблица • filter