Iptables Ubuntu server

В данной публикации будет описана базовая конфигурация iptables на сервере, выполняющем роли маршрутизатора и межсетевого экрана. Все действия будут производится на Ubuntu server 16.04.01.

netfilter-diagram-rus

Для начала определимся с терминологией:

iptables — утилита командной строки, интерфейс управления  межсетевым экраном.
Правило — состоит из критерия, действия и счетчика.
Цепочка — упорядоченная последовательность правил.
Таблица — совокупность базовых и пользовательских цепочек.

Любой пакет, который пришёл на любой сетевой интерфейс будет двигаться по схеме представленной выше.  Подробное описание компонентов схемы можно прочитать здесь. Из данной схемы мы будем использовать таблицу nat из цепочки PREROUTING для публикации сервисов из внутренней сети во внешнюю. Например таких как web сервер, или почтовая система. В таблице filter цепочки INPUT мы определим правила для входящих соединений к локальным сервисам маршрутизатора, к примеру доступ по ssh. Таблица filter цепочки FORWARD определяет правила для входящих и исходящих соединений хостов внутренней сети во внешнюю. Таблица filter цепочки OUTPUT содержит правила исходящих соединений, инициированных локальными сервисами маршрутизатора. Таблица nat цепочки POSTROUTING используется для маскирования частных адресов из внутренней сети во внешний адрес маршрутизатора, с целью обеспечения доступа в интернет хостам внутренней сети. Иными словами цепочки PREROUTING и POSTROUTING используются для перенаправления и натирования пакетов. Цепочки INPUT, FORWARD и OUTPUT для фильтрации пакетов.

 

Просмотр состояния межсетевого экрана

# iptables -L  - просмотр текущих правил и политик в таблице filter
# iptables -L -t nat - просмотр текущих правил и политик в таблице nat


Более подробный вывод

# iptables -nL -v --line-numbers
# iptables -nL -v --line-numbers -t nat

Краткая форма просмотра

# iptables -S
# iptables -S -t nat

 

Работа с правилами

Добавить правило

# iptables -A  «имя цепочки»

Вставить правило

# iptables -I  «имя цепочки» «номер правила»

Удалить правило

# iptables -D  «имя цепочки» «номер правила»

*номер правила можно посмотреть в подробном выводе

Очистить таблицу от правил

# iptables -F – по умолчанию чистит таблицу filter
# iptables -F -t nat

Поменять состояние политики

# iptables -P  «имя цепочки» DROP/ACCEPT

 

Включение пересылки пакетов между сетевыми интерфейсами

Для этого нужно раскоментировать соответствующие строки в файле /etc/sysctl.conf

#net.ipv4.ip_forward=1
#net.ipv6.conf.all.forwarding=1

И применить изменения командой

# sysctl -p

 

Практический пример

Имеем сервер с Ubuntu server 16.04.01 и двумя сетевыми интерфейсами:

ens32 IP 192.168.1.51/24 — смотрит во внешнюю сеть.
ens33 IP 192.168.100.2/24 — смотрит во внутреннюю сеть.

Во внутренней сети есть клиентская машина с Windows 10, имеющая один сетевой интерфейс с IP 192.168.100.11/24

По умолчанию во всех цепочках используется разрешающая политика.

 

Изменим политику на запрещающую для цепочек INPUT и FORWARD

# iptables -P INPUT DROP
# iptables -P FORWARD DROP

Таким образом мы запретили любые входящие соединения к маршрутизатору(INPUT DROP), а также входящие и исходящие соединения для внутренней сети (FORWARD DROP) во внешнюю.

Важно! Утилита iptables используется для работы с протоколом IPv4. Для работы с протоколом IPv6 нужно использовать утилиту ip6tables. Так как в сети не планируется использование протокола IPv6, запретим по нему любые соединения

# ip6tables -P INPUT DROP
# ip6tables -P FORWARD DROP
# ip6tables -P OUTPUT DROP

 

Разрешим любой входящий трафик на петлевом интерфейсе

# iptables -I INPUT 1 -i lo -j ACCEPT

 

Правила для внешней сети

Когда маршрутизатор посылает какой-либо пакет с запросом на соединение с внешнего интерфейса, срабатывает разрешающая политика цепочки OUTPUT, пакет благополучно проходит. Затем хост, с которым инициируется соединение, посылает ответный пакет, который попадает под действие запрещающей политики в цепочке INPUT. Соединение не проходит. Для того чтобы соединения проходили делаем следующее:

Разрешим поддержку установленных ранее соединений

# iptables -A INPUT -i ens32 -d 192.168.1.51 -m state --state RELATED,ESTABLISHED -j ACCEPT

Разрешим проверку связи (ping) на внешнем интерфейсе

# iptables -A INPUT -i ens32 -d 192.168.1.51 -p icmp --icmp-type 8 -j ACCEPT

Разрешим подключение по ssh на внешнем интерфейсе с адреса 192.168.1.10

# iptables -A INPUT -i ens32 -s 192.168.1.10 -d 192.168.1.51 -p tcp --dport ssh -j ACCEPT

 

Правила для внутренней сети

Добавим правило NAT, для маскировки пакетов идущих из внутренней сети во внешнюю

# iptables -t nat -A POSTROUTING -o ens32 -s 192.168.100.0/24 -j SNAT --to 192.168.1.51

Или так для динамического IP на внешнем интерфейсе

# iptables -t nat -A POSTROUTING -o ens32 -s 192.168.100.0/24 -j MASQUERADE

Разрешим поддержку установленных ранее соединений

# iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT

Разрешим проверку связи (ping) из внутренне сети во внешнюю

# iptables -A FORWARD -i ens33 -o ens32 -s 192.168.100.0/24 -p icmp --icmp-type 8 -j ACCEPT

Разрешим проверку связи (ping) к маршрутизатору из внутренне сети на внутренний адрес маршрутизатора 192.168.100.2

# iptables -A INPUT -i ens33 -s 192.168.100.0/24 -d 192.168.100.2 -p icmp --icmp-type 8 -j ACCEPT

Разрешим dns запросы к серверу с IP 192.168.1.1

# iptables -A FORWARD -i ens33 -o ens32 -s 192.168.100.0/24 -d 192.168.1.1 -p udp --dport domain -j ACCEPT

Разрешим web трафик из внутренне сети во внешнюю

# iptables -A FORWARD -i ens33 -o ens32 -s 192.168.100.0/24 -p tcp -m multiport --dport http,https -j ACCEPT

Разрешим подключение по ssh к маршрутизатору от хоста из внутренне сети с IP 192.168.100.11 на внутренний адрес маршрутизатора 192.168.100.2

# iptables -A INPUT -i ens33 -s 192.168.100.11 -d 192.168.100.2 -p tcp --dport ssh -j ACCEPT

 

Публикация внутренних ресурсов во внешнюю сеть

Опубликуем на внешнем интерфейсе порт 33899, на внутренний ресурс с IP 192.168.100.11 порт 3389

# iptables -t nat -A PREROUTING -i ens32 -d 192.168.1.51 -p tcp --dport 33899 -j DNAT --to-destination 192.168.100.11:3389
# iptables -A FORWARD -i ens32 -o ens33 -d 192.168.100.11 -p tcp --dport 3389 -j ACCEPT

Опубликуем на внешнем интерфейсе порт 8080, на локальный web сервер, работающий на маршрутизаторе, на внутреннем интерфейсе с IP 192.168.100.2 порт 80. Также этот веб сервер должен быть доступен хостам из внутренне сети по порту 80.

Для внешней сети
# iptables --t nat -A PREROUTING -i ens32 -d 192.168.1.51 -p tcp --dport 8080 -j DNAT --to-destination 192.168.100.2:80
# iptables -A INPUT -i ens32 -d 192.168.100.2 -p tcp --dport http -j ACCEPT

Для внутренней сети
# iptables -A INPUT -i ens33 -s 192.168.100.0/24 -d 192.168.100.2 -p tcp --dport http -j ACCEPT

 

Сохранение правил в файл

Все выше указанные правила хранятся в ОЗУ и работают до перезагрузки. Для сохранения правил в файл используется утилита iptables-save.

# iptables-save > /etc/iptables.rules
# ip6tables-save > /etc/ip6tables.rules

 

Активация правил при загрузке

Для восстановления правил из файла используется утилита iptables-restore.

Способ 1

Добавляем скрипт /etc/network/if-pre-up.d/iptables

#!/bin/sh
iptables-restore /etc/iptables.rules
ip6tables-restore /etc/ip6tables.rules
exit 0

Добавляем возможность исполнения

# chmod +x /etc/network/if-pre-up.d/iptables

Способ 2

# echo "pre-up iptables-restore < /etc/iptables.rules" >> /etc/network/interfaces
# echo "pre-up ip6tables-restore < /etc/ip6tables.rules" >> /etc/network/interfaces

 

Правила описанные выше имеют подробный вид для того, чтобы более наглядно показать работу межсетевого экрана. Запись может быть упрощена путем указания только обязательных параметров.

 

Iptables Ubuntu server: 4 комментария

  1. Дмитрий

    есть маршрутер на ubuntu. за ним вебсервер, проброс портов 80 и 443 c wan на вебсервер. Если заходишь с другого соединения все сервисы работают, если из локалки за роутером — сервис недоступен. Что надо разрешить, что бы заработало?

    inet -> wan:router:80:443 -> Ok
    local -> wan:router:80:443 -> *****

    P.S. настраивал по этому мануалу.

    1. Андрей Автор записи

      Так работать не будет в принципе.
      По логике нужно было бы пробросить порт на внутреннем интерфейсе, правило бы имело вид:
      iptables -t nat -A PREROUTING -i «внутренний интерфейс» -d «ip внешнего интерфейса» -p tcp —dport 80 -j DNAT —to-destination «внутренний адрес веб сервера»:80
      К примеру веб сервер имеет адрес 192.168.1.100, клиент имеет адрес 192.168.1.101. Внешний интерфейс роутера имеет адрес 11.0.0.11.
      Клиент посылает пакет на адрес внешнего интерфейса роутера 11.0.0.11 на порт 80, пакет попадает на внутренний интерфейс роутера (адрес шлюза у клиента) и срабатывает указанное выше правило.
      Запрос типа
      192.168.1.101 > 11.0.0.11
      меняется на
      192.168.1.101 > 192.168.1.100
      роутер благополучно маршрутизирует пакет, и отправляет его на адрес веб сервера 192.168.1.100.
      Веб сервер успешно получает пакет, и ответ посылает на адрес источника, т.е. 192.168.1.101.
      Так как адрес веб сервера и клиента находятся в одной сети, шлюз не используется
      и ответ от веб сервера отправляется на адрес клиента 192.168.1.101.
      Клиент благополучно дропает пакет, так как он не инициировал соединение с адресом 192.168.1.100.
      Т.е. запрос на соединение посылается с адреса 192.168.1.101 на адрес 11.0.0.11, а ответ приходит с адреса 192.168.1.100, а должен с 11.0.0.11.

      Чтобы из внутренней сети попасть на веб сервер, нужно обращаться к нему по внутреннему адресу, без использования шлюза.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *