Настройка iptables: Самая простая конфигурация
Если говорить про боевые сервера, то настройка фаервола на двух серверах может сильно различаться, в зависимости от задач, которые выполняют эти сервера. Поэтому я постараюсь описать общие принципы, которыми можно пользоваться при настройке фаервола для любых серверов. Это только база для дальнейшей настройки.
В первую очередь, необходимо очистить загруженные правила:
iptables -F INPUT iptables -F OUTPUT iptables -F FORWARD
INPUT, OUTPUT, FORWARD — это три основные цепочки, по которым будут идти пакеты, входящие, исходящие и проходящие с интерфейса на интерфейс.
После этого необходимо задать политику по умолчанию. Их всего две — ACCEPT и DROP, принимать пакеты или не принимать. Для боевого сервера всегда необходимо выбирать DROP, а затем открывать всё, что необходимо и не более того.
Для задания таких политик необходимо предварительно разрешить соединения по SSH, будем считать, что мы не меняли стандартный порт (что обычно следует на боевых серверах делать сразу после установки SSH-сервера).
iptables -t filter -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
И после этого уже можно приступать к изменению политик по умолчанию:
iptables -P INPUT DROP iptables -P OUTPUT ACCEPT iptables -P FORWARD DROP
Для цепочки OUTPUT пока можно оставить политику по умолчанию ACCEPT, разрешающую исходящие соединения, к ней можно переходить после настройки цепочки INPUT, когда мы запретим входящие соединения. На многих серверах достаточно бывает правильно настроить цепочку INPUT, но мы рассмотрим позже также и настройку OUTPUT для более жесткой конфигурации.
Итак. В данный момент у нас открыт только порт SSH-сервера для входящих соединений, на все остальные порты соединения проходить не будут. Теперь надо добавить прием соединений на порты остальных сервисов, если они на вашем сервере запущены.
SMTP:
iptables -t filter -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT
DNS (обычно достаточно разрешить UDP, но можно также добавить и TCP):
iptables -t filter -A INPUT -p udp -m udp --dport 53 -j ACCEPT
HTTP:
iptables -t filter -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
POP3:
iptables -t filter -A INPUT -p tcp -m tcp --dport 110 -j ACCEPT
HTTPS:
iptables -t filter -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
И так далее. Порты, которые необходимо открыть для того или иного сервиса, и протокол можно посмотреть в файле /etc/services, в котором перечислены все закрепленные за определенными сервисами порты.
Но это еще не всё. Порты открыты, сервисы доступны извне, но почта не работает и доменные имена не резолвятся. Дело в том, что при запросе DNS-серверов запрос отправляется с произвольного свободного порта из числа непривелегированных, точно так же, как и соединение с другим почтовым сервером. И ответ эти сервисы отправляют на тот же самый порт. А этот порт, как вы понимаете, у нас закрыт. Мы могли бы открыть этот порт, но мы не знаем, с какого порта будет исходящее соединение. Поэтому мы можем сделать самое простое, что может быть,- разрешить соединения с определенных портов удаленного компьютера:
SMTP:
iptables -t filter -A INPUT -p tcp -m tcp --sport 25 -j ACCEPT
DNS:
iptables -t filter -A INPUT -p udp -m udp --sport 53 -j ACCEPT
Эти два правила разрешают входящие соединения с портов 25/tcp и 53/udp, поэтому, когда с этих портов приходят пакеты по соответствующему протоколу, они будут приняты. Если вы планируете обновлять систему, программное обеспечение или устанавливать пакеты, необходимые для работы, то вам придется разрешить соединения с 80 порта удаленных машин.
Вот теперь самая простая конфигурация iptables у нас готова.
После внесения правил в таблицы, необходимо их сохранить. Для этого можно воспользоваться, например, таким скриптом.
Предоставление доступа к сервисам на шлюзе
Предположим, что на нашем шлюзе запущен некий сервис, который должен отвечать на запросы поступающие из сети интернет. Допустим он работает на некотором TCP порту nn. Чтобы предоставить доступ к данной службе, необходимо модифицировать таблицу filter в цепочке INPUT (для возможности получения сетевых пакетов, адресованных локальному сервису) и таблицу filter в цепочке OUTPUT (для разрешения ответов на пришедшие запросы).
Итак, мы имеем , который маскарадит (заменяет адрес отправителя на врешний) пакеты во внешнюю сеть. И разрешает принимать все установленные соединения. Предоставление доступа к сервису будет осуществляться с помощью следующих разрешающих правил:
netfilter:~# iptables -A INPUT -p TCP --dport nn -j ACCEPT netfilter:~# iptables -A OUTPUT -p TCP --sport nn -j ACCEPT
Данные правила разрешают входящие соединения по протоколу tcp на порт nn и исходящие соединения по протоколу tcp с порта nn. Кроме этого, можно добавить дополнительные ограничивающие параметры, например разрешить входящие соединения только с внешнего интерфейса eth0 (ключ -i eth0) и т.п.
Устройство фильтра iptables
Для iptables в общем виде правила выглядят так:
iptables command [target/jump]
Не обязательно ставить описание действия (target/jump) последним в строке, но лучше придерживаться именно такой нотации для удобочитаемости правил.
Если в правило не включается спецификатор , то по умолчанию предполагается использование таблицы filter, если же предполагается использование другой таблицы, то это требуется указать явно. Спецификатор таблицы также можно указывать в любом месте строки правила, однако, более или менее, стандартом считается указание таблицы в начале правила.
Далее, непосредственно за именем таблицы должна стоять команда управления фильтром. Если спецификатора таблицы нет, то команда всегда должна стоять первой. Команда определяет действие iptables, например: вставить правило, или добавить правило в конец цепочки, или удалить правило и т.п. Тело команды в общем виде выглядит так:
Ключ указывает на то, что нужно сделать с правилом, например, команда -А указывает на то, что правило нужно добавить в конец указанной цепочки.
указывает, в какую цепочку нужно добавить правило. Стандартные цепочки — INPUT, OUTPUT, FORWARD, PREROUTING и POSTROUTING. Они находятся в таблицах фильтра. Не все таблицы содержат все стандартные цепочки.
Раздел задает критерии проверки, по которым определяется, подпадает ли пакет под действие этого правила или нет. Здесь можно указать самые разные критерии — IP-адрес источника пакета или сети, сетевой интерфейс и т.д.
указывает, какое действие должно быть выполнено при условии выполнения критериев в правиле. Здесь можно передать пакет в другую цепочку правил, «сбросить» пакет и забыть про него, выдать на источник сообщение об ошибке и т.д.
Когда пакет приходит на сетевое устройство, он обрабатывается соответствующим драйвером и далее передается в фильтр в ядре ОС. Далее пакет проходит ряд таблиц и затем передается либо локальному приложению, либо переправляется на другую машину.
Настройка переадресации портов
При обращении клиентов локальной сети к внешним сайтам Squid должен прозрачно для клиента перехватить запрос и обработать его согласно своим правилам — решить, какой контент отдать, логировать ли активность пользователя, можно ли вообще этому пользователю выходить в интернет. Наша задача — сделать так, чтобы на самом клиенте не надо было бы делать никаких настроек броузеров. Клиент просто подключился к локальной сети и уже работает через наш прокси-сервер и НИКАК иначе. Т.е. даже если кто-либо захочет обойти наш прокси, без хитростей ему уже не обойтись.
Переадресация портов в FreeBSD
Если на нашем шлюзе установлена FreeBSD и брандмауэр по-умолчанию — IPFW, то для выполнения этой задачи мы должны на шлюзе установить переадресацию (проброс) портов:
# Redirect to local proxy
/sbin/ipfw add 0170 fwd 127.0.0.1,3128 tcp from 192.168.1.0/24 to any 80
где:
- 0170 — номер правила (в вашем случае может быть любой).
- fwd 127.0.0.1,3128 — куда будем направлять пакеты, — в нашем случае нашему любимому Squid, запущенному на порту 3128 на шлюзе, — …
- from 192.168.1.0/24 — … отправленные компьютерами локальной сети…
- to any 80 — … на какой-либо сайт в интернете
Теперь внимание! Это правило нужно добавить ДО того, как правила NAT (Network Address Translation) получат этот запрос. Объясню немного неакадемично: что делает NAT? В нашем случае NAT изменяет адрес источника (заменяет локальный IP клиента на внешний IP шлюза и запоминает, от какого внутреннего клиента был запрос
Для того, чтобы Squid обработал запрос от клиента, ему не нужно ничего преобразовывать — он и сам с этим справится. Поэтому Squid должен получить пакет в первозданном виде и сам решить, что делать дальше.
К тому же NAT и Squid — все-таки разные вещи, и пакет, адресованный, скажем к , не содержит информации, как попасть в Squid (на порт шлюза). И пакет будет обрабатываться только средствами NAT. Squid пакет так и не увидит. Поэтому наша задача — просто отдать Squid-у тот пакет, который отправил броузер пользователя. Объясню на примере части конфига ipfw:
cmd="ipfw -q add" $skip="skipto 5000" pif="xl1" #внешний интерфейс ... # Redirect to local proxy $cmd 0170 fwd 127.0.0.1,3128 tcp from 192.168.1.0/24 to any 80 # NAT $cmd 0200 divert natd ip from any to any in via $pif # Allow keep-state statement. $cmd 0201 check-state # POP3/POP3S $cmd 0325 $skip tcp from any to any 110 out via $pif setup keep-state $cmd 0326 $skip tcp from any to any 995 out via $pif setup keep-state # WWW (HTTP/HTTPS/..) $cmd 0350 $skip tcp from any to any 80 out via $pif setup keep-state $cmd 0352 $skip tcp from any to any 443 out via $pif setup keep-state # This is skipto location for outbound stateful rules $cmd 5000 divert natd ip from any to any out via $pif ...
В конфиге выше запрос открыть сайт сначала обрабатывается правилом , которое заворачивает запрос в Squid. Squid (как и любая другая программа) также выполняет требования брандмауэра — только для него правило не действует, а вот правило разрешает Squid отправить запрос в интернет. Для того, чтобы выходить в интернет без Squid, необходимо закоментировать правило . В этом случае Squid не получит ничего, а все запросы броузеров из локальной сети будут обрабатываться правилом .
Переадресация портов в Linux
Если на нашем шлюзе установлена Linux и iptables, то вышеуказанная команда будет выглядеть так:
iptables -t nat -A PREROUTING -i eth0 -p tcp —dport 80 -j REDIRECT —to-port 3128
где eth0 — внутренний интерфейс.
В остальном смысл переадресаций и пр. аналогичен тому, как это объяснялось для . Разнятся только правила постороения конфигурационных файлов и . Пример правил iptables можно изучить здесь.
С этим разобрались. Теперь надо дать указание Squid о том, что он должен обрабатывать пакеты, изначально на него не направленные. Переходим к включению режима прозрачности Squid.
Настройка netfilter/iptables для подключения нескольких клиентов к одному соединению.
Давайте теперь рассмотрим наш Linux в качестве шлюза для локальной сети во внешнюю сеть Internet. Предположим, что интерфейс eth0 подключен к интернету и имеет IP 198.166.0.200, а интерфейс eth1 подключен к локальной сети и имеет IP 10.0.0.1. По умолчанию, в ядре Linux пересылка пакетов через цепочку FORWARD (пакетов, не предназначенных локальной системе) отключена. Чтобы включить данную функцию, необходимо задать значение 1 в файле /proc/sys/net/ipv4/ip_forward:
netfilter:~# echo 1 > /proc/sys/net/ipv4/ip_forward
Чтобы форвардинг пакетов сохранился после перезагрузки, необходимо в файле /etc/sysctl.conf раскомментировать (или просто добавить) строку net.ipv4.ip_forward=1.
Итак, у нас есть внешний адрес (198.166.0.200), в локальной сети имеется некоторое количество гипотетических клиентов, которые имеют адреса из диапазона локальной сети и посылают запросы во внешнюю сеть. Если эти клиенты будут отправлять во внешнюю сеть запросы через шлюз «как есть», без преобразования, то удаленный сервер не сможет на них ответить, т.к. обратным адресом будет получатель из «локальной сети». Для того, чтобы эта схема корректно работала, необходимо подменять адрес отправителя, на внешний адрес шлюза Linux. Это достигается за счет (маскарадинг) в , в .
netfilter:~# iptables -A FORWARD -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT netfilter:~# iptables -A FORWARD -m conntrack --ctstate NEW -i eth1 -s 10.0.0.1/24 -j ACCEPT netfilter:~# iptables -P FORWARD DROP netfilter:~# iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
Итак, по порядку сверху-вниз мы разрешаем уже установленные соединения в цепочке FORWARD, таблице filter, далее мы разрешаем устанавливать новые соединения в цепочке FORWARD, таблице filter, которые пришли с интерфейса eth1 и из сети 10.0.0.1/24. Все остальные пакеты, которые проходят через цепочку FORWARD — отбрасывать. Далее, выполняем маскирование (подмену адреса отправителя пакета в заголовках) всех пакетов, исходящих с интерфейса eth0.
Примечание. Есть некая общая рекомендация: использовать правило -j MASQUERADE для интерфейсов с динамически получаемым IP (например, по DHCP от провайдера). При статическом IP, -j MASQUERADE можно заменить на аналогичное -j SNAT —to-source IP_интерфейса_eth0. Кроме того, SNAT умеет «помнить» об установленных соединениях при кратковременной недоступности интерфейса. Сравнение MASQUERADE и SNAT в таблице:
Кроме указанных правил так же можно нужно добавить правила для фильтрации пакетов, предназначенных локальному хосту — как описано в . То есть добавить запрещающие и разрешающие правила для входящих и исходящих соединений:
netfilter:~# iptables -P INPUT DROP netfilter:~# iptables -P OUTPUT DROP netfilter:~# iptables -A INPUT -i lo -j ACCEPT netfilter:~# iptables -A OUTPUT -o lo -j ACCEPT netfilter:~# iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT netfilter:~# iptables -A INPUT -p icmp --icmp-type 8 -j ACCEPT netfilter:~# iptables -A OUTPUT -p icmp -j ACCEPT netfilter:~# cat /proc/sys/net/ipv4/ip_local_port_range 32768 61000 netfilter:~# iptables -A OUTPUT -p TCP --sport 32768:61000 -j ACCEPT netfilter:~# iptables -A OUTPUT -p UDP --sport 32768:61000 -j ACCEPT netfilter:~# iptables -A INPUT -p TCP -m state --state ESTABLISHED,RELATED -j ACCEPT netfilter:~# iptables -A INPUT -p UDP -m state --state ESTABLISHED,RELATED -j ACCEPT
В результате, если один из хостов локальной сети, например 10.0.0.2, попытается связаться с одним из интернет-хостов, например, 93.158.134.3 (ya.ru), при , их исходный адрес будет подменяться на внешний адрес шлюза в цепочке POSTROUTING таблице nat, то есть исходящий IP 10.0.0.2 будет заменен на 198.166.0.200. С точки зрения удаленного хоста (ya.ru), это будет выглядеть, как будто с ним связывается непосредственно сам шлюз. Когда же удаленный хост начнет ответную передачу данных, он будет адресовать их именно шлюзу, то есть 198.166.0.200. Однако, на шлюзе адрес назначения этих пакетов будет подменяться на 10.0.0.2, после чего пакеты будут передаваться настоящему получателю в локальной сети. Для такого обратного преобразования никаких дополнительных правил указывать не нужно — это будет делать все та же операция MASQUERADE, которая помнит какой хост из локальной сети отправил запрос и какому хосту необходимо вернуть пришедший ответ.
Примечание: желательно негласно принято, перед всеми командами iptables очищать цепочки, в которые будут добавляться правила:
netfilter:~# iptables -F ИМЯ_ЦЕПОЧКИ
Пример 2: FORWARD с одного ip на другой (DNAT с MASQUERADE, меняется адрес источника и назначения)
Не всегда перенаправление совершается из/в локальную сеть. Бывает, что необходимо сделать проброс соединения на какой-то сервер, используя промежуточный. Это может быть необходимо для дополнительной фильтрации подключаемых клиентов, для разделения нагрузки и других задач.
Есть хост с публичным IP-адресом (1.1.1.1), ему может быть сопоставлено доменное имя, для которого могут быть выпущены SSL-сертификаты и прочее.
Нужно, чтобы клиенты, обращающиеся на 1.1.1.1:25, направлялись бы на 2.2.2.2:25, с 1.1.1.1:443 — на 3.3.3.3:443, а с ip 4.4.4.4 обращения на порт 3535 шли бы на 3.3.3.3:22.
1.1.1.1, 2.2.2.2, 3.3.3.3 — это публичные IP-адреса (а могут быть и внутренними, не важно, могут быть от разных ISP и вообще, в разных местах). Подключающимся клиентам это знать незачем, не придется ничего перенастраивать в почтовых программах и т.п
(!) Естественно, хосты 2.2.2.2 и 3.3.3.3 должны разрешать трафик на соответствующие порты!
Вот идея правил iptables на сервере 1.1.1.1:
#!/bin/sh IF_EXT="eth0" IPT="/sbin/iptables" # flush $IPT --flush $IPT -t nat --flush $IPT -t mangle --flush $IPT -X # loopback $IPT -A INPUT -i lo -j ACCEPT $IPT -A OUTPUT -o lo -j ACCEPT # default $IPT -P INPUT DROP $IPT -P OUTPUT DROP $IPT -P FORWARD DROP # allow forwarding echo 1 > /proc/sys/net/ipv4/ip_forward # NAT $IPT -t nat -A PREROUTING -i $IF_EXT -p tcp --dport 25 -j DNAT --to 2.2.2.2:25 $IPT -t nat -A PREROUTING -i $IF_EXT -p tcp --dport 443 -j DNAT --to 3.3.3.3:443 $IPT -t nat -A PREROUTING -i $IF_EXT -p tcp -s 4.4.4.4 --dport 3535 -j DNAT --to 3.3.3.3:22 $IPT -t nat -A POSTROUTING -o $IF_EXT -j MASQUERADE # FORWARD $IPT -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT $IPT -A FORWARD -i $IF_EXT -o $IF_EXT -s 4.4.4.4 -d 3.3.3.3 -j ACCEPT $IPT -A FORWARD -i $IF_EXT -o $IF_EXT -d 2.2.2.2 -j ACCEPT $IPT -A FORWARD -i $IF_EXT -o $IF_EXT -d 3.3.3.3 -j ACCEPT # log #$IPT -A FORWARD -j LOG --log-prefix " ---FORWARD-LOG--- " # INPUT $IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP $IPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # ssh $IPT -A INPUT -p tcp --dport 22 -j ACCEPT # OUTPUT $IPT -A OUTPUT -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
Комментарии к скрипту:
1) INPUT разрешен только для 22/tcp, для ssh.
2) Несмотря на то, что интерфейс всего один, masquerade включен все равно
При переброске трафика все последующие сервера будут считать, что источник всего — это 1.1.1.1, а не реальные клиенты! Это важное отличие от предыдущего примера forward, когда менялся только адрес назначения!. 3) Пусть вас не смущает, что OUTPUT по дефолту DROP, а ниже — все ACCEPT
Привык всегда вначале ставить DROP на все, а потом по необходимости разрешаю. В данном случае нет необходимости фильтровать исходящие со шлюза пакеты
3) Пусть вас не смущает, что OUTPUT по дефолту DROP, а ниже — все ACCEPT. Привык всегда вначале ставить DROP на все, а потом по необходимости разрешаю. В данном случае нет необходимости фильтровать исходящие со шлюза пакеты.
Отладка
На удаленном компьютере-клиенте запустите что-то вроде «telnet 1.1.1.1 25». Пакет должен прийти на 1.1.1.1:25. Это можно контролировать, запустив на сервере 1.1.1.1 в консоли команду:
tcpdump -n port 25
Если все правильно, то на удаленном клиенте пойдет сеанс связи с SMTP-сервером 2.2.2.2.
Если что-то не так, вы должны понимать, что пакет все же пришел на 1.1.1.1:25. А вот потом не ушел. Он не должен попасть никуда, кроме FORWARD. Поэтому для отлова отбрасываемого трафика в цепочке FORWARD раскомментируйте правило лога (есть в примере) и просматривайте события в реальном времени (например, «tail -f /var/log/messages»). В соответствии с тем, что вы увидите в логе, испрвьте ваши правила iptables. Все должно получиться. Когда это произойдет, не забудьте выключить логирование (иначе размер лог-файла станет огромным).
Авторизуйтесь для добавления комментариев!
Минимальный набор правил iptables для шлюза
Задача: 1. Раздать интернет в локальную сеть при помощи NAT’а. 2. Разрешить обращение машин из локальной сети к внешним HTTP, HTTPS и DNS серверам 3. Пробросить порт на веб сервер, находящийся в этой локальной сети.
### Переменные # Интерфейс, смотрящий в интернет INET_IF="eth0" # Белый IP адрес, принадлежащий $INET_IF INET_IP="x.x.x.x" # TCP порты, по которым разрешено ходить в интернет машинам из локальной сети FORWARD_TCP_PORTS="53,80,443" # UDP порты, по которым разрешено ходить в интернет машинам из локальной сети FORWARD_UDP_PORTS="53" # Локальная сеть LOCAL_NET="192.168.0.0/24" # IP адрес локального веб сервера WEB_SERVER="192.168.0.10" # Путь до sysctl SYSCTL="/sbin/sysctl -w" # Включить в ядре форвард IPv4 пакетов if then echo "1" > /proc/sys/net/ipv4/ip_forward else $SYSCTL net.ipv4.ip_forward="1" fi ### Правила по умолчанию iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT ### INPUT # Разрешить входящие соединения с локалхоста iptables -A INPUT -i lo -j ACCEPT # Разрешить принимать уже установленные соединения iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Разрешить SSH iptables -A INPUT -p TCP --dport 22 -j ACCEPT ### FORWARD # Разрешить уже установленные пересылаемые соединения iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # Разрешить машинам локальной сети ходить в интернет по указанным TCP портам iptables -A FORWARD -p TCP -s $LOCAL_NET -m multiport --dport $FORWARD_TCP_PORTS -j ACCEPT iptables -A FORWARD -p TCP -d $LOCAL_NET -m multiport --dport $FORWARD_TCP_PORTS -j ACCEPT # Разрешить машинам локальной сети ходить в интернет по указанным UDP портам iptables -A FORWARD -p UDP -s $LOCAL_NET -m multiport --dport $FORWARD_UDP_PORTS -j ACCEPT iptables -A FORWARD -p UDP -d $LOCAL_NET -m multiport --dport $FORWARD_UDP_PORTS -j ACCEPT ### NAT # Включить NAT для локальной подсети iptables -t nat -A POSTROUTING -s $LOCAL_NET -o $INET_IF -j SNAT --to-source $INET_IP # Пробросить порт на локальный веб сервер iptables -t nat -A PREROUTING -p TCP -d $INET_IP --dport 80 -j DNAT --to-destination $WEB_SERVER:80
Надо отметить, что если пробрасывается порт, отличный от списка $FORWARD_TCP_PORTS, то необходимо его туда добавить, т.к. он будет дропаться политикой по умолчанию.В итоге, скрипт iptables для шлюза будет выглядеть следующим образом. Отличается от предыдущих правил.
#!/bin/sh # Очистить все правила iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P POSTROUTING ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -t mangle -P PREROUTING ACCEPT iptables -t mangle -P OUTPUT ACCEPT iptables -F iptables -t nat -F iptables -t mangle -F iptables -X iptables -t nat -X iptables -t mangle -X ### Переменные # Интерфейс, смотрящий в интернет INET_IF="eth0" # Белый IP адрес, принадлежащий $INET_IF INET_IP="x.x.x.x" # Локальная сеть LOCAL_NET="192.168.0.0/24" # IP адрес локального веб сервера WEB_SERVER="192.168.0.10" # Включить в ядре форвард IPv4 пакетов # Путь до sysctl SYSCTL="/sbin/sysctl -w" if then echo "1" > /proc/sys/net/ipv4/ip_forward else $SYSCTL net.ipv4.ip_forward="1" fi ### Правила по умолчанию iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT ### INPUT # Разрешить входящие соединения с локалхоста iptables -A INPUT -i lo -j ACCEPT # Разрешить принимать уже установленные соединения iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # Разрешить SSH только из локальной сети iptables -A INPUT -p TCP -s $LOCAL_NET --dport 22 -j ACCEPT # Разрешить запросы к кэширующему DNS серверу только из локальной сети iptables -A INPUT -p TCP -s $LOCAL_NET --dport 53 -j ACCEPT iptables -A INPUT -p UDP -s $LOCAL_NET --dport 53 -j ACCEPT ### FORWARD # Разрешить уже установленные пересылаемые соединения iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT # TCP порты, по которым разрешено ходить в интернет машинам из локальной сети FORWARD_TCP_PORTS="80,443" # Разрешить машинам локальной сети ходить в интернет по указанным TCP портам iptables -A FORWARD -p TCP -s $LOCAL_NET -m multiport --dport $FORWARD_TCP_PORTS -j ACCEPT iptables -A FORWARD -p TCP -d $LOCAL_NET -m multiport --dport $FORWARD_TCP_PORTS -j ACCEPT ### NAT # Включить NAT для локальной подсети iptables -t nat -A POSTROUTING -s $LOCAL_NET -o $INET_IF -j SNAT --to-source $INET_IP # Пробросить порт на локальный веб сервер на нестандартный порт iptables -t nat -A PREROUTING -p TCP -d $INET_IP --dport 80 -j DNAT --to-destination $WEB_SERVER:8090
Ключи утилиты iptables
Ключ | Пример | Пояснения |
-v, -verbose |
-list, -append, -insert, -delete, -replace |
Данный ключ используется для повышения информативности вывода и, как правило, используется совместно с командой -list. В случае использования с командой -list, в вывод этой команды включаются также имя интерфейса, счетчики пакетов и байт для каждого правила. Формат вывода счетчиков предполагает вывод кроме цифр числа еще и символьные множители K (x1000), M (x1,000,000) и G (x1,000,000,000). Для того чтобы заставить команду -list выводить полное число (без употребления множителей), требуется применять ключ -x, который описан ниже. Если ключ -v, -verbose используется с командами -append, -insert, -delete или -replace, то на вывод будет выдан подробный отчет о произведенной операции. |
-x, -exact |
-list |
Для всех чисел в выходных данных выводятся их точные значения без округления и без применения множителей K, M, G. |
-n, -numeric |
-list |
Iptables выводит IP-адреса и номера портов в числовом виде, предотвращая попытки преобразовать их в символические имена. |
-line-numbers | -list | Ключ -line-numbers включает режим вывода номеров строк при отображении списка правил. |
-c, -set-counters |
-insert, -append, -replace |
Этот ключ используется при создании нового правила для установки счетчиков пакетов и байт в заданное значение. Например, ключ -set-counters 20 4000 установит счетчик пакетов = 20, а счетчик байт = 4000. |
-modprobe |
Любая команда |
Ключ -modprobe определяет команду загрузки модуля ядра |
Перенаправление пакетов на другой порт
Перенаправление портов можно использовать для самых разных задач. Например, перенаправление пользователей из разных сетей на разные экземпляры веб-сервера, перенаправление порта на другой, если изменился порт какого-то сервиса, настройка прозрачного проксирования и так далее. Общая идея в том, что пакеты с определенного порта перенаправляются на другой порт на том же сетевом интерфейсе той же самой машины, либо на loopback’е.
Для перенаправления порта, например, 80, с внешнего интерфейса на порт 80 на loopback-интерфейсе мы можем использовать правило
iptables -t nat -A PREROUTING -d 192.168.0.1/32 -p tcp -m tcp --dport 80 -j DNAT --to-destination 127.0.0.1:80
Это правило позволит перенаправить пакеты на loopback, изменив назначение пакета путем трансляции адреса (Destination NAT), и после этого можно будет их отфильтровать в цепочке, которая будет задана для loopback-интерфейса. Естественно, нужно будет сделать и обратную трансляцию:
iptables -t nat -A POSTROUTING -s 127.0.0.1/32 -p tcp -m tcp --dport 80 -j SNAT --to-source 192.168.0.1
Таким образом, происходит обратный процесс, при этом изменяется Source NAT, то есть, транслируется адрес источника соединения.
Установка и настройка dnsmasq в Debian
Выполним установку dnsmasq на дебиан:
# apt-get install -y dnsmasq
Сделаем минимальную настройку программы. Нам нужно просто выдавать сетевые настройки пользователям. Для этого приводим конфигурационный файл dnsmasq к следующему виду:
# mcedit /etc/dnsmasq.conf domain-needed bogus-priv interface=eth1 dhcp-range=eth1,10.0.15.50,10.0.15.150,24h
В данном случае мы будем выдавать пользователям ip адреса в диапазоне от 10.0.15.50 до 150. Сохраняем конфиг, добавляем программу в автозагрузку и запускаем.
# insserv dnsmasq # /etc/init.d/dnsmasq start
Теперь можно запускать компьютер пользователя локальной сети, получать сетевые настройки по dhcp и проверять работу интернет шлюза.
Посмотреть выданные leases можно в файле /var/lib/misc/dnsmasq.leases. На этом настройка интернет шлюза на debian 8 закончена. Все что нужно для обеспечения доступа в интернет из локальной сети сделано. Получился программный роутер с широкими возможностями по наращиванию функционала.