Возникла задача предоставить сервис для клиентов, использующих внешние динамические адреса.
Доступ к сервису ограничен правилами IPTABLES.Клиентам, которым необходимо получить услугу предлагается создать учетную запись на ресурсе dyndns.org,
клиент получит доменное имя в виде client.dyndns.org.При каждом изменении ip адреса клиента мы всегда узнаем его адрес по доменному имени. Если мы добавим
правило в iptables для этого доменного имени, правило будет работать только для текущего ip адреса клиента
и при последующем изменении ip адреса, доступ к сервису будет ограничен.Оригинал решения был найден здесь: http://dave.thehorners.com/content/view/86/65/ , а мы всего лишь доработаем этот скрипт.
Создаем несколько каталогов:
/root/dynhosts/ - общий каталог
/root/dynhosts/zones/ - здесь будем хранить файлы доменных зон клиентов
/root/dynhosts/logs/ - лог файлы работы скрипта
/root/dynhosts/scripts/ - здесь будет находится сам запускаемый скриптСоздаем лог-файл:
touch /root/dynhosts/logs/dynhosts.log
Создаем файл зоны клиента:
touch /root/dynhosts/zones/client.dyndns.org
Создаем сам скрипт /root/dynhosts/scripts/firewall-dynhosts.sh
#!/bin/bash
#
# filename: firewall-dynhosts.sh
#
NOW=$(date)
CHAIN="dynamichosts" # change this to whatever chain you want.
IPTABLES="/sbin/iptables"
# create the chain in iptables.
$IPTABLES -N $CHAIN
# insert the chain into the input chain @ the head of the list.
$IPTABLES -I INPUT 1 -j $CHAIN
# flush all the rules in the chain
$IPTABLES -F $CHAIN
FILES=`ls --format=single-column /root/dynhosts/zones/`
echo $FILES
for file in $FILES
do
HOSTFILE="/root/dynhosts/zones/$file"
echo $HOSTFILE# lookup host name from dns tables
IP=`/usr/bin/dig +short $file | /usr/bin/tail -n 1`
if [ "${#IP}" = "0" ]; then
echo "$NOW Couldn't lookup hostname for $file, failed." >> /root/dynhosts/logs/dynhosts.logcontinue
fi
OLDIP=""
if [ -a $HOSTFILE ]; then
OLDIP=`cat $HOSTFILE`
echo "CAT returned: $?"
fi# save off new ip.
echo $IP>$HOSTFILEecho "Updating $file in iptables."
echo "Inserting new rule ($IP)"
$IPTABLES -A $CHAIN -s $IP/32 -j ACCEPTdone
exit0Запускаем скрипт:
/root/dynhosts/scripts/firewall-dynhosts.sh
iptables: Chain already exists
client.dyndns.org
CAT returned: 0
Updating client.dyndns.org in iptables.
Inserting new rule (213.64.141.6)Проверяем,
cat /root/dynhosts/zones/client.dyndns.org
213.64.141.6/sbin/iptables -nL dynamichosts
Chain dynamichosts
target prot opt source destination
ACCEPT all - 213.64.141.6 0.0.0.0/0Если такого доменного имени не существует в /root/dynhosts/logs/dynhosts.log была бы запись следующего содержания:
Tue Aug 25 09:47:15 MSD 2009 Couldn't lookup hostname for client.dyndns.org, failed.
После того как контракт с клиентом истек достаточно удалить файл его зоны из /root/dynhosts/zones/.
Осталось добавить выполнение скрипта в крон.
URL: http://subnets.ru/blog/?p=1007
Обсуждается: http://www.opennet.me/tips/info/2155.shtml
А по логину и паролю или сертификату нельзя было разграничить доступ? :)
>А по логину и паролю или сертификату нельзя было разграничить доступ? :)Причин может быть много, от желания лишний раз перестраховаться и дополнительно прикрыть сервис фаерволом, до варианта когда за каждым IP сидит домашняя сетка с кучей людей через NAT и им нужно простым способом дать доступ к web/ftp.
Гм, а прикрутить какой-нибудь port knock демон, "слушающий" не отдельный диапазон портов, а [закрытый по умолчанию] порт охраняемого сервиса, и открывающий его по успешной проверке обратного dyndns разрешения адреса? Ну, плюс какое-нибудь выстраивание проверок в очередь, чтоб не заDOSисли...Регистрация на dyndns -> первая попытка соединения -> облом + отработка кнокера -> вторая попытка подключения -> норм.соединение.
Хотя, выкидывать из разрешающих таблиц тоже как-то надо. ipt_recent - ом "expire"-ить?...
Главное, чтоб никакого крона. %)
И кста, об event-драйвен (врагам udev-а: сильно не пинайте, я же даже не написал никаких _пастчей_): даёшь %) ipt_resent-у и ipt_set-у CRUD-hookи-callbackи?
Интересно, ломящиеся на порт ssh бот-неты такую конструкцию быстро положат? $) А противо-бот-нет-ные костыли придумать...
а теперь представим ситуацию, я легитимный пользователь получаю IP, регистрирую зону , создаю там запись в автоматическом режиме , пользуюсь интернетом всё хорошо. выключаюсь , и вдруг мой IP выдаётся другому клиенту, скрипт лезет по файлам, находит что IP принадлежит мне(я не удалял запись и не менял её мне инет в данный момент не нужен) и пускает нелегитимного пользователя как менятеперь рассмотрим скрипт
$IPTABLES -F $CHAIN
те этой строкой мы очищаем таблицу правил для того чтобы создать новую таблицу но !!!!!
1.время формирования новой таблицы не равно 0 и соответственно мы прерываем все соединения от всех динамических клиентов
2. если использовать крон то данное действие мы будем производить с определённой периодичностью(чем актуальнее для нас скорость обновления тем чаще будут обрываться соединения)исправление разрывов можно избежать добавив первым(для уменьшения нагрузки) правилом
$IPTABLES -I INPUT 1 -m state --state RELATED,ESTABLISHED -j ACCEPT
$IPTABLES -I INPUT 2 -j $CHAINREM вот не помню но !! по моему инзерт (-I) сдвигает правила, а не заменяет текущую позицию(-R), посмотрите после N запусков содержимое таблицы INPUT и не удивляйтесь потом почему это у меня такая большая загрузка системы в пространстве ядра
производить формирование таблицы правил в отдельный файл
echo #/bin/bash > temp_rules.sh
chmod 700 temp_rules.shfor file in $FILES
...Skip...
echo "$IPTABLES -A $CHAIN -s $IP/32 -j ACCEPT" >> temp_rules.sh
...Skip...
doneи очистку таблицы $CHAIN производить после обработки всех данных сразу же перед внесением новых правил
$IPTABLES -F $CHAIN
temp_rules.sh
rm -f temp_rules.shну гдето так :)
PS: господа если пишем в новости "а мы всего лишь доработаем этот скрипт" так давайте дорабатывать
строку echo #/bin/bash > temp_rules.sh заменить на echo "#!/bin/bash" > temp_rules.sh
Мой вариант скрипта для разрешения прохода мимо маршрутизатора нужных хостов на удалёную машину#!/bin/bash
#
# filename: firewall-dynhosts.sh
#
PATH="/usr/local/sbin/dynhosts"
NOW=$(/bin/date)
CHAIN="dynamichosts" # change this to whatever chain you want.
IPTABLES="/sbin/iptables"# create the chain in iptables.
$IPTABLES -N $CHAIN -t natFILES=`/bin/ls --format=single-column $PATH/zones/`
echo $FILESfor file in $FILES
do
HOSTFILE="$PATH/zones/$file"
echo $HOSTFILE# lookup host name from dns tables
IP=`/usr/bin/dig +short $file | /usr/bin/tail -n 1`
if [ "${#IP}" = "0" ]; then
echo "$NOW Couldn't lookup hostname for $file, failed." >> /$PATH/logs/dynhosts.logcontinue
fiOLDIP=""
if [ -a $HOSTFILE ]; then
OLDIP=`cat $HOSTFILE`
echo "CAT returned: $?"
fi# save off new ip.
echo $IP>$HOSTFILE
echo "Updating $file in iptables."
echo "Inserting new rule ($IP)"
$IPTABLES -I $CHAIN -t nat -p tcp -s $IP --dport 6666 -j DNAT --to-destination 192.168.1.1:3389done
#$IPTABLES -F $CHAIN
NUMFILES=`/bin/ls $PATH/zones -1A|/usr/bin/wc -l`
for file in $FILES
do
I=1
let "SUM=$I+$NUMFILES"
echo "Deleting $SUM rule from $CHAIN"
`$IPTABLES -t nat -D $CHAIN $SUM `
let "I=$I+1"done
exit