ADG Оставить заявку
Блог Инфраструктура 4 мин чтения

Переводим шлюз на iptables: две подсети, маскарадинг и первый нормальный конфиг

Ядро Linux 2.4 принесло iptables - и мы перевели офисный шлюз с ipchains на нормальный NAT. Две подсети, маскарадинг, правила цепочек - конфиг, который с тех пор берём за основу.

Контекст момента

iptables появился в ядре Linux 2.4, вытесняя ipchains

Когда вышло ядро Linux 2.4, первым делом мы посмотрели на netfilter и iptables. До этого на шлюзах жил ipchains, и жил, честно говоря, так себе - правила писались неочевидно, таблицы NAT и фильтрации перемешивались, и каждый раз когда надо было что-то добавить, человек, который это писал, чувствовал себя немного гадальщиком.

У одного клиента как раз была задача переделать раздачу интернета. Офис вырос, добавили второй этаж, под него отдельный коммутатор и отдельная подсеть. Итого: два сегмента, один канал наружу, один шлюзовой Linux-сервер посередине. Старый ipchains-конфиг с одной подсетью туда уже не вписывался нормально - начались хаки поверх хаков.

Решили не латать, а переписать с нуля на iptables.

Архитектура получилась такой. eth0 смотрит в интернет, получает внешний IP от провайдера. eth1 - первый офисный сегмент, 192.168.1.0/24. eth2 - второй сегмент, 192.168.2.0/24. Оба хотят наружу, оба должны ходить между собой.

iptables работает принципиально иначе, чем ipchains. Есть три таблицы: filter (само собой, фильтрация), nat (трансляция адресов) и mangle (модификация пакетов, нам пока не нужна). В каждой таблице - цепочки. В filter это INPUT, OUTPUT, FORWARD. В nat - PREROUTING, POSTROUTING, OUTPUT. Путать их нельзя: маскарадинг прописывается в POSTROUTING таблицы nat, а не в FORWARD фильтра - это первая грабля, на которую наступает половина людей, читавших только ipchains-туториалы.

Базовый конфиг написали примерно так. Сначала - политики по умолчанию:

iptables -P INPUT DROP
iptables -P FORWARD DROP
iptables -P OUTPUT ACCEPT

Потом - разрешаем уже установленные соединения, без этого ничего работать не будет:

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

Модуль state - это одно из главных улучшений по сравнению с ipchains. Отслеживание состояния соединений прямо в ядре: не надо вручную прописывать обратные правила для каждого протокола, ядро само знает что этот пакет - ответ на наш запрос.

Разрешаем форвардинг между обоими сегментами и наружу:

iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth2 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth1 -o eth2 -j ACCEPT
iptables -A FORWARD -i eth2 -o eth1 -j ACCEPT

И маскарадинг - источник трафика с обоих внутренних сегментов подменяется на внешний IP шлюза:

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.2.0/24 -o eth0 -j MASQUERADE

И не забыть включить форвардинг на уровне ядра:

echo 1 > /proc/sys/net/ipv4/ip_forward

Плюс в /etc/sysctl.conf прописать net.ipv4.ip_forward = 1, иначе после перезагрузки всё встанет.

Несколько вещей, которые выяснились в процессе. MASQUERADE удобен когда внешний IP динамический - он сам подхватывает текущий адрес интерфейса. Если IP статический, лучше SNAT с явным указанием адреса - чуть быстрее, потому что не нужно каждый раз смотреть на интерфейс. У клиента IP был по DHCP от провайдера, так что MASQUERADE - правильный выбор.

Правила надо сохранять. iptables-save выдаёт весь конфиг в читаемом виде, iptables-restore загружает обратно. В rc.local добавили строчку с iptables-restore из файла - и конфиг переживает перезагрузку. Звучит очевидно, но половина первых инсталляций погорала именно на этом: правила настроены, интернет работает, сервер перезагружается - и ничего нет.

SSH на шлюзе разрешили отдельным правилом в INPUT только с внутренних адресов, как и делали на других серверах после перехода с telnet. Снаружи - закрыто. DNS и DHCP уже работали на отдельном сервере в первом сегменте - его трафик тоже форвардится без проблем.

Клиент спросил: а как посмотреть что сейчас работает? iptables -L -v -n - список всех правил с счётчиками пакетов и байт. Очень удобно для диагностики: видно какое правило сколько трафика ловит, и можно сразу понять если что-то идёт не туда.

Весь конфиг вместе с комментариями уложился в один файл примерно на 40 строк. По сравнению с предыдущим ipchains-зоопарком - небо и земля. Читаемо, структурировано, понятно что и зачем.

Теперь когда надо поднять новый шлюз, берём этот файл за основу и правим под конкретику. Пока работает.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.