OpenVPN сервер для офисного шлюза на FreeBSD [2010]
Недавно мы развернули шлюз для небольшого офиса и организовали на нём учёт трафика. Следующей задачей, которую полезно решить, является удалённый доступ сотрудников в офисную сеть. Для этого можно использовать одну из реализаций VPN. Мы будем использовать OpenVPN, как наиболее гибкий и удобный в использовании вариант.
Первым делом установим OpenVPN:
cd /usr/ports/security/openvpn && make install clean
Приступаем к настройке. Сначала создадим необходимые директории:
Ключи будут сгенерированы в директории /usr/local/etc/openvpn/easy-rsa/keys. Однако удобнее будет использовать в файлах конфигурации путь /usr/local/etc/openvpn/keys, поэтому создадим симлинк:
Следующим шагом редактируем по своему вкусу файл /usr/local/etc/openvpn/easy-rsa/vars, который описывает большую часть настроек для новых ключей, после чего переходим в директорию со скриптами:
cd /usr/local/etc/openvpn/easy-rsa
FreeBSD использует в качестве оболочку по умолчанию /bin/csh, а скрипты генерации ключей написаны в расчёте на /bin/sh и при использовании их в csh наблюдаются проблемы с использованием переменных окружения. Чтобы решить эту проблему запустим классически шелл:
sh
По умолчанию со скриптов снят атрибут "исполняемый". Установим его:
chmod +x *
Считаем настройки для генерации скриптов:
. ./vars
Генерируем ключ для сервера:
./clean-all && ./build-ca && ./build-dh && ./build-key-server server
Теперь создадим файл /usr/local/etc/openvpn/server.conf, описывающий конфигурацию сервера. Здесь и далее мы исходим из того, что для клиентов нашего OpenVPN-сервера мы выделяем сеть 172.31.254.0/24:
# OpenVPN запускается в режиме сервера
mode server
# Используем TLS-шифрование
tls-server
# Работаем в режиме демона
daemon
# Настройки виртуального интерфейса на стороне сервера
ifconfig 172.31.254.1 255.255.255.0
# Порт, на котором будет слушать
port 1194
# Используем протокол tcp
proto tcp-server
# Имя интерфейса, который будет использовать сервер
Далее нужно подгрузить модуль для работы с tap-интерфейсами:
kldload if_tap
Чтобы модуль автоматически подгружался при загрузке нужно добавить в /boot/loader.conf строку:
if_tap_load="YES"
Наконец запускаем сервер:
/usr/local/etc/rc.d/openvpn start
Теперь нам нужно внести изменения в настройки пакетного фильтра, который мы настроили в предыдущей статье. Сразу приведём обновлённый вариант файла /etc/pf.rules:
# Основные настройки
if_ext = "le0"
if_int = "em0"
if_vpn = "tap0"
net_int = "172.31.255.0/24"
net_vpn = "172.31.254.0/24"
set block-policy drop
set state-policy if-bound
scrub all reassemble tcp fragment reassemble
# NAT для локальной сети
nat pass on $if_ext from $net_int -> ($if_ext) static-port
# Разрешаем всё на loopback-интерфейсе
pass quick on lo0 all
# Разрешаем исходящий трафик
pass out quick on $if_ext inet proto tcp from ($if_ext) to any flags S/SA keep state
pass out quick on $if_ext inet proto { udp, icmp } from ($if_ext) to any keep state
# Разрешаем исходщящий трафик в сторону локальной сети
pass out quick on $if_int from ($if_int) to $net_int
pass out quick on $if_int from $net_vpn to $net_int
# Разрешаем входящий трафикк со стороны локальной сети
pass in quick on $if_int from $net_int to any keep state
# Разрешаем исходящий трафик в сторону VPN-сети
pass out quick on $if_vpn from ($if_vpn) to $net_vpn
pass out quick on $if_vpn from $net_int to $net_vpn
# Разрешаем входящий трафик со стороны VPN-сети
pass in quick on $if_vpn from $net_vpn to any keep state
# Разрешаем обращение к нашему VPN-серверу снаружи
pass in quick on $if_ext inet proto tcp from any to ($if_ext) port 1194 flags S/SA keep state
# Запрещаем весь остальной трафик
block drop all
Применяем правила:
pfctl -f /etc/pf.rules
Теперь посмотрим как нужно действовать когда появляется необходимость предоставить некоторому пользователю удалённый доступ в офис. Первым делом снова перейдём в директорию со скриптами для генерации ключей:
cd /usr/local/etc/openvpn/easy-rsa
Запустим оболочку, в контексте которой будут работать скрипты:
sh
Установим необходимые переменные окружения:
. ./vars
Сгенерируем ключ для пользователя "username":
./build-key username
Затем создадим файл /usr/local/etc/openvpn/ccd/username примерно вот такого содержания:
ifconfig-push 172.31.254.101 255.255.255.0
Здесь мы указываем IP-адрес и маску сети, которые будут на виртуальном интерфейсе у клиента. Разумеется что адреса разных клиентов не должны совпадать.
Файл конфигурации клиента будет иметь вид:
client
dev tap
proto tcp
# Внешний адрес офисного сервера
remote office.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
comp-lzo
ns-cert-type server
# Файлы ключей
ca ca.crt
cert username.crt
key username.key
Настройки OpenVPN-клиента в разных ОС уже описывалась ранее и потому подробно рассматривать этот вопрос мы не будем.