В данной статье я приведу пример личного опыта по созданию защищённого туннеля между двумя сетями (офисами). Шлюзом для каждого из офисов будет выступать машина на FreeBSD 7.0. Процесс создания VPN через IPSec во FreeBSD 7.0 имеет несколько принципиальных различий, что и послужило толчком для написания данной статьи.
Будем считать, что система уже установлена и перейдем сразу к процессу настройки. Внимание! Все действия, описанные в данной статье, необходимо выполнять с правами пользователя root.
Исходные данные:
офис #1: внешний адрес сервера - 111.111.111.111; внутренний адрес сервера - 192.168.1.1; адрес внутренней офисной сети - 192.168.1.0/24.
офис #2: внешний адрес сервера - 222.222.222.222; внутренний адрес сервера - 192.168.2.1; адрес внутренней офисной сети - 192.168.2.0/24.
1. Обновления системы и дерева портов
обновляем систему, используя утилиту для бинарного обновления системы - freebsd-update:
freebsd-update fetch && freebsd-update install
скачиваем и обновляем коллекцию портов
portsnap fetch portsnap extract
2. Пересборка ядра системы
Для работы IPSec и pf на уровне ядра необходимо пересобрать ядро. Для этого скопируем файл настройки ядра GENERIC под некоторым именем.
затем необходимо добавить в наш файл следующие строчки:
options IPSEC device crypto
Внимание! Для работы IPSEC во FreeBSD, начиная с версии 7.0, необходимо указывать только эти строчки!
Как я уже упомянул выше, мы будем использовать фаервол pf, который также будет транслировать адреса (NAT) в нашу внутреннюю сеть. pf отличается простой настройкой и высокой скоростью работы, т.к. он работает на уровне ядра + в него встроена поддержка трансляции адресов NAT.
Добавляем поддержку нашего фаервола pf:
device pf device pflog device pfsync
собираем наше новое ядро:
cd /usr/src
make buildkernel KERCONF=MYKERNEL make installkernel KERCONF=MYKERNEL
Когда наше ядро собралось, необходимо перезагрузиться
reboot
3. Установка пакета ipsec-tools
cd /usr/ports/security/ipsec-tools make install clean
в начале установки будет предложено выбрать опции для установки. Я убрал поддержку IPv6, NATT, HYBRID. Демон racoon, необходимый для шифрования данных, уже включён в пакет ipsec-tools и установится автоматически.
4. Настраеваем фаервол pf с трансляцией nat'а
Внимание! Для того, чтобы наш сервер выпускал соединения из локальной сети, в /etc/rc.conf должен обязательно присутствовать параметр gateway_enable="YES". Создаем файл /etc/pf.conf:
# vr0 - имя сетевой карточки, смотрящей в офисную сеть int_if="vr0" # rl0 - имя сетевой карточки, смотрящей в интернет ext_if="rl0"
localnet="192.168.1.0/24"
#определяем через переменные ip-адреса офисов office1_ip="111.111.111.111" office2_ip="222.222.222.222"
#опять таки, через переменную перечисляем какие порты выпускать из офиса во внешний мир tcp_ports="{22,80,443,25,110,465,995,5190}" udp_ports="{53}"
#не фильтруем трафик, проходящий по интерфейсу lo0 (интерфейс внутренней петли), gif0 (виртуальный туннель между офисами) и $int_if (интерфейс внутренней офисной сети) set skip on lo0 set skip on gif0 set skip on $int_if
#отбрасываем входящие пакеты, с нестандартными опциями scrub in all
#создаем правило трансляции адресов из офисной сети во внешний мир nat on $ext_if from $localnet to any -> ($ext_if)
#включаем антиспуфинг для внешнего интерфейса antispoof quick for $ext_if
#блокируем все по умолчанию block all
#разрешаем доступ из офисной сети во внешний мир портам, перечисленным в переменных tcp_ports и udp_ports: pass out on $ext_if proto tcp to any port $tcp_ports keep state pass out on $ext_if proto udp to any port $udp_ports keep state
#разрешаем доступ к нашей машине по ssh из внешнего мира pass in inet proto tcp from any to $ext_if port 22 keep state
#разрешаем пинг pass inet proto icmp all
#разрешаем исходящий трафик IPSec с офиса 1 на офис 2 pass out quick on $ext_if proto udp from office1_ip port = isakmp to office2_ip port = isakmp pass out quick on $ext_if proto esp from office1_ip to office2_ip pass out quick on $ext_if proto ipencap from office1_ip to office2_ip
#разрешаем входящий трафик IPSec, пришедший с офиса 2 на офис 1 pass in quick on $ext_if proto udp from office2_ip port = isakmp to office1_ip port = isakmp pass in quick on $ext_if proto esp from office2_ip to office1_ip pass in quick on $ext_if proto ipencap from office2_ip to office1_ip
Это были приведены настройки сервера офиса 1, для второй машины необходимо поменять IP-адреса зеркально. Для проверки правил (на случай если вы допустили где-то синтаксическую ошибку) можно воспользоваться командой pfctl -n -f /etc/pf.conf
Добавляем в /etc/rc.conf:
#включем наш фаервол на этапе загрузки системы pf_enable="YES" #указываем откуда загружать правила pf_rules="/etc/pf.conf" #указываем где находится программа для управления pf pf_program="/sbin/pfctl" pf_flags=""
Соездаем файлик psk.txt, в котором будет храниться фраза аутентификации удаленного хоста. Синтаксис psk.txt такой:
ip_удаленного_хоста фраза
Например, для первой машины это будет:
222.222.222.222 sometext
А для второй:
111.111.111.111 sometext
Устанавливаем соответствующие права на psk.txt (обязательно!)
chmod 600 psk.txt
Теперь переходим в /usr/local/etc/rc.d
cd /usr/local/etc/rc.d
После установки пакета ipsec-tools там появится скрипт для запуска демона шифрования racoon. Мы его удалим и создадим на его месте новый, более простой скрипт. (Лично у меня возникали непонятные глюки при использовании стандартного скрипта).
rm racoon
Затем создаем файл racoon.sh со следующим содержанием:
#!/bin/sh
case "$1" in
start) if [ -x /usr/local/sbin/racoon ]; then /usr/local/sbin/racoon -f /usr/local/etc/racoon/racoon.conf \ && echo -n ' racoon' fi ;;
#прописываем статический рутинг для удаленной сети static_routes="vpn" route_vpn="192.168.2.0/24 -interface gif0"
После перезагрузки должен появиться виртуальный интерфейс gif0. Внимание! Соединение VPN устанавливается не моментально! Обычно в течении 10 секунд, после того как прийдет пакет, необходимый для отправки по VPN.
6. Защита сервера
После настройки VPN хорошо бы позаботиться о безопасности наших серверов.
Добавляем в /etc/sysctl.conf:
#устанавливаем так называемую "черную дыру" для пакетов, приходящих на закрытый порт, что усложняет процесс сканирования злоумышленником портов. net.inet.tcp.blackhole=2 net.inet.udp.blackhole=1
net.inet.ip.random_id=1
#указываем размер очереди сокета kern.ipc.somaxconn=1024
# включаем удаленный доступ по ssh sshd_enable="YES" # отключаем sendmail sendmail_enable="NONE" # очищаем каталог /tmp при каждой загрузке системы clear_tmp_enable="YES" portmap_enable="NO" icmp_bmcastecho="NO" fsck_y_enable="YES" log_in_vain="YES"
Мы открыли доступ из вне для подключения на наш ssh сервер. Рано или поздно в логах можно будет увидеть, что кто-то пытался подключиться и переберал пару логин/пароль. При использовании сложного пароля атака с перебором пароля практически не грозит. Но все же немного не спокойно. Для автоматического блокирования "переборщиков паролей" существует отличная утилита sshit, причем очень простая в настройке и использовании. Устанавливаем sshit:
cd /usr/ports/security/sshit/ make install clean
затем добавляем в /etc/syslog.conf
после строчки: auth.info;authpriv.info /var/log/auth.log строчку: auth.info;authpriv.info |exec /usr/local/sbin/sshit
в файл конфигурации фаервола /etc/pf.conf добавляем после правила block all:
table persist block quick on $ext_if from to any
в файл настройки /usr/local/etc/sshit.conf увеличиваем параметр RESET_IP (время в секундах, на сколько блокировать нежелательный хост)
RESET_IP = 86400
Теперь при трех неудачных попытках авторизоваться, удаленный хост будет заблокирован на сутки. Перезагружаемся.
У меня уже через час появился один заблокированный адрес. Просмотреть список заблокированных адресов можно так:
pfctl -t badhosts -T show
Для мониторинга сетевых соединений в режиме реального времени есть очень удобная и простая утилита - pftop, которая находится в портах и работает по принципу стандартной unix-овой команды top.
cd /usr/ports/sysutils/pftop/ make install clean
Вот собственно и все. Мы соединили два офиса в одну сеть. Аналогичным образом можно подключить несколько сетей.