Теперь до того, как мы начнем, вы должны иметь машину с двумя интерфейсами Ethernet, но только один из этих интерфейсом настроен. То есть в файле /etc/rc.conf должна быть только одна строка ifconfig. С настроенным сетевым мостом это остается так. Но есть одна деталь, требующая некоторых размышлений. По умолчанию функции сетевого моста не включены. Это означает, что до тех, пока не будут выполнены вызовы sysctl, включающие функции сетевого моста, и не в самом начале загрузки, эта машина остается обычной машиной с двумя интерфейсами, только один из которых настроен из файла /etc/rc.conf. Это обстоятельство становится важным для тех частей начального запуска, которые требуют сетевого доступа, скажем, для обращения к DNS. Следует внимательно выбирать интерфейс, который должен быть настроен. В большинстве случаев вам лучше выбрать "внешний" (то есть интерфейс, подключенный к Интернет). В дальнейшем давайте будем полагать, что интерфейс fxp0 является ''внешним'', а fxp1 ''внутренним''. Это означает, что fxp0 должен фигурировать в разделах конфигурации интерфейсов файла /etc/rc.conf, а fxp1 не должен. Вызовы sysctl, включающие функции сетевого моста, заставят работать fxp1 автоматически.
5. Настройка межсетевого экрана Теперь самое время начать пополнять набор правил межсетевого экрана IP для защиты внутренней сети. Здесь есть некоторые сложности, потому что не вся функциональность межсетевого экрана IP применима для проходящих через сетевой мост пакетов. К тому же имеется разница между пакетами, которые будут передаваться через сетевой мост, и пакетами, которые получает локальная машина. В общем, пакеты, передаваемые через сетевой мост, проходят через правила межсетевого экрана IP только один раз, а не два, как это обычно бывает. Пакеты, передаваемые через сетевой мост, фильтруются в процессе приема, поэтому правила, использующие ключевые слова out или xmit, никогда не будут применяться. Обычно я использую in via, что является несколько устаревшим, но удобочитаемым синтаксисом. Другим ограничением является то, что для фильтрации проходящих через сетевой мост пакет вы можете использовать только операции pass или drop. Сложные операции, такие, как divert, forward или reject, недоступны. Эти операции все же можно использовать, но только для трафика к или от машины, являющейся сетевым мостом.
Новой во FreeBSD 4.0 является концепция фильтрацией с отслеживанием состояния. Это дает большой эффект для трафика UDP, который обычно представляет собой исходящий запрос, за которым вскоре следует ответ с точно тем же набором адресов IP и номеров портов (но, конечно, с обратным порядком следования параметров отправителя и получателя). Для межсетевых экранов, которые не отслеживают состояние, практически нет способа для работы с таким типом трафика, кроме как посредством организации прокси. Но для межсетевого экрана, который может ''запомнить'' исходящий пакет UDP и в течение следующих нескольких минут разрешить прохождение ответа, работа с сервисами UDP представляется тривиальной задачей. В следующем примере показано, как это сделать. Настоящий параноик может также задать подобные правила для работы с TCP. Это позволяет вам избежать некоторых типов атак типа отказа в обслуживании или других не менее веселых вещей, но также обычно приводит к быстрому росту таблицы состояний.
Давайте рассмотрим пример настройки. Заметьте сначала, что в самом начале файла /etc/rc.firewall мы уже позаботились о loopback-интерфейсе и хак для ARP уже должен работать. Так что в дальнейшем мы больше о нем заботиться не будем.
us_ip=192.168.1.1
oif=fxp0
iif=fxp1
# Things that we've kept state on before get to go through in a hurry.
${ipfw} add check-state
# Throw away RFC 1918 networks
${ipfw} add deny log ip from 10.0.0.0/8 to any in via ${oif}
${ipfw} add deny log ip from 172.16.0.0/12 to any in via ${oif}
${ipfw} add deny log ip from 192.68.0.0/16 to any in via ${oif}
# Allow the bridge machine to say anything it wants (keep state if UDP)
${ipfw} add pass udp from ${us_ip} to any keep-state
${ipfw} add pass ip from ${us_ip} to any
# Allow the inside net to say anything it wants (keep state if UDP)
${ipfw} add pass udp from any to any in via ${iif} keep-state
${ipfw} add pass ip from any to any in via ${iif}
# Allow all manner of ICMP
${ipfw} add pass icmp from any to any
# TCP section
# established TCP sessions are ok everywhere.
${ipfw} add pass tcp from any to any established
# Pass the "quarantine" range.
${ipfw} add pass tcp from any to any 49152-65535 in via ${oif}
# Pass ident probes. It's better than waiting for them to timeout
${ipfw} add pass tcp from any to any 113 in via ${oif}
# Pass SSH.
${ipfw} add pass tcp from any to any 22 in via ${oif}
# Pass DNS. Only if you have name servers inside.
#${ipfw} add pass tcp from any to any 53 in via ${oif}
# Pass SMTP to the mail server only
${ipfw} add pass tcp from any to mailhost 25 in via ${oif}
# UDP section
# Pass the "quarantine" range.
${ipfw} add pass udp from any to any 49152-65535 in via ${oif}
# Pass DNS. Only if you have name servers inside.
#${ipfw} add pass udp from any to any 53 in via ${oif}
# Everything else is suspect
${ipfw} add deny log ip from any to any
Те из вас, кто ранее уже настраивал межсетевые экраны, может заметить отсутствие некоторых вещей. В частности, нет правил против spoof-атак. То есть мы не добавили следующее:
${ipfw} add deny ip from ${us_ip}/24 to any in via ${oif}
Это означает отбрасывание пакетов, в которых прописано, что они исходят из нашей сети, когда как они пришли извне. Это то, что вы обычно делаете, если хотите быть уверенными, что никто не сможет попытаться обойти фильтр пакетов путем создания нечестных пакетов, которые выглядят так, как будто исходят изнутри сети. Проблема здесь заключается в том, что имеется по крайней мере один хост со стороны внешнего интерфейса, который вам нельзя игнорировать--ваш маршрутизатор. В моем частном случае, имеется несколько машин во внешней сети и несколько во внутренней, но мне не так уж необходимо обеспечить внешним машинам доступ к внутренней сети. В то же самое время я не хочу передавать их трафик наружу. В моем случае мой провайдер выполняет отслеживание spoof-атак на своем маршрутизаторе, так что мне беспокоиться не нужно. И, вообще говоря, чем меньше правил, тем лучше, потому что на обработку каждого из них тратится время и ресурсы процессора.
Отметьте также, что последнее правило является почти что точной копией правила по умолчанию с номером 65536. Однако когда оно применяется при организации сетевого моста, проявляются два больших отличия. Наше правило записывает протокол, когда, конечно же, происходит отбрасывание пакетов, но наше правило будет работать только для трафика IP. Кроме хитрости с UDP 0.0.0.0, нет способа работать с не IP трафиком, так что правило, используемое по умолчанию с номером 65536 будет отбрасывать ВЕСЬ трафик, не только весь не IP трафик. Сетевым эффектом будет то, что будет протоколироваться трафик IP, не удовлетворяющий правилам, кроме не-IP трафика. Если хотите, вы можете добавить параметр IPFIREWALL_DEFAULT_TO_ACCEPT к вашему файлу конфигурации ядра и не-IP трафик будет проходить через мост, а не отбрасываться. Но в случае сетевого моста с фильтрацией между вами и Интернет, вряд ли вы будете это делать (если вы достаточно параноидальны).
Здесь есть правило для пропуска SMTP к почтовому серверу, если он у вас имеется. Очевидно, что полный набор правил выше должен быть испробован, и это является примером исключения для некоторой службы. Заметьте, что для того, чтобы ''почтовый сервер'' работал, сервер имен должен заработать ДО того, как будет включена функция сетевого моста. Это пример проверки на то, что вы включили правильный интерфейс.
Другим стоящим внимания моментом является то, что правила DNS настроены так, что относятся только к работе серверов DNS. Это значит, что если у вас нет сервера DNS, то вам эти правила не нужны.
Те, кто настраивал межсетевые экраны IP, также использовали правило reset или forward для пакетов ident (порт TCP с номером 113). К сожалению, в коде сетевого моста нет такой опции, поэтому остается только просто пропускать их к получателю. Пока эта машина-получатель не заработает даемон ident, это не страшно. Другим способом является отбрасывание соединений к порту 113, что повредит таким программам, как IRC (проверка ident должна приводить к тайм-ауту).
Единственным не очень хорошим моментом, который вы уже могли заметить, является то, что есть правило, позволяющее работать ${us_ip}, и отдельное правило, разрешающее работать внутренней сети. Запомните, что это нужно, потому что эти два типа трафика проходят разную обработку в ядре и фильтре пакетов. Внутренняя сеть обрабатывается кодом сетевого моста. Однако локальная машина будет использовать для работы обычный стек протоколов IP. Таким образом имеются два правила для обработки различных случаев. Правила для входящего через ${oif} трафика работают в обоих случаях. В общем, если в фильтре вы используете правила in via, то вам нужно будет делать исключение для локально генерируемых пакетов, потому что они не могут ''войти'' как-то иначе.
6. Контрибуторы
Можно сказать, что материал для этого обсуждения является комбинацией вопросов, которые затронул Луиджи Риззо (Luigi Rizzo) в своей лекции о Dummynet на конференции FreeBSDcon '99 и Марк Мюррэй (Mark Murray) в своей лекции о сетевой безопасности. Кроме того, достаточное количество раз я выполнял настройку сетевых мостов с функцией фильтрации пакетов для друзей и коллег, которые получили дома DSL-подключение.