На главную
Last update: 15:04 18/05/2009  

Установка и настройка FreeBSD

От автора

Эта статья в основном расчитана на администраторов локальных сетей небольших организаций, которые хотят доверить предметной ОС доступ в Интернет. Но приведенные здесь рекомендации также могут быть полезны и другим опытным "айтишникам", которые хотят использовать эту ОС в работе. Впрочем, никаких гениальных изобретений и исчерпывающих выкладок здесь нет. Если есть острое желание изучить эту ОС, что называется "с потрохами", то рекомендую книжку "Сага о FreeBSD" Алексея Федорчука.

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

Загрузка с CD и разбивка дисков

Начиная с 5.x версии, загрузчик предлагает нам до загрузки ядра выбрать варианты. Это пригодится, если вдруг в обычном режиме ядро подвисает, не успевая выдать рюшечки sysinstall - перезагружаемся и выбираем safe mode (что-то это мне напоминает :). Кстати, в sysinstall везде лучше пользоваться кнопкой "Space" чтобы нажимать, и кнопками "Tab" и стрелками чтобы перемещаться; "Enter" здесь очень часто приводит к нежелательным результатам. Не следует пугаться слова "Expert" при выборе способа установки - нам нужен именно "Custom"-ный вариант.

Разбивая диски следует быть уверенным в том, что список имеющихся задач для этого сервера существенно дополняться не будет, ибо менять потом разбивку весьма затруднительно. В любом случае советую завести следующие разделы:

  • / - не менее гигабайта, т.к. ядро с модулями значительно распухло со времен 4.x.
  • SWAP - как минимум в два раза больше объема оперативной памяти (2*RAM + ядро); система гарантирует, что даже в худьшем варианте замусоривания памяти (вся ОП выгружена на диск, снова до конца заполнена, и нужно вернуть назад все выгруженное - требуется удвоенный объем "свопа"), все колом не встанет (подробности тут). Если дисков (массивов) несколько, то не помешает разместить SWAP на каждом из них.
  • /tmp - в зависимости от того, насколько часто перезагружается сервер (чем чаще - тем меньше тут надо места).
  • /var - если уверенности нет, то лучше сделать на глаз 2-3 (20-30 :) гигабайт; по мере накопления опыта и размножения всяческих сервисов Интернета место тут обязательно когда-нибудь кончится, и в этом случае помогут симлинки.
  • /usr - все оставшееся пространство.
После приобретения опыта, вышеприведенная схема разделов у Вас скорее всего изменится.

Установка

В Distributions выбираем Minimal, а затем заходим в Custom, чтобы добавить то, что надо. Если есть возможность, то Ports лучше не ставить, а скачать после установки свежие с FTP (см. ниже). Но если сразу после установки доступа к Интернету нет, а порты нужны (например у Вас исходники в distfiles есть с собой) - то можно ставить, а затем (как только доступ появится) сразу обновить через cvsup, о чем речь пойдет ниже.

Оболочка sysinstall ничего реально не делает на дисках, пока мы не делаем одно из двух:

  • нажимаем кнопку "W" в разделах "Partition" и "Label"
  • нажимаем "Commit" и далее
В обоих случаях оболочка предупреждает о последствиях. С этим знанием можно без проблем "тренироваться" до посинения, не боясь потерять данные.

После завершения процессов копирования, sysinstall возвращает назад в меню. Когда я первый раз в жизни ставил FreeBSD, у меня на этом месте возникла мысль "она че, не установилась чтоли?!?", а затем мои руки начали установку по-новой. И так происходило до тех пор, пока я не решил перезагрузиться. Имхо, только глубокое понимание принципа UNIX ("инструменты, а не политика") дает ясность относительно причин этого конфуза - на самом деле ОС установилась, и поэтому следует выходить из утилиты и перезагружаться.

Настройка

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

  • установка даты и времени
  • настройка сценария /etc/rc
  • сборка и установка ядра
  • установка и настройка так называемого "окружения" (различных удобных приложений для работы)
  • настройка периодических работ
  • настройка пакетного фильтра

Установка даты и времени

Это очень важно. Стоит пренебречь этим один раз на реально работающем сервере, чтобы потом крепко-накрепко усвоить важность правильной установки даты и времени. Время, которое установлено в BIOS, не содержит в себе часового пояса. Поэтому лучше расчитать и выставить текущее время по гринвичу командой date (или перезагрузиться и сделать это через CMOS Setup, или, если уже есть Интернет, командой ntpdate pool.ntp.org), а затем выбрать подходящую зону из /usr/share/zoneinfo и скопировать ее в /etc/localtime (а еще лучше - сделать туда симлинк).

Настройка rc

Вообще, сценарий rc можно сравнить с автозагрузкой в windows, однако это не передает широты и глубины процесса запуска сервисов FreeBSD. В начале своего UNIX-пути я читал Maurice J. Bach "Архитектура операционной системы UNIX" и при этом понимал не больше тридцати процентов написанного, что не мешало мне увлекаться этим процессом так, как будто это "Властелин колец". В двух словах: ядро распознает все железо на машине, подгружает модули, а затем запускает init, который в свою очередь использует rc для запуска и настройки всех возможных приложений (включая конфигурацию сетевых интерфейсов, пакетного фильтра, запуск сервисов интернета, баз данных и всего прочего). Управлять работой сценария rc можно, редактируя его "рабочую инструкцию" /etc/rc.conf. Здесь я предлагаю скачать мой шаблонный rc.conf, а за подробностями обратиться к man rc.conf.

Сборка и установка ядра

При переустановке системы я обычно забываю про файл конфигурации ядра, поэтому его лучше разместить в /root/kernel.CONFIG, сделать симлинк к нему из /usr/src/sys/amd64/conf/local и прописать его в /etc/make.conf:
KERNCONF=local
В качестве шаблона лучше взять файл GENERIC. Опять таки, советую с конфигурированием разобраться самостоятельно, чтобы потом все делать всегда с первого раза. Но некоторые советы все же дам; например - убираем все то, в чем точно уверены что не нужно; а то что не уверены - не трогаем. Не советую убирать device miibus (нужен для большинства сетевых карт, однако для некоторых совсем не нужен - например, em), device bpf (нужен для работы dhcp и tcpdump). В целом же, лучше взять /var/run/dmesg.boot в качестве контрольного документа, там видны устройства, найденные ядром GENERIC при загрузке.

Придумаем какой нибудь осмысленный IDENT. Добавим поддержку ipfw:
options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=2000

Не советую добавлять IPFIREWALL_DEFAULT_TO_ACCEPT, см. "Настройка пакетного фильтра". Если будем крутить NAT, то также добавим:
options IPDIVERT
Если у нас в железе SCSI не пахнет - убираем все, кроме scbus и da (которые пригодятся для работы с USB-флэшками).
Рядом с device sc добавим:
options SC_HISTORY_SIZE=2000
Это значительно увеличит глубину скроллинга консоли.
Убираем Serial ports, Parallel ports, PCCARD - если конечно они не нужны.

Теперь заходим в /usr/src и пишем: make buildkernel, а затем make installkernel. Если ошибки на buildkernel, то редактируем файл конфигурации ядра и пробуем снова. Если ядро установилось нормально, но при перезагрузке возникла проблема, то можно загрузится с GENERIC ядром и повторить попытки.

Настройка окружения

Свежескачанные порты (ftp://ftp.freebsd.org/pub/FreeBSD/ports/ports/ports.tar.gz) распакуем в разделе /usr. Если у нас имеется свой ftp сервер, где складируются distfiles для экономии трафика, то пропишем в /etc/make.conf для него адрес:
MASTER_SITE_OVERRIDE=ftp://ftp.mydomain.ru/pub/FreeBSD/distfiles/${DIST_SUBDIR}/

Если нам нужен INDEX (например, для make search ...), а он не хочет скачиваться с помощью make fetchindex (а нам лень ждать make index, и нам мешает какой-то внешний firewall лить http напрямую), то можно сделать это вручную через прокси:
$ cd /usr/ports
$ export HTTP_PROXY=http://pro.xy.IP.addr:port
$ fetch http://www.FreeBSD.org/ports/INDEX-7.bz2
$ bunzip2 INDEX-7.bz2

Установим из портов следующие приложения:

  • удобный shell (у меня это shells/bash)
  • удобный редактор (у меня это editors/vim с переменной NO_GUI=yes, конфиг для которого после установки можно взять в /usr/local/share/vim/vim__/vimrc_example.vim - добавим туда set tabstop=4, уберем или закоментим секцию про backup и строку filetype plugin indent on)
  • security/sudo: сразу же сделаем доступ для всех в группе wheel командой visudo и уничтожим пароль рута командой vipw (заменяем хэш пароля звездочкой [*])
  • sysutils/coreutils: затем gls --color записываем в алиасы и у нас появляется цветной листинг файлов как в линуксе (не забываем указать TERM=xterm-color в SSH клиенте)

Сборку редактора vim из портов следует производить с переменной NO_GUI=yes, чтобы он не пытался ставить x11. После установки, хороший конфиг можно взять из /usr/local/share/vim/vim__/vimrc_example.vim (и положить себе в домашнюю директорию с именем .vimrc), с небольшими изменениями:

  • пропишем set tabstop=4, чтобы tab-отступ был в 4 символа (а не 8, как по-умолчанию);
  • уберем set backup (мне лично не нравятся "слепые" бэкапы, ибо если надо мониторить - поставим какую нибудь RCS, например, devel/mercurial);
  • уберем filetype plugin indent on (эта штуковина пытается "умничать", когда я вставляю текст в режиме insert из буфера - проще руками отступы делать);
  • пропишем set encoding=1251
    set fileencoding=1251
    set termencoding=koi8-r

    ибо по умолчанию русификация консоли в koi8-r (и терминал соответственно тоже), а файлы чаще всего содержат кирилицу в Windows-1251.

Я лично пользуюсь MC (misc/mc) лишь в некоторых случаях:

  • нужно залить (или наоборот скачать) дерево файлов на FTP
  • нужно найти в системе файл по содержимому
Если Вы знаете, как (чем) еще можно делать эти операции, отпишите мне пожалуйста - буду весьма признателен.

Некоторые замечания по поводу доступа к правам root через sudo. С точки зрения безопасности, не следует делать его через NOPASSWD. Чисто теоретически, какой-нибудь троян, использующий sudo, при запуске непременно спалится, если мы не используем NOPASSWD. Но, если мы не пускаем кого попало в группу wheel (сервисы я имею в виду), не оставляем консоль без присмотра и самостоятельно следим за дырами в ОСи и сервисах (что абсолютно обязательно для администратора) то ничего страшного в этом я лично не вижу. С другой стороны, использование NOPASSWD вместе с доступом SSH без пароля с помощью ключа дает прекрасную защиту от клавиатурных снифферов на нашей рабочей машине, на которой частенько стоит именно Windows. Напрашивается вывод о том, что в каждом конкретном случае следует решить это отдельно. Например на desktop-е лучше не использовать NOPASSWD, т.к. качество приложений для X в области безопасности оставляет желать лучшего. Но на сервере, где пакетным фильтром все зашито, а также софт регулярно обновляется и ничего лишнего нет - лучше авторизоваться по ключу и использовать NOPASSWD.

Кстати, при запуске bash пользователям на входе в систему, он (bash) читает файлы .profile и .bash_profile. А когда bash запускается с командной строки (например, через sudo bash) - он читает .bashrc домашней директории вошедьшего пользователя независимо от того, чьи права приобретаются в результате. Обычно в консоли работа идет под root-ом, поэтому лучше все нужные переменные окружения и алиасы писать в .bashrc. Мой пример:
export EDITOR=vim
export PAGER=less
alias ls="gls --color"
alias mc="mc -a"

По поводу кодировки в консоли. Русификация консоли делается в koi8-r, а файлики в системе чаще всего содержат текст в кодировке Windows-1251. Общего решения на этот счет (насколько я знаю) не существует, но я нашел способ настроить редактор vim так, чтобы он перекодировал содержимое файлов на лету при редактировании (а после закрытия и/или записи файла - перекодировал назад). Делается это в .vimrc:

set encoding=cp1251
set fileencoding=cp1251
set termencoding=koi8-r

Настройка периодических работ

Возьмем шаблон sup-файла для обновления портов (/usr/share/examples/cvsup/ports-supfile), подредактируем его в области *default host, закометируем ports-all и включим (уберем решетку) на всех портах, за исключением ненужных категорий. После чего запишем его куда-нибудь (например в /root/ports-supfile) и добавим в crontab задание для обновления портов /usr/bin/csup -1 -L 0 -l /var/run/ports-update.lock /root/ports-supfile.

Также есть специальная программа для обновления портов: ports-mgmt/portsnap. Если у нас имеются проблемы с прохождением пакетного фильтра cvsup-ом, либо наличествует паранойя относительно man-in-the-middle атаки, либо нас не устраивает скорость обновления, то пробуем использовать эту программу.

Очень часто сервера под FreeBSD стоят без MTA. Sendmail выключается совсем, чтобы не отправлял отчеты. Надо сказать, что это не очень хорошая практика. Однако, если все же sendmail выключается совсем, то следует прикрутить чистку очереди писем, которая накапливается и может в конечном итоге переполнить раздел /var. Чтобы совсем выключить sendmail, нужно в /etc/rc.conf:
sendmail_enable=no
sendmail_submit_enable=no
sendmail_outbound_enable=no
sendmail_msp_queue_enable=no

Теперь, автоматическая чистка очереди раз в сутки в /etc/crontab:
5 2 * * * root /usr/bin/find /var/spool/clientmqueue/ -type f -delete

Настройка пакетного фильтра

Бытует мнение, что firewall (он же пакетный фильтр) - штука геморройная и, в большинстве случаев, ненужная. Я согласен с этим, но с большой оговоркой - настройка и применение firewall-а необязательно (нецелесообразно) лишь в некоторых случаях. Если Вы не применяете пакетный фильр для защиты сервисов, то защита ложится на "плечи" самих сервисов. Следует понять, что настройка фильтра - это разовый геморрой (который лечится раз и навсегда изучением предмета), а слежение за дырами в сервисах (порою - многочисленных, далеко не все из которых нужно "выставлять на публику") является геморроем постоянным.

Конфигурационный файл по умолчанию - /etc/rc.firewall можно подредактировать и оставить, но лучше все сделать самостоятельно в отдельном файле /etc/rc.firewall.local.

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

Чтобы спать спокойно, настроив firewall, нужно знать основы работы как минимум следующих протоколов: IP, TCP, UDP, ICMP. А также следует знать принцип работы необходимого минимума конкретных сервисов (приложений): DNS, SSH. Если отсутствует знание, то крутить пакетный фильтр вообще не рекомендую. Поэтому, я предлагаю Вам небольшую шпаргалку. Повторюсь - Вы должны сколько-нибудь хорошо разбираться в принципах работы протоколов стэка TCP/IP.

    Шпора :)
  • Протокол TCP (в отличие от UDP) оперирует понятием "соединение". Т.е. прежде чем передавать по этому протоколу полезные данные (состояние соединения = ESTABLISHED), обе стороны (клиент и сервер) должны обменяться несколькими пакетами. С точки зрения сервера по соединению проходит три таких пакета: SYN от клиента, SYN+ACK к клиенту, ACK от клиента; с точки зрения клиента - два пакета: SYN к серверу, SYN+ACK от сервера.
  • Для идентификации конкретных сервисов (или прикладных протоколов, которые находятся выше стэка TCP/IP, согласно модели OSI) в протоколах UDP и TCP определена нумерация портов (от 1 до 65535).
  • WKS (well-known services) - это перечень общеизвестных (стандартных) сервисов, за которыми закреплены строго определенные номера портов. Так сделано для того, чтобы клиент мог с успехом добраться до нужного ему сервиса, "обладая" лишь адресом сервера.
  • Для передачи пакета (TCP или UDP), клиент также обязан выбрать номер порта со своей стороны. Если на сервере эти порты строго определяются через WKS, то на клиенте этот порт выбирается динамически (на усмотрение ОС клиента). Однако, из этого правила есть исключения (например, FTP data-соединение в активном режиме устанавливается сервером, который на своей стороне для этого всегда использует порт tcp/20).
  • Кроме TCP и UDP, пакеты IP могут "нести на себе" и другие протоколы, которые не содержат в себе портов. Например, протокол ICMP оперирует типами. Но следует всегда помнить, что IP является транспортом для всех остальных протоколов стэка TCP/IP; и поэтому невозможно запретить IP, но оставить при этом, например, ICMP.
  • Утилиты сетевой диагностики (такие, как ping и traceroute) чаще всего используют протокол ICMP, который для этого, собственно, и предназначен.
  • Особо хочется сказать о протоколе DNS, который является жизненно важным для нормальной работы большинства сервисов. Этот протокол находится выше TCP и UDP по модели OSI, и использует их оба для транспорта: TCP используется для копирования зон между DNS-серверами, UDP используется для трансформации доменных имен в адреса (и наоборот). При этом в обоих транспортных протоколах (TCP и UDP) используется один и тот же номер порта - 53. С точки зрения клиента обязательным является доступность именно UDP-сервиса DNS. Сервер DNS не во всех случаях нуждается в доступности порта tcp/53, однако эти случаи скорее исключения, чем правило.
  • В нашем случае (настройка ОС FreeBSD) скорее-всего появится необходимость удаленного (терминального) управления сервером. Этим занимается сервис sshd (работающий по протоколу SSH), за которым закреплен WKS-порт номер 22.
Если вышеописанная шпаргалка показалась Вам банальной и ненужной - прошу Вас, не пишите мне никогда.

На данный момент большинство ISP дают доступ по протоколам PPPoE/PPTP. В этом случае описанные в настоящей статье рекомендации вполне применимы с той лишь разницей, что ppp кроме обычного динамического маскарадинга ничего больше дать не сможет. Но об этом будет сказано ниже в соответствующей части статьи.

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

  • Фильтр по принципу работы похож на сторожа, который просматривает список правил сверху вниз для каждого проходящего мимо него сетевого пакета.
  • Этот сторож (фильтр) сравнивает текст правила со свойствами конкретного пакета.
  • Фильтр прекращает сверять пакет со списком правил, если ему встретилось правило, подходящее всем свойствам данного конкретного пакета.
  • Когда подходящее пакету правило нашлось, фильтр выполняет относительного этого пакета действие, указанное в правиле.

За деталями работы пакетного фильтра freebsd, обратитесь к man ipfw.

Возьмем исходный файл rc.firewall и отредактируем его в rc.firewall.local, убирая все лишнее. Оставляем:

  • выборку переменных из rc.conf:
    if [ -z "${source_rc_confs_defined}" ]; then
    	if [ -r /etc/defaults/rc.conf ]; then
    		. /etc/defaults/rc.conf
    		source_rc_confs
    	elif [ -r /etc/rc.conf ]; then
    		. /etc/rc.conf
    	fi
    fi
    
  • использование переменной firewall_quiet:
    case ${firewall_quiet} in
    [Yy][Ee][Ss])
            fwcmd="/sbin/ipfw -q"
            ;;
    *)
            fwcmd="/sbin/ipfw"
            ;;
    esac
    
  • инициализацию правил и защиту "петлевой" сети:
    ${fwcmd} -f flush
    
    ${fwcmd} add 100 pass all from any to any via lo0
    ${fwcmd} add 200 deny all from any to 127.0.0.0/8
    ${fwcmd} add 300 deny ip from 127.0.0.0/8 to any
    
Пожалуй, это все, что нужно оставить из исходного файла rc.firewall. Не забудем подправить firewall_script в /etc/rc.conf. Теперь будем добавлять нужные нам правила, помня о выбранной политике: "Все что явно не разрешено, должно быть запрещено."

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

${fwcmd} add deny icmp from any to any frag
${fwcmd} add allow icmp from me to any
${fwcmd} add allow icmp from any to me

ipfw умеет оперировать состоянием tcp соединения, т.е. видеть разницу между установкой (SYN пакет), и установленным (ACK+SYN и другие флаги). Разрешим любым пакетам "бегать" по уже установленным соединениям (established), но также конкретно определим разрешенные соединения на этапе установки (setup):

${fwcmd} add allow tcp from any to any established
${fwcmd} add allow tcp from me to any setup
${fwcmd} add allow tcp from any to me 25,110 setup

admins="212.0.65.150 212.0.65.0/25 192.168.22.0/24 192.168.1.0/24"
for i in $admins;
do
        ${fwcmd} add allow tcp from $i to me 22 setup ;
done
Никакой "дыры" здесь нет: если пришел пакет с флагом ACK (который подходит под правило с established), а наш сервер при этом не имеет никаких сокетов для этого пакета (не было никаких SYN пакетов, которые подходят под правило setup), то ответ на это будет вполне однозначный - RST. В примере выше, я разрешил входящие соединения TCP откуда угодно только на порты 25 и 110, а с перечисленных (админских) адресов на порт 22.

Чтобы разрешить прохождение пакетов, в которых не поддерживается соединение (например, UDP), нужно добавлять по два правила для каждого случая (для пакета "туда", и отдельно для пакета "обратно"). Например, чтобы разрешить исходящие (наши) запросы DNS:

${fwcmd} add allow udp from me to any 53
${fwcmd} add allow udp from any 53 to me
В случае, если протокол не поддерживает порты, а разрешать больше, чем надо не хочется, то следует воспользоваться возможностью ipfw создавать динамические правила. Идея здесь состоит в том, чтобы фильтр запоминал "прошедьшие мимо него" запросы, и затем разрешал проходить обратно ответам. Например, чтобы разрешить доступ извне к нашему VPN:
${fwcmd} add allow tcp from any to me dst-port 1723 setup
${fwcmd} add allow gre from any to me keep-state
Обратные пакеты-ответы gre будут разрешены по правилу keep-state. Однако следует иметь в виду, что если ответ придет позднее, чем несколько секунд, то как ответ он уже не засчитывается - фильтр будет смотреть список правил дальше. Время жизни динамических правил можно конфигурировать sysctl-переменными net.inet.ip.fw.dyn_*_lifetime (см. секцию SYSCTL VARIABLES в man ipfw). С точки зрения устойчивости к отказам в обслуживании (DoS), динамические правила являются довольно опасными, и поэтому опция SYSCTL net.inet.ip.fw.dyn_max однозначно ограничивает их максимальное количество. Насколько у Вас в фильтре много правил, опирающихся на динамические, настолько много сервисов окажутся недоступными при переполнении списка последних. Т.е. желательно не злоупотреблять этим, но использовать вполне можно. Например, вместо описанных выше пары правил для DNS пакетов (UDP), можно применить одно правило с keep-state. Приведу сходный пример для "наших" NTP пакетов (тоже UDP транспорта):
${fwcmd} add allow udp from me to any 123 keep-state

В идеале, перед настройкой пакетного фильтра, следует иметь доступ к консоли сервера (физический, IPKVM), но в большинстве случаев можно обойтись и без него. С самого начала добавим в самый конец списка всеразрешающее правило

${fwcmd} add allow log all from any to any
Теперь можно смело (не боясь потерять терминальную связь с сервером) перезагрузить правила:
$ /etc/rc.d/ipfw restart
$ ipfw show
Фильтр записывает в журнал свойства каждого пакета, который он обработал по правилу с log. Смотрим этот журнал, и видим там абсолютно все пакеты, которые нами явно еще не разрешены. Очень удобно смотреть эа этим с помощью tail -f /var/log/security или less /var/log/security (внутри нажать Shift-F). На данном этапе большинство правок списка правил состоит в добавлении новых разрешающих правил, а также в исправлении синтаксических ошибок в уже добавленных правилах.

Редактируйте правила фильтра до тех пор, пока у Вас не наберется решимости поменять это последнее правило на

${fwcmd} add deny log all from any to any
После чего фильтр будет записывать в журнал все те же неразрешенные правилами пакеты, с той лишь разницей, что они будут блокироваться. Чтобы явно ненужные (но частенько появляющиеся) пакеты не засоряли журнал, добавляем для них обычные запрещающие правила перед последним (теперь уже всезапрещающим). Например:
# we dont have any SMB/CIFS services here
${fwcmd} add deny udp from any to any 137,138,139
${fwcmd} add deny tcp from any to any 137,138,139
Но сильно этими "антимусорными" правилами увлекаться не надо, т.к. они сильно снижают эффективность диагностики работы фильтра через журнал /var/log/security. Количество записей в этом журнале строго ограничено, и мы это ограничение указали при сборке ядра - IPFIREWALL_VERBOSE_LIMIT. По достижении этого лимита, фильтр перестает писать, и в этом ничего страшного нет; чтобы фильтр снова начал писать журнал, достаточно скомандовать ipfw resetlog.

Режим работы роутера (настройка NAT)

Компьютер превращается в роутер в том случае, если он правильно умеет обрабатывать транзитные IP-пакеты. Это можно сравнить с тем случаем, когда для тушения пожара люди выстраиваются в цепочку от водоема до горящего объекта: IP-пакетом в данном примере является ведро с водой, а роутером - отдельно взятый человек в цепочке :). В целом, маршрутизация в Интернете гораздо сложнее приведенной аналогии, и для полного ее понимания (осмысления) следует подробно изучить протокол IP в соответствующей области. Также, даже хорошо понимая принципы IP-маршрутизации, следует изучить принципы трансляции адресов насколько это возможно - очень часто начальная простая схема динамической трансляции в дальнейшем дополняется более сложной статической. Рекомендую для этого данную статью.

NAT во FreeBSD тесно связан с пакетным фильтром (ipfw). Поэтому, плюсом ко всему, что уже есть в уме, нужно держать там также следующее:

  • При включении режима роутера (gateway_enable=yes в /etc/rc.conf) фильтр проверяет все транзитные пакеты по два раза: на входе и на выходе.
  • Передав транзитный пакет сервису NAT для корректировки адресов, фильтр затем получает его обратно и продолжает проверять его уже с новыми адресами по списку правил дальше с того места, где закончил.

Сейчас я опишу процедуру настройки NAT в случае доступа в Интернет со статическим (ручным) или динамическим (DHCP) назначением IP-конфигурации. Практика использования NAT на роутерах показала, что при начальной простой настройке трансляции, со временем последняя может значительно усложниться. В связи с этим, лучше с самого начала вынести все ключи в файл /etc/natd.conf; для простой динамической трансляции (с которой лучше начать) этот файл будет пустым. Разрешаем запуск сервиса natd в /etc/rc.conf:

natd_enable=yes
natd_flags="-f /etc/natd.conf"
natd_interface=rl0
Опция natd_interface указывает на сетевой интерфейс, где следует производить трансляцию. Обычно это сетевая карта, которая "смотрит в Интернет".

Теперь я опишу процедуру настройки NAT в случае доступа в Интернет через PPPoE/PPTP штатными для FreeBSD средствами (программу ppp я имею в виду). В ppp NAT вообще ничего кроме простой динамической трансляции (маскарадинга) делать не умеет. И в связи с этим файл /etc/natd.conf не нужен вовсе, а вместо вышеописанных действий следует сделать следующее:

  • включить трансляцию адресов средствами программы ppp в /etc/rc.conf:
    ppp_enable=yes
    ppp_mode=ddial
    ppp_nat=yes
    ppp_profile="my_isp_profile"
    
  • заполнить соответствующий профиль в /etc/ppp/ppp.conf:
    my_isp_profile:
     set device PPPoE:"rl0"
     set dial ""
     set login ""
     set authname "mylogin"
     set authkey "password"
     add default HISADDR
    
Сам по себе канал PPP не является устойчивым, ведь он имеет сеансовую природу. В связи с этим бывает так, что связь лагует и ppp подвисает характерным образом - сотрудники жалуются, что Интернет не работает или страшно лагует. Если перезапуск ppp всегда помогает, то можно доверить эту "грязную" работу моей самописной "собаке". Ей для работы нужно поставить из портов перловый модуль net/p5-Net-Ping-External. Сохраним ее например в /root/ppp_watchdog.pl и пропишем в /etc/crontab:
*/5 * * * * root /root/ppp_watchdog.pl

В остальном, настойка пакетного фильтра в режиме роутера для этих двух вариантов доступа не отличается. Однако следует отметить, что программа ppp непосредственно с пакетным фильтром не связана; более того, она "сама" умеет фильтровать трафик. Соответственно, в /etc/rc.conf нужно выбрать одно из двух: либо natd_enable=yes, либо ppp_nat=yes - не оба варианта одновременно! Если со временем все же придется усложнять настройку NAT, то можно отказаться от трансляции в ppp, и включить более умелый natd, указав ему в качестве интерфейса tun0. Последний вариант я лично не проверял, если Вам удалось - отпишите мне пожалуйста.

Итак, теперь у сервера несколько (обычно два) сетевых интерфейсов. Чтобы обеспечить взаимодействие ipfw с сервисом natd только в случае включения последнего в /etc/rc.conf, скопируем соответствующую секцию в /etc/rc.firewall.local повыше (например, перед инициализацией правил - flush):

case ${natd_enable} in
[Yy][Ee][Ss])
    if [ -n "${natd_interface}" ]; then
        ${fwcmd} add 50 divert natd ip4 from any to any via ${natd_interface}
    fi
    ;;
esac
Рекомендации по настройке пакетного фильтра, изложенные выше не обеспечивают доступ из локальной сети, поэтому дополним их правилами в /etc/rc.firewall.local. Все нижеперечисленные правила следует добавлять выше любых запрещающих правил.

Для начала, опишем диапазон адресов, которые используются внутри ЛВС (здесь и далее - Локальной сети):

lan="192.168.0.0/16"
Для большинства случаев, такой диапазон подойдет. Можно также безболезненно вынести эту переменную в /etc/rc.conf обозвав ее более осмысленно с точки зрения содержимого последнего (например, firewall_lan).

Разрешим утилитам сетевой диагностики и DNS-клиентам доступ в Интернет:

${fwcmd} add allow icmp from $lan to any keep-state
${fwcmd} add allow udp from $lan to any 53
${fwcmd} add allow udp from any 53 to $lan

Разрешим доступ из ЛВС на данный сервер:

${fwcmd} add allow tcp from $lan to me setup
${fwcmd} add allow ip from $lan to me keep-state
В зависимости от политики доступа сотрудников компании в Интернет, следует соответствующим образом добавлять разрешающие правила. Я лишь приведу несколько примеров.

Разрешим доступ из ЛВС к FTP-серверу провайдера:

my_isp_ftp="124.1.90.5"
${fwcmd} add allow tcp from $lan to $my_isp_ftp setup
В этом случае не следует указывать порты, т.к. FTP через NAT работает только в пассивном режиме - исходящие data-соединения (tcp) пойдут в заранее неизвестном диапазоне.

Разрешим из ЛВС "ходить" по web-страничкам в Интернете:

${fwcmd} add allow tcp from $lan to any 80-84 setup
${fwcmd} add allow tcp from $lan to any 443 setup

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

Упаси Вас Господь разрешать все и вся по интерфейсу ЛВС, ведь в таком случае вся вышеописанная защита от паразитного трафика из ЛВС будет сведена практически к нулю. Пример такого "всеразрешающего" правила по локальному интерфейсу:

${fwcmd} add allow tcp from any to any via rl1
К сожалению, практика показывает, что очень многие администраторы настраивают пакетные фильтры именно таким образом. Не делайте этого! Принцип "Все запрещено, что явно не разрешено" должен стать опорой в настройке пакетного фильтра.

Благодарности

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

В заключение

Ваши пожелания, замечания, и особенно критику пишите в гостевую книгу или мне на email: airay [обезьяна] yandex.ru.

На главную
Hosted by uCoz