Есть провайдер предоставляющий доступ в Интернет через PPPoE-соединение, которое устанавливается через внутреннюю сеть. Клиентам разрешён обмен, как через PPPoE соединение, так и через внутреннюю сеть. Скорость внутренней сети 100 Мбит/с, скорость PPPoE - контрактная. Для нормальной работы внутренней сети требуется прописать несколько маршрутов, которые провайдер раздаёт с использованием поля опций в DHCP-пакетах - бесклассовые маршруты.
Т.к. планировалось использовать внутреннюю сеть провайдера, то необходимо настроить получение и установку маршрутов. Конечно, можно было прописать их вручную, но это всё равно, что рыть себе яму - что-то изменится, и танцы с бубном обеспечены.
Теоретическая часть подробно описана в [1, 2, 3].
Исходные данные:
- ОС на шлюзе: OpenBSD 4.6;
- внешний интерфейс: rl0;
- подсеть: 192.168.15.0/24;
- DHCP-сервер: 192.168.15.3;
- маршруты: 10.1.0.0/16 через 192.168.15.1, 10.2.0.0/16 через 192.168.15.2;
1. Установка DHCP-клиента
Уже установленный DHCP-клиент для решения поставленной задачи не подходит, т.к. не поддерживает данную опцию и не имеет возможности описывать собственные опции. Так что придётся ставить дополнительный клиет из пакетов.
Листинг 1.1 Установка DHCP-клиента
Код: Выделить всё
# pkg_add -i -v ftp://ftp.openbsd.org/pub/OpenBSD/4.6/packages/i386/isc-dhcp-client
Листинг 1.2. Патч для dhclient-script
Код: Выделить всё
# cat dhclient-script.patch
--- /usr/local/sbin/dhclient-script.bak Fri Aug 13 01:15:23 2010
+++ /usr/local/sbin/dhclient-script Fri Aug 13 02:10:46 2010
@@ -1,7 +1,7 @@
#!/bin/sh
make_resolv_conf() {
- if x"$new_domain_name_servers" != x ]; then
+ if [ x"$new_domain_name_servers" != x ]; then
cat /dev/null > /etc/resolv.conf.dhclient
if [ x"$new_domain_search" != x ]; then
echo search $new_domain_search >> /etc/resolv.conf.dhclient
@@ -15,7 +15,11 @@
echo nameserver $nameserver >>/etc/resolv.conf.dhclient
done
- mv /etc/ersolv.conf.dhclient /etc/resolv.conf
+ if [ -f /etc/resolv.conf.tail ]; then
+ cat /etc/resolv.conf.tail >> /etc/resolv.conf.dhclient
+ fi
+
+ mv /etc/resolv.conf.dhclient /etc/resolv.conf
fi
}
Листинг 1.3 Проверка DHCP-клиента
Код: Выделить всё
# /usr/local/sbin/dhclient -d rl0
Internet Systems Consortium DHCP Client V3.1.1
Copyright 2004-2008 Internet Systems Consortium.
All rights reserved.
For info, please visit http://www.isc.org/sw/dhcp/
Listening on BPF/rl0/xx:xx:xx:xx:xx:xx
Sending on BPF/rl0/xx:xx:xx:xx:xx:xx
Sending on Socket/fallback
DHCPDISCOVER on rl0 to 255.255.255.255 port 67 interval 7
DHCPOFFER from 192.168.15.3
DHCPREQUEST on rl0 to 255.255.255.255 port 67
DHCPACK from 192.168.15.3
New Network Number: 192.168.15.0
New Broadcast Address: 192.168.15.255
bound to 192.168.15.240 -- renewal in 1590 seconds.
^C
Во избежание конфликтов с уже установленным клиентом настройки нового клиента будут сохранены в файле dhclient-isc.conf. Указываем путь к скрипту обработки данных, описываем новую опцию и перечисляем опции которые хотим получить от DHCP-сервера.
Листинг 2.1 Конфигурационный файл DHCP-клиента
Код: Выделить всё
# cat /etc/dhclient-isc.conf | grep -v "^#"
script "/usr/local/sbin/dhclient-script";
option classless-static-routes code 121 = array of { unsigned integer 8 } ;
request subnet-mask, broadcast-address, classless-static-routes,
domain-name, domain-name-servers;
require subnet-mask, domain-name-servers;
Листинг 2.2 Проверка новой конфигурации
Код: Выделить всё
# /usr/local/sbin/dhclient -d rl0 -cf /etc/dhclient-isc.conf
Т.к. используется не стандартный DHCP-клиент, то простой строкой "dhcp" здесь не отделаться - придётся прописывать полные пути. Для избежания конфликтов со стандартным клиентом используются отличные PID и lease файлы.
Листинг 3.1 Конфигурационный файл интерфейса
Код: Выделить всё
# cat /etc/hostname.rl0
!/usr/local/sbin/dhclient rl0 \
-lf /var/db/dhclient-isc.leases \
-cf /etc/dhclient-isc.conf \
-pf /var/run/dhclient-isc.pid
Листинг 3.2 Проверка конфигурации интерфейса
Код: Выделить всё
# sh /etc/netstart rl0
Формат опции был описан выше, в конфигурационном файле, остаётся только обработать полученные данные. В реализации ISC, DHCP-клиент после получения данных от сервера вызывает скрипт, устанавливающий необходимые параметры. Этот скрипт поддерживает использование т.н. Hook'ов - дополнительных скриптов, которые вызываются до (/etc/dhclient-enter-hooks) и после (/etc/dhclient-exit-hooks) выполнения основных действий. Для установки маршрутов удобнее использовать последний. Необходимо будет разобрать входные данные (строка чисел, разделённая пробелами) в соответствии с [3] и установить маршруты.
Листинг 4.1 Скрипт для обработки опции "Бесклассовые маршруты"
Код: Выделить всё
# cat /etc/dhclient-exit-hooks
#
# Process classless static route DHCP option (code 121)
# By BlackCat
#
# TODO: perform sanity checks.
# TODO: process other reasons (RENEW, REBIND, etc)
#
if [ -n "$new_classless_static_routes" ]; then
if [ x"$reason" == x"BOUND" -o x"$reason" == x"REBOOT" ]; then
state=STATE_PREF_LEN
for byte in $new_classless_static_routes; do
case $state in
STATE_PREF_LEN)
pref_len=$byte
cnt=`expr $byte % 8`
if [ $cnt -eq 0 ]; then
cnt=`expr $byte / 8`
else
cnt=`expr $byte / 8 + 1`
fi
state=STATE_DEST
dest=
gw=
;;
STATE_DEST)
if [ -z $dest ]; then
dest=$byte
else
dest="$dest.$byte"
fi
cnt=`expr $cnt - 1`
if [ $cnt -eq 0 ]; then
state=STATE_ROUTER
cnt=4
fi
;;
STATE_ROUTER)
if [ -z $gw ]; then
gw=$byte
else
gw="$gw.$byte"
fi
cnt=`expr $cnt - 1`
if [ $cnt -eq 0 ]; then
state=STATE_PREF_LEN
route add $dest/$pref_len \
$gw > /dev/null 2>&1
fi
;;
*)
echo "Parsing error. Exit."
exit 1
esac
done
fi
fi
5. Список литературы
- RFC 1231: Dynamic Host Configuration Protocol // http://tools.ietf.org/rfc/rfc2131.txt
- RFC 2132: DHCP Options and BOOTP Vendor Extensions // http://tools.ietf.org/rfc/rfc2132.txt
- RFC 3442: The Classless Static Route Option for DHCPv4 // http://tools.ietf.org/rfc/rfc3442.txt