Настройка маршрутизатора на базе FreeBSD сервера

Предлагаю описать задачу:

Настроить простой шлюз предназначенный для роутинга пакетов из одной сети в другую.

Предположим, что у нас есть две сети, и сетевые карты на шлюзе соответственно:

rl0: 10.10.10.0/24

rl1: 192.168.0.0/16

Для начала нам необходимо настроить локальную сеть на интерфейсах rl0 и rl1 в соответствии с указанным ТЗ.

Для этого воспользуемся программой ifconfig:

Зададим на эти интерфейсы первые адреса из этих подсетей, предположив что они свободны:

/sbin/ifconfig rl0 10.10.10.1 netmask 255.255.255.0

/sbin/ifconfig rl0 192.168.0.1 netmask 255.255.0.0

Для уверенности стоит удостоверится что оба интерфейса видят сеть. Об этом можно судить по статусу интерфейса "active" при положительном и "no carrier" при отрицательном исходе этого вопросa при просмотре через утилиту

/sbin/ifconfig

Можно так же проверить наличие сети послав несколько ICMP запросов заведомо известным поднятым в этих сетях серверам, например ping утилитой. При этом удостоверьтесь - принимают ли такие пакеты доверенные серверы использованные для тестирования.

Если устройства подняты а ICMP пакеты не доходят - то возможно сеть неисправна, но есть так же большая вероятность того что сервер на который они отсылаются - блокирует их и не отвечает. Возможно так же что на нашем шлюзе

уже стоит firewall и не дает доступа отсылать эти пакеты. Часто в последнем случае можно видеть сообщение о невозможности отправки пакета из-за отсутствия доступа.

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

sysctl net.inet.ip.forwarding=1

Теперь, стоит настроить роутинг между интерфейсами rl0 и rl1.

Проставив шлюзом на подсеть 192.168.0.0/16 машину с ip адресом 10.10.10.1 компьютеры из сети 10.10.10.0/24 смогут обращаться к сети 192.168.0.0/16, и, в свою очередь, компьютеры подсети 192.168.0.0/16, проставив у себя шлюзом машину с ip адресом 192.168.0.1 смогут обращаться в подсеть 10.10.10.0/24, чего мы и добивались.

Настройка сети выполнена руками и при первой же перезагрузке системы - потеряет свою силу. Потому рекомендую сделать возможной её автоматическую установку при старте системы.

Можно написать sh скрипт в котором просто указать все выполненные нами программы, но ...

Система FreeBSD - система стандартов, она спроектирована так чтобы если другой администратор пришел на ваш шлюз - ему стало понятно что где и почему, и не возникало лишних вопросов. Это часть идеологии этой системы, и потому я

думаю, стоит её придерживаться.

Принято настройки сетевых интерфейсов указывать в загрузочном файле /etc/rc.conf Вот в таком виде:

ifconfig_rl0="inet 10.10.10.1 netmask 255.255.255.0"

ifconfig_rl1="inet 192.168.0.1 netmask 255.255.0.0"

Просто путем добавления этих строк в конфиг.

Разрешить пересылку пакетов между интерфейсами можно добавив в этот же файл запись:

gateway_enable="YES" # Set to YES if this host will be a gateway.

Кстати, в большинcтве дистрибутивов Linux того же самого можно добиться, указав в файле /etc/sysconfig/network:

FORWARD_IPV4="yes"

Что бы применить настройки внесенные в /etc/rc.conf можно вызвать программу netstart:

/etc/netstart

FIREWALL

Собственно, тема огненной стены не может быть пропущена в этом разделе - как никак базовая защита системы от внешних воздействий, атак, взломов.. И не только системы, но и сети которая стоит за нашим шлюзом, т.е. речь идет не

просто о фаерволе на эту машину - речь идет о фаерволе на всю подсеть!

Есть много типов фаерволов, - например iptables, IpFilter, PF(Pocket Filter) - кстати очень хорошая система, общепринятая в OpenBSD и портированная во FreeBSD.

Здесь мы остановимся на фаерволе ipfw как на наиболее простом и удобном, несложном в настройке и надежном, стабильном и быстром средстве, которое работает на уровне ядра и являет собой дефолтовый фаервол системы вот уже

много лет.

Для того чтобы ipfw смог работать - необходимо включить его поддержку в ядре.

Можно пойти простым путем и динамически подгрузить требуемый модуль ipfw.ko при помощи системной утилиты kldload:

/sbin/kldload ipfw.ko

Для автоматизации этого процесса при перезагрузке системы можно воспользоваться средствами её загрузчика,

а именно конфигурационным файлом /boot/loader.conf прописав там:

ipfw_load="YES":

echo ipfw_load="YES" >>/boot/loader.conf

Второй вариант - пересобрать ядро с поддержкой вышеуказанного модуля.

Это более надежный и правильный на мой взгляд метод.

Перед пересборкой ядра в его конфигурационный файл следует включить опции поддержки фаервола:

options IPFIREWALL

Здесь же, с верой в будущее и осознанием настоящего - подумайте - возможно вам в последствии захочется настроить трансляцию адресов на сервере (NAT - Networke Address Translation)? Если так - то включите и эту поддержку заранее:

options IPDIVERT

Способов пересборки ядра - много. Я пользуюсь наиболее простым из них:

cd /usr/src

make kernel

Еще рекомендуется редактировать конфиг ядра в другом файле, да бы случайно не запортить дефолтовый конфиг GENERIC.

Для этого стоит скопировать имеющийся GENERIC в отдельный файл, назовем его MYCONF и собрать его из него:

cd /usr/src/sys/i386/conf

cp GENERIC MYCONF

... включаем опции в конфиг ...

cd /usr/src

make kernel KERNCONF=MYCONF

Если страшно собирать и устанавливать ядро в одну строку(последнюю в приведенном листинге), - можно её разделить на две:

make buildkernel KERNCONF=MYCONF

make installkernel KERNCONF=MYCONF

Можно сделать по handbook-у, через /usr/sbin/config MYCONF

Но не забудьте при этом переменную MYCONF определить в /etc/make.conf :

cd /usr/src/sys/i386/conf

/usr/sbin/config MYCONF

cd ../compile/MYCONF (cd ../../compile/MYKERNEL for FreeBSD versions prior to 5.0)

make depend

make

make install

- но по моему всё это лишняя работа.

Подробнее о сборке ядра - не здесь. Читайте handbook если интересно.

После сборки ядра (или во время), или после поднятия модуля если вы всё таки решили пойти таким путем, в конфигурационном файле /etc/rc.conf стоит определить загрузку фаервола следующей записью:

firewall_enable="YES"

Здесь же можно определить тип фаервола.

В наличии имеются несколько типов, в частности открытый, закрытый, и заданный через файл.

Открытый тип (open) - это когда по умолчанию всё разрешено, другими словами

allow all from any to any;

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

Второй тип - обратный первому. Закрытый (close) тип фаервола более безопасен в плане безопасности системы (но более опасен в плане неграмотности её настройки, особенно если настройка удаленная), - идея в том чтобы открыть

только то что требуется, и всё остальное закрыть.

Здесь последним правилом ставится следующее: deny all from any to any;

Зависит от конфигурации ядра, но по умолчанию во freebsd профелируется закрытый тип.

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

Следует помнить о том что к всем прочитанным правилам после перечтения файла, присоединится еще одно - запрещающие всё, как и в закрытом типе.

Указывается тип фаервола следующим образом в /etc/rc.conf:

firewall_type="<ТИП>"

Где тип open, close или путь к файлу соответственны описанным выше типам.

В первых двух случаях можно написать какой -либо shell скрипт который сам задаст требуемые правила, но мы пойдем иным путем.

Мы будем использовать файл с правилами, в котором для начала напишем allow all from any to any чтобы для начала удовлетворить любым запросам.

Итак, добавим правило в файл настроек, назовем его /etc/firewall.conf :

echo add 100 allow all from any to any >/etc/firewall.conf

Добавим тип фаервола в /etc/rc.conf:

echo firewall_type="/etc/firewall.conf" >>/etc/rc.conf

Если компилировали ядро - то загружаем систему, если подгружали модуль то пробуем

/etc/netstart

ГЛАВА 2.

В этой главе предлагаю рассмотреть настройку уже настроенного нами маршрутизатора пакетов между сетями

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

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

Положим начальные условия:

внутренняя сеть: rl0: 10.10.10.1/24

внешняя сеть: rl1: 192.168.0.1/16,

Задача: На базе начальных условий настроить систему трансляции адресов так, чтобы внутренняя сеть видела и могла обращаться к любому адресу внешней сети, от имени(ip) настраиваемого нами шлюза, а внешняя сеть, в свою очередь, не могла определить с какого адреса внутренней сети поступает запрос, и отвечала обратно шлюзу же, который бы транслировал адреса обратно.

Предположим так же что у нас настроена система роутинга, настроен фаервол ipfw,

поднят демон routed.

Есть много систем позволяющих транслировать ip адреса различных подсетей от своего имени.

Частные наиболее популярные случаи это natd и ipnat.

natd - очень хорошая система, но у неё есть один серьезный недостаток.

Все соединения открывающиеся в системе - проходят через отдельный демон natd, что может сильно нагрузить систему при больших объемах трафика.

ipnat не страдает этой проблемой, так как встроен в ядро системы, потому предлагаю использовать именно его.

Для конфигурации ipnat нужно создать соответствующий конфигурационный файл с настройками - правилами по которым эта система будет работать.

Назовем его: /etc/ipnat.rules

И внесем туда следующие строки:

map rl1 from 10.10.10.0/24 to 192.168.0.0/16 -> 192.168.0.1/32 proxy port ftp ftp/tcp

map rl1 from 10.10.10.0/24 to 192.168.0.0/16 -> 192.168.0.1/32

Расшифровка первой записи: переименовать исходящий адрес пакета идущего через внешний rl1 интерфейс с

адреса принадлежащего подсети 10.10.10.0/24 в сеть 192.168.0.0/16 - в адрес "192.168.0.1" - правило действительно для всех ftp соединений.

Последние - специальное допущение сделанное в рамках использования ftp протокола.

Расшифровка второй записи: переименовать исходящий адрес пакета идущего через внешний rl1 интерфейс с адреса принадлежащего подсети 10.10.10.0/24 в сеть 192.168.0.0/16 - в адрес "192.168.0.1" - правило действительно для всех

соединений не попавших под предыдущие правило.

После проведенного действия следует подгрузить модуль ipl.ko: ipl - IP packet log device, после которого станет доступно устройство /dev/ipnat необходимое для работы ipnat:`

kldload ipl

Далее, перечитаем конфиг ipnat-a следующей командой:

/sbin/ipnat -CF -f /etc/ipnat.rules

- o принадлежности флагов подробнее читайте man ipnat;

Проверим вступившие в оборот правила командой:

/sbin/ipnat -l

Результат выполнения должен быть примерно таким:

List of active MAP/Redirect filters:

map rl1 from 10.10.10.0/24 to 192.168.0.0/16 -> 192.168.0.1/32 proxy port ftp ftp/tcp

map rl1 from 10.10.10.0/24 to 192.168.0.0/16 -> 192.168.0.1/32

List of active sessions:

Для включения поддержки ipnat-а в /etc/rc.conf можно внести следующие строки:

ipnat_enable="YES"

ipnat_program="/sbin/ipnat -CF -f"

ipnat_rules="/etc/ipnat.rules"

ipnat_flags=""

FIREWALL

Вообще, рекомендуется настроить фаервол для безопасности внутренней сети и ограничения к ней подключений из внешней сети. Как это сделать - я возможно напишу позднее, а на данном этапе можно обойтись и без этого:)

ГЛАВА 3.

Задача:

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

IP адрес выделенного во внешней сети шлюза: 192.168.10.10

Выполнить эту задачу не просто, а очень просто!

Достаточно определить по умолчанию маршрут на который будут отсылаться все пакеты адресованные подсети не имеющий отношения к нашим ( ни к внутренней, ни к внешней ).

После этого надо будет настроить ipnat на трансляцию адресов еще и туда, и

наша задача будет выполнена.

Первую часть сделать проще простого - нужно просто добавить маршрут по умолчанию "default" (0.0.0.0), и сделать это можно программой route:

/sbin/route add default 192.168.10.10

Здесь мы указали в качестве следующей точки - выданный нам внешней сетью сервер 192.168.10.10.

Если на наш шлюз придет пакет, адрес назначения которого не будет относиться ни к одной из определенных на наших интерфейсах ( rl0 rl1 ) сетей, - то этот пакет наш шлюз направит именно на "внешний шлюз", - а тот уже сам разберется

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

Чтобы автоматизировать процесс выставления роутера по умолчанию - можно прописать запись о нем в всё тот же пресловутый конфигурационный файл

/etc/rc.conf:

defaultrouter="192.168.10.10"

И тогда, при загрузке системы, маршрут будет вступать в силу.

Посмотреть его можно при помощи утилиты netstat передав ей параметр "r", что бы она показала таблицу роутинга в системе:

gw$ netstat -r | grep default

default 192.168.10.10 UGS 18562067 rl1

Теперь, добавим в /etc/ipnat.rules строки для того чтобы научить наш шлюз транслировать через себя пакеты проходящие в глобальную сеть.

Сделать это можно по образу и подобию предыдущих записей:

map rl1 from 10.10.10.0/24 to 0.0.0.0/0 -> 192.168.0.1/32 proxy port ftp ftp/tcp

map rl1 from 10.10.10.0/24 to 0.0.0.0/0 -> 192.168.0.1/32

или короче:

map rl1 10.10.10.0/24 -> 192.168.0.1/32 proxy port ftp ftp/tcp

map rl1 10.10.10.0/24 -> 192.168.0.1/32

- так вроде, даже и симпатичнее:)

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

regards, procool@

Обновлено: 12.03.2015