++ ВведениеНа сервере 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/megafonmegafon:
#!/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 минуты.
URL:
Обсуждается: http://www.opennet.me/tips/info/2909.shtml
А вот такой штуки у вас там нет, что ли, что ректально всё так? http://linux.die.net/man/8/dhclient-script
Спасибо за наводку.
Попробую dhclient-script
Судя по описанию, он позволит сократить вызов cron
Со squid.conf все равно получается некрасиво.
Он параметром новый IP получает, если что. Так что парсить ничего не нужно.
> Он параметром новый IP получает, если что. Так что парсить ничего не нужно.Это слишком просто. Как это - не надо выносить коня из горящей избы? День прожит зря!!!
В линуксе я бы сделал маскарадинг для фаервола, а для сквида создал бы виртуальный tap интерфейс, слал бы туда трафик, и создал бы вторую таблицу маршрутизации iproute2 с дефолтным гейтвеем на интерфейс динамика.
use cisco ?
Нет!
Слишком сложно.
1) Используете ipfw NAT на интерфейсе ue0
2) При подключении по dhcp переписываем default (в /etc/dhclient.conf)
3) не трогаем tcp_outgoing_address в aquid
4) Профит!Еще вариант через setfib и ipfw fwd
получить ip адрес интерфейса:ifconfig ue0 | awk '/-->/ {print $2}'Вместо демона megafon - man devd
Что люди только не делают, лишь бы не использовать pf.
я то же самое подумал
Ох блин как много действийПоднимаем alias (10.0.0.1) на интерфейсе с динамическим ip, прописываем его ip как tcp_outgoing_address в squid.
Маркируем все пакеты с alias ip при помощи:
# iptables -t mangle -A OUTPUT -s 10.0.0.1 -j MARK --set-mark 0x1
маскарадим
# iptables -t nat -A POSTROUTING -o ppp1 -j MASQUERADE
дальше направляем в нужную нам таблицу
# ip rule add fwmark 0x1 table channel2
# ip rule add from 10.0.0.1 table channel2profit
Используйте несколько таблиц маршрутизации:# echo net.fibs=2 >> /boot/loader.conf
# echo squid_enable=\"YES\" >> /etc/rc.conf
# echo squid_fib=\"1\" >> /etc/rc.conf
# shutdown -r now
# setfib 1 dhclient ue0
Коллеги, спасибо за советы.
Ясно дело, изначально заметка не так красива и ясна, как многие из советов.
Спасибо за отклики, спасибо за рекомендации.
iptables не используется, за сим и мне, лично мне, не пойдет. Но это еще не повод не начать его использовать :)
Спасибо за совет awk к ifconfig, не пришло в голову. Красиво и просто получить адрес. Хотя, тот же awk через dhcpclient получает адрес :) Но сложнее.
По поводу алиаса на ue0, попробую. Пока не скажу :)
> Хотя, тот же awk через dhcpclient получает адрес :) Но сложнее.Программа на awk слишком некрасивая и длинная. Если уж говорить о использовании чисто awk, то код займет несколько строчек.
data=`cat dhcpd.leases | awk 'tolower($1) ~ /(fixed-address|option routers)/ && \
$2 { key=($1=="fixed-address" : tolower($1)); arr[key]=$2 } \
END { for (key in arr) print key arr[key] }'`
set -- ${data}
case ${1} in
address:*) address=${1#fixed-address:} ;;
router:*) router=${1#routers:} ;;
esac
case ${2} in
address:*) address=${2#fixed-address:} ;;
router:*) router=${2#routers:} ;;
esacКод скорее всего содержит огрехи, но у меня нет перед глазами живой dhcpd.leases перед глазами.
воспользовался dhclient-scriptДобавляем /etc/dhclient-enter-hooks :
if [ $reason == "PREINIT" ]; then
echo 'AT^NDISDUP=1,1,"internet"' > /dev/cuaU1
fi
Добавляем /etc/dhclient-exit-hooks :
if [ $reason == "BOUND" ]; then
if [ $new_ip_address != $old_ip_address ]; then
echo $new_ip_address > /etc/megafon_ip
echo $new_routers > /etc/megafon_router#Обновляем ipfw
/usr/local/sbin/sh_firewall#Формируем новый конфиг squid. К сожалению, tcp_outgoing не умеет брать адрес из файла.
sed 's/#ip_megafon#/'$new_ip_address'/g' /usr/local/etc/squid/squid.conf.etalon > /usr/local/etc/squid/squid.conf#Рестарт squid.
/usr/local/sbin/squid -k reconfigure
fi
fiУходит вызов скрипта в cron.
Спасибо за советы.
дешевле и надежней поставить роутер tplink воткнув в него модем.
зачем прокся ? а затем что бы ничего не создавать, а что-нибудь контролировать.
и интернет что бы не нормальный был а тормозной 3G
Машко, прокси ещё кэширущий бывает, а ещо авторизация, а ещо редиректы,....
> Машко, прокси ещё кэширущий бывает, а ещо авторизация, а ещо редиректы,....А ещо запреты роскомнадзора
Используйте PF
($ext_if) будет получать ip динамического д линка автоматически
> Используйте PF
> ($ext_if) будет получать ip динамического д линка автоматическиЭто бесподезно, люди хотят использовать единственно правильный инструмент.