Метки
amd bittorrent bug centos debian enlightenment fedora fedora 8 fedora 9 fedora 10 fedora 11 fedora 12 fedora 13 fedora 15 fedora 16 FedoraMD fglrx firefox flash player gnome google intel interview java kde kernel linux livecd migrate moldova nvidia openoffice OpenStreetMap opera Orange ovirt radeon red hat rpmfusion Sandel skype video virtualisation vmware wine
динамическая фильтрация траффика OpenVPN через iptables
2013-05-04 13:34 | Автор: jekader | Filed under: FedoraMD
Нашёл одну интересную задачу применительно к OpenVPN, возможно будет полезно кому-то ещё. Заключается она в фильтрации траффика OpenVPN для каждого клиента в отдельности прямо на сервере.
Вступление:
OpenVPN - это реализация VPN поверх SSL, очень гибкая и универсальная штука. Может служить и как Remote Access VPN (для подключения удалённых пользователей), так и как Site 2 Site (для взаимоподключения сетей). При этом, и на сервере и на клиенте появляется виртуальный интерфейс, и на этот интерфейс назначаются маршруты. Это позволяет, к примеру, не гонять интернет траффик зашифрованным, а открывать только отдельные сети.
Дано:
Итак, допустим у нас есть OpenVPN сервер, и к нему подключаются пользователи A, B и С
Пользователю A нужен доступ только к SVN серверу, сидящему по адресу 192.168.2.2
Пользователю B помимо SVN нужен ещё и файл-сервер 192.168.6.100
Пользователю C требуется доступ к "боевым" серверам в сети 10.25.25.0.24
Решение:
каждому пользователю высылаем свой пакет маршрутов, это очень тривиально делается в OpenVPN директивой ccd. Каждый пользователь имеет свой файлик конфигурации, где написаны его личные настройки.
OK, отправили маршруты, все счастливы. Но что будет, если пользователь A вручную пропишет себе маршруты пользователя C? OpenVPN никак этому не будет препятствовать, и пользователь получит доступ куда не надо!
В моём примере всё просто решается добавлением пары правил в iptables. Но что если таких пользователей не трое, а 100? Или 1000? А также есть несколько OpenVPN серверов в целях повышения надёжности, и права пользователей меняются по несколько раз в день?
Ничего готового на эту тему не было, так что на помощь пришла гибкость OpenVPN: я написал два маленьких bash скрипта. первый при подключении пользователя парсит конфиг и на каждый маршрут добавляет правило в цепочку FORWARD. Второй при отключении стирает правила, созданные первым скриптом. Благодаря этому, левый траффик отвергается, и клиент может ходить только в сети, разрешённые сервером.
Первый скрипт, on_connect.sh, запускается при подключении:
Второй скрипт, on_disconnect.sh - запускается при отключении:
#!/bin/bash
#scripts that removes rules with a given comment
#make sure the script is run once at a time.
#This will leave some rules in place, however that's much better than
#having two scripts running simultaneously and screwing up iptables
#
logfile="/var/log/openvpn/iptables.log"
date >> $logfile
pidfile=/var/lock/openvpn_disconnect.pid
if [ -e $pidfile ]; then
pid=`cat $pidfile`
if kill -0 $pid > /dev/null 2>&1; then
# echo "Already running"
exit 1
else
rm $pidfile
fi
fi
echo $$ > $pidfile
#the script itself
rulecomment=$common_name"_openvpn"
#list rules with line numbers | get needed rules | sort reverse| remove line by line
/usr/bin/sudo /sbin/iptables -L FORWARD --line-numbers | grep $rulecomment | sort -r -n | while read line; do
rulenumber=$(echo $line | cut -f1 -d" ")
echo "iptables -D FORWARD $rulenumber" >> $logfile
/usr/bin/sudo /sbin/iptables -D FORWARD $rulenumber
done
#remove the PID file after everything is done
rm $pidfile
exit 0
Пояснения: первый скрипт читает конфиг openVPN и CCD файл, если такой существует. На каждое упоминание "push route" создаётся правило с комментарием вида username_openvpn. Второй скрипт стирает все правила с этим комментарием. Так как он работает по номерам строк, я сделал lock file, чтобы два скрипта не запустились одновременно. Это чревато порчей правил в iptables. Пускай лучше останутся пару лишних правил, чем упадёт весь сервер.
Чтобы это счастье работало есть ещё несколько шагов.
1) включаем скрипты в конфиг OpenVPN:
script-security 2
client-connect /etc/openvpn/on_connect.sh
client-disconnect /etc/openvpn/on_disconnect.sh
2) настраиваем sudo (ведь OpenVPN мы запускаем под nobody, а iptables может пускать только root):
cat /etc/sudoers.d/openvpn_iptables
Defaults:nobody !requiretty
nobody ALL = NOPASSWD: /sbin/iptables
3) настраиваем Selinux (мы ведь параноики):
сначала отключаем временно enforcement
setenforce 0
теперь подключаемся к OpenVPN серверу с клиента, потом отключаемся, проверяем что всё работает.
Дальше дело за малым - создать политику. Для этого запускаем:
grep openvpn /var/log/audit/audit.log | audit2allow -M openvpn_sudo_ipt
модуль готов, устанавливаем!
semodule -i openvpn_sudo_ipt.pp
включаем назад enforcement:
setenforce 1
теперь наши скрипты должны запускаться и работать как следует!
TODO: парсинг директивы iroute
PS: замечу, что эти скрипты были написаны за пару часов человеком без особого знания скриптинга. Если есть предложения к улучшению - комментируйте! Скрипты также закинул на gitHub для удобства: https://github.com/jekader/openvpn-iptables
Метки:
6, 2013 11:11
Отлично. Спасибо за скрипты. Пригодятся.