Sugar 30.06.2010 12:13

Linux Network AdministrationОткрытие портов на некоторое время

Доброго времени суток, welinux.ru
Работаю сисадмином в некоторой конторе, есть сетка, есть прокси-сервер, он же шлюз, на основе ОС GNU/Linux.
На сервачке всё как положено - весь инет идет через прокси (squid), файрвол настроен, все политики по умолчанию установлены в drop, нескольким машинам открыты нужные им порты. Всё вроде хорошо, маршрутизация настроена, пакетики бегают, юзеры довольны, но есть одно но...

Иногда, а бывает даже и часто, требуется открывать определённые порты определенным хостам. Например ПО какое-нибудь обновить, которое не понимает аутентификации моего прокси, или открыть порт требуется для какой-нибудь машины в сети, или просто что-то протестировать/проверить на клиентской машине, либо вообще временно ей предоставить доступ в инет по всем непривилегированным портам, да и мало ли всякое бывает. При чем так, чтобы открыл, поставил нужное время, и пошел спокойно к той машине свои дела делать, а через время эти порты сами и закрылись.

Так что вот для этой цели и был написан на баше скрипт-обертка для iptables, который я и представляю здешней общественности.
Установка и принцип работы у него простые. Для начала копируем себе скрипт, обзываем его как Вам нравится (у меня это openport.sh), даем права на выполнение, помещаем в любой каталог с исполняемыми файлами (например /usr/bin/), и можем спокойно использовать.

Опции он принимает такие:
open|close - открыть/закрыть порт(ы)-m - подключение расширения iptables "-m multiport"--host $arg - ip машины (можно указать и подсеть в таком виде - 192.168.11.0/24)--port $arg - порт(ы), для такой записи - 1024:2048, опция -m не требуется, а для такой - 22,80,443, требуется--proto $arg - протокол (tcp, udp), для которого требуется открыть порты--sleep $arg - время в минутах, через которое следует закрыть порты, которые вы открыли, игнорируется при действии close.

Далее, если есть аргументы open и --sleep скрипт открывает нужные порты (добываляет нужные правила), а затем уходит в фоновый режим, погружается в сон, затем через опеределенное время просыпается и закрывает открытые до этого порты (удаляет добавленные правила). Как видите, все просто.
Вот сам листинг скрипта:

  1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
#!/bin/bash
# This is script for opening and closing the port to
# the tatget host for a specified time, or without it.
# Anton Ukolov, 2010

usage() {
echo "Script for opening and closing port to the target host"
echo "open - open the port"
echo "close - close the port"
echo "or"
echo "$0 open|close <--host (ip_addr/net)> <-m> <--port port_num> <--proto tcp|udp|icmp> <--sleep minutes>"
echo "proto tcp is default"
exit 1
}

# Выкидываем дубликаты параметров, это важно, так как при таком вводе:
# openport open -m --host 192.168.0.111 --port 22 --port 20
# скрипт без проверки повторов молча присаивает последнее значение порта (20)
check_param() {
RES=`echo $STR | grep "$PARAM"`
if << "$RES" >>; then
echo "duplicated param: $PARAM"
echo
usage
fi
}

# Здесь в зависимости от значения $ACT выполняем нужно действие (open|close)
do_act() {
case "$ACT" in
open)
iptables -A FORWARD $MULTI -s $HOST -p $PROTO --dport $PORT -j ACCEPT
iptables -A FORWARD $MULTI -d $HOST -p $PROTO --sport $PORT -m state --state ESTABLISHED -j ACCEPT
;;
close)
iptables -D FORWARD $MULTI -s $HOST -p $PROTO --dport $PORT -j ACCEPT
iptables -D FORWARD $MULTI -d $HOST -p $PROTO --sport $PORT -m state --state ESTABLISHED -j ACCEPT
;;
*)
echo "wrong action, it may be open or close"
echo
usage
;;
esac
}

# Эту функцию вызываем со встроенным параметром "&", вследсвтие чего она проваливается
# в background, и выполняет свои действия уже в фоновом режиме.
do_sleep() {
sleep $SLEEP
ACT="close"
do_act
# echo "ports are closed!"
}

# Значения по умолчанию, устанавливаем нужные нам
HOST="192.168.0.5"
PORT="80"
PROTO="tcp"
SLEEP=""
MULTI=""

# Выделяем желаемое дейтсвие админа, а также в случае надобности включаем
# расширение iptables - multiport
ACT="$1"
shift
if << $1 -eq '-m' >>
then
MULTI="-m multiport"
shift
fi

# Проверяем количество оставшихся параметров (должно быть четным)
RES=$(($#%2))
if << $RES -eq 0 >>; then
# Пока строка не кончилась делаем выборку параметров - КЛЮЧ = ЗНАЧЕНИЕ
# Все параметры (кроме "open|close" и "-m") парные
# Порядок параметров роли играет (кроме первых двух)
while < $# -gt 0 >
do
case $1 in
--host)
PARAM="$1"; shift
STR="$*"; HOST="$1"
check_param; shift
;;
--port)
PARAM="$1"; shift
STR="$*"; PORT="$1"
check_param; shift
;;
--proto)
PARAM="$1"; shift
STR="$*"; PROTO="$1"
check_param; shift
;;
--sleep)
PARAM="$1"; shift
STR="$*"; SLEEP=$(($1*60))
check_param; shift
;;
*)
echo "wrong param: $1"
echo
usage
;;
esac
done
else
echo "wrong number of params"
echo
usage
fi

# Выполняем действие
do_act
# Проверяем, нужно ли закрыть порты через нужное время
# Затем вызываем функцию в фоновом режиме
if << $ACT -eq "open" && "$SLEEP" >>; then
do_sleep &
fi


Например, его можно использовать так:

openport.sh open --host 192.168.0.25 --port 8080 --sleep 25

Т.е. открываем порт 8080 для протокола tcp (т.к. стоит по умолчанию) для хоста 192.168.0.25 на 25 минут.

Почему поместил не в блог "Скрипты", а в "Linux Network Administration"? Отвечаю, задача непосредственно из области администрирования сети, в Linux (да и в UNIX в целом) многие задачи решаются с помощью написания скриптов, поэтому постить в блог "Скрипты", где свалены разношерстные по задачам сценарии, не захотелось. Да и людям, решающим конкретные задачи по сетевому администрирования Linux проще будет найти именно в этом блоге.

В этом скрипте много чего еще можно реализовать, как то: открытие порта из нета к локальной машине, отмена проверки устанговленного соединения (т.е. отменая расширения "-m state"), поддержка протокола icmp и его кодов, и т.д. и т.п.
Замечания и предложения приветствуются.

p.s. При определенном уровне интереса могу запостить скрипт на гитхабе для дальнейшего его развития. Пожелания можно слать на почту sugar.61rus сбк gmail тчк com


Тэги: bash iptables Netwrok script
+ 8 -
Похожие Поделиться

dfx 30.06.2010 12:35 #
Очень полезно, спасибо! Можно, конечно, и самому такое было бы написать, но когда это делают для тебя — вдвойне хорошо :)
Sugar 30.06.2010 12:53 #
Пожалуйста, пользуйтесь =)
thebeetlebum 30.06.2010 12:56 #
Такую штуку можно запихнуть в крон, чтобы все машины сети могли в одно и тоже время обновиться)
Sugar 30.06.2010 14:04 #
Кстати, отличная идея, спасибо!
VGusev2007 30.06.2010 15:28 #
Жесть! Вот зачем такое городить?

Используйте SOCKS!
Sugar 30.06.2010 16:17 #
Почему писал:
1) Писалось для себя за отсутствием нужного мне функционала, просто решил выложить, может кому пригодится.
2) Интересно.
3) UNIX-way все-таки.
Кстати добрая часть ваших любимых графических настраивалок системы это всего лишь фронтенды к вот таким вот шелловым скриптам.

Немного почитал про этот SOCKS, немного не понял как он в этой ситуации мне поможет.
VGusev2007 30.06.2010 16:20 #
Уважаемый, это не UNIX way. Это костыль. SOCKS это управляемая дырка. То есть ставите его, и практически все человеческие приложения умеют его использовать. В общем аналог сквида, только это для любого вида трафика. Логин/Пароль всё поддерживается.
Sugar 30.06.2010 18:14 #
Уважаемый, это не UNIX way. Это костыль.

Уважаемый, зачем так категорично и резко?
Это не костыль, это скрипт. По UNIX way вот, раздел - Майк Ганцарз: Философия UNIX, седьмой пункт.
SOCKS это управляемая дырка. То есть ставите его, и практически все человеческие приложения умеют его использовать.

Я знаю что такое SOCKS, но не все приложения у меня знают, что такое прокси, в итоге порты все равно придется открывать.
Плюс заметка, если ты не заметил, вообще-то не о прокси, а о временном открытии порта на файрволе. У кого-то вообще может не быть прокси, а аутентификация производится по мак-адресу. И тут все рулится iptables'ом.
И раз ты предложил SOCKS, перефразирую свой вопрос: поясни, пожалуйста, как открыть временно порты с помощью этой штуки?
В общем аналог сквида, только это для любого вида трафика. Логин/Пароль всё поддерживается.

Ну понятно, что пароль поддерживается. Только вот по сквиду масса статей по настройке, документации, разлчиные сопутствующие хаутушки. И в любом случае один на один с проблемой не останешься. Да и все-таки сквид очень мощная и надежная сволочь, я уверен, что если мне завтра придется настраивать выход в инет на 300 юзеров, я буду это делать только на сквиде.

зы Нравится SOCKS? Юзай, пожалуйста, мне проще написать скрипт, чем заново все настраивать, так-то. =)
Sov1et 30.06.2010 18:29 #
Вы, наверное, не совсем поняли, что говорил предыдуший оратор.
Расскажу на своём примере:
На шлюзе стоит сквид, который прозрачно всё проксирует. Все ненужные порты закрыты.
Также паралельно стоит сокс сервер 3proxy, на который можно завернуть любую программу.
Для запуска программ, которые отказываются работать через соксы, есть замечательна программа соксификатор FreeCap.
Плюс такого решения в том, что в настройках сокс сервера можно явно указать кому и на какой порт через наш сервер можно ходить и пробрасывать абсолютно любой трафик (а не только http и частично ftp).
Sugar 30.06.2010 18:50 #
Спасибо, интересно.
Кстати, сквид поддерживает метод CONNECT, что расширяет его облась применения помимо протоколов http и ftp.
time2die 30.06.2010 19:07 #
Я знаю что такое SOCKS, но не все приложения у меня знают, что такое прокси, в итоге порты все равно придется открывать.

а фаерволом весь трафик разве нельзя принудительно заворачивать на прокси ?
Sugar 30.06.2010 19:12 #
Можно, конечно, на прозрачный прокси. Но у меня сквид работает в обычном режиме.
cppmm 30.06.2010 22:43 #
Чего набросились-то на человека? Понятное дело, что если надо постоянно держать открытые(много, а не одно) соединения или если надо ими рулить в больших сетях для большого количества машин, определённо надо ставить SOCKS-сервер. А если раз в три года надо открыть один порт для одной машины, городить из-за этого здоровенный сервак с кучей настроек, имхо, извращение. Лично я использую иhttp, и socks-прокси, но иногда работаю простыми правилами, которые очищаются криптиком в cron.
VGusev2007 01.07.2010 09:52 #
Набросились от того, что вот это открыть порт по времени, потом закрыть, написать скрипт для этого - это всё косяки. Если случится проблема, или надо будет кого то о чём то попросить, то потом всё это забывается, и трахайся потом как хочешь после такого "горе админа" и такого "Unix way".
macumazan 01.07.2010 10:54 #
Только вот не надо гнать пургу про косяки. И то, что все забывается и вам/еще_кому-то приходится трахаться, то это ваше/чье-то личное, можете об этом написать отдельный пост, а не зудеть здесь высокомерным тоном от имени гуру админских дел.
Автор молодец, задачу решил и не поленился с решением поделиться.
VGusev2007 01.07.2010 10:59 #
То, что он молодец, и хорошо, что выложил скрипт это вне сомнений. Просто не только я но и другие люди подсказали более СТАНДАРТНОЕ решение. В частности: Sov1et , говорит совершенно верно.

А вот всё остальное, что Вы написали голословно. Что я могу, а что нет, это я знаю и сам. Флеймить не надо. Пишите аргументированно пож-та.
Sugar 01.07.2010 11:30 #
Все эти проблемы временных правил решаются так:
service iptables restart
В моем дистрибутив (альт), еще и так:
efw restart
Скрипт просто лежит в бинарниках, и без нужды сам по себе не запускается.
Кстати, проблемы "горе-админов" решаются документацией, та же вики например.
Кстати, Вы так и не ответили на поставленный вопрос.
VGusev2007 01.07.2010 11:39 #
Кстати, Вы так и не ответили на поставленный вопрос.

Про порты? Я конкретно не задавался вопросом проброса конкретных портов. Смотрите почему: Ставим сокс сервер, ставим мониторинг на него, настраиваем LDAP, и прочие пироги там SSL или чего ещё. Берём нужный комп, нужное приложение, выпускаем его через сокс. И не надо мороки с определением портов и так далее.
VGusev2007 01.07.2010 11:43 #
И да: сам скрипт хороший, повторюсь не очень нравится идея "на время". Ибо это потенциально запутанное действие. - Ещё раз повторяюсь, кто не понял.
cppmm 01.07.2010 13:31 #
o_O
"Эти русские совсем оборзели. У них на полях около Семипалатинска крысы завелись, так они их так вывели, что всему миру три раза аукнулось". (с) Американское народное творчество.
cppmm 01.07.2010 13:24 #
Для того, чтобы быстро протестировать виртуалхост в апаче, отзывающийся на ещё не прописанное в dns регистратора доменное имя, надо поднимать два dns-сервера или можно просто временно прописать соответствующую строку в /etc/hosts? Пример ТС из той же серии.
cppmm 01.07.2010 13:20 #
А документировать свои действия админ по вашему не должен? Я, например, держу для этого отдельный виртуалхост на внутреннем апаче с поднятым движком wikimedia, где те, кому разрешён доступ к серверу в любой момент может посмотреть подробное описание всех настроенных сервисов, всех скриптов и набор типовых действий на случай возникновения проблем. Помимо этого работа организовавается ещё и через redmine, где всегда можно глянуть, какие задачи были поставлены передо мной и как я их решил. А что, в серьёзных организациях такого не делается?
VGusev2007 01.07.2010 13:23 #
Сейчас я поднимаю такой сервис. Это должно делаться, и это правильно. Но всё же в целом, я считаю, что чем меньше всяких там пользовательских сценариев тем лучше. При том самые важные инструкции необходимо держать и в печатном виде.

Скажите, каким образом доступ к wikimedia разграничиваете? Тупо средствами apache или плугинами какими?
cppmm 01.07.2010 14:03 #
squid'ом и nginx'ом. :)
У меня прозрачный прокси, в котором идёт разграничение по ip и пользователям, потом идёт проксирующий nginx, который не принимает коннекты ни от куда, кроме адреса прокси, на нём модуль Auth Basic, а он уже в свою очередь проксирует запросы к разным серверам(среди которых и тот, на котором крутится апач с викимедией).
Sugar 02.07.2010 16:10 #
Вот это очень интересно, спасибо.
Т.о., в общем случае, получается такая вешь: ставим апача с веб-приложением, например вики, назначаем ему порт, отличный от 80, разрешаем к нему доступ только с 127.0.0.1, вешаем енжикса с auth_basic, и в нем уже рулим доступом. Я правильно Вас понял?
cppmm 03.07.2010 07:48 #
Совершенно верно.
И самый класс в таком подходе то, что если у вас появляется ещё один сервер(ну, к примеру, у меня есть хост с кучей виртмашин, на каждой из которых находится отдельный проект) и программистам, чтобы смотреть на проекты я даю не ip-адреса виртмашин, а адрес типа virtual1.companyname.com заведённому в nginx.
Sov1et 01.07.2010 17:30 #
А мы вот в google docs пишем. В последней версии очень удобно работать с расшаренными документами.
А на счёт того, что это не локально и всё зависит от интернета -- делаю локальные бэкапы.
cppmm 03.07.2010 07:49 #
У меня начальство несколько параноидально в плане безопасности и моё предложение попробовать GoogleDocs, GoogleWave и GoogleCode было отклонено по причине "Гугл может стырить наши данные". :))
Sugar 06.07.2010 21:31 #
Ксати, Столлман о том же самом предупреждает ))
k4m454k 02.07.2010 15:43 #
У iptables есть интересный модуль Time. Позволяет создавать правила включаемые(и выключаемые) в определённое время. Может быть очень полезной штукой, например можно резать торренты на работе только в рабочее время, а ночью нихай качают)
Sugar 02.07.2010 16:12 #
Тоже ксати любопытное замечание, гляну как-нибудь надосуге! Спасибо.