Устанавливаем корпоративный шлюз (два провайдера) на базе Ubuntu Server

Рассмотрим далее построение шлюза компании, выполняющего функции фаерволла. Шлюз будет построен на базе ОС Ubuntu Server 10.10. Итак, пусть имеется такая схема подключения корпоративной сети к Интернет:

Задачи, которые необходимо решить:

Важнейшая составляющая задачи построения шлюза состоит в необходимости маршрутизации компьютеров локальной сети через провайдеров: основная часть компьютеров будет маршрутизироваться через Провайдера 2 (Yota, в моем случае модем USB модель SAMSUNG ???), т.к. это дешевый канал, но и медленный, а один из компьютеров локальной сети должен выходить в Интернет через Провайдера 1 (ADSL) - быстрее чем Yota, но соответственно и дороже.

Этапы работы.

1) Установка ОС. Процесс установки подробно описан в сети, в частности вы можете посмотреть источник: http://www.howtoforge.com/perfect_setup_ubuntu_6.06 Некоторые замечания: я устанавливаю базовую версию ОС (т. е. без графической оболочки и т. п.). Все, что нужно, вы потом сможете самостоятельно доставить. Итак, считаем, что ОС поставлена.

2) Выполняем базовую настройку ОС.

  1. Задаем имя шлюза в /etc/hostname
  2. если нужно, меняем пароль для root: sudo passwd root
  3. если нужно, правим файл /etc/hosts
  4. выполняем обновление ПО системы: apt-get update && apt-get upgrade
  5. устанавливаем SSH сервер: apt-get install ssh openssh-server

Выполняем настройку сетевых интерфейсов /etc/network/interfaces:

# The loopback network interface
auto lo
iface lo inet loopback

# WAN (ADSL)
auto eth0
iface eth0 inet static
address 192.168.1.10
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1
##metric 100
dns-nameservers 192.168.1.1
## dns-nameserver IP1 IP2

# WAN (WiMax)
auto wimax0

iface wimax0 inet dhcp

# LAN
auto eth2
iface eth2 inet static
address 192.168.0.250
netmask 255.255.255.0
network 192.168.0.0
broadcast 192.168.0.255

3) Установка драйвера модема Yota. Linux был выбран не случайно: на данный момент времени имеются корректно работающие драйвера под эту ОС для модема Yota, тогда как для FreeBSD ситуация плачевная: драйвер есть, однако пока только для Current (в котором есть libusb-1.0 ?), и работа его не стабильна (качество связи с провайдером низкое, иногда связь вообще пропадает). Итак, поставим драйвер для модема Yota. Для этого с адреса http://code.google.com/p/madwimax/ скачаем последнюю сборку драйвера (или можете скачать у нас здесь). Как устанавливать:

  1. Заходим в консоль от имени рута (sudo -s). Распаковываем архив в отдельную папку.
  2. Выполняем скрипт ./configure. Смотрим внимательно на вывод, т.к. в только что установленной системе нет многих компонентов, необходимых для сборки. Например, среди прочего, скрипт потребует установить docbook, docbook2x (apt-get install <имя требуемого пакета>), также будет сообщено о необходимости установки компилятора C (apt-get install gcc). Итак, строк вида error не имеется, можно выполнить команду:
  3. make (находимся в том же каталоге, куда распаковали драйвер), и make install.

Если сборка и установка будет пройдена успешно, подключаем модем. При этом, в системе должно появиться новое сетевое устройство с именем wimax0:

# ifconfig | grep wimax
wimax0    Link encap:Ethernet  HWaddr 00:24:91:34:18:d7

4) Итак, ОС поставлена, ПО обновлено, драйвер модема поставлен. Включим режим маршрутизации.

Источники:

Выполняем:

sudo sh -c "echo 1 > /proc/sys/net/ipv4/ip_forward"

Добавляем в /etc/sysctl.conf:

net.ipv4.conf.default.forwarding=1
net.ipv4.conf.all.forwarding=1

5) Следующая задача состоит в настройке фаерволла iptables, который уже встроен в ядро. Источники:

