Наконец-то мне удалось развить систему разграничения сетей через браузер для доступа к открытым и закрытым системам с веб-интерфейса. Сейчас расскажу все детали.
Задача
На ряде компьютеров нужно осуществить подключение к сети Интернет, а также подключение к некоторым базам данных, находящихся в другой интра-сети. Причём есть ряд требований.
- Доступ не должен быть одновременно и к сети Интернет и к базе данных, т.к. создаются предпосылки для нецелевого использования – доступа удалённых злоумышленников посредством TeamViewer и прочих RAdmin-ов. Такого не надо
- Доступ к базам осуществляется с использованием средств криптографической защиты ViPNet 3-ей и 4-ой версии (к разным базам – через разные клиенты) посредством той же сети Интернет.
Решение
Придумал вот что.
- Завёл две виртуальные машины под ViPNet Client-ы. На каждую – соответствующий клиент и дистрибутив ключей. Первая виртуалка может обращаться на защищённые узлы 1.1.1.1, 2.2.2.2, 3.3.3.3, вторая – на 4.4.4.4, 5.5.5.5 соответственно. (адреса завуалированы, там, соответственно, ещё и порты различные).
- На каждую из виртуальных машины поставил Nginx под Windows. В настройках прописал типа такого:
server {
listen 80;
server_name baza1.localdomain;
location / {
proxy_pass http://1.1.1.1;
}
}
И так для каждого удалённого узла. Если используются нестандартные порты – всё указывается как есть. - Для одной из машин создаём также сервер с server_name базы, доступной из другой виртуалки и проксируем запросы на вторую. Цель – каскадная передача информации, чтобы с одного веб-сервера были доступны вообще все базы.
- Настраиваем межсетевой экран в ViPNet Client таким образом, чтобы разрешались нужные порты для соответствующих узлов. Если что – лезть в “Фильтры открытой сети”. Если что – смотреть журнал IP-пакетов, какие пакеты отбрасываются и на каком фильтре.
Доступ на первую виртуалку делаем только с IP-адреса нашего шлюза (GW – в п.5), чтобы нельзя было пойти в обход. - Теперь самое интересное – как сделать, чтобы одновременно работал либо Интернет, либо эти самые базы.
Создаём следующие правила в iptables:
#адрес первой виртуалки, с которой доступно всё
virtual1=192.168.1.ZZ
#адрес шлюза Интернет
GW=192.168.1.XX
$iptables -t nat -A PREROUTING -m set --match-set baza src -d $GW -p t cp -m tcp --dport 80 --j DNAT --to-destination $virtual1:80
$iptables -t nat -A PREROUTING -m set --match-set baza src -d $GW -p t cp -m tcp --dport 5000 --j DNAT --to-destination $virtual1:5000
$iptables -I FORWARD -d $virtual1 -m set --match-set baza src -j ACCEPT
$iptables -I FORWARD -s $virtual1 -m set --match-set baza dst -j ACCEPT
$iptables -I FORWARD -m set --match-set baza dst -i $WAN -j DROP
#да, у меня одна из баз на 5000-ом порту – приходится мириться. - Создаём список ipset типа hash:ip с именем baza. Таким образом IP-адреса, находящиеся в этом списке могут получать доступ к базам, используя шлюз как ретранслятор, а не находящиеся – могут ходить в Интернет. Осталось только либо помещать IP абонента в список, либо извлекать из него, в зависимости от желания пользователя. Решено было сделать это при помощи связки PHP+AJAX. См. следующий пункт.
- Создаём скриптец примерно такого вида:
<?php
header('Access-Control-Allow-Origin: *');
$IP = $_SERVER['REMOTE_ADDR'];
switch ($_POST['mode']){
case 'inet':
exec("/bin/ipset -D baza $IP");
break;
case 'base':
exec("/bin/ipset -A baza $IP");
break;
}
echo json_encode($output);
?>
Да-да, пришлось вынести ipset в /bin и назначить SUID ему… Маленькая хитрость. Но по другому не смог – не запускать же весь веб-сервер с правами рута?.
Осталось сделать веб-страничку с переключателем (на каком-нибудь красивом UI-фреймворке и влепить передачу параметра ‘mode’ = “inet” или “base” в зависимости от того, что мы хотим получить. - Ну и осталось поднять зону DNS, которая будет обслуживать адреса вида *.localdomain и посылать всех на адрес шлюза.
Теперь всё выглядит так. Клиент открывает браузер – у него прописана домашняя страничка – заглушка с переключателем и краткой инструкцией. Выставляет переключатель в нужное положение в зависимости от того, что ему нужно получить – Интернет или Базы. При этом на скрипт посылается соответствующий параметр. Скрипт добавляет/удаляет IP-адрес клиента в ipset list “baza”. При выборе доступа к базам отображается перечень всех баз с доменными именами (DNS посылает всех на шлюз). И шлюз редиректит все обращения на свой 80 порт дальше, на первую виртуальную машину.
Та виртуальная машина держит NGINX, который, в зависимости от запрашиваемого хоста проксирует запрос дальше.
P.S. Я ещё реализовал примочку запроса текущего состояния, чтобы при закрытии и открытии браузера ползунок оставался в последнем заданном положении.
P.P.S. Пока не поборол проблему проксирования https.
Comments: