Debian простой шлюз и firewallПодписка на Комментарии к "Debian простой шлюз и firewall"

Аватар zenon

Каждый выход в интернет не только дает возможность подключаться к различным серверам и сайтам, но и создает потенциальную опасность проникновения на наш компьютер извне. Не стоит пренебрегать этой опасностью. Ситуация усугубляется оттого, что в некоторых (пока еще) широко распространенных операционных системах по умолчанию остаются открытыми многие порты, что позволяет подключаться из интернета к пользователю незаметно для последнего.
Поэтому в основу любого firewall должны быть заложены правила по закрытию и контролированию портов.
В нашем случае действуют политики по умолчанию - всё закрыть, открыть извне только то что нам необходимо ("block everything, then open up holes as neccessary"), а также сам шлюз и компьютеры локальной сети могут открывать порты в обратную сторону самостоятельно, вот как эти правила выглядят на языке iptables:

# Закрываем изначально ВСЁ (т.е. изначально все что не разрешено - запрещено):
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
# Состояние ESTABLISHED говорит о том, что это не первый пакет в соединении.
# Пропускать все уже инициированные соединения, а также дочерние от них
iptables -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
# Пропускать новые, а так же уже инициированные и их дочерние соединения
iptables -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# Разрешить форвардинг для новых, а так же уже инициированных и их дочерних соединений
iptables -A FORWARD -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

....
Несколько основных политик, заданных с самого начала, могут стать фундаментом для построения более точных правил, определяемых пользователем правил. Для создания правил по умолчанию в IPTables используются политики (-P). Думающие о безопасности администраторы обычно применяют политику отбрасывания всех пакетов и задают разрешающие правила только для каждого конкретного случая. Следующие правила блокируют все входящие и исходящие пакеты:

iptables -P INPUT DROP
iptables -P OUTPUT DROP

Кроме этого рекомендуется, чтобы все пересылаемые пакеты (пакеты, маршрутизируемые брандмауэром к точке назначения) также были запрещены — это защитит внутренних клиентов от нежелательного влияния Интернета. Для этого добавьте следующее правило:
iptables -P FORWARD DROP

Прежде чем двигаться дальше - убедитесь, что ...
Всё ваше аппаратное обеспечение работоспособно. То есть Вы подключили все оборудование, модули грузятся, устройства видны в системе. Полезно в начале проверить, что соединение с интернетом возможно и без всяких там iptables. Нет ничего хуже, чем в течении многих часов возиться с упрямой программой, ругая её почём зря, а потом понять, что сетевая карта не работает или модем сконфигурирован неправильно.
Предупреждение: Такая ситуация возможна и после успешной начальной настройки iptables. Поэтому на этапе настройки, когда что-то не работает так, как предполагается, полезно включить логирование всех reject'ов и почитывать лог. Главное после завершения отладки не забыть выключить.

Вы имеете представление о сетевых технологиях и Вы знакомы с администрированием Linux и Debian Linux в частности. То есть необходимы навыки работы с такими базовыми вещами как ifconfig, rc-update, /etc/init.d/networking, /etc/network/interfaces, и так далее. Если для Вас это пока пустые звуки, то, пожалуйста предварительно изучите

Итак приступим:
Исходные данные.
Компьютер подключенный к интернет через pppoe (для настройки лучше использовать pppoeconf - это скрипт входящий в стандартную установку Debian), интерфейс ppp0.
Шлюзом будет машина с ip = 192.168.0.1
Для того чтобы наш шлюз раздавал dns клиентам необходимо поствить dnsmasq, а также на всякий случай убедиться что пакет iptables установлен в системе (хотя я не помню ни одного случая чтобы он по-умолчанию в Debian не был установлен):
$ aptitude install dnsmasq iptables
Настраивать dnsmasq никак не надо - если у вас стоит какой-то другой кэшируюший dns-сервер то dnsmasq устанавливать нет необходимости.
Раздача интернета будет осуществлена на локальную сеть подключенную к интерфейсу eth1, ip адреса: 192.168.0.0/24.
Все это можно в принципе изменить, в скрипте введены для этого переменные в шапке - например если у вас интернет подключен напрямую к eth0 без pppoe, то достаточно изменить .export WAN=ppp0 на export WAN=eth0, так же и с остальным.
В нашем случае вот примерно как будут выглядеть настройки сетевых интерфейсов:

$ cat /etc/network/interfaces
# Файл описывает сетевые интерфейсы доступные в системе
# и способы активирования их.
# The loopback network interface
auto lo
   iface lo inet loopback
# PPPoE
auto eth0
iface eth0 inet manual
   auto dsl-provider
iface dsl-provider inet ppp
   pre-up ifconfig eth0 up
   provider dsl-provider
# eth1 - Локальная сеть
auto eth1
iface eth1 inet static
   address 192.168.0.1
   netmask 255.255.255.0
   network 192.168.0.0
   broadcast 192.168.0.255

Ну собственно вот наш скрипт:

#!/bin/bash
# Тут в принципе может и не надо этого всего но не помеха
# вдруг какой модуль не подгружен или форвардинг не включен
echo "1" > /proc/sys/net/ipv4/ip_forward
echo "1" > /proc/sys/net/ipv4/ip_dynaddr
modprobe iptable_nat
modprobe ip_conntrack_ftp
modprobe ip_nat_ftp

# Объявление переменных
export IPT="iptables"

# Интерфейс который смотрит в интернет
export WAN=ppp0

# Локальная сеть
export LAN=eth1
export LAN_IP_RANGE=192.168.0.0/24

# Очистка всех цепочек iptables
$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

# разрешаем локальный траффик для loopback и внутренней сети
$IPT -A INPUT -i lo -j ACCEPT
$IPT -A INPUT -i $LAN -j ACCEPT
$IPT -A OUTPUT -o lo -j ACCEPT
$IPT -A OUTPUT -o $LAN -j ACCEPT

# Состояние ESTABLISHED говорит о том, что это не первый пакет в соединении.
# Пропускать все уже инициированные соединения, а также дочерние от них
$IPT -A INPUT -p all -m state --state ESTABLISHED,RELATED -j ACCEPT
# Пропускать новые, а так же уже инициированные и их дочерние соединения
$IPT -A OUTPUT -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
# Разрешить форвардинг для новых, а так же уже инициированных
# и их дочерних соединений
$IPT -A FORWARD -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT

# Включаем фрагментацию пакетов. Необходимо из за разных значений MTU
$IPT -I FORWARD -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

# Отбрасывать все пакеты, которые не могут быть идентифицированы
# и поэтому не могут иметь определенного статуса.
$IPT -A INPUT -m state --state INVALID -j DROP
$IPT -A FORWARD -m state --state INVALID -j DROP

# Приводит к связыванию системных ресурсов, так что реальный
# обмен данными становится не возможным.
$IPT -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
$IPT -A OUTPUT -p tcp ! --syn -m state --state NEW -j DROP

# Разрешаем доступ из внутренней сети наружу
$IPT -A FORWARD -i $LAN -o $WAN -j ACCEPT

# Запрещаем доступ снаружи во внутреннюю сеть
$IPT -A FORWARD -i $WAN -o $LAN -j REJECT

# Маскарадинг
$IPT -t nat -A POSTROUTING -o $WAN -s $LAN_IP_RANGE -j MASQUERADE


# Далее дано как пример открытие портов извне:
# **********************************************************************
# Открываем порт для ssh
$IPT -A INPUT -i $WAN -p tcp --dport 22 -j ACCEPT

# Открытие портов для торрентов (такие же указать в torrent-клиенте)
$IPT -A INPUT -i $WAN -p tcp -m multiport --ports 49152:65535 -j ACCEPT

# Открытие 443 порта
$IPT -A INPUT -p tcp --dport 443 -j ACCEPT

# Открываем 80 порт для веб сайтов
$IPT -A INPUT -i $WAN -p tcp --dport 80 -j ACCEPT
$IPT -A INPUT -i $WAN -p udp --dport 80 -j ACCEPT

# Открытие портов для игровых серверов
$IPT -A INPUT -i $WAN -p tcp --dport 27010:27030 -j ACCEPT
$IPT -A INPUT -i $WAN -p udp --dport 27010:27030 -j ACCEPT

# Открытие порта для голосового сервера Team Speak
$IPT -A INPUT -i $WAN -p tcp --dport 9987 -j ACCEPT
$IPT -A INPUT -i $WAN -p udp --dport 9987 -j ACCEPT
# **********************************************************************
 
# Вывод информации о состоянии таблиц.
route -n
$IPT -L
$IPT -L -v -n
$IPT -L -v -n -t nat

Сохранить скрипт в файл, допустим /etc/firewall.sh, сделать исполняемым
$ chmod +x /etc/firewall.sh

Для начала чтобы скрипт выполнялся во время загрузки можно поместить ссылку в rc.local до строчки exit 0:

$ cat rc.local
#!/bin/sh -e
# rc.local
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
# In order to enable or disable this script just change the execution
# bits.
# By default this script does nothing.
sh /etc/firewall.sh
exit 0

Поместить запуск в rc.local конечно не есть самое правильное решение, более правильно - это сохранить правила iptables перед выключением, потом перед поднятием сетевого интерфейса загрузить правила, объясню как это сделать:
Для сохранения правил iptables существует команда:
$ iptables-save > /etc/ip_rulles.lst
После этого правила будут сохранены в файле (имя произвольное) /etc/ip_rulles.lst
Для загрузки правил соответственно:
$ iptables-restore < /etc/ip_rulles.lst

Ну и самое интересное - в файле настроек сети /etc/network/interfaces в каждый из интерфейсов можно добавлять секции которые будут выполнятся до поднятия, после поднятия, до отключения и после отключения интерфейса - секции:

pre-up
up
post-down
down

В нашем примере сохранение \ восстановление правил лучше поместить в секцию с loopback interface (это не обязательное правило можно поместить в секцию другого интерфейса), вот как это будет выглядеть:

# The loopback network interface
auto lo
  iface lo inet loopback
   pre-up echo "1" > /proc/sys/net/ipv4/ip_forward  # Включаем форвардинг пакетов
   pre-up iptables-restore < /etc/ip_rulles.lst     # Загружаем правила
   post-down iptables-save > /etc/ip_rulles.lst     # Сохраняем правила

После этого из rc.local необходимо лишнее убрать.
Теперь необходимо выполнить наш скрипт и сохранить правила
$ sh /etc/firewall.sh
$ iptables-save > /etc/ip_rulles.lst

Теперь все правила будут выставляться автоматически.
Также если сделать restart сети - правила сохраняться и сразу загрузятся.
Чтобы обновить можно принудительно сделать:
$ /etc/init.d/networking restart   # start | stop | force-reload
или
$ ifdown lo
$ ifup lo

IP-калькулятор
Руководство по iptables
Wiki
Хороший мануал по iptables.
По следам темы http://linuxforum.ru/viewtopic.php?id=13140
Еще одна неплохая статья на linuxforum

PS. Открытие портов в скрипте приведено как пример.
Немного о том, как пробросить порт со шлюза на другую машину во внутренней сети:
Например, нужно пробросить порт 8081. Адрес, на который обращается клиент, назовём внешний_ip, а адрес, на который он должен попасть — внутренний_ip.

$ iptables -t nat -A PREROUTING -p tcp -d внешний_ір --dport 8081 -j DNAT --to-destination внутренний_ір:8081
$ iptables -t nat -A POSTROUTING -p tcp --dst внутренний_ір --dport 8081 -j SNAT --to-source внешний_ір

И обязательно нужно что-то вроде:
$ iptables -t filter -A FORWARD -m conntrack --ctstate DNAT -j ACCEPT

PS2. На последок приведу пример самого элементарного firewall для веб-сервера:

# Разрешаем исходящий трафик и запрещаем весь входящий и транзитный:
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
# Разрешаем уже инициированные соединения, а также дочерние от них:
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Разрешаем ssh, dns, ldap, ftp и веб сервисы:
iptables -A INPUT -p tcp --dport ssh -i eth0 -j ACCEPT
iptables -A INPUT -p tcp --dport domain -i eth0 -j ACCEPT
iptables -A INPUT -p tcp --dport ldap -i eth0 -j ACCEPT
iptables -A INPUT -p udp --dport ldap -i eth0 -j ACCEPT
iptables -A INPUT -p tcp --dport 21 -i eth0 -j ACCEPT
iptables -A INPUT -p udp --dport 21 -i eth0 -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -i eth0 -j ACCEPT
# local loopback:
iptables -A INPUT -i lo -j ACCEPT
# Разрешаем ping:
iptables -I INPUT -p icmp --icmp-type destination-unreachable -j ACCEPT
iptables -I INPUT -p icmp --icmp-type source-quench -j ACCEPT
iptables -I INPUT -p icmp --icmp-type time-exceeded -j ACCEPT

Такой скрипт подойдет, допустим для первоначальной настройки VPS сервера.
Похожие материалы:
Аватар vadym

Доброго времени суток, подскажите, как закрыть доступ с локального ip или подсети на внешний ip, а лучше на dns имя (ip часто меняется). Заранее спасибо. P.S. перепробовал уйму вариантов, но доступ не блокируется.(((

Аватар zenon

vadym, политика на FORWARD должна быть изначально DROP, потом разрешения.
DNS блокировки делаются не с помощью iptables, хотя конечно тоже можно на linuforum я выкладывал скрипт блокировки, можешь поискать, и тут разместить.
DNS блокировки лучше делать с помощью dns-сервера, если это для локальной сети, то дополнительно надо закрывать внешние IP адреса dns-серверов таких например как 8.8.8.8 (гугл).

Аватар Виталий

Добрый день. Куда обратится за помощью в настройке шлюза на Debian
У меня 3 провайдера.
1. Вэб. ФТП. SSH (default)
2. Удаленный рабочий стол
3. VPN
Хочу заменить Kerio

Аватар R12

Мучаюсь уже второй день. Никак не получается настроить, может ты мне подскажешь. eth0 - интернет, eth1 сеть. Только мне надо наоборот закрыть все порты для локальной сети, кроме 80 допустим.
Пробовал за место
$IPT -A FORWARD -i $LAN -o $WAN -j ACCEPT
писать
$IPT -A FORWARD -i $LAN -o $WAN -p tcp --dport 80 -j ACCEPT
То все равно получаются открыты все порты(icq, почта работает).

Также эксперементировал с $IPT -A FORWARD -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
$IPT -A FORWARD -i eth0 -p all -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT (в таком варианте интернета в сети вообще нету).

Подскажи как быть ?

Страницы

Добавить комментарий