Firewall iptables


Итак в один прекрасный момент возникла необходимость установить фаервол на сервере под линуксом, который будет интернет-шлюзом и не только. Основные задачи:
- закрыть доступ сотрудникам на определенные сайты - соц. сети и прочие, при этом не закрывая их для начальства.
- закрыть аську (есть чат для сотрудников), также оставив доступ к ней начальству.
- запретить выход в сеть другим нежелательным приложениям.
- сделать проброс портов для возможности it-отделу подключаться к своим рабочим компьютерам из внешней сети.
- открыть доступ из вне к серверу для администрирования через ssh.
- открыть из вне 80ый порт для доступа к будущему сайту.
- открыть из вне порты 25 и 110 для почтового сервера.
- Для IT-отдела отдельно открывать все, что понадобится)
 
В итоге сотрудникам в внешнюю сеть открыты только порты 80 (http) 443 (https) 53 (dns), и закрыты вконтактики и проч.. Аськи работать не будут так как используют др. порты (основной 5190).
 
Реализовывать эти задачи будем с помощью iptables — утилиты командной строки, является стандартным интерфейсом управления работой межсетевого экрана (брандмауэра) netfilter для ядер Linux версий 2.4 и 2.6. После дня изучения был создан достаточно простой скрипт настройки, наверно не лишенный недостатков но вполне рабочий. Теорию копипастить не буду, в сети ее море, да и из комментариев  ниже многое понятно. Приступим. Если iptables не установлен - ставим:
 
sudo su
apt-get install iptables
 
Создаем скрипт настройки и даем права на его выполнение:
 
touch fw.sh
chmod +x fw.sh
 
Создаем два текстовых файла. в одном будет храниться список vip ip-адресов, с которых будут доступны все сайты, во втором - список запрещенных сайтов:
 
touch sbd.txt
touch ipbd.txt
 
и заполняем их:
 
nano sbd.txt
 
vkontakte.ru
durov.ru
vk.com
odnoklassniki.ru
и прочие....
 
nano ipbd.txt
 
10.10.10.10
10.10.10.11
и.т.д.
 
Далее переходим к написанию скрипта настройки. Имеем следующее: локальная сеть 10.10.10.0/24 на сетевом адаптере eth1, внешняя сеть на адаптере eth0 c ip к примеру 88.45.65.2.
 
nano fw.sh
 
#!/bin/bash
###################################################
# Переменные
###################################################
 
#указываем внешний ip сервера и внешн. сетевой интерфейс
INET_IP1=88.45.65.2
INET_IFACE1=eth0
 
# указываем внутренний ip сервера и внутр. сетевой интерфейс
LAN_IP=10.10.10.4
LAN_IFACE=eth1
 
# внутренняя сеть
LAN_RANGE=10.10.10.0/24
 
# сетевой интерфейс петли и ip
LO_IFACE=lo
LO_IP=127.0.0.1
 
# IP адреса в локалке, на которые делаем проброс портов
IP_FORW[1]=10.10.10.57
# внешний порт
PORT_V[1]=3389
# внутренний порт
PORT_I[1]=3389
PRTCL[1]=tcp
 
IP_FORW[2]=10.10.10.50
# внешний порт
PORT_V[1]=3489
# внутренний порт
PORT_I[1]=3389
PRTCL[2]=tcp
 
ip=iptables
 
# указываем путь к текстовому файлу, содержащему список запрещенных сайтов
badsite=( $(cat "/home/virtdiver/sbd.txt") )
 
# указываем путь к текстовому файлу, содержащему список ip,
# для которых все сайты открыты
goodip=( $(cat "/home/virtdiver/ipbd.txt") )
 
###################################################
# Сброс настроек iptables (Очистка таблиц)
###################################################
 
$ip -F -t filter
$ip -F -t nat
$ip -F -t mangle
$ip -F
 
###################################################
# Политики по умолчанию: все блокировать что явно
# не разрешено ниже  =)
###################################################
 
$ip -P INPUT DROP
$ip -P OUTPUT DROP
$ip -P FORWARD DROP
 
###################################################
# Разрешаем форвардинг
###################################################
# только разрешаем
# настройка самого форвардинга ниже
# ставим в файл "1". (по умолчанию "0" - выключен)
echo 1 > /proc/sys/net/ipv4/ip_forward
 
###################################################
# Включаем NAT (сетевую трансляцию адресов) для
# возможности выхода в интернет из локалки
###################################################
 
# "!" = адреса назначения все, кроме $LAN_RANGE
$ip -t nat -A POSTROUTING -o $INET_IFACE1 -s $LAN_RANGE ! -d $LAN_RANGE -j SNAT --to-source $INET_IP1
 
###################################################
# Делаем проброс портов, для доступа например
# через удаленный рабочий стол (RDP) из внешней
# сети к компьютеру в локалке.
###################################################
 
# Подставляем в цикле значения ip, портов, и протоколов
# из массива, обьявленного в разделе "переменные"

for ((i=1; i<=${#IP_FORW[*]}; i++)); do


# Прокидываем порт

$ip -t nat -A PREROUTING --dst $INET_IP1 -p ${PRTCL[$i]} --dport ${PORT_V[$i]} -j DNAT --to-destination ${IP_FORW[$i]}:${PORT_I[$i]}
$ip -t nat -A POSTROUTING -p ${PRTCL[$i]} --dst ${IP_FORW[$i]} --dport ${PORT_I[$i]} -j SNAT --to-source $LAN_IP
# Разрешаем трафик между внешней сеткой и компьютером в сети, идущий с\на определенный порт
$ip -A FORWARD -i $INET_IFACE1 -o $LAN_IFACE -d ${IP_FORW[$i]} -p ${PRTCL[$i]} --dport ${PORT_I[$i]} -j ACCEPT
$ip -A FORWARD -i $LAN_IFACE -o $INET_IFACE1 -s ${IP_FORW[$i]} -p ${PRTCL[$i]} --sport ${PORT_I[$i]} -j ACCEPT

done

 
###################################################
# Отбрасываем все пакеты, которые не могут быть
# идентифицированы и поэтому не могут иметь
# определенного статуса.
###################################################
 
$ip -A INPUT   -m state --state INVALID -j DROP
$ip -A FORWARD -m state --state INVALID -j DROP
 
###################################################
# Разрешаем трафик через петлю
###################################################
 
# Разрешаем входящий трафик на интерфейс петли
$ip -A INPUT -p all -i $LO_IFACE -j ACCEPT
 
# Разрешаем исходящий трафик с интерфейса петли
$ip -A OUTPUT -p all -o $LO_IFACE -j ACCEPT
 
###################################################
# Разрешаем трафик через внутренний сет. адаптер
###################################################
 
# между сервером и локалкой пока разрешаем все, так как в функции сервера
# будет входить много др. задач....
# Разрешаем входящие новые и установившиеся соединения
# в сет. адаптер лок.сети из лок.сети
$ip -A INPUT -p all -i $LAN_IFACE -s $LAN_RANGE --match state --state NEW,ESTABLISHED -j ACCEPT
 
# Разрешаем исходящие новые и установившиеся соединения
# в внутреннюю сеть c сет. адаптера лок. сети
$ip -A OUTPUT -p all -o $LAN_IFACE -d $LAN_RANGE --match state --state NEW,ESTABLISHED -j ACCEPT
 
###################################################
# Разрешаем входящие новые и установившиеся
# tcp-соединения с внешней сети к серверу и
# установившиеся и инициированные ими соединения
# с сервера в внешнюю сеть на порты 80(http) и
# 22(ssh)
###################################################
 
# т.е. к примеру из внешней сети можно будет подключиться к серверу по ssh,
# а с сервера к другому в интернете нельзя, так как в эту сторону
# новые  подключения блокируются
$ip -A INPUT -p tcp -i $INET_IFACE1 -m multiport --dports 80,22,25,110 --match state --state NEW,ESTABLISHED -j ACCEPT
$ip -A OUTPUT -p tcp -o $INET_IFACE1 -m multiport --sports 80,22,25,110 --match state --state ESTABLISHED,RELATED -j ACCEPT
 
###################################################
# Разрешаем при необходимости непосредственно с
# сервера выход в внешнюю сеть на определенные
# порты, например dns,http,https
###################################################
 
$ip -A INPUT -i $INET_IFACE1 -p tcp -m multiport --sports 80,53,443 -j ACCEPT
$ip -A OUTPUT -o $INET_IFACE1 -p tcp -m multiport --dports 80,53,443 -j ACCEPT
$ip -A INPUT -i $INET_IFACE1 -p udp -m multiport --sports 53 -j ACCEPT
$ip -A OUTPUT -o $INET_IFACE1 -p udp -m multiport --dports 53 -j ACCEPT
 
###################################################
# открываем IT-отделу, то бишь себе) ,
# все что понадобится
###################################################
 
# tcp
$ip -A FORWARD -p tcp -s 10.10.10.9 ! -d $LAN_RANGE -m multiport --dports 80,53,443,22,25,110,5190 -j ACCEPT
$ip -A FORWARD -p tcp -d 10.10.10.9 ! -s $LAN_RANGE -m multiport --sports 80,53,443,22,25,110,5190 -j ACCEPT
# udp
$ip -A FORWARD -p udp -s 10.10.10.9 ! -d $LAN_RANGE -m multiport --dports 53 -j ACCEPT
$ip -A FORWARD -p udp -d 10.10.10.9 ! -s $LAN_RANGE -m multiport --sports 53 -j ACCEPT
 
# tcp
$ip -A FORWARD -p tcp -s 10.10.10.20 ! -d $LAN_RANGE -m multiport --dports 80,53,443,22,25,110,5190 -j ACCEPT
$ip -A FORWARD -p tcp -d 10.10.10.20 ! -s $LAN_RANGE -m multiport --sports 80,53,443,22,25,110,5190 -j ACCEPT
# udp
$ip -A FORWARD -p udp -s 10.10.10.20 ! -d $LAN_RANGE -m multiport --dports 53 -j ACCEPT
$ip -A FORWARD -p udp -d 10.10.10.20 ! -s $LAN_RANGE -m multiport --sports 53 -j ACCEPT
 
# tcp
$ip -A FORWARD -p tcp -s 10.10.10.21 ! -d $LAN_RANGE -m multiport --dports 80,53,443,22,25,110,5190 -j ACCEPT
$ip -A FORWARD -p tcp -d 10.10.10.21 ! -s $LAN_RANGE -m multiport --sports 80,53,443,22,25,110,5190 -j ACCEPT
# udp
$ip -A FORWARD -p udp -s 10.10.10.21 ! -d $LAN_RANGE -m multiport --dports 53 -j ACCEPT
$ip -A FORWARD -p udp -d 10.10.10.21 ! -s $LAN_RANGE -m multiport --sports 53 -j ACCEPT
 
###################################################
# Разрешаем аську избранным
###################################################
 
i=0
for i in "${goodip[@]}"
do
$ip -A FORWARD -p tcp -d $i --sport 5190 -j ACCEPT
$ip -A FORWARD -p tcp -s $i --dport 5190 -j ACCEPT
done
 
###################################################
# Закрываем доступ к запрещеным сайтам всем кроме
# VIP ip-адресов. Файлы со списками обьявлены в
# разделе "переменные"
###################################################
 
# !!! то правило, что выше - то главнее!!!
# поэтому этим правилом разрешаем избранным
j=0
for j in "${badsite[@]}"
do
i=0
for i in "${goodip[@]}"
do
$ip -A FORWARD -d $i -s $j -j ACCEPT
done
done
 
# а этим правилом запрещаем всем. Так как первое правило выше,
# значит главнее, оно не убьется вторым
i=0
for i in "${badsite[@]}"
do
$ip -A FORWARD -s $i -j DROP
done
 
###################################################
 
###################################################
# Разрешаем пакеты с внутренней сети во
# внешнюю и обратно, идущие через порты
# http\dns\https\ и др. по необходимости
###################################################
# tcp
$ip -A FORWARD -p tcp -s $LAN_RANGE ! -d $LAN_RANGE -m multiport --dports 80,53,443 -j ACCEPT
$ip -A FORWARD -p tcp -d $LAN_RANGE ! -s $LAN_RANGE -m multiport --sports 80,53,443 -j ACCEPT
# udp
$ip -A FORWARD -p udp -s $LAN_RANGE ! -d $LAN_RANGE -m multiport --dports 53 -j ACCEPT
$ip -A FORWARD -p udp -d $LAN_RANGE ! -s $LAN_RANGE -m multiport --sports 53 -j ACCEPT
 
 
###################################################
# Разрешаем c сервера ping наружу, а сервер с
# внешней сети пинговать запрещаем
###################################################
 
$ip -A INPUT -p icmp -m icmp -i $INET_IFACE1 --icmp-type echo-reply -j ACCEPT
$ip -A OUTPUT -p icmp -m icmp -o $INET_IFACE1 --icmp-type echo-request -j ACCEPT
 
Запускаем файл:
 
fw.sh
 
Проверяем внесение правил командами:
 
iptables -L # таблицы input, output, forward
и
iptables -L -t nat # таблица nat
 
При перезагрузке правила не сохранятся, поэтому стоит добавить скрипт в автозагрузку (в /etc/rc.local) или воспользоваться встроенной утилитой iptables-save.
 
Выходим из рута:
 
exit
 
И на этом настройка закончена.

Oct. 10, 2010