В данной статье я приведу пример личного опыта по созданию защищённого туннеля между двумя сетями (офисами). Шлюзом для каждого из офисов будет выступать машина на 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 под некоторым именем.
cp /usr/src/sys/i386/conf/GENERIC /usr/src/sys/i386/conf/MYKERNEL
затем необходимо добавить в наш файл следующие строчки:
options IPSEC
device crypto
Внимание! Для работы IPSEC во FreeBSD, начиная с версии 7.0, необходимо указывать только эти строчки!
Как я уже упомянул выше, мы будем использовать фаервол pf, который также будет транслировать адреса (NAT) в нашу внутреннюю сеть. pf отличается простой настройкой и высокой скоростью работы, т.к. он работает на уровне ядра + в него встроена поддержка трансляции адресов NAT.
Добавляем поддержку нашего фаервола pf:
device pf
device pflog
device pfsync
собираем наше новое ядро:
cd /usr/src
make buildkernel KERNCONF=MYKERNEL
make installkernel KERNCONF=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=»»
#включаем логирования для pf
pflog_enable=»YES»
pflog_logfile=»/var/log/pf.log»
pflog_program=»/sbin/pflogd»
pflog_flags=»»
pfsync_enable=»NO»
pfsync_syncdev=»»
pfsync_ifconfig=»»
После перезагрузки мы получим рабочий шлюз на FreeBSD с NAT.
5. Настройка VPN
Создаем файл /etc/ipsec.conf, в котором будет описываться политика шифрования проходящего трафика между нашим виртуальным туннелем.
#!/usr/local/sbin/setkey -f
flush;
spdflush;
spdadd 192.168.1.0/24 192.168.2.0/24 any -P out ipsec
esp/tunnel/111.111.111.111-222.222.222.222/require;
spdadd 192.168.2.0/24 192.168.1.0/24 any -P in ipsec
esp/tunnel/222.222.222.222-111.111.111.111/require;
Это я привел пример настройки для сервера первого офиса. Для второй машины надо просто поменять IP местами.
Переходим в директорию /usr/local/etc, где создадим каталог racoon
cd /usr/local/etc
mkdir racoon
cd racoon
создаем файл racoon.conf следующего содержания:
#указываем где будет лежать файл, с фразой авторизации
path pre_shared_key «/usr/local/etc/racoon/psk.txt»;
#указываем на каком интерфейсе слушать соединения
listen
{
isakmp 111.111.111.111;
}
#указываем, что любой аутентифицированный хост будет приниматься как anonymous. Вместо anonymous можно указать ip-адрес удаленного сервера.
remote anonymous
{
exchange_mode aggressive;
my_identifier address;
lifetime time 24 hour;
proposal {
encryption_algorithm 3des;
hash_algorithm sha1;
authentication_method pre_shared_key;
dh_group 2;
}
}
sainfo anonymous
{
pfs_group 2;
lifetime time 12 hour;
encryption_algorithm 3des, blowfish, des, rijndael;
authentication_algorithm hmac_sha1, hmac_md5;
compression_algorithm deflate;
}
Соездаем файлик 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
;;
stop)
/usr/bin/killall racoon && echo -n ‘ racoon’
;;
*)
echo «Usage: `basename $0` { start | stop }»
exit 64
;;
esac
Устанавливаем для racoon.sh флаг +x (для того, чтобы этот скрипт был исполняемым).
chmod +x racoon.sh
racoon.sh лежит в каталоге /usr/local/etc/rc.d, и будет сам автоматически запускаться вместе с загрузкой системы.
Добавляем в /etc/rc.conf:
# включим racoon
racoon_enable=»YES»
racoon_flags=»-F -f /usr/local/etc/racoon/racoon.conf»
#включим ipsec
ipsec_enable=»YES»
ipsec_file=»/etc/ipsec.conf»
#создаем виртуальный gif-интерфейс
gif_interfaces=»gif0″
gifconfig_gif0=»111.111.111.111 222.222.222.222″
ifconfig_gif0=»inet 192.168.1.1 192.168.2.1 netmask 0xffffffff»
#прописываем статический рутинг для удаленной сети
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
# отрубаем ip-редиректы
net.inet.icmp.drop_redirect=1
net.inet.icmp.log_redirect=1
net.inet.ip.redirect=0
net.inet6.ip6.redirect=0
# определяем размеры буфера для TCP-подключений
net.inet.tcp.sendspace=32768
net.inet.tcp.recvspace=32768
# обновляем ARP-таблицу каждые 20 минут
net.link.ether.inet.max_age=1200
# запрещаем отвечать на все лишние запросы
net.inet.ip.sourceroute=0
net.inet.ip.accept_sourceroute=0
net.inet.icmp.bmcastecho=0
net.inet.icmp.maskrepl=0
Добавляем в /etc/rc.conf
# включаем удаленный доступ по 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 < badhosts > persist
block quick on $ext_if from < badhosts > 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
Вот собственно и все. Мы соединили два офиса в одну сеть. Аналогичным образом можно подключить несколько сетей.
Если возникли какие-то сложности, пишите в нашем форуме.