Недавно мы развернули шлюз для небольшого офиса и организовали на нём учёт трафика. Следующей задачей, которую полезно решить, является удалённый доступ сотрудников в офисную сеть. Для этого можно использовать одну из реализаций VPN. Мы будем использовать OpenVPN, как наиболее гибкий и удобный в использовании вариант.
Первым делом установим OpenVPN:
cd /usr/ports/security/openvpn && make install clean
Приступаем к настройке. Сначала создадим необходимые директории:
mkdir -p /usr/local/etc/openvpn/{ccd,easy-rsa/keys}
Скопируем скрипты для генерации ключей в более удобное для нас место:
cp -av /usr/local/share/doc/openvpn/easy-rsa/2.0/* /usr/local/etc/openvpn/easy-rsa/
Ключи будут сгенерированы в директории /usr/local/etc/openvpn/easy-rsa/keys. Однако удобнее будет использовать в файлах конфигурации путь /usr/local/etc/openvpn/keys, поэтому создадим симлинк:
ln -sf /usr/local/etc/openvpn/easy-rsa/keys /usr/local/etc/openvpn/
Следующим шагом редактируем по своему вкусу файл /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 # Имя интерфейса, который будет использовать сервер dev tap0 # Сертификаты ca /usr/local/etc/openvpn/keys/ca.crt cert /usr/local/etc/openvpn/keys/server.crt key /usr/local/etc/openvpn/keys/server.key dh /usr/local/etc/openvpn/keys/dh1024.pem # Отдаём клиентам маршрут на офисную сеть push "route 172.31.255.0 255.255.255.0 172.31.254.1" # Директория, в которой будут описаны настройки для всех клиентов client-config-dir /usr/local/etc/openvpn/ccd # Настройки поддержания соединения keepalive 10 120 # Разрешаем трафик между клиентами client-to-client # Используем сжатие comp-lzo # Не перечитывать ключевые файлы при переподключении клиентов persist-key # Не пересоздавать виртуальный интерфейс persist-tun # Уровень детализации в логе verb 3 # Файл лога log-append /var/log/openvpn.log
Для автоматического запуска openvpn при старте системы нужно добавить в файл /etc/rc.conf строки:
openvpn_enable="YES" openvpn_configfile="/usr/local/etc/openvpn/server.conf"
Далее нужно подгрузить модуль для работы с 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-клиента в разных ОС уже описывалась ранее и потому подробно рассматривать этот вопрос мы не будем.
На этом всё. Приятной работы!