[an error occurred while processing this directive]

Установка параметров шлюза на базе FreeBSD по динамическому адресу
Введение

На сервере FreeBSD 10.1 установлены два интернет канала. Первый вполне
нормальный Ethernet, выделенный ip адрес.
Второй - LTE модем, адрес соответственно динамический.
Весь трафик squid должен уходить на второй канал.
Для этого используется опция tcp_outgoing в squid.conf
В правилах ipfw добавлены два правила для обеспечения forward на новый шлюз

   ipfw add 10 fwd <адрес шлюза на втором канале> all from <динамический адрес второго канала> to not 192.168.1.0/24 out
   ipfw add 11 pass all from any to <динамический адрес второго канала> via <интерфейс LTE модема> in

Механизм ясен. Осталось сделать следующее:

1. При изменении динамического адреса надо подставлять новые значения в ipfw и в squid

2. Сделать это при старте сервера

По тексту интерфейс ue0 - интерфейс LTE модема.

Получение нового динамического адреса

После инициализации модема и запуска dhclient мы получим динамический IP адрес.
dhclient формирует leases в своем файле.

Пример файла:

	lease {
	  interface "ue0";
	  fixed-address 100.67.50.124;
	  option subnet-mask 255.255.255.248;
	  option routers 100.67.50.121;
	  option domain-name-servers 83.149.32.225,83.149.32.224;
	  option dhcp-lease-time 518400;
	  option dhcp-message-type 5;
	  option dhcp-server-identifier 100.67.50.121;
	  option dhcp-renewal-time 259200;
	  option dhcp-rebinding-time 453600;
	  renew 1 2015/6/15 08:59:05;
	  rebind 3 2015/6/17 14:59:05;
	  expire 4 2015/6/18 08:59:05;
	}
	lease {
	  interface "ue0";
	  fixed-address 100.67.3.43;
	  option subnet-mask 255.255.255.248;
	  option routers 100.67.3.41;
	  option domain-name-servers 83.149.32.225,83.149.32.224;
	  option dhcp-lease-time 518400;
	  option dhcp-message-type 5;
	  option dhcp-server-identifier 100.67.3.41;
	  option dhcp-renewal-time 259200;
	  option dhcp-rebinding-time 453600;
	  renew 6 2015/6/13 16:12:27;
	  rebind 1 2015/6/15 22:12:27;
	  expire 2 2015/6/16 16:12:27;
	}

Lease в текущий момент будет последним. Нас интересует две строки.
fixed-address - это сам динамический адрес. option routers - это адрес шлюза на
этом интерфейсе.

Я получаю эти поля через awk, только потому, что lease несколько и нам нужен
последний. Через awk это удобно сделать.

Скрипт для получения ip
megafon_get_ip.awk:

	BEGIN {nline=1
	}
	
	{
	   tag1[nline]=$1
	   tag2[nline]=$2
	   nline=nline+1
	}
	
	END {
	    for (u=1;u<nline;u++)
	      {
	        if (tag1[u]=="fixed-address")
	        {
	# Делаем замену последнего символа, что бы не мешал.
	                gsub(";","",tag2[u]);
	                ip = tag2[u];
	        }
	      }
	    print ip;
	    }

Скрипт для получения routers

megafon_get_router.awk:

	BEGIN {nline=1
	}
	
	{
	   tag2[nline]=$2
	   tag3[nline]=$3
	   nline=nline+1
	}
	
	END {
	    for (u=1;u<nline;u++)
	      {
	        if (tag2[u]=="routers")
	        {
	# Делаем замену последнего символа, что бы не мешал.
	                gsub(";","",tag3[u]);
	                router = tag3[u];
	        }
	      }
	
	   print router;
	}

Обновление таблиц ipfw

Считывание нового динамического адреса и адреса шлюза в ipfw сделано через cat

Выдержка из rc.firewall:

	...
	eth_megafon="ue0"
	ip_megafon=`cat /etc/megafon_ip`
	router_megafon=`cat /etc/megafon_router`
	${fwcmd} add 10 fwd $router_megafon all from $ip_megafon to not 192.168.0.0/16 out
	${fwcmd} add 11 pass all from any to $ip_megafon via $eth_megafon in
	...

Как видно, текущие адреса хранятся в /etc/megafon_ip и /etc/megafon_router

Обновление squid.conf

К сожалению, опция tcp_outgoing_address требует указания адреса. То есть фокус
как в rc.firewall не пройдет.
Значит надо будет делать замену.

Создаем файл squid.conf.etalon:
	...

	tcp_outgoing_address #ip_megafon#

	...

И остается применить 

   sed 's/#ip_megafon#/'< новый динамический адрес >'/g' /usr/local/etc/squid/squid.conf.etalon > /usr/local/etc/squid/squid.conf

Основной скрипт

Итак, получать новые адреса научились. Обновлять в ipfw, менять squid.conf тоже.

Полученные новые адреса пишем во временные файлы, потом сравниваем новый
динамический адрес с прежним.
Прежний (текущий) адрес храним в файл /etc/megafon. Если адреса не совпадают,
обновляем файл с адресом и запускаем механизм обновления

megafon_get_ip:

	#Получаем новый ip
	awk -f /usr/local/scripts/megafon_get_ip.awk /var/db/dhclient.leases.ue0 > /tmp/megafon_ip
	
	#Получаем новый router. Хотя можно и позже, но для удобства понимания можно и тут
	awk -f /usr/local/scripts/megafon_get_router.awk /var/db/dhclient.leases.ue0 > /tmp/megafon_router
	
	#Сравниваем его с существующим
	ip_new=`cat /tmp/megafon_ip`
	ip_now=`cat /etc/megafon_ip`
	
	if [ $ip_new != $ip_now ]; then
	        # Обновляем файлы. Нужно обновлять и таблицы ipfw
	        cp /tmp/megafon_ip /etc/megafon_ip
	        cp /tmp/megafon_router /etc/megafon_router
	
	        #Обновляем ipfw. Эта конструкция не отрубает соединение при обновлении правил ipfw
		sh /etc/rc.firewall > /dev/null 2>&1
	
 	       #Формируем новый конфиг squid. К сожалению, tcp_outgoing не умеет брать адрес из файла.
         sed 's/#ip_megafon#/'$ip_new'/g'
/usr/local/etc/squid/squid.conf.etalon > /usr/local/etc/squid/squid.conf
	
	        #Рестарт squid.
	        /usr/local/sbin/squid -k reconfigure
	fi

Запуск основного скрипта при старте сервера

Для получения динамического адреса самым простым виделось поставить в rc.conf
строку ifconfig_ue0="DHCP"

Но модем от Мегафона, его надо инициализировать перед запросом адреса. Заодно
обеспечим вызов основного скрипта.
Создал /usr/local/etc/rc.d/megafon

megafon:

	#!/bin/sh
	#
	# PROVIDE: megafon
	# REQUIRE: dhclient
	# KEYWORD: shutdown
	
	. /etc/rc.subr
	
	name=megafon
	
	load_rc_config ${name}
	
	command=/usr/local/etc/megafon
	command_args=""
	
	run_rc_command "$1"

В rc.conf добавляем:

	...
	megafon="YES"
	...

Сам стартовый скрипт

/usr/local/etc/megafon:

	#Инициализация модема
	echo 'AT^NDISDUP=1,1,"internet"' > /dev/cuaU1
	#Стартуем клиента
	/sbin/dhclient -b ue0

 #Через 10 секунд надо вызвать обновление таблиц и всего остального. Приводит к
10 секундной задержке старта сервера.
	sleep 10
	#Вызов основного скрипта
	/usr/local/scripts/megafon_get_ip

Периодическое обновление 

Механизма вызова сторонних скриптов при обновлении динамического адреса не
нашел. Если поставить основной скрипт в cron с периодом запуска 1 минута, то
при обновлении адреса время потери составит связи не больше 1 минуты.
 
12.06.2015 , Автор: als
Ключи: freebsd, dhcp, squid, ipfw / Лицензия: CC-BY
Раздел:    Корень / Администратору / Система / FreeBSD специфика / Установка и апгрейд FreeBSD и приложений.

[an error occurred while processing this directive]

[an error occurred while processing this directive]