Возможно, это не законченный вариант статьи. Шпаргалка будет обновляться, по мере того как я буду узнавать что-то новое или находить ошибки.
Iptables - утилита командной строки для управления брандмауэром netfilter ядра
Linux >=2.4
.
В книге "Unix и Linux Руководство системного администратора" дается следующее описание iptables
:
Утилита
iptables
применяет к сетевым пакетам упорядоченные цепочки правил. Наборы цепочек образуют таблицы и используются для обработки определенных видов трафика.
По умолчанию используется таблица
filter
. Цепочки правил в этой таблице используются для пакетной фильтрации сетевого трафика
Ручная настройка, особенно впервые, вызывает значительные затруднения, авторы указанной книги этого не отрицают.
iptables
включает следующие таблицы:
filter
- фильтрация сетевого трафикаnat
- управление преобразованием сетевых адресовmangle
- модификация и замена содержимого сетевых пакетов вне контекста NAT
и фильтрации пакетовРассматривать мы будем именно filter
, которая является таблицей по умолчанию для всех команд утилиты iptables
, если иное не сказано явно.
Цепочка - это упорядоченный набор правил.
Цепочки бывают базовые/встроенные и пользовательские (можно создать самому).
К базовым цепочкам относятся:
INPUT
- входящий трафик (адресованный локальному хосту)FORWARD
- транзитный трафик поступающий на локальную машину с целью передачи его на другую машину (трафик передаваемый в docker
контейнер тоже будет считаться транзитным), при этом транзитный трафик проходит в обоих направлениях (с текущей машины на другую и с другой машины на текущую)OUTPUT
- исходящий из локального хоста трафикВ новую цепочку можно направлять пакеты чтобы подвергуть их анализу правил. Например для отладки правил или настройки особого движения пакетов как это сделано в
Docker
.
Правило - состоит из условия/критерия (если нет значит применяется ко всему трафику) действия (может не быть) и счетчика (для учета пакетов попавших под правило).
Условия:
-p
- протокол (TCP
, UDP
, ICMP
, ALL
)-s
- ip адрес источника (можно с маской 10.0.0.0/24
), допускается отрицание (т.е. все кроме) -s ! 10.0.0.0/24
-d
- ip адрес получателя (аналогично -s
)-i
- интерфейс с которого пришел пакет (только для INPUT
, FORWARD
, PREROUTING
), например ens3
, допускается указать ens+
что означает все имена интерфейсов начинающиеся с заданной строки, допускается отрицание -i ! ens+
-o
- интерфейс локального хоста, из которого выходит трафик (только для OUTPUT
, FORWARD
, PREROUTING
)--sport
- порт с которого был отправлен TCP
/UDP
пакет (допускаются имена служб из /etc/services
), поддерживаются диапазоны вида 20:80
что значит от 20
до 80
порта, так же можно опустить одно из значений :80
(от 0 до 80) или 20:
(от 20 до 65535), отрицание поддерживается даже к диапазонам --sport ! 20:80
--dport
- аналогично --sport
только речь идет про порт, которому адресован пакет--icmp-type
- тип ICMP
сообщения (номер или название), поддерживается отрицание. RFC 792 или iptables --protocol icmp --help
-m mac --mac-source
- MAC
адрес устройства передавшего пакет, поддерживается отрицание-m state --state
- состояние соединения:
INVALID
- неизвестное соединение, возможно ошибочноеNEW
- новое соединениеESTABLISHED
- уже установленное соединениеRELATED
- пакет принадлежит уже существующему соединению, но он отправляется по новому-m ttl
- Time To Live:
--ttl-eq N
- TTL
пакета равен N
--ttl-lt N
- TTL
пакета меньше N
--ttl-gt N
- TTL
пакета больше N
Действия:
ACCEPT
- пакет принят в текущей таблицеDROP
- пакет сбрасывается и перестает движение в системеLOG
- пакет журналируется и продолжает дальнейшие движение по цепочке правил и таблицам (рассмотрим ниже)REJECT
- аналогично DROP
только отдает сообщение об ошибке на хост отправителя (работает на всех цепочках таблицы filter
):
--reject-with
- тип ответа, RFC 793 или iptables -j REJECT -h
RETURN
- возврат пакета в вышестоящую цепочку для применения действия по умолчанию, при отсутствии вышестоящей цепочки применится действие по умолчаниюПравила
iptables
действуют до перезагрузки системы, так что если было сделано что-то не так, можно перезагрузить машину и правилаiptables
будут сброшены.
Справка вызывается стандартно:
$ sudo iptables -h
А так можно просмотреть таблицу filter
в табличном виде со статистикой и нумерацией правил:
$ sudo iptables -vnL --line-numbers
Это скриншот правил таблицы filter
для vpn
сервера, здесь видно что:
INPUT
политика по умолчанию DROP
, в итоге было отброшено 78606 пакетов (4536кб)FORWARD
политика по умолчанию тоже DROP
, но пакетов подходящих под правила не былоOUTPUT
политика по умолчанию ACCEPT
и через эту цепочку прошло 347 млн. пакетов (59гб)Также можно распечатать правила:
$ sudo iptables -S
Вывод:
-P INPUT DROP
-P FORWARD DROP
-P OUTPUT ACCEPT
-A INPUT -p udp -m udp --dport 1194 -j ACCEPT
-A INPUT -i tun+ -j ACCEPT
-A INPUT -p udp -m udp --dport 53 -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i tun+ -j ACCEPT
-A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
Добавить правило (разрешить весь трафик с tun
интерфейсов) в конец цепочки INPUT
(-A
, --append
):
$ sudo iptables -A INPUT -i tun+ -j ACCEPT
Вставить правило в позицию 2 цепочки INPUT
(-I
, --insert
):
$ sudo iptables -I INPUT 2 -i lo -j ACCEPT
Установить политику по умолчанию DROP
для цепочки INPUT
(-P
, --policy
):
$ sudo iptables -P INPUT DROP
Создание новой цепочки правил:
$ sudo iptables -N LOGGING
Предположим что для цепочки INPUT
политика по умолчанию DROP
, это значит что все входящие пакеты будут отброшены, но нам нужен некоторый входящий трафик.
Разрешим трафик на локальный DNS
сервер, без этого могут быть долгие подключения по ssh
:
$ sudo iptables -A INPUT -p udp -m udp --dport 53 -j ACCEPT
Разрешим движение трафика из интерфейсов создаваемых Docker
(при политиках по умолчанию DROP
, контейнеры не смогут общаться с другими интерфейсами):
$ sudo iptables -A INPUT -i br+ -j ACCEPT
Разрешим любой входящий трафик из localhost
и откроем http
/https
порты (80
/443
), например для случая когда у нас есть веб-сервер и наши сайты должны быть доступны снаружи:
$ sudo iptables -A INPUT -i lo -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
Если не разрешить входящий трафик от
localhost
то могу быть странные задержки с ответами, а при дебаге можно увидеть отклоенные пакеты от127.0.0.1
Теперь локальный DNS
на 53
порту доступен, docker
контейнеры тоже, с localhost
трафик разрешен, и для внешнего мира открыты 80
и 443
порты для наших сайтов. Но это все только для установления соединения и рукопожатия. Теперь нам нужно разрешить все установленные и связанные с ними соединения чтобы трафик действительно пошел (еще вот):
$ sudo iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
# удаление всех цепочек
$ sudo iptables -F
# разрешение всего входящего трафика
$ sudo iptables -P INPUT ACCEPT
# разрешение перенаправление трафика
$ sudo iptables -P FORWARD ACCEPT
# разрешение всего исходящего трафика
$ sudo iptables -P OUTPUT ACCEPT
Полезно иметь возможно отладить свои правила, экономия времени и
iptables
становится понятнее.
Суть отладки правил iptables
такова:
Создание новой цепочки:
$ sudo iptables -N LOGGING
Добавляем правило логирования каждого пакета с префиксом:
$ sudo iptables -A LOGGING -j LOG --log-prefix "ipt denied: "
Отклоняем пакет:
$ sudo iptables -A LOGGING -j DROP
В цепочку, откуда будут приходить пакеты для отклонения добавляем новое правило перенаправления в новую цепочку логирования:
$ sudo iptables -A INPUT -j LOGGING
Теперь добавим конфиг rsyslog
:
$ sudo nano /etc/rsyslog.d/10-iptables.conf
Вставим следующий текст:
:msg, contains, "ipt denied: " -/var/log/iptables.log
& ~
Сохраним и перезагрузим демона rsyslog
:
$ sudo service rsyslog restart
Теперь откроем файл и будем следить за 20 последних строк:
$ sudo echo > /var/log/iptables.log
$ sudo tail -f -n 20 /var/log/iptables.log
Можно наблюдать что-то такое:
Feb 19 17:43:36 logic kernel: [14331.939805] ipt denied: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=20640 DF PROTO=TCP SPT=49104 DPT=6000 WINDOW=65495 RES=0x00 SYN URGP=0
Feb 19 17:43:44 logic kernel: [14340.132036] ipt denied: IN=lo OUT= MAC=00:00:00:00:00:00:00:00:00:00:00:00:08:00 SRC=127.0.0.1 DST=127.0.0.1 LEN=60 TOS=0x00 PREC=0x00 TTL=64 ID=20641 DF PROTO=TCP SPT=49104 DPT=6000 WINDOW=65495 RES=0x00 SYN URGP=0
Feb 19 17:43:46 logic kernel: [14342.030775] ipt denied: IN=ens3 OUT= MAC=52:54:00:10:23:3f:4c:96:14:68:fb:f0:08:00 SRC=78.155.213.173 DST=185.105.90.67 LEN=40 TOS=0x00 PREC=0x00 TTL=250 ID=8008 PROTO=TCP SPT=57587 DPT=54402 WINDOW=1024 RES=0x00 SYN URGP=0
Feb 19 17:43:52 logic kernel: [14348.160719] ipt denied: IN=ens3 OUT= MAC=52:54:00:10:23:3f:4c:96:14:68:fb:f0:08:00 SRC=89.248.165.209 DST=185.105.90.67 LEN=40 TOS=0x00 PREC=0x00 TTL=248 ID=63021 PROTO=TCP SPT=49784 DPT=23988 WINDOW=1024 RES=0x00 SYN URGP=0
При перезагрузке системы правила
iptables
будут сброшены.
Чтобы происходило восстановление сохраненных правил нужен пакет iptables-persistent
:
$ sudo apt install iptables-persistent
Необходимо проверить работает ли демон systemd
:
$ sudo systemctl status netfilter-persistent
Если нет, его нужно запустить:
$ sudo systemctl start netfilter-persistent
После настройки и отладки правил
iptables
нужно сохранить их в файл/etc/iptables/rules.v4
чтобы при старте системы демонnetfilter-persistent
загрузил их вiptables
.
Сохранение правил iptables
в файл:
$ sudo iptables-save > /etc/iptables/rules.v4
Теперь правила должны загружаться после перезагрузки системы.
Для ручной загрузки правил правил из файла в iptables
можно сделать так:
$ sudo iptables-restore < /etc/iptables/rules.v4
Эта шпаргалка не получилась бы без сторонних источников откуда я черпал информацию для изучения. Здесь я узнал про сохранение правил iptables
, а в этом руководстве почерпнул много теории (и здесь). На некоторые вопросы дал ответы этот топик, а про локальный dns
узнал здесь. Отладку взял отсюда, а доделать правила для vpn
помог этот топик.