Настройка firewall в Debian 8.

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

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

# mcedit /etc/iptables.sh

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

#!/bin/bash

export IPT=»iptables»

# Внешний интерфейс
export WAN=eth0
export WAN_IP=192.168.1.52

# Для роутера. Для обычного компьютера и сервера данная часть не нужна.
# Локальная сеть
#export LAN1=eth1
#export LAN1_IP_RANGE=10.0.15.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

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

# Разрешаем localhost
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT

# Разрешаем локалку
# Для роутера. Для обычного компьютера и сервера данная часть не нужна.
#$IPT -A INPUT -i $LAN1 -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 атак:

# Закрываемся от 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 INPUT -p tcp —tcp-flags SYN,ACK,FIN,RST RST -m limit —limit 1/s -j ACCEPT
$IPT -A INPUT -p tcp —tcp-flags SYN,ACK,FIN,RST RST -j DROP

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

# Для роутера. Для обычного коомпьютера и сервера данная часть не нужна.
# Разрешаем доступ из локалки наружу
#$IPT -A FORWARD -i $LAN1 -o $WAN -j ACCEPT

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

# Для роутера. Для обычного коомпьютера и сервера данная часть не нужна.
# Закрываем доступ снаружи в локалку
#$IPT -A FORWARD -i $WAN -o $LAN1 -j REJECT

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

# Для роутера. Для обычного коомпьютера и сервера данная часть не нужна.
# Включаем NAT
#$IPT -t nat -A POSTROUTING -o $WAN -s $LAN1_IP_RANGE -j MASQUERADE

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

# открываем доступ к SSH
$IPT -A INPUT -i $WAN -p tcp —dport 22 -j ACCEPT

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

# Сохраняем правила
/sbin/iptables-save > /etc/iptables.rules

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

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

# chmod 0740 /etc/iptables.sh

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

# iptables -L -v -n

Видим, что на настраиваемом роутере firewall полностью открыт. Теперь применим новые правила и посмотрим на результат:

# /etc/iptables.sh

Все в порядке, правила применились, доступ к серверу я не потерял.

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

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

#Открываем доступ к web серверу
$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 сервер в своей работе.
Если у вас установлен почтовый сервер, то нужно разрешить на него входящие соединения по всем используемым портам:

# Открываем доступ к почтовому серверу
#$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

#Открываем доступ к DNS серверу
#$IPT -A INPUT -i $WAN -p udp —dport 53 -j ACCEPT

# Сохраняем правила
/sbin/iptables-save > /etc/iptables.rules

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

В последней строчке скрипта есть команда:

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

С ее помощью готовый набор правил iptables выгружаются в файл. Нам нужно сделать так, чтобы эти правила применялись при включении сетевого интерфейса во время загрузки сервера. Для этого открываем файл interfaces на редактирование и добавляем в самый конец строчку:

# mcedit /etc/network/interfaces

post-up iptables-restore < /etc/iptables.rules

Для проверки перезагружаем шлюз и проверяем, все ли в порядке.

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

# systemctl stop iptables.service

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

# systemctl disable iptables.service

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

Проброс (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

Если вы не хотите светить снаружи известным портом, то можно сделать перенаправление с нестандартного порта на порт 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 -o $LAN1 -j REJECT

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

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

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

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

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


ИСТОЧНИКИ.

Пошаговая настройка роутера на Debian.

Настройка iptables в CentOS 7.

Скачать скрипт правил iptables: