PDA

Bekijk de volledige versie : Люди, что я делаю не так при настройке алиаса на WLANe роутера



cipipi
05-01-2009, 16:22
Преамбула:
Есть некий пров N, который для абонентов с прямыми подключением и внешними стат. IP не делает разграничения между локальным и внешним трафиком. Хотел это побороть. Зная, что на последней миле ходят пакеты от локальной сети 10.64.20.0/24 + IP всех мучеников с вешним статическим, я мог потенциально стать участником локальной сети, если правильно пропишу локальный IP, локальный шлюз + настрою роуты. Их я выяснил.

$2=10.64.20.11/24 -- мой локальный IP (любой свободный)
$3=10.64.20.1/24 -- шлюз
$4=10.64.20.255 -- Broadcast



Написал скрипт поднятия алиаса на WLANe (с коментами не проверял работоспособность):



#!/bin/sh

#Имя файла конфигурации iptables
NAME_IPTBL_ORIG=".iptbl.orig"
#МикроHELP
echo "wlan-alias [up|down] [Local IP] [Local Gate] [Local Broadcast]"

#Подсети где прячутся DC++, FTP сервера (ну понятно какой провайдер)
subnet1="212.1.226.0"
subnet2="212.1.224.0"

#Аргументов у вызова скрипта нет - ничего не делаем
if [ -z $1 ]; then

echo "Nothing to be done!!!"

exit 1
fi;

#Поднимаем алиас на WLANe
if [ $1 = "up" ]; then

#Если файл настроек iptables есть, то уже поднято - ничего не делаем
[ -f $NAME_IPTBL_ORIG ] && exit 1

#Если нехватает аргументов вызова, то ничего не делаем
[ -z $2 ] && exit 1
[ -z $3 ] && exit 1
[ -z $4 ] && exit 1

#Сохраняем таблицу iptables в файл
iptables-save >> $NAME_IPTBL_ORIG

#Собственно поднимаем второй IP (алиас) на WLANe
ifconfig vlan1:0 $2 netmask 255.255.255.0 broadcast $4

#прописываем в таблице маршрутизации локальный шлюз
route add $3 dev vlan1:0

#регистрируем локальную сеть в маршрутах
route add -net 10.0.0.0 netmask 255.0.0.0 gw $3 dev vlan1:0
#регистрируем дополнительные локальные подсети не из диапазона 10.0.0.0/8
#route add -net $subnet1 netmask 255.255.255.0 gw $3 dev vlan1:0
#route add -net $subnet2 netmask 255.255.255.0 gw $3 dev vlan1:0

#настраиваем маскарадиг + перенаправления на открытые порты (VSERVER)
#настораживает, что на вторую строчку iptables выдает варнинг на название интерфейса
iptables -t nat -A PREROUTING -d $2 -j VSERVER
iptables -t nat -A POSTROUTING -s ! $2 -o vlan1:0 -j MASQUERADE

echo "Alias on WLAN is open"

exit 0

fi;

#Закрываем алиас на WLANe
if [ $1 = "down" ]; then

#Если конфига iptables нет, то обратно восстанавливать не будем. Да поможет великий reboot
if [ ! -f $NAME_IPTBL_ORIG ]; then

echo "ERROR: Has no original iptables save file!!"
exit 1

fi;

#Кладем алиас. Автоматически снимаются прописанные в таблице маршруты
ifconfig vlan1:0 down

#Все правила в iptables нафиг очищаем (навсякий, т.к. не разбирался).
iptables --flush
iptables -t nat --flush
iptables -t mangle --flush
iptables -X

#потом восстанавливаем оригинальные правила до поднятия алиаса
iptables-restore $NAME_IPTBL_ORIG

#удаляем файл оригинальной конфигурации iptables
rm $NAME_IPTBL_ORIG

echo "Alias on WLAN is closed"

exit 0

fi;

exit 0





