Мини-HOWTO: Совместное использование мостов и Firewall в Linux

Peter Breuer

Перевод: Станислав Рогин, ASPLinux


Содержание
Введение
Что и Зачем (и Как?)
Мосты
FIREWALL
Авторские права

Введение

Вам неплохо было бы посмотреть на "Мини-HOWTO: Мосты" автора Chris Cole, чтобы взглянуть на всю эту проблему по-другому. Его адрес - chris@polymer.uakron.edu. Мой документ основан на выдержках из этого документа версии 1.03 от 23 августа 1996.


Что и Зачем (и Как?)

Что?

Мост - это интеллектуальное соединение между двумя сетевыми картами. Firewall - это интеллектуальный изолятор.


Почему?

Мост вам может понадобиться, если у вас имеется несколько компьютеров, и вы хотите:

  1. сэкономить на покупке хаба, если у вас есть еще одна запасная сетевая карта.

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

  3. избежать проблем с поддержкой в будущем, когда все изменится!

"Несколько компьютеров" - это минимум 3 рабочих станции, которые занимаются маршрутизацией, мостами, или просто часто переносятся из одной комнаты в другую! Вам может также понадобиться мост, если вам просто интересно, что же он на самом деле делает. Мне мост потребовался по 2-ой причине.

Если у вас действительно возникла 1-ая проблема, то вы один из немногих. Прочтите Howto: Сеть-2 и HOWTO: Последовательные порты, и вы, возможно, найдете там советы получше.

Firewall может вам понадобиться, если:

  1. Вы пытаетесь защитить сеть от доступа извне, или

  2. Вы хотите запретить доступ к внешнему миру изнутри.

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


Как?

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

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

-> Вход моста -> Вход firewall -> Ядро -> Выход firewall -> Выход моста ->

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


Мосты

Программы

Возьмите утилиту настройки мостов с домашних страниц Alan Cox. Это та же ссылка, что и в документе Chris. Я просто не знал, что это ftp, а не http URL ...


Литература для предварительного прочтения.

Прочтите HOWTO: Несколько Ethernet-карт, и вы найдете там несколько советов о том, как заставить работать несколько сетевых карт одновременно.

Более подробные советы по "магии загрузки системы", которая может понадобиться, вы найдете в HOWTO: Приглашение системы при загрузке.

Конечно можно обойтись без чтения HOWTO: Сеть-2, хотя это очень хороший и объемный труд, и вы сможете почерпнуть из него все необходимые детали.


Конфигурация загрузки

В литературе, упомянутой выше, вы прочтете, что вам надо подготовить ядро к обнаружению второй сетевой карты в процессе загрузки, добавив в ваш файл /etc/lilo.conf, и затем перезапустив lilo:

append = "ether=0,0,eth1" 

Обратите внимание на "eth1". "eth0" - это первая карта. "eth1" - соответственно вторая. Вы всегда можете добавить эти параметры в строку, которую вам предлагает lilo в самом начале. Ниже приведен пример для трех карт:

linux ether=0,0,eth1 ether=0,0,eth2 

Я лично использую loadlin для загрузки моего ядра из DOS:

loadlin.exe c:\vmlinuz root=/dev/hda3 ro ether=0,0,eth1 ether=0,0,eth2 

Заметьте, что этот способ заставляет ядро автоматически определять параметры карт при загрузке. Это не сработает, если драйвера сетевых карт собраны у вас в виде modules (это сделано из соображений устойчивости, так как в этом случае нельзя определить порядок установки карт), поэтому, в случае использования модулей, вам придется добавить соответствующие номера IRQ и портов в параметры драйвера в файл /etc/conf.modules. У меня записано следующее

alias eth0 3c509
alias eth1 de620
options 3c509 irq=5 io=0x210
options de620 irq=7 bnc=1 

Вы можете просто выяснить, используются ли в вашей системе модули, набрав "ps -aux", и поискать там kerneld , а также проверив подкаталоги каталога /lib/modules на предмет наличия в нем .o файлов. Вас интересует подкаталог, имя которого вам даст команда uname -r. Если у вас есть kerneld и/или foo.o, тогда исправьте файл /etc/conf.modules и внимательно прочитайте man depmod.

Заметьте, что до последней (2.0.25) версии ядра драйвер карты 3c509 не мог использоваться в виде модуля более одного раза. Я видел патч, который это исправлял. Возможно, когда вы это читаете, ядро уже исправлено.


Конфигурация ядра

Пересоберите ядро, разрешив в нем опцию "мосты".

CONFIG_BRIDGE=y 

Я лично пересобрал ядро также с поддержкой firewall и IP-переадресации, а также с маскарадингом и т.п. Это необходимо, если вам нужен и firewall тоже...

CONFIG_FIREWALL=y           
CONFIG_NET_ALIAS=y          
CONFIG_INET=y               
CONFIG_IP_FORWARD=y         
CONFIG_IP_MULTICAST=y       
CONFIG_IP_FIREWALL=y        
CONFIG_IP_FIREWALL_VERBOSE=y
CONFIG_IP_MASQUERADE=y      

Вам, вероятнее всего, нужно не все. Все что вам надо - это просто поддержка сети:

CONFIG_NET=y 

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

Установите новое ядро, перезапустите lilo и перезагрузитесь с новым ядром. К этому моменту ничего не должно измениться!


Сетевые адреса

Chris говорит, что мост не должен иметь IP-адреса, но я опишу прямо противоположный вариант.

Если вы собираетесь использовать свою машину для подключения к сети, то вам понадобится IP-адрес. Необходимо проверить, нормально ли настроено устройство обратной петли, чтобы программы могли общаться с тем, с чем они предполагают это общение возможным. Если устройство обратной петли выключено, то DNSили другие сетевые сервисы могут отказать. Прочтите "HOWTO: Сеть-2", но скорее всего, у вас эта часть стандартной конфигурации должна уже присутствовать:

ifconfig lo 127.0.0.1 route add -net 127.0.0.0 

Вам также будет необходимо проставить адреса для сетевых карт. Я исправил файл /etc/rc.d/rc.inet1 в моем дистрибутиве Slackware (3.x), чтобы он работал с двумя сетевыми картами, и вам, скорее всего, также, как и мне, придется просто найти файл конфигурации сети и удвоить или утроить несколько команд, отвечающих за настройку сетевой карты. Предположим, что у вас уже есть адрес

192.168.2.100 

(он входит в пространство адресов, зарезервированное для частных сетей, но не волнуйтесь - если вы используете этот адрес, то проблем ни у кого не возникнет), то у вас в скрипте уже есть примерно такая строка:

ifconfig eth0 192.168.2.100 netmask 255.255.255.0 metric 1 

Первое, что вам надо будет сделать - это, по-видимому, разделить адресное пространство, занимаемое этой картой пополам, чтобы затем настроить мост или firewall между этими двумя половинами. Для этого добавьте строку, сокращающую маску сети:

ifconfig eth0 netmask 255.255.255.128 

Испытайте такой режим. Эта строка ограничивает адресное пространство карты, как минимум, от .0 до .127.

Теперь вы можете настроить вторую карту, выделив ей адрес из оставшейся половины адресного пространства. Убедитесь в том, что ни у кого этот адрес не используется. Для симметрии я использую 228=128+100. Подойдет любой адрес, не входящий в сеть первой карты (в принципе можно и входящий, но...). Избегайте специальных адресов типа .0, .1, .128 и т.п.., используйте их только в том случае, если точно знаете, что делаете.

ifconfig eth1 192.168.2.228 netmask 255.255.255.128 metric 1 

Эта строка отводит к сети второй карты адреса от .128 до .255.


Сетевая маршрутизация

Вот здесь как раз и всплывает подводный камень схемы мост+firewall: нельзя отфильтровывать пакеты, которые не прошли через маршрутизацию. Нет маршрутизации - нет firewall. По крайней мере, это так в ядре версии 2.0.30 и более новых. Фильтры firewall очень близки и пересекаются с кодом ip-переадресации.

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

Другими словами, чтобы настроить firewall, необходимо точно знать и контролировать назначение конкретных пакетов.

У меня имеется небольшая сеть с машинами, подключенных к хабу, включенному в мой eth0, поэтому конфигурируем эту сеть:

route add -net 192.168.2.128 netmask 255.255.255.128 dev eth0 

128 было бы заменено на 0, если бы у меня была полная сеть класса C. Но у меня ее нет, так как я ополовинил сеть ранее. Опции "dev eth0" в этом конкретном случае не обязательны, но они могут понадобиться для вас. Кто-то может захотеть иметь более одной карты, работающей с одной подсетью (127 компьютеров на одном сегменте - ничего себе), но эти карты будут соединены вместе с одной и той же маской сети, поэтому для кода маршрутизации они будут неразличимы.

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

                                                  клиент 129
         __                                           |    __ 
клиент 1   \    .0                    .128            |   /   сеть 1
клиент 2 --- Хаб - eth0 -  Ядро  - eth1 - Хаб - Маршрутизатор --- сеть 2
клиент 3 __/       .100            .228            .2 |   \__ сеть 3
                                                      |
                                                  клиент 254 

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

route add 192.168.2.2 dev eth1 

Я опишу сеть второй карты тоже, хотя у меня и нет в той половине адресов ни одной машины. Разделение адресных пространств карт позволяет мне настроить более "прочный" firewall, но вы можете справиться с этим и при помощи значительно более простой маршрутизации.

route add -net 192.168.2.128 netmask 255.255.255.128 dev eth1 

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

route add default gw 192.168.2.2 


Настройка сетевых карт

Достаточно сетевых настроек, но, так как мы устроили мост, то необходимо воспринимать на обеих картах пакеты, которые направлены не нам. Следующие строки необходимо поместить в файл настройки сети.

ifconfig promisc eth0 ifconfig promisc eth1 

В man написано использовать опцию allmulti=promisc, но у меня это не сработало.


Дополнительная маршрутизация

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

ifconfig arp eth1 

На всякий случай, я проставил этот режим и другой карте.

ifconfig arp eth0. 


Конфигурация моста

Вставьте в ваш конфигурационный скрипт строку, разрешающую работу моста:

brcfg -enable 

Наверное, вы уже пытались запустить эту строку! Конфигурация моста выдаст на экран несколько цифр. Вы можете поэкспериментировать, включая и выключая порты:

brcfg -port 0 -disable/-enable
brcfg -port 1 -disable/-enable 

Статус работы моста можно получить в любой момент простой командой:

brcfg 

без параметров. Вы увидите, что мост ждет пакетов, затем обрабатывает и перенаправляет их. (Я не знаю почему, но программа выдавала одинаковые аппаратные адреса на обеих моих картах, но не обращайте на это внимания... В HOWTO Chris-а говорится, что это нормально)


Испытания

Если у вас до сих пор все работает и ничего не сломалось, испробуйте свой конфигурационный скрипт - выключите обе карты и запустите скрипт:

ifconfig eth0 down ifconfig eth1 down /etc/rc.d/rc.inet1 

С достаточной долей везения различные сетевые подсистемы этого не заметят (nfs, ypbind, и т.п.). Не пытайтесь сделать это, если вы находитесь не за клавиатурой системной консоли!

Если вы привыкли быть более аккуратным, чем в вышеприведенном примере, тогда отключите максимально возможное количество демонов перед испытаниями, и отключите сетевые каталоги NFS. Наихудшее, что может произойти - это то, что вам придется перезагрузиться в однопользовательском режиме (параметр "single" , переданный lilo или loadlin) и внести требуемые изменения до перезагрузки.


Дополнительные проверки

Проверьте, различается ли трафик на интерфейсах:

tcpdump -i eth0 (в одном окне)
tcpdump -i eth1 (в другом окне)

Вы должны привыкнуть использовать tcpdump, чтобы искать то, чего не должно быть или искать отсутствие того, что быть должно.

Последите за пакетами, идущими, например, через мост на вторую карту из внутренней сети. Ниже я слежу за пакетами, идущими от машины с адресом .22:

tcpdump -i eth1 -e host 192.168.2.22

Затем выполните команду ping от хоста .22 к маршрутизатору. Вы должны увидеть пакеты в окне tcpdump.

На этот момент у вас должен быть настроен и работать мост с двумя адресами. Проверьте возможность ping на них снаружи и изнутри сети, затем испробуйте telnet, ftp и т.п. с разных сторон.


FIREWALL

Программы и дополнительная литература

Вы должны прочитать HOWTO: Firewall.

Там сказано, что вам понадобится утилита ipfwadm, если у вас ее еще нет. Существуют, правда, и другие, но как я начал использовать ipfwadm, так на нем и остановился. Он достаточно удобен и прост! Вы всегда знаете, что конкретно он делает.


Предварительные проверки

Вы уже собрали IP-переадресацию и маскарадинг в ядро, поэтому проверьте, находится ли firewall в его стандартном (разрешающем) состоянии командой

ipfwadm -I -l ipfwadm -O -l ipfwadm -F -l 

Эти команды выдадут список правил соответственно для входного, выходного и переадресуемых потоков firewall. Опция "-l" означает "list" (список).

Возможно, вы собрали и систему учета IP-пакетов:

ipfwadm -A -l 

Вы увидите, что ни одно правило не определено, и что, по умолчанию, firewall пропускает все пакеты. Вы всегда можете вернуться к этому состоянию командами

ipfwadm -I -f
ipfwadm -O -f
ipfwadm -F -f 

Опция "-f" означает "flush" (сбросить, очистить). Эта опция вам может понадобиться.


Основное правило

Я хочу отрезать внешний мир от моей сети и не более того, поэтому мое последнее (воспринимаемое по умолчанию) правило будет следующим - firewall должен игнорировать любые пакеты, идущие из внутренней сети во внешний мир. Я поместил все правила в файл /etc/rc.d/rc.firewall и запускаю его из /etc/rc.d/rc.local в процессе загрузки.

ipfwadm -I -a reject -S 192.168.2.0/255.255.255.128 -D 0.0.0.0/0.0.0.0 

Опция "-S" задает адрес источника и маску. "-D" - адрес и маску получателя.

Это - достаточно подробный формат. Ipfwadm понимает сетевые имена и некоторые сокращения (все это описано в man).

Наверно, более удобно поместить некоторые или все эти правила в выходной поток firewall, используя "-O" вместо "-I", но я оставлю эти правила на входящем потоке.


Исключения для адресов

Все исключения этому общему отрицанию я должен поместить до установки основного правила.

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

ipfwadm -I -i accept -S 192.168.2.100/255.255.255.255 \
 -D 0.0.0.0/0.0.0.0 

Я также разрешу клиентам внутренней сети общаться с firewall-машиной. Возможно, они попытаются таким образом постараться выбраться во внешний мир!

ipfwadm -I -i accept -S 192.168.2.0/255.255.255.128 \
 -D 192.168.2.100/255.255.255.255 

На этом моменте вы можете попытаться добраться до клиентов снаружи firewall, при помощи telnet, но у вас ничего не получится. Это означает, что вы смогли увидеть их машины, но они не могут послать вам ничего. Вы сможете установить контакт с внутренними машинами, если firewall у вас играет роль простого аудитора. Испытайте rlogin и ping , а также tcpdump на первой или второй карте. Вы должны понять, что вы увидите.


Исключения для протоколов

Я буду облегчать правила протокол за протоколом. Первое, что я хочу сделать - разрешить ping снаружи внутрь и получать ответ, поэтому я добавлю правило:

ipfwadm -I -i accept -P icmp -S 192.168.2.0/255.255.255.128 \
 -D 0.0.0.0/0.0.0.0 

Опция "-P icmp" как раз отвечает за протокол.

Пока я не настроил должным образом ftp-proxy, я также разрешу вызовы ftp, используя конкретные порты - 20, 21 и 115 на внешние машины.

ipfwadm -I -i accept -P tcp -S 192.168.2.0/255.255.255.128 \
 -D 0.0.0.0/0.0.0.0 20 21 115 

Я так и не смог заставить работать sendmail между внутренними машинами без DNS. Вместо настройки собственного DNS-сервера, я просто разрешил запросы с моей сети к внешнему серверу, поместив заодно его адрес в файлы /etc/resolv.conf на машинах моей сети ("nameserver 123.456.789.31" в отдельной строке).

ipfwadm -I -i accept -P tcp -S 192.168.2.0/255.255.255.128 \
 -D 123.456.789.31/255.255.255.255 54 

Номер порта и протокол определенного сервиса вы можете узнать при помощи tcpdump. Задействуйте этот сервис при помощи ftp или telnet или чего-нибудь подобного с внутренней машины или на нее, и затем проверяйте порты firewall при помощи tcpdump, например:

tcpdump -i eth1 -e host client04 

В файле /etc/services также есть много интересного. Чтобы разрешить telnet и ftp ВНУТРЬ сети ИЗВНЕ через firewall, вам придется разрешить локальным клиентам производить вызовы НАРУЖУ на определенных портах. С ftp все понятно - это сервер, организующий собственное соединение с получателем - но я не очень понимаю, зачем это необходимо для telnet.

ipfwadm -I -i accept -P tcp -S 192.168.2.0/255.255.255.128 ftp telnet \
 -D 0.0.0.0/0.0.0.0 

Иногда возникает проблема с некоторыми демонами, которые пытаются выяснить имя машины-firewall, чтобы узнать собственный сетевой адрес. У меня лично возникла проблема с Rpc.yppasswdd. Он настаивал на передаче информации наружу от firewall (через вторую карту). Это привело к тому, что клиенты изнутри его не видели.

Вместо запуска IP-алиасинга или правки кода демона, я просто переписал имя машины на адрес внутренней карты в клиентских файлах /etc/hosts.


Проверка

Вам, наверное, надо будет проверить работу telnet, rlogin и ping снаружи. Изнутри вы должны смочь произвести ping наружу. Вы также должны иметь возможность команды telnet на firewall-машину изнутри сети, а на самой этой машине должно быть возможно все.

Вот и все. Далее вам, наверно, стоит узнать подробнее про rpc/Yellow Pages и работу с файлом паролей. Сеть с firewall должна работать так, чтобы обычные пользователи не могли войти в firewall (если они смогут зайти в него, они смогут выбраться наружу). Хороших вам HOWTO!


Авторские права

Авторские права на русский перевод этого текста принадлежат ╘ 2000 ASPLinux Все права зарезервированы.

Этот документ является частью проекта Linux HOWTO.

Авторские права на документы Linux HOWTO принадлежат их авторам, если явно не указано иное. Документы Linux HOWTO, а также их переводы, могут быть воспроизведены и распространены полностью или частично на любом носителе, физическом или электронном, при условии сохранения этой заметки об авторских правах на всех копиях. Коммерческое распространение разрешается и поощряется; но, так или иначе, автор текста и автор перевода желали бы знать о таких дистрибутивах.

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

Мы бы хотели распространить эту информацию по всем возможным каналам. Но при этом сохранить авторские права и быть уведомленными о всех планах распространения HOWTO. Если у вас возникли вопросы, пожалуйста, обратитесь к координатору проекта Linux HOWTO по электронной почте: или к координатору русского перевода Linux HOWTO компании ASPLinux по адресу