СЕРГЕЙ СУПРУНОВ
FreeBSD tips: ARP в «заморозке»
При работе в локальной сети правила безопасности на сервере чаще всего относятся сразу ко всей подсети. Причем вполне обычная практика – оставлять в адресном пространстве резерв для будущего расширения. Да и невозможно в принципе задать подсеть, содержащую ровно 7 адресов, – все равно придется выделять 14. То есть практически в любой сети есть неиспользуемые адреса, на которые распространяются общие правила доступа. Конечно, любые поползновения извне можно очень эффективно отсекать пакетными фильтрами и прочими изобретениями изворотливого человеческого разума. Но вряд ли найдется организация, в которой системный администратор может свято верить в грамотность, ответственность и порядочность всех без исключения сотрудников, работающих в сети изнутри. А если политика компании включает еще и попытки учитывать и ограничивать трафик с каждого IP-адреса, то нет никаких гарантий, что никому не придет в голову «случайно» прописать в своих настройках адрес соседа…
Данная заметка о том, как решить указанную выше проблему, если роутер, через который локальная сеть выходит в «мир», построен на базе FreeBSD, а сама сеть включает два-три десятка машин, сосредоточенных в одном сегменте (при большем количестве компьютеров эффективность описываемой методики заметно снижается, хотя она и остается вполне работоспособной). Не могу гарантировать, что на всех версиях этой ОС все будет работать так, как описано, но для FreeBSD 5.2 никаких проблем обнаружено не было. Да, собственно, и взяться им неоткуда, настолько все просто.
Сначала немного теории. Для передачи кадра (речь будет идти об Ethernet) другому устройству сетевой адаптер машины должен знать его физический (MAC) адрес. Удаленное устройство будет принимать только кадры, содержащие в заголовке (поле Destination) его адрес, то есть адресованные именно ему. Ну еще широковещательные кадры, адресованные на специальный адрес ff:ff:ff:ff:ff:ff. Но поскольку работа протоколов верхних уровней основана на IP-адресах, то кто-то должен уметь сопоставлять IP-адрес сетевого устройства с MAC-адресом его адаптера. Этим «кем-то» является протокол ARP (address resolution protocol).
Собственно говоря, вся работа ARP заключается в том, чтобы по IP-адресу хоста возвратить MAC-адрес его адаптера, который используется для связи с данной машиной. Для этого ARP формирует в памяти компьютера (или другого устройства, на котором он запущен, например, коммутатора) таблицу соответствия, именуемую далее ARP-таблицей. Если требуемый физический адрес в ARP-таблице существует, то все соответствующие кадры направляются на него. Если нет, то отправляется широковещательный фрейм с IP-адресом искомого хоста. Этот фрейм принимают все адаптеры, и если, обработав этот запрос, удаленный хост видит в нем свой интернет-адрес, то он отсылает ответ запросившему устройству, в котором помимо прочего содержится и MAC-адрес его адаптера. Эта информация добавляется в ARP-таблицу для дальнейшего использования.
Формируемые описанным выше способом, то есть динамически, записи в ARP-таблице сохраняются временно. Если в течение 20 минут (значение по умолчанию) обращения к записи не происходит, она удаляется из таблицы.
Помимо динамических записей в ARP-таблице могут быть созданы постоянные (permanent), они же статические, записи. Они хранятся «вечно» (точнее, до перезагрузки), и, кроме того, попытка установить соединение с «чужим» IP-адресом с треском провалится, а в системном журнале появится сообщение об ошибке. К слову сказать, изменение динамической записи также сопровождается соответствующим сообщением, но соединение при этом устанавливается без каких-либо трудностей. Кроме того, если на момент подмены IP-адреса динамической записи с его участием в ARP-таблице не существует, то и никаких разоблачающих сообщений не появится.
Управлять записями ARP-таблицы позволяет одноименная утилита arp. Ее полный синтаксис доступен в man arp(8). Нам понадобятся следующие команды:
- arp –a – выводит содержимое таблицы ARP.
- arp – выводит ARP-запись для заданного хоста.
- arp –d – удаляет запись, соответствующую хосту.
- arp –d –a – удаляет все записи таблицы.
- arp –s – добавляет запись.
- arp –f – добавляет записи из файла соответствия.
Таким образом, дальнейшие действия понятны – для всех «критических» (а если сеть небольшая, то просто для всех) IP-адресов можно создать статические записи в ARP-таблице, тем самым исключив их подмену. Для этого существует два пути:
- Использовать команду arp –s для создания каждой записи;
- Создать файл соответствия и выполнить команду arp –f .
Первый способ слишком трудоемкий, поэтому возьмем на вооружение второй вариант. В этом случае файл соответствия требуется создать один раз, и в дальнейшем будет очень легко обеспечить автоматическое заполнение ARP-таблицы статическими записями при перезагрузке компьютера.
Формат файла соответствия продемонстрирован на следующем примере:
# Host MAC-address
192.168.0.1 00:05:5d:ce:d6:3f
192.168.0.2 00:05:5d:29:ec:f4
То есть в каждой строке записывается IP-адрес хоста (либо его каноническое имя) и через пробелы или символы табуляции – соответствующий ему MAC-адрес. Заполнить его достаточно просто – включите все машины сегмента и обратитесь с них к серверу (или с сервера к ним) любым способом, например, запустите на них браузер или выполните обычный пинг. Это обновит ARP-таблицу, после чего достаточно будет сохранить в файле результат выполнения команды «arp –an» и немного его подправить, удалив все лишнее и добавив нужное. Сократить необходимые правки позволит следующая команда:
# arp –an | awk –v OFS=” ” ‘{print(substr($2, 2, length($2)-2), $4)}’ > ethers
Теперь файл ethers будет заполнен нужным образом. Останется только удалить записи, которые мы хотим оставить динамическими (например, маршрутизаторы CISCO при перезагрузке могут менять MAC-адрес своих интерфейсов, выбирая их из некоторого пула, а добираться среди ночи на работу, чтобы подправить ARP-таблицу – занятие не из приятных).
Для адресов, которые не задействованы в подсети, можно создать статические записи с фиктивными физическими адресами (например, 00:11:22:33:44:55). Это исключит возможность использования кем-либо данных IP-адресов.
Далее очищаем ARP-таблицу и заполняем ее из сформированного файла:
# arp –d –a
# arp –f /usr/local/etc/ethers
Естественно, имя и местоположение файла соответствия может быть любым – удобным для вас. Теперь осталось занести указанные команды в сценарий автозапуска, например, с именем /usr/local/etc/rc.d/statarp.sh:
#!/bin/sh
# Static ARP-table loader
case $1 in
start)
arp -d -a > /dev/null
arp -f /usr/local/etc/ethers > /dev/null
echo "Static ARP-table is loaded"
;;
stop)
arp -d -a > /dev/null
echo "Static ARP-table is unloaded"
;;
restart)
arp -d -a > /dev/null
arp -f /usr/local/etc/ethers > /dev/null
echo "Static ARP-table is reloaded"
;;
status)
arp -an
;;
*)
echo "Usage: `basename $0` {start|stop|restart|status}" >&2
;;
esac
exit 0
Осталось не забыть сделать данный файл исполняемым.
Итак, мы получили статическую таблицу соответствия между IP- и MAC-адресами. Теперь выход в Интернет через FreeBSD-сервер с «чужого» IP-адреса станет невозможным, если, конечно, заодно не подменить и MAC-адрес (с последним явлением можно бороться разве что организационными методами).
Но любая палка, как известно, о двух концах. За повышение защищенности сети придется платить дополнительными заботами по администрированию, поскольку теперь добавление новой машины в сеть, замена сетевого адаптера, смена IP-адреса должны сопровождаться правкой и перезагрузкой ARP-таблицы. Хотя это все равно лучше, чем бегать по этажам, «вычисляя» недобросовестного пользователя.