Таблица маршрутизации до запуска скрипта


Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
INET GW 0.0.0.0 255.255.255.255 UH 0 0 0 vlan1
192.168.0.0 0.0.0.0 255.255.255.0 U 0 0 0 br0
INET SUBNET 0.0.0.0 255.255.255.112 U 0 0 0 vlan1
127.0.0.0 0.0.0.0 255.0.0.0 U 0 0 0 lo
0.0.0.0 INET GW 0.0.0.0 UG 0 0 0 vlan1

Таблица маршрутизации после запуска скрипта


Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
10.64.20.1 * 255.255.255.255 UH 0 0 0 vlan1
INET GW * 255.255.255.255 UH 0 0 0 vlan1
192.168.0.0 * 255.255.255.0 U 0 0 0 br0
INET SUBNET * 255.255.255.112 U 0 0 0 vlan1
10.64.20.0 * 255.255.255.0 U 0 0 0 vlan1
subnet1 10.64.20.1 255.255.255.0 UG 0 0 0 vlan1
subnet2 10.64.20.1 255.255.255.0 UG 0 0 0 vlan1
10.0.0.0 10.64.20.1 255.0.0.0 UG 0 0 0 vlan1
127.0.0.0 * 255.0.0.0 U 0 0 0 lo
default INET GW 0.0.0.0 UG 0 0 0 vlan1



, где INET GW - интернетский шлюз для моего статичесого IP,
INET SUBNET - адресное пространство в котором распологается мой стат внешний IP.



Запустил. Проверил. Интерфейс vlan1:0 поднялся. Дополнительные рауты в таблице маршрутизации появились.
Полез с моей машины 196.168.0.0/24 конектиться к локальному DC серверу, который находится в subnet1=212.1.226.0/24 (ну вы поняли, что за провайдер N ;) )
Сервер DC при соединении отписал мой внешний IP
(в настройках DC клиента установил адрес 10.64.20.11 - адрес алиаса).

Что я делаю не так?

Power
05-01-2009, 23:42
1.

$2=10.XX.YY.BB/24 -- мой локальный IP
$3=10.XX.YY.AA/24 -- шлюз
$4=10.XX.YY.255 -- Broadcast

Надеюсь, адреса всё же передаются в скрипт без части "/24".


2.

#прописываем в таблице маршрутизации локальный шлюз
route add $3 dev vlan1:0

Это лишнее, т.к. адрес лежит в подсети 10.XX.YY.0/24, маршрут к которой уже есть (он поднимается автоматом при поднятии интерфейса vlan1:0).


3.

#настораживает, что на вторую строчку iptables выдает варнинг на название интерфейса
...
iptables -t nat -A POSTROUTING -s ! $2 -o vlan1:0 -j MASQUERADE

Тут засада, iptables не понимает названия интерфейсов с двоеточием. Он обрабатывает пакеты с интерфейса vlan1:0 как если бы они были с vlan1. Соответственно, под это правило попадёт 0 пакетов. Более того, в цепочке POSTROUTING уже есть правило, которое обработает такие пакеты, в вашем случае оно выглядит примерно так:


iptables -t nat -A POSTROUTING -o vlan1 ! -s основной_адрес_интерфейса_vlan1 -j MASQUERADE

Лучше всего, я думаю, будет добавить следующее правило (добавится первым в цепочку):


iptables -t nat -I POSTROUTING -o vlan1 -j MASQUERADE

Оно разберётся с обоими адресами (на vlan1 и vlan1:0).


---
Но по большому счёту, это всё не влияет на проблему. Будет проще, если вы напишете IP-адрес сервера DC, к которому пытаетесь присоединиться, а также приведёте настоящие адреса вместо запутывающих XX.YY и подобных.

cipipi
06-01-2009, 12:47
2Power
По вашему совету исправил некоторые неясности.
Со всем согласен.
Скорее всего в 3 пункте может быть загвоздка и правило действительно не отрабатывается.
Напишу как вы сказали:


iptables -t nat -I POSTROUTING 1 -o vlan1 -j MASQUERADE


Только не пойму, как же iptables будет делать маскарадинг,
если он не различает интерфейсы vlan1 и vlan1:0? Я так понимаю,
что маскарадинг производится програмно на уровне ядра, а не аппаратно.

cipipi
06-01-2009, 15:01
Все заработало (thx 2 Power).
Не правильно был настроен маскарадинг.
В скрипте строчку:


iptables -t nat -A POSTROUTING -s ! $2 -o vlan1:0 -j MASQUERADE

меняем на


iptables -t nat -I POSTROUTING 1 -o vlan1 -j MASQUERADE


Строчку шлюза решил оставить


route add $3 dev vlan1:0

может у кого он в другой подсети.

Теперь остались неразрешенные вопросы:
1. Как точно узнать, что локальный IP не занят, т.к. на мою сторону DHCP сервер не раздает IP?
2. А если раздает, то как проверить? (
пробовал


$udhcpc vlan1:0

, не помогло)

Power
06-01-2009, 22:25
1. Как точно узнать, что локальный IP не занят, т.к. на мою сторону DHCP сервер не раздает IP?


Может, arping поможет? Там есть замечательная опция -D


arping -I vlan1 -c 3 -D предполагаемый_IP_адрес

Если ответ от айпишника придёт (т.е. он занят), команда завершится с кодом 1, если не придёт - с кодом 0.
Но с другой стороны, DHCP-сервер может выдать этот айпишник кому-то уже после того, как вы его займёте.

cipipi
06-01-2009, 23:49
Уххх, пришлось сочинить маленькую вставочку в скрипт для прописи в таблице маршрутизации
длинющего списка подсетей, т.к. провайдер переложил эту обязанность на плечи пользователей.
Вот она:


#регистрируем дополнительные локальные подсети не из диапазона 10.0.0.0/8
PIRING_TABLE="/opt/etc/piringtbl"

#Если файла нет - ничего не прописываем в таблицы
if [ -f $PIRING_TABLE ]; then
#Меняем стандартный поток, сохраняя его дескриптор, на поток из файла таблицы пиринга
exec 9<&0 0<$PIRING_TABLE
#читаем построчно пока не кончится файл
while read line; do
#формируем строку команды: route add -net [подсеть] netmask [маска_подсети] gw $3 dev vlan1:0
#и тут же ее выполняем.
$(echo $line | awk '{print "route add -net " $1 " netmask " $2 " gw " IP " dev vlan1:0"}' IP=$3)
done
#Восстанавливаем стандартный поток
exec 0<&9
fi


Формат таблицы пиринга [подсеть] [маска_подсети], пример:


195.225.128.0 255.255.255.0
195.225.130.0 255.255.254.0


Прошу не пинать ногами, а прошу помочь.
Если кто сможет написать этот кусок опимальней по производительности , киньте сюда.

cipipi
06-01-2009, 23:52
Но с другой стороны, DHCP-сервер может выдать этот айпишник кому-то уже после того, как вы его займёте.
То есть DHCP-сервер не проверяет соединение перед тем как выдать этот IP?


arping -I vlan1 -c 3 -D предполагаемый_IP_адрес
Действительно работает для локальных IP моей подсети, на которые не действует обычный пинг.
Буду думать, как прикрутить сие чудо к скрипту.

Power
07-01-2009, 01:13
То есть DHCP-сервер не проверяет соединение перед тем как выдать этот IP?


А кто его знает...






#регистрируем дополнительные локальные подсети не из диапазона 10.0.0.0/8
PIRING_TABLE="/opt/etc/piringtbl"

#Если файла нет - ничего не прописываем в таблицы
if [ -f $PIRING_TABLE ]; then
#Меняем стандартный поток, сохраняя его дескриптор, на поток из файла таблицы пиринга
exec 9<&0 0<$PIRING_TABLE
#читаем построчно пока не кончится файл
while read line; do
#формируем строку команды: route add -net [подсеть] netmask [маска_подсети] gw $3 dev vlan1:0
#и тут же ее выполняем.
$(echo $line | awk '{print "route add -net " $1 " netmask " $2 " gw " IP " dev vlan1:0"}' IP=$3)
done
#Восстанавливаем стандартный поток
exec 0<&9
fi



1. Я бы заменил "[ -f $PIRING_TABLE ]" на "[ -r $PIRING_TABLE ]" - так будет гарантия, что файл доступен для чтения.

2. Конструкцию с перенаправлением ввода-вывода ("exec 9<&0 0<$PIRING_TABLE", "exec 0<&9") можно заменить на перенаправление для самого цикла (да, так можно)


while read line; do
...
done < $PIRING_TABLE


3. Пути лучше писать полностью (/usr/bin/awk, /sbin/route), если вы собираетесь вызывать это всё из каких-либо post-* скриптов.

4. Если в файле писать подсети сразу в формате 195.225.128.0/24, то можно строчку


$(echo $line | /usr/bin/awk '{print "/sbin/route add -net " $1 " netmask " $2 " gw " IP " dev vlan1:0"}' IP=$3)

сократить до


$(echo $line | /usr/bin/awk '{print "/sbin/route add -net " $1 " gw " IP " dev vlan1:0"}' IP=$3)

а так как поле получается только одно на строку, то и вовсе до


/sbin/route add -net $line gw $3 dev vlan1:0

cipipi
07-01-2009, 01:42
а так как поле получается только одно на строку, то и вовсе до


/sbin/route add -net $line gw $3 dev vlan1:0

"А ларчик просто открывался".

2 Power Тогда немного отвлеченный вопрос. А маска может быть такой: 255.0.255.128, или она должна обязательно состоять из непрерывного одного поля единиц бинарного кода.
255.255.255.128 d = 11111111.11111111.11111111.10000000 b точно можно.
255.0.255.128 d = 11111111.00000000.11111111.10000000 b можно?

Power
07-01-2009, 10:14
А маска может быть такой: 255.0.255.128, или она должна обязательно состоять из непрерывного одного поля единиц бинарного кода.
255.255.255.128 d = 11111111.11111111.11111111.10000000 b точно можно.
255.0.255.128 d = 11111111.00000000.11111111.10000000 b можно?

Выдержка из RFC 950 (http://tools.ietf.org/html/rfc950)


Since the bits that identify the subnet are specified by a bitmask, they need not be adjacent in the address. However, we recommend that the subnet bits be contiguous and located as the most significant bits of the local address.

То есть, единицы не обязаны идти непрерывно, но рекомендуется так не делать.
На практике большинство систем не позволят вам задать не-непрерывную маску. Например, iptables понимает такие маски (в виде 10.0.20.0/255.0.255.0), а route - нет.

cipipi
07-01-2009, 13:52
Выкладываю предфинальный скрипт без определения
свободного IP, сделанный под чутким руководством Power ;).



#!/bin/sh
NAME_IPTBL_ORIG="/tmp/iptbl"
PIRING_TABLE="/opt/etc/piring"

#AWK="/usr/bin/awk"
RM="/bin/rm"
ROUTE="/sbin/route"
IFCONFIG="/sbin/ifconfig"
ECHO="/bin/echo"
IPTABLES="/usr/sbin/iptables"
IPTABLES_SAVE="/usr/sbin/iptables-save"
IPTABLES_RESTORE="/usr/sbin/iptables-restore"
CAT="/bin/cat"

$ECHO "wlan-alias [up|down] [Local IP] [Local Gate] [Local Broadcast]"

if [ -z $1 ]; then

$ECHO "Nothing to be done!!!"

exit 1

fi;


if [ $1 = "up" ]; then

[ -r $NAME_IPTBL_ORIG ] && exit 1
[ -z $2 ] && exit 1
[ -z $3 ] && exit 1
[ -z $4 ] && exit 1

$IPTABLES_SAVE >> $NAME_IPTBL_ORIG

$IFCONFIG vlan1:0 $2 netmask 255.255.255.0 broadcast $4
$ROUTE add $3 dev vlan1:0

if [ -r $PIRING_TABLE ]; then
for i in $($CAT $PIRING_TABLE); do
$ECHO "Add to route table subnet: " $i
$ROUTE add -net $i gw $3 dev vlan1:0
done
fi


$IPTABLES -t nat -A PREROUTING -d $2 -j VSERVER
$IPTABLES -t nat -I POSTROUTING 1 -o vlan1 -j MASQUERADE

$ECHO "Alias on WLAN is open"

exit 0

fi;

if [ $1 = "down" ]; then

if [ ! -r $NAME_IPTBL_ORIG ]; then

$ECHO "ERROR: Has no original iptables save file!!"
exit 1

fi

$IFCONFIG vlan1:0 down
$IPTABLES --flush
$IPTABLES -t nat --flush
$IPTABLES -t mangle --flush
$IPTABLES -X
$IPTABLES_RESTORE $NAME_IPTBL_ORIG

$RM $NAME_IPTBL_ORIG

$ECHO "Alias on WLAN is closed"

exit 0

fi;


Для него полагается файл пиринговых сетей $PIRING_TABLE=/opt/etc/piring в формате:


10.0.0.0/8
79.120.53.0/24
79.120.54.0/24
79.120.122.0/24

cipipi
07-01-2009, 21:55
Немного погодя беру свои слова обратно:


arping -I vlan1 -c 3 -D предполагаемый_IP_адрес
Действительно работает для локальных IP моей подсети, на которые не действует обычный пинг.
Буду думать, как прикрутить сие чудо к скрипту.
Увы и ах, пока я не подключен непосредственно интерфейсом vlan1:0 к своей подсети 10.64.20.0... видится весьма ограниченое число IP. :mad:

Чего делать, не знаю.

Power
08-01-2009, 13:44
Увы и ах, пока я не подключен непосредственно интерфейсом vlan1:0 к своей подсети 10.64.20.0... видится весьма ограниченое число IP. :mad:


С этого места поподробнее. Работоспособность arping не должна зависеть от наличия интерфейса vlan1:0. А с опцией -D он не светит ваш айпи, а использует 0.0.0.0 (фактически, опция -D включает режим обнаружения повторяющихся IP-адресов, т.е. ровно то, что вам нужно).






RM="/bin/rm"
...
ECHO="/bin/echo"
...
CAT="/bin/cat"



Это уже, пожалуй, лишнее. Команды из /bin/ точно можно использовать, не указывая путь (да наверняка и некоторые другие, но точных данных нет, так что все пишут пути на всякий случай).

cipipi
08-01-2009, 21:03
С этого места поподробнее...
Для проверки работы arping написал небольшую тулзу


#!/bin/sh
IP="10.64.20."

for i in $(echo $IP | /usr/bin/awk ' {for (j = 1; j <= 254; j++) {print($1 j)}} '); do

/opt/bin/arping -I vlan1 -c 1 -D $i | grep "Unicast reply"

done


Да, вы оказались правы. Только так все медленно работает + не удалось
сделать условный вывод по возвращаемому значению arping

Power
08-01-2009, 23:55
Скрипт выведет список тех айпи, которые не ответили на запрос (то есть, предположительно свободны)


#!/bin/sh

i=1
net='10.64.20.'
while [ $i -lt 255 ]
do
ip="${net}${i}"
arping -I vlan1 -c 1 -D -q "$ip" && echo "$ip"
i=`expr $i + 1`
done


Насчёт "медленно работает" - а что вы хотели, нужно дождаться ответа от получателя (таймаут ожидания около 1 секунды).

cipipi
09-01-2009, 00:56
Опять я лоханулся. Забыл в конструкции if ;then fi подавить вывод arping при проверке возвращаемого значения. В данном случае это делается параметром -q. Я потом нашел еще вариант: дописать в конце проверяемой комманды > /dev/null 2>&1

Power, огромное thx. Помогли разобраться в критических моментах.

Теперь я знаю потенциальные возможности моего коннекта с сетью. Буду разбираться с провом, почему он "кричит" и говорит, что не может одновременно мне предоставить внешний и локальный IP..

Хотел добавить, что не имеет смысла встраивать определение свободного IP в разработанный "предфинальный" скрипт, т.к. через несколько минут он может быть уже несвободным. Я помониторил сеть во время высокой ее активности приведенной выше тулзой, которая обозначила промежутки в диапазоне, в которых не назначаются IP почему-то. Например, выше 189 не назначаются, в промежутке от 85 до 112 тоже. Наибольшее скопление назначенных IP в начале диапазона от 2 до 80.