Установка и настройка FreeBSD
2011.11.29От автора
Эта статья в основном расчитана на сетевых администраторов небольших организаций, которые хотят доверить предметной ОС доступ в Интернет. Но приведенные здесь рекомендации также могут быть полезны и другим опытным "айтишникам", которые хотят использовать эту ОС в работе. Впрочем, никаких гениальных изобретений и исчерпывающих выкладок здесь нет. Если есть острое желание изучить эту ОС, что называется "с потрохами", то рекомендую книжку "Сага о FreeBSD" Алексея Федорчука . Однако я постарался описать процесс так, чтобы вызвать у читателя желание разбираться самостоятельно. Надеюсь, что это получилось.
Введение
Наступая на грабли и разбираясь с установкой этой ОС самостоятельно, человек приобретает опыта несравнимо больше (богаче), нежели с пошаговым руководством. Посему, я предлагаю самостоятельно разобраться с загрузкой с CD, разбивкой диска и собственно установкой. Однако некоторые рекомендации по этому поводу будут.
Прелесть FreeBSD (как впрочем и большинства POSIX-овых операционок) - иерархия файловой системы с единым корнем. В любую точку этой иерархии можно монтировать (совершенно прозрачно для большинства приложений) разделы диска. Это значит, что если у вас, например, кончилось место в /var, и больше всего съел /var/mail, то вы спокойно выносите его (mail) на отдельный раздел не меняя ничего в настройках софта.
Загрузка с CD и разбивка дисков
Начиная с 5.x версии, загрузчик предлагает нам до загрузки ядра выбрать варианты. Это пригодится, если вдруг в обычном режиме ядро подвисает, не успевая выдать рюшечки sysinstall - перезагружаемся и выбираем safe mode. Кстати, в sysinstall везде лучше пользоваться кнопкой "Space" чтобы нажимать, и кнопками "Tab" и стрелками чтобы перемещаться; "Enter" здесь очень часто приводит к нежелательным результатам. Не следует пугаться слова "Expert" при выборе способа установки - нам нужен именно "Custom"-ный вариант.
Partitions - это то, что называется раздел носителя (жесткого диска, например), который непосредственно виден как UFS (Unix File System). На "живой" системе он виден например так /dev/ad0s1. Можно его использовать весь целиком, но лучше его разбить на логические разделы - label (то, что я обычно называю разделами). Неразберихи не возникает, т.к. обычно из контекста понятно, о чем речь, и почти всегда это именно Label. В системе такой логический раздел виден (соответственно) так: /dev/ad0s1a. "a" - это всегда корень, тогда как "c" - все label-ы сразу. В некоторых случаях можно использовать для файловой системы один единственный раздел на весь носитель сразу. Но для гибкости лучше разбивать на физические и логические разделы.
Отмечу, что если на носителе уже есть разделы (с MS Windows, например), то они будут видны например так: /dev/ad0s2. "ad" - это своего рода семейство носителей, категория (atapi disk). ad0 - первый винт, ad1 - второй и т.д. "s" - это физический раздел (slice, partition). ad0s1 - первый раздел на первом винте, ad1s3 - третий раздел на втором винте, и т.д.
Создайте один физический раздел в Partitions и затем в Label создаем:
- / - не менее гигабайта (лучше 2G), т.к. ядро с модулями значительно распухло со времен 4.x.
- SWAP - как минимум в два раза больше объема оперативной памяти (2*RAM + ядро), подробности тут. Если дисков (массивов) несколько, то не помешает разместить SWAP на каждом из них.
- /tmp - в зависимости от того, насколько часто перезагружается сервер (чем чаще - тем меньше тут надо места, для начала подойдет 1G).
- /var - если уверенности нет, то лучше сделать на глаз 2-3 (4-5) гигабайт.
- /home - примерно 3-5 гигабайт, но все зависит от того, собираетесь ли вы париться о личных данных пользователей. Лучше конечно бэкапить этот раздел, и поэтому сделайте его поменьше (1-2G), чтоб юзерам было не повадно складывать туда некритичный для работы хлам.
- /usr - также как и /var. Эти разделы должны быть разными по причинам, описанным в man hier. Если софт ставить правильно, то в /usr попадают статические (изменяющиеся руками) файлы, а в /var соответственно динамические (которые меняются системой в автономном режиме).
- /storage - все остальное. Этот раздел будет использоваться для некритичного для работы самого сервера контента, а также для файлов сервисов, которые надо бэкапить своими средствами.
Установка
В 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 (а еще лучше - сделать туда симлинк).
Каталог /usr/share/zoneinfo является частью дистрибутива и его можно обновить (например, когда часовые пояса меняются, как было когда Медведев отменил переход на зимнее время) либо из исходников, либо из порта misc/zoneinfo.
Настройка rc
Вообще, сценарий rc можно сравнить с автозагрузкой в windows, однако это не передает широты и глубины процесса запуска сервисов FreeBSD. В начале своего UNIX-пути я читал Maurice J. Bach "Архитектура операционной системы UNIX" и при этом понимал не больше тридцати процентов написанного, что не мешало мне увлекаться этим процессом так, как будто это "Властелин колец". В двух словах: ядро распознает все железо на машине, подгружает модули, а затем запускает init, который в свою очередь использует rc для запуска и настройки всех возможных приложений (включая конфигурацию сетевых интерфейсов, пакетного фильтра, запуск сервисов интернета, баз данных и всего прочего). Управлять работой сценария rc можно, редактируя его "должностную инструкцию" /etc/rc.conf. Многие настраивают его через sysinstall, но меня лично это бесит. Гораздо лучше делать это напрямую.
Здесь я предлагаю вам минимальные настройки, а за подробностями - man rc.conf.
hostname="someserver.domain.tld"
sshd_enable="yes"
firewall_enable="yes"
firewall_quiet="yes"
firewall_logging="yes"
firewall_type="open"
tcp_extensions="no"
icmp_drop_redirect="yes"
icmp_log_redirect="no"
ip_portrange_first="16384"
ip_portrange_last="49151"
background_fsck="no"
fsck_y_enable="no"
update_motd="no"
clear_tmp_enable="yes"
keymap="ru.koi8-r"
keyrate="fast"
scrnmap="koi8-r2cp866"
font8x16="cp866-8x16"
font8x14="cp866-8x14"
font8x8="cp866-8x8"
blanktime="300"
saver="fade"
sendmail_enable="no"
Настройки, которые применяются до просмотра этого файла можно посмотреть в /etc/defaults/rc.conf. Принцип очень простой - прописывайте то, что хотите изменить. Скрипты, которые смотрят этот файл, в основном находятся в /etc/rc.d. Весь софт, который не поставляется в дистрибутиве, держит свои скрипты запуска в /usr/local/etc/rc.d (если вы конечно в ладах с hier и пакетным менджером).
Сборка и установка ядра
Собирать и устанавливать свое ядро обычно не требуется. В современных реалиях это не дает хоть какого-то прироста производительности. Однако делать это в некоторых случаях таки приходится (например, чтобы добавить IPSEC), поэтому я опишу процесс, но вам советую делать это по необходимости.
При переустановке системы я обычно забываю про файл конфигурации ядра, поэтому его лучше разместить в /root/kernel.CONFIG, сделать симлинк к нему из /usr/src/sys/amd64/conf/my_kern и прописать его в /etc/make.conf:
KERNCONF=my_kern
В качестве шаблона берем файл GENERIC.
Придумаем какой нибудь осмысленный IDENT, добавим поддержку ipfw:
options IPFIREWALL
options IPFIREWALL_VERBOSE
options IPFIREWALL_VERBOSE_LIMIT=2000
Не советую добавлять IPFIREWALL_DEFAULT_TO_ACCEPT, см. "Настройка пакетного фильтра". Если будем крутить NAT, то также добавим:
options IPDIVERT
Рядом с device sc
добавим:
options SC_HISTORY_SIZE=2000
Это значительно увеличит глубину скроллинга консоли.
Теперь заходим в /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.
Кстати, при запуске bash пользователям на входе в систему, он (bash) читает файлы .profile и .bash_profile.
А когда bash запускается с командной строки (например, через sudo bash) - он читает .bashrc домашней директории
вошедьшего пользователя независимо от того, чьи права приобретаются в результате. Обычно в консоли работа идет
под root-ом, поэтому лучше все нужные переменные окружения и алиасы писать в .bashrc. Мой пример:
export EDITOR=vim
export PAGER=less
alias ls="gls --color"
По поводу кодировки в консоли. Русификация консоли делается в 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 нужно в том случае, если есть риск, что кто-то по незнанию поднимет на сервере какой-то сетевой сервис для внутреннего пользования и забудет при этом зарезать прослушку внешнего IP. Например, СУБД mysql для локального использования не должна слушать ничего кроме порта на 127.0.0.1 и/или unix-сокета. Я всегда за этим слежу на своих серверах. Поэтому 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.
- Фильтр по принципу работы похож на сторожа, который просматривает список правил сверху вниз для каждого проходящего мимо него сетевого пакета.
- Этот сторож (фильтр) сравнивает текст правила со свойствами конкретного пакета.
- Фильтр прекращает сверять пакет со списком правил, если ему встретилось правило, подходящее всем свойствам данного конкретного пакета.
- Когда подходящее пакету правило нашлось, фильтр выполняет относительного этого пакета действие, указанное в правиле.
За деталями работы пакетного фильтра 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
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
*/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Не делайте этого! Принцип "Все запрещено, что явно не разрешено" должен стать опорой в настройке пакетного фильтра.
Благодарности
Большое спасибо Пантелеймонову Дмитрию за конструктивную критику и советы. Он значительно помог мне сделать статью ближе к читателю, а также успокоиться относительно проблемы достаточной хорошести. :)