Настройка iptables Debian, CentOS.

 

   1 Вступление

   2 Настройка фаервола

   3 Установка Iptables

   4 Открытие портов

   5 Проброс (forward) порта

   6 Включение логов

  7 Как отключить iptables

 

1. Вступление

 

Iptables в настоящее время является стандартом де-факто в среде современных linux дистрибутивов. Я даже сходу не могу припомнить, что еще используют в качестве фаервола. Так что любому администратору линукс приходится сталкиваться в своей работе с настройкой этого межсетевого экрана.

 

К этому фаерволу существуют разные обвязки, которые используются для более «удобной» настройки. В ubuntu есть ufw, в centos — firewalld, с другими не знаком. Лично я не вижу никакого удобства в использовании этих инструментов. Я привык настраивать линуксовый фаервол по-старинке, как научился в самом начале работы. Мне кажется это наиболее простым и удобным способом, которым я с вами и поделюсь. Суть его сводится к тому, что создается скрипт с правилами фаервола. Этот скрипт можно легко редактировать под свои нужды и переносить с сервера на сервер.

 

2. Установка iptables

 

На самом деле фаервол у нас на сервере уже стоит и работает, просто нет никаких правил, все открыто. Установить нам нужно будет дополнительные утилиты управления, без которых конфигурировать iptables невозможно. Например, нельзя будет перезапустить фаервол:

 

# systemctl restart iptables.service

Failed to issue method call: Unit iptables.service failed to load: No such file or directory.

 

Или добавить в автозапуск не получится:

 

# systemctl enable iptables.service

Failed to issue method call: No such file or directory

 

Чтобы подобных ошибок не было, установим необходимый пакет с утилитами:

 

# yum -y install iptables-services

 

Теперь можно добавить iptables в автозагрузку и запустить:

 

# systemctl enable iptables.service

# systemctl start iptables.service

 

3. Настройка фаервола

 

Для управления правилами фаервола я использую скрипт. Создадим его:

 

# mcedit /etc/iptables.sh

 

Мы рассмотрим ситуацию, когда сервер является шлюзом в интернет для локальной сети.

 

Первым делом зададим все переменные, которые будем использовать в скрипте. Это не обязательно делать, но рекомендуется, потому что удобно переносить настройки с сервера на сервер. Достаточно будет просто переназначить переменные.

 

#!/bin/bash

 

export IPT="iptables"

 

# Внешний интерфейс

export WAN=ens34

export WAN_IP=192.168.100.7

 

# Локальная сеть

export LAN1=ens33

export LAN1_IP_RANGE=192.168.103.0/24

 

Перед применением новых правил, очищаем все цепочки:

 

$IPT -F

$IPT -F -t nat

$IPT -F -t mangle

$IPT -X

$IPT -t nat -X

$IPT -t mangle -X

 

Блокируем весь трафик, который не соответствует ни одному из правил:

 

$IPT -P INPUT DROP

$IPT -P OUTPUT DROP

$IPT -P FORWARD DROP

 

Разрешаем весь трафик локалхоста и локалки:

 

$IPT -A INPUT -i lo -j ACCEPT

$IPT -A INPUT -i $LAN1 -j ACCEPT

$IPT -A OUTPUT -o lo -j ACCEPT

$IPT -A OUTPUT -o $LAN1 -j ACCEPT

 

Разрешаем делать ping:

 

$IPT -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT

$IPT -A INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT

$IPT -A INPUT -p icmp --icmp-type time-exceeded -j ACCEPT

$IPT -A INPUT -p icmp --icmp-type echo-request -j ACCEPT

 

Если вам это не нужно, то не добавляйте разрешающие правила для icmp.

 

Открываем доступ в инет самому серверу:

 

$IPT -A OUTPUT -o $WAN -j ACCEPT

 

Если вы хотите открыть все входящие соединения сервера, то добавляйте дальше правило:

 

$IPT -A INPUT -i $WAN -j ACCEPT

 

!!!ВНИМАНИЕ! Делать это не рекомендуется, привожу просто для примера, если у вас появится такая необходимость.

 

Дальше разрешим все установленные соединения и дочерние от них. Так как они уже установлены, значит прошли через цепочки правил, фильтровать их еще раз нет смысла:

 

$IPT -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPT -A OUTPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT

$IPT -A FORWARD -p all -m state --state ESTABLISHED,RELATED -j ACCEPT

 

Теперь добавим защиту от наиболее распространенных сетевых атак. Сначала отбросим все пакеты, которые не имеют никакого статуса:

 

$IPT -A INPUT -m state --state INVALID -j DROP

$IPT -A FORWARD -m state --state INVALID -j DROP

 

Блокируем нулевые пакеты:

 

$IPT -A INPUT -p tcp --tcp-flags ALL NONE -j DROP

 

Закрываемся от syn-flood атак:

 

$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP

$IPT -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP

 

Следом за этими правилами рекомендуется поставить правила на запрет доступа с определенных IP, если у вас имеется такая необходимость. Например, вас задолбал адрес 84.122.21.197 брутом ssh. Блокируем его:

 

$IPT -A INPUT -s 84.122.21.197 -j REJECT

 

Если вы не ставите ограничений на доступ из локальной сети, то разрешаем всем выход в интернет:

 

$IPT -A FORWARD -i $LAN1 -o $WAN -j ACCEPT

 

Следом запрещаем доступ из инета в локальную сеть.

 

!!!!ЭТО ПРАВИЛО ОБЯЗАТЕЛЬНО В САМОМ КОНЦЕ ПРАВИЛ FORWARD

 

$IPT -A FORWARD -i $WAN -o $LAN1 -j REJECT

 

Чтобы наша локальная сеть пользовалась интернетом, включаем nat:

 

$IPT -t nat -A POSTROUTING -o $WAN -s $LAN1_IP_RANGE -j MASQUERADE

 

Чтобы не потерять доступ к серверу, после применения правил, разрешаем подключения по ssh:

 

$IPT -A INPUT -i $WAN -p tcp --dport 2222 -j ACCEPT

 

И в конце записываем правила, чтобы они применились после перезагрузки:

Подправлено под iptables-persistent.

 

$ /sbin/iptables-save  > /etc/iptables.rules

 

Мы составили простейший конфиг, который блокирует все входящие соединения, кроме ssh и разрешает доступ из локальной сети в интернет. Попутно защитились от некоторых сетевых атак.

 

Сохраняем скрипт, делаем исполняемым и запускаем:

 

# chmod 0740 /etc/iptables.sh

# /etc/iptables.sh

 

Выполним просмотр правил и проверим, все ли правила на месте:

 

# iptables -L -v -n

 

 

4. Открытие портов

 

Теперь немного расширим нашу конфигурацию и откроем в iptables порты для некоторых сервисов. Допустим, у нас работает веб-сервер и необходимо открыть к нему доступ из интернета. Добавляем правила для веб-трафика:

 

$IPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT

$IPT -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT

 

Было добавлено разрешение на входящие соединения по 80-му и 443-му портам, которые использует web сервер в своей работе.

 

Если нужно открыть порт только для определенных IP:

 

export HTTP_ALLOW=77.38.225.139,94.145.151.246,133.21.15.74

$IPT -A INPUT -i $WAN -s $HTTP_ALLOW -p tcp --dport 80 -j ACCEPT

 

Доступ к http порту будут иметь только ip адреса 77.38.225.139 94.145.151.246 133.21.15.74.

 

Если у вас установлен почтовый сервер, то нужно разрешить на него входящие соединения по всем используемым портам:

 

$IPT -A INPUT -p tcp -m tcp --dport 25 -j ACCEPT

$IPT -A INPUT -p tcp -m tcp --dport 465 -j ACCEPT

$IPT -A INPUT -p tcp -m tcp --dport 110 -j ACCEPT

$IPT -A INPUT -p tcp -m tcp --dport 995 -j ACCEPT

$IPT -A INPUT -p tcp -m tcp --dport 143 -j ACCEPT

$IPT -A INPUT -p tcp -m tcp --dport 993 -j ACCEPT

 

Для корректной работы DNS сервера, нужно открыть UDP порт 53

 

$IPT -A INPUT -i $WAN -p udp --dport 53 -j ACCEPT

 

И так далее. По аналогии можете открыть доступ для всех необходимых сервисов.

 

«А возможно заблокировать сети Vk, Одноклассники и спутники мейл.ру???»

 

На примере Facebook.

 

1. Найти все адреса

 

host -t a http://www.facebook.com

 

команда определит список адресов Facebook (31.13.65.17 — один из них)

 

whois 31.13.65.17 | grep inetnum

31.13.64.0 — 31.13.127.255

 

2. Конвертировать вышеуказанный дипазон адресов в CIDR-notation (www.ipaddressguide.com/cidr) и получаем 31.13.64.0/18

 

3. Запрет исходящих запросов к Facebook

 

$IPT -A OUTPUT -p tcp -i eth0 -o eth1 -d 31.13.64.0/18 -j DROP

 

Пример про facebook взят с другого ресурса, Поэтому синтаксис не проверен.

 

 

5. Проброс (forward) порта

 

Рассмотрим ситуацию, когда необходимо выполнить проброс портов с внешнего интерфейса на какой-то компьютер в локальной сети. Допустим, вам необходимо получить rdp доступ к компьютеру 10.1.3.50 из интернета. Делаем проброс TCP порта 3389:

 

$IPT -t nat -A PREROUTING -p tcp --dport 3389 -i ${WAN} -j DNAT --to 10.1.3.50:3389

$IPT -A FORWARD -i $WAN -d 10.1.3.50 -p tcp --dport 3389 -j ACCEPT

 

Если вы не хотите светить снаружи известным портом, то можно сделать перенаправление с нестандартного порта на порт rdp конечного компьютера:

 

$IPT -t nat -A PREROUTING -p tcp --dport 23543 -i ${WAN} -j DNAT --to 10.1.3.50:3389

$IPT -A FORWARD -i $WAN -d 10.1.3.50 -p tcp --dport 3389 -j ACCEPT

 

ВНИМАНИЕ! Если вы пробрасываете порт снаружи внутрь локальной сети, то обязательно либо закомментируйте правило, либо, что правильнее перенесите в самый конец правил FORWARD, Это равило которое блокирует доступ из внешней сети во внутреннюю. В моем примере это правило:

 

$IPT -A FORWARD -i $WAN -o $LAN1 -j REJECT

 

Либо перед этим правилом создайте разрешающее правило для доступа снаружи к внутреннему сервису, например вот так:

 

$IPT -A FORWARD -i $WAN -d 10.1.3.50 -p tcp -m tcp --dport 3389 -j ACCEPT

 

6. Включение логов

 

Во время настройки полезно включить логи, чтобы мониторить заблокированные пакеты и выяснять, почему отсутствует доступ к необходимым сервисам, которые мы вроде бы уже открыли. Я отправляю все заблокированные пакеты в отдельные цепочки (block_in, block_out, block_fw), соответствующие направлению трафика и маркирую в логах каждое направление. Так удобнее делать разбор полетов. Добавляем следующие правила в самый конец скрипта, перед сохранением настроек:

 

$IPT -N block_in

$IPT -N block_out

$IPT -N block_fw

 

$IPT -A INPUT -j block_in

$IPT -A OUTPUT -j block_out

$IPT -A FORWARD -j block_fw

 

$IPT -A block_in -j LOG --log-level info --log-prefix "--IN--BLOCK"

$IPT -A block_in -j DROP

$IPT -A block_out -j LOG --log-level info --log-prefix "--OUT--BLOCK"

$IPT -A block_out -j DROP

$IPT -A block_fw -j LOG --log-level info --log-prefix "--FW--BLOCK"

$IPT -A block_fw -j DROP

 

Все заблокированные пакеты вы сможете отследить в файле /var/log/messages.

 

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

 

7. Как отключить iptables

 

Если вы вдруг решите, что firewall вам больше не нужен, то отключить его можно следующим образом:

 

# systemctl stop iptables.service

 

Эта команда останавливает фаервол. А следующая удаляет из автозагрузки:

 

# systemctl disable iptables.service

 

Отключив сетевой экран, мы разрешили все соединения.