Возможно, это не законченный вариант статьи. Шпаргалка будет обновляться, по мере того как я буду узнавать что-то новое или находить ошибки.
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 -hRETURN - возврат пакета в вышестоящую цепочку для применения действия по умолчанию, при отсутствии вышестоящей цепочки применится действие по умолчаниюПравила
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 помог этот топик.