Для начала, я сгенерировал правила со странички http://easyfwgen.morizot.net/gen/index.php. Это самый быстрый и простой способ «въехать» в фаерволл (т.к. я всегда работал с ipfilter во FreeBSD). Полученный код сохранил в текстовый файл, сделал его исполняемым. Выполнил. Проверил, что выполняются функции NAT. Замечания.

if [ "$SYSCTL" = "" ]
then
    echo "1" > /proc/sys/net/ipv4/ip_forward
else
    $SYSCTL net.ipv4.ip_forward="1"
fi

Также, я закомментировал блок:

#if [ "$SYSCTL" = "" ]
#then
#    echo "1" > /proc/sys/net/ipv4/conf/all/rp_filter
#else
#    $SYSCTL net.ipv4.conf.all.rp_filter="1"
#fi

Почему это сделано, я поясню ниже. Также закомментировал блок:

# if [ "$SYSCTL" = "" ]
# then
#    echo "1" > /proc/sys/net/ipv4/conf/all/log_martians
#else
#    $SYSCTL net.ipv4.conf.all.log_martians="0"
#fi

Т.к. со всех сторон шлюза я получаю адреса из частной сети, фаерволл не пропускал такие пакеты при включенной опции net.ipv4.conf.all.log_martians.

$IPT -P INPUT DROP
$IPT -P OUTPUT DROP
$IPT -P FORWARD DROP

задает политику по умолчанию - т.е. все, что явно не разрешено, будет запрещено.

route del -net 0.0.0.0 dev eth0

Здесь я удалил маршрут по умолчанию к ADSL провайдеру (см. рис. выше), т.е. у меня остался всего один маршрут по-умолчанию к провайдеру Yota. Советую сразу команду по удалению маршрута по-умолчанию прописать в /etc/network/interfaces в группе настройки соответствующего интерфейса:

# WAN (ADSL)
auto eth0
...
up route del -net 0.0.0.0 dev eth0
...

Что это дает? Каждый раз при старте компьютера будет удаляться один маршрут по-умолчанию.

Дальше, отладив скрипт, проверив связность фаерволла и локальной сети с Интернет, выполняем скрипт с ключом save. При этом в отдельный файл будут записаны текущие правила фаерволла (в формате, читаемом iptables). Чтобы каждый раз при старте системы загружались сохраненные правила, прописываем в /etc/network/interfaces:

# WAN (ADSL)
auto eth0
...
pre-up iptables-restore < /etc/iptables.rules.2

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

6) Формирование таблиц маршрутизации

Источники:

Итак, на данный момент у нас имеется «полунастроенный» шлюз, который маршрутизирует весь трафик к Интернет только по одному каналу (в моем случае, Yota) (выше было объяснено, почему был удален один из маршрутов по умолчанию в случае, когда вы имеете подключение более, чем к одному провайдеру). Вначале было сказано, что важнейшей задачей является маршрутизация одного из компьютеров в локальной сети по другом каналу, т.е. нужно так настроить шлюз, чтобы он принимал решение, к какому из провайдеров направить очередной пакет из локальной сети. Займемся этим.

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

ip route show
route -n

По-умолчанию в Линукс имеется три таблицы маршрутизации: локальная, главная и по-умолчанию. Чтобы увидеть, какие таблицы маршрутизации имеются в системе, выполните команду ip rule list. Например, чтобы посмотреть, какие маршруты хранятся в таблице маршрутизации main выполните: ip route list table main. Кстати, по-умолчанию, ip route show и route -n выводят маршруты именно из этой таблицы. Наша задача состоит в том, чтобы создать новую таблицу маршрутизации, где будут храниться все маршруты для канала ADSL. Создадим новую таблицу, для этого добавим в конец файла /etc/iproute2/rt_tables строку в формате «число1 имя_таблицы». Здесь: число1 - порядковый номер таблицы, имя_таблицы - буквенное имя. Совет: чтобы не путаться дальше, лучше задать одинаковое числовое значение в обоих полях. К примеру, выполним команду:

echo 4 4 >> /etc/iproute2/rt_tables

Тем самым мы создали новую таблицу маршрутизации с именем и порядковым номером, равным 4. Далее выполним команды:

echo "Erase the route..."
/bin/ip route flush cache
/bin/ip route flush table 4

echo "Copy main routing table to adsl (ID 4) table"
/bin/ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table 4 $ROUTE ; done
/bin/ip route add table 4 default via eth0

Первые две команды очищают кеш таблиц маршрутизации, третья команда копирует все содержимое главной таблицы маршрутизации в нашу только что созданную под номером 4, за исключением маршрута по-умолчанию. Действительно, зачем нам в новой таблице маршрутизации запись о маршруте по-умолчанию из главной таблицы, если мы хотим прописать новый маршрут по-умолчанию? Четвертая команда как раз добавляет запись о маршруте по-умолчанию для ADSL линии в таблицу 4.

Итак, мы хотим, чтобы наш компьютер в локальной сети с IP 192.168.0.90 выходил в сеть через ADSL провайдера, а все остальные компьютеры - через WiMax модем. В главной таблице маршрутизации у нас уже имеется маршрут по-умолчанию для провайдера Yota. Его мы «трограть» не будем. Но как нам сказать, что все, что идет от 192.168.0.90 должно идти через другой канал, т.е. другими словами, как привязать только что созданную таблицу маршрутизации к пакетам от 192.168.0.90? Делается это так (добавьте в конце файла с правилами iptables):

$IPT -t mangle -A PREROUTING -s 192.168.0.90/32 -j MARK --set-mark 0x4
/bin/ip rule add fwmark 4 table 4

Все, теперь все пакеты от 192.168.0.90 будут «привязаны» к новой таблице маршрутизации, где запись маршрута по-умолчанию говорит, что пакеты надо отсылать через сетевой интерфейс, соединенный с каналом ADSL.

Замечание.

#!/bin/sh
# 
#if.up.sh
echo "Erase the route..."

INET_ADSL_GW="192.168.1.1"

/bin/ip route flush cache
/bin/ip route flush table 4

echo "Copy main routing table to adsl (ID 4) table"

/bin/ip route show table main | grep -Ev ^default | while read ROUTE ; do ip route add table 4 $ROUTE ; done
/bin/ip route add table 4 default via $INET_ADSL_GW

/bin/ip rule add fwmark 4 table 4

/bin/echo 0 > /proc/sys/net/ipv4/conf/eth0/rp_filter
/bin/echo 0 > /proc/sys/net/ipv4/conf/all/rp_filter

и поместил вызов в соответствующий блок в /etc/network/interfaces, т.о.:

# WAN (ADSL)
auto eth0
iface eth0 inet static
address 192.168.1.10
netmask 255.255.255.0
network 192.168.1.0
broadcast 192.168.1.255
gateway 192.168.1.1
##metric 100
dns-nameserver 192.168.1.1
pre-up iptables-restore < /etc/iptables.rules.2
up /root/scripts/if.up.sh
up route del -net 0.0.0.0 dev eth0

7) Принуждение записи логов IPTABLES в отдельный файл

Я думаю, что многие сталкивались с проблемой, как заставить писать Iptables в отдельный файл, а не системный syslog и пр. Вот решение:

  1. Выполняем команды:
    touch /etc/rsyslog.d/iptables.conf

    Прописываем /etc/rsyslog.d/iptables.conf:

    :msg, contains, "fw: " -/var/log/iptables.log
    
  2. Самое главное: во всех log-инструкциях Iptables я указываю префикс, который начинается с fw, типа этого:
    $IPT -A bad_packets -p ALL -m state --state INVALID -j LOG --log-prefix "fw: Invalid packet: "

    Т.е. Rsyslog будет отлавливать такие инструкции и помещать в отдельный файл.

  3. Создаем файл /var/log/iptables.log, выполняем
    chown syslog /var/log/iptables.log
  4. Перезапускаем rsyslogd:
    /etc/init.d/rsyslog restart
  5. Убеждаемся, что логи Iptables идут по правильному адресу и не мусорят syslog и messages.

TAG: