02 ноября 2014

Ни один браузер не работает

Если страницы перестали открываться сразу во всех браузерах и вы везде получаете сообщение "невозможно отобразить страницу". Но подключение к интернету при этом присутствует. Тогда перво наперво попробуйте сбросить стек Winsock. 

В командной строке выполняете 
C:\ netsh winsock reset

После перезагрузки должно помочь!

ZFS FreeBSD

Это учебная статья посвященная ZFS, из которой вы узнаете, что это такое, как использовать и как лучше настроить.
Для тех, кто не в курсе это локально-распределенная файловая система нового поколения, которая объединяет отдельные диски в пулы с возможностью создания RAID 0, 1, 10, 5. Это 128-битная файловая система с переменным размером блока (или кластера, как в терминологии fat) до 128 КБ. Таким образом каждый пул может адресовать огромный массив данных, в идеале (2^128)*128 КБ. В качестве полезных функций имеются встроенные механизмы квотирования, резервирования, контроля целостности данных и некоторые др. Отличительные черты - быстродействие, надежность и удобство.

Сразу стоит сказать, что ZFS требовательна к ресурсам, минимально для комфортной работы ей нужно не менее 1 Гб оперативной памяти на любой архитектуре, но чем больше тем лучше. Поэтому 64-битные системы предпочтительней, у них нет жестких ограничений адресного пространства.

Журналируемость, транзакционность и контрольные суммы каждого блока в совокупности с основным приемуществом ZFS - методом записи "Copy On Write" обеспечивают уверенную отказоустойчивость при нештатных отключениях питания.

По технологии "CoW" новые данные не перезаписывают старые, а пишутся в свободное пространство и меняется только указатель. Правда у нее есть и обратная сторона медали, при чрезмерном заполнении пула происходит падение производительности. Поэтому  рекомендуется активно пользоваться квотированием и не допускать заполнения больше, чем на 80%.

Учитывая, такие факторы, как распределение нагрузки между всеми дисками, входящими в пул, использование быстрого кэша и блока с переменным размером, можно ожидать от ZFS порядочного быстродействия. 

И ради любопытства я провел дилетантское сравнение быстродействия с UFS (журнал + soft update) при операции записи. Я выполнял копирование с помощью dd if=/dev/zero of=file bs=1M count=2000. Как и следовало ожидать на моем слабом железе ZFS оказался медлительней.

Действительно, что ZFS может сделать на стареньком P4 3Гц, c 2ГБ памяти и одним жестким диском SATA.  Хотя в процессе тестирования я и пытался настраивать разные параметры производительности ZFS (их мы рассмотрим чуть ниже), но лучшие результаты все равно оказались следующими ZFS - 26, 35 сек против UFS - 19,67 сек.

Поэтому отдаем себе отчет, что ZFS предназначена для достаточно мощного и современного оборудования с 64-битной архитектурой и с не менее, чем 4 Гб памяти. Но на старом железе конечно тоже будет работает, проверено лично. Но какой результат и зачем мучить свой старенький комп?

И так, приступим к препарированию.
 
B ZFS нет понятий томов и слайсов, как в традиционных ФС. Есть пул, внутри которого создаются файловые системы или как их еще называют датасеты. Размер файловых систем не фиксируется и может быть легко увеличен в результате присоединения нового диска к пулу. Поэтому здесь не может наступить критической ситуации полного заполнения диска.

Уменьшить размер ZFS пула уже не возможно! К примеру нельзя изъять диск, если это не зеркало. Это сразу приведет в выходу из строя всего пула! Заменить диск на другой, большего размера, всегда пожалуйста. Поэтому единственное, как можно уменьшить пул, это сохранить все данные на внешнем носителе, разрушить пул и создать новый.

Установка FreeBSD на ZFS
Нужно загрузиться с CD-диска или USB Memstick и начать установку как обычно. В FreeBSD 10 установка на ZFS уже полностью автоматизирована через bsdinstaller. На этапе разметки дисков достаточно выбрать пункт ZFS и система все сделает за вас. Ну а если хотите сделать это руками, то заходите в shell.
Здесь следует обратить внимание на следующие настройки: тип пула (stripe, mirror или raidz1, raidz2, raidz3), далее выбрать нужные диски для его создания. Пункт "forse 4k sectors" устанавливает выравнивание по 4К для каждого созданного раздела. Это важно, если у вас новые жесткие диски большого объема с размером сектора 4K, а не 512Б. Если нет, то укажите NO.
Давайте разберем, какие шаги выполняет установщик и заодно научимся работать с пулами. Описанные команды так же можно выполнять в ручном режиме, результат будет одинаковый.

Установщик автоматически создает три раздела GPT: один для загрузчика, раздел swap и основной раздел под пул.
Посмотрим для начала на структуру диска
# gpart show ada0 
Так удаляется старая таблица разделов
# gpart destroy ada0
Создается новая таблица GPT
# gpart create -s GPT ada0
Добавляются три раздела
# gpart add -s 512 -a 4k -t freebsd-boot -l boot0 ada0 
# gpart add -s 4g -a 4k -t freebsd-swap -l swap0 ada0 
# gpart add -a 4k -t freebsd-zfs -l disk0 ada0
Здесь с помощью опции -a задается выравнивание разделов по 4Кб. Если у вас старые винты с физическим сектором 512б, то опцию пропускаем.

Устанавливается загрузчик
# gpart bootcode -b /boot/pmbr -p /boot/gptzfsboot -i 1 ada0
Здесь используются два загрузчика, первый pmbr в области Protective MBR перед GPT, он передает управление второму gptzfsboot, он на первом секторе раздела freebsd-boot. А уже на третьем этапе вызывается loader.

Если вдруг вы решите не использовать ZFS, а вернетесь к UFS, то надо использовать другой загрузчик
# gpart bootcode -b /boot/pmbr -p /boot/gptboot -i 1 da0
Для работы с ZFS загружаем модуль
# kldload zfs
При использовании дисков с сектором 4К важно задать размер блока ZFS.  Поскольку диск для совместимости рапортует о секторе 512Б. И по умолчанию такой размер выбирается автоматически для блока при создании пула.  Поэтому обязательно перед созданием пула нужно сделать следующее!

Поверх диска создается устройство gnop с размером сектора 4К
# gnop create –S 4096 /dev/gpt/disk0
Создается пул
# zpool create -o altroot=/mnt -O canmount=off -m none zroot /dev/gpt/disk0.nop
Отсоединяется пул
# zpool export zroot
Удаляется устройство gnop
# gnop destroy /dev/gpt/disk0.nop
Снова присоединяется пул
# zpool import zroot
Проверяем, если ashift=12, то блок установлен правильно 2^12=4К. Если 9, то 2^9=512Б.
# zdb –C tank | grep ashift
Так же в FreeBSD 10  размер блока ZFS можно задать проще, с помощью 
# sysctl vfs.zfs.min_auto_ashift=12 
Сделать это нужно так же перед созданием пула и добавить в /etc/sysctl.conf, что бы не делать это вручную каждый раз в будущем.

Задаем алгоритм проверки контрольных сумм fletcher4, по умолчанию используется fletcher2.
# zfs set checksum=fletcher4 zroot
Запрещаем обновление времени доступа при каждом обращении к файлу.  
# zfs set atime=off zroot
Создаем файловые системы
# zfs create -o mountpoint=none zroot/ROOT 
# zfs create -o mountpoint=/ zroot/ROOT/default 
# zfs create -o mountpoint=/tmp -o compression=lzjb -o setuid=off zroot/tmp 
# chmod 1777 /mnt/tmp
# zfs create -o mountpoint=/usr zroot/usr zfs create zroot/usr/local
# zfs create -o mountpoint=/home -o setuid=off zroot/home
# zfs create -o compression=lzjb -o setuid=off zroot/usr/ports

# zfs create -o compression=off -o exec=off -o setuid=off zroot/usr/ports/distfiles 

# zfs create -o compression=off -o exec=off -o setuid=off zroot/usr/ports/packages
# zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/usr/src 

# zfs create zroot/usr/obj
# zfs create -o mountpoint=/var zroot/var 

# zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/crash 
# zfs create -o exec=off -o setuid=off zroot/var/db 
# zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/var/db/pkg 
# zfs create -o exec=off -o setuid=off zroot/var/empty 
# zfs create -o compression=lzjb -o exec=off -o setuid=off zroot/var/log 
# zfs create -o compression=gzip -o exec=off -o setuid=off zroot/var/mail 
# zfs create -o exec=off -o setuid=off zroot/var/run 
# zfs create -o compression=lzjb -o exec=on -o setuid=off zroot/var/tmp 
# chmod 1777 /mnt/var/tmp
Указываем корневую ФС.
# zpool set bootfs=zroot/ROOT/default zroot
Добавляем swap раздел в fstab
# vi /tmp/bsdinstall_etc/fstab
--# Device        Mountpoint FStype Options Dump Pass# 

/dev/gpt/swap0  none       swap   sw      0    0
После того как будут созданы все файловые системы, если выполняли в ручном режиме, то нужно выйти из shell, пишем exit. Далее установка продолжается, как обычно.

Так же для ручного режима, перед перезагрузкой нужно еще раз зайти в shell и прописать автоматическое монтирование файловых систем.
# mount -t devfs devfs /dev 
# echo 'zfs_enable="YES"' >> /etc/rc.conf 
# echo 'zfs_load="YES"' >> /boot/loader.conf
Для порядка зададим только чтение для /var/empty, поскольку она всегда должна быть пустой.
# zfs set readonly=on zroot/var/empty 
На этом установка завершена.  Но, если вам хочется добиться лучшей производительности можно настроить еще некоторые параметры.

Способы оптимизации сильно зависят от назначения вашей системы и будут отличаться для БД, вэб-сервера и файлового сервера. В числе основных рекомендаций, можно найти такие, отключение обновления времени доступа при каждом обращении atime (мы уже это сделали), иметь как можно меньше снимков состояний,  использовать для ZIL и L2ARC отельные SSD диски. Использовать для файловых систем разные recordsize, соразмерно хранимым на них файлам. Если много мелких файлов, то recordsize лучше сделать 16Кб, а по умолчанию он 128Кб.
# zfs create -o recordsize=8k tank/mysql
Есть конечно и параметры, влияющие работу в целом. Рассмотрим их.

Как вы знаете на i386 архитектуре ядро FreeBSD по умолчанию  резервирует под все свои нужды всего 1Гб адресного пространства из 4 возможных, а остальное оставляет процессам. Но, если в ядре есть такой большой потребитель оперативной памяти, как ZFS, то его может и не хватить!  Поэтому нужно увеличить это значение хотя бы до 2Гб, добавив в ядро опцию.
options KVA_PAGES=512 
(размер страницы — 4 Кб)*512=2Гб.
Но после пересборки ядра, во время загрузки, у меня начались "double fault panic". Как оказалось, проблема распространенная и многие пользователи ZFS на i386 архитектуре наблюдают переполнение стека ядра. Это начало происходить с того момента, как Clang сделали компилятором по умолчанию. Для того, что бы этого избежать нужно добавить еще одну опцию.
options KSTACK_PAGES=4
Или задать в /etc/sysctl.conf параметр
kern.kstack_pages=4
На amd64 проблем с нехваткой адресного пространства нет. Там по умолчанию отвели ядру 512 Гб  виртуальных адресов, поэтому вышеописанное не потребуется.

Теперь, когда виртуальное адресное пространство ядра KVА (Kernel Virtual Address space) увеличено, надо этим поделиться с ZFS. В /boot/loader.conf добавляем параметры
vm.kmem_size="1G" 
vm.kmem_size_max="1G"
kmem - это участок KVA, который используется для динамического выделения памяти malloc, и соответственно он будет использоватьcя ZFS.

ARC
Еще одним важным параметром влияющим на быстродействие ZFS является размер кэша адаптивной замены ARC (Adjustable Replacement Cache). Это очень быстрый кэш, расположенный в ОЗУ, построенный на двух алгоритмах MRU им MFU. Общий смысл его заключается в том, что бы обеспечить доступ к наиболее часто используемым данным прямо из памяти, а не с медленного диска. И поэтому, чем у вас больше оперативной паями, тем лучше для ZFS. 

По умолчанию ARC разрешается использовать всю свободную память по необходимости, кроме 1Гб зарезервированного ядром. Но если если у вас категорическая не хватка паями и ее обязательно надо оставить для других важных задач, то имеет смысл ограничивать размер кэша
vfs.zfs.arc_max="512M"
Если этого не сделать, то может произойти kernel panic по причине отсутствия свободного пространства. Поэтому проверяйте
# sysctl vm.kvm_free
Так же есть дешевый способ увеличить размер кэша при помощи обычной флешки. Изначально для этого задумано использовать SATA SSD-диски. Это называется вторым уровнем кэша L2ARC. В этой статье человек делится опытом подключения флешки 1G в качестве L2ARC.
# zpool add pool cache device
# zpool remove pool device
Но в виду того, что пропускная способность шины USB 2.0 ниже, чем у механических жестких дисков: 30 против 100 Мбайт/сек, то в качестве полноценного кэша старая флешка не годиться. Да и быстро выйдет из строя из-за постоянной перезаписи и отсутствия механизма выравнивания износа. Тем не менее сгодится для домашнего использования при малой нагрузке. Ведь время поиска (seek time) y флешек гораздо меньше, чем у дисков и составляет от 1 до 3 мсек, против 12 мсек. Поэтому прирост скорости можно получить только на произвольном (не последовательном) чтении данных. И лучше хранить на ней только метаданные, это позволит прослужить ей дольше.
# zfs set secondarycache=metadata pool
Что касается usb 3.0, то там полезная скорость возросла до 500 Мбайт/с и возможно такие флешки уже пригодны, но надо тестировать.

ZIL
На случай потери данных при сбоях и отключении питания некоторые приложения (например, NFS и БД) используют синхронную запись данных. Для этих целей у ZFS имеется целевой журнал ZIL (ZFS Intent log). Когда приложение хочет записать данные на диск, оно отправляет запрос ОС и ждет ответа. ОС сначала кэширует данные в ROM,  затем сохраняет их в ZIL и только после этого возвращает управление приложению. При этом ZIL обязательно должен находиться в энергонезависимой памяти и по умолчанию располагается на диске внутри пула. Вот это и является узким местом при увеличении производительности. Но ZFS позволяет использовать в качестве log-устройства отдельные диски или даже несколько дисков одновременно.  Поэтому обязательно обзаведитесь  быстрым  SSD-диском.
# zpool add pool log c2d0
В особых случаях, если нет SSD, то ZIL лучше отключить, производительность возрастет, но появится опасность потери данных при записях во время сбоев.
В /boot/loader.conf добавляем
vfs.zfs.zil_disable="1"
Еще можно отключать zil отдельно для каждой файловой системы.
# zfs set sync=disabled pool/name

Теперь рассмотрим функциональность и познакомимся с основными командами для управления ZFS.

Здесь все просто, для работы с пулами используется утилита zpool, а с файловыми системами - zfs. Они имеют смысловые команды типа create, desptoy, attach, deattach и т.д.

Работа с пулами
Пулы создается командой 
# zpool create pool /dev/ada0
Если пул не загрузочный, то можно использовать весь диск целиком без GPT разбивки.
Удаляется пул командой 
# zpool destroy pool
Вывести список подключенных пулов
# zpool list
Узнать состояние
# zpool status pool
Отсоединить пул
# zpool export pool
Присоединить
# zpool import pool
Если использовать команду import без параметров, то получите список доступных пулов.

Добавить дополнительный диск к пулу
# zpool add pool ada3
Присоединяем зеркало. Диски должны быть одинакового размера, иначе по меньшему. После этого начнется resilvering, процесс синхронизации.
# zpool attach pool /disk /new-disk
Отсоединяем зеркало
# zpool detach pool /disk
Замена одного устройства на другое
# zpool replace pool /disk /new-disk
После завершения выполнения команды диск отключается от конфигурации и может быть удален из системы.

Посмотреть все  параметры пула можно так
# zpool get all
Файловые системы
Создание файловой системы в пуле осуществляется командой
# zfs create pool/name
По умолчанию каждая созданная ФС монтируется в одноименный каталог. Но точку монтирования можно указать и другую.
# zfs set mountpoint=/new/puth pool/name
Все созданные файловые системы монтируюся автоматически при присоединении пула, поэтому их не надо прописывать в fstab.

Монтирование файловой системы в пул
# zfs mount myzfs/bob
# zfs unmount myzfs/bob
Файловая система созданная внутри другой наследует ее свойства. К ним относится алгоритм сжатия и алгоритм вычисления контрольных сумм, размер блока, квота и мн. др. Посмотреть все свойства  можно по команде
# zfs get all
Зарезервировать место для файловой системы
# zfs set reservation=100G pool/name
Задать квоту
# zfs set quota=50G pool/name
Квоты можно задавать отдельно для групп и пользователей
# zfs set userquota@user=5G pool/name
# zfs set groupquota@group=10G pool/name 
Смотреть общую информацию по использованию квот можно так
# zfs userspace pool/name
# zfs groupspace pool/name
или конкретно для каждого
# zfs get userused@user pool/name
# zfs get groupused@group pool/name
ZFS предлагает  очень удобный механизм резервного копирования. Для этого используются снимки и клоны.

Снимок - это копия состояния ФС, хранящаяся прямо в пуле и по началу совсем не занимающая места. Но по мере изменения данных снимок начинает расти, поскольку продолжает ссылаться на старые данные и препятствует их удалению. Поэтому рекомендуется хранить минимальное число снимков.

Получить прямой доступ к снимкам нельзя. Их можно только клонировать, создавать резервные копии, выполнять откат и др. Создается снимок так
# zfs snapshot pool/name@snap_name
если указать параметр рекурсии -r, то создаются снимки всех дочерних ФС. Располагаются в директории .zfs/snapshot в корне каждой файловой системы.
# zfs snapshot -r pool/name@now
Удалить снимок 
# zfs destroy pool/name@snap_name
Можно переименовывать снимки
# zfs rename pool/name@old_name new_name
Вывести список всех снимков 
# zfs list -t snapshot
Выполнить откат к снимку
# zfs rollback pool/name@snap_name
ФС предварительно должна быть размонтирована. Все изменения, а так же созданные снимки после будут удалены и система вернется к состоянию на момент снимка.

На основе снимков можно создавать клоны.
# zfs clone pool/name@yesterday pool/clone
Уничтожить клон
# zfs destroy pool/clone
Можно выполнить замену исходной файловой системы на клон.
# zfs promote pool/clone
NFS
Есть удобный механизм добавления ресурсов в NFS. Для этого сперва нужно убедиться, что у вас запущены службы NFS. В /etc/rc.conf пишем

nfs_server_enable="YES"
nfs_server_flags="-u -t -n 4"
rpcbind_enable="YES"
mountd_enable="YES"
mountd_flags="-r"
Что бы добавить общий ресурс используется следующий синтаксис.
# zfs set sharenfs=on pool/name
Ресурс будет доступен всем для записи и чтения и свойства автоматически наследуются для всех дочерних файловых систем. В качесте параметров sharenfs можно использовать все опции доступные в exports.

Что бы задачть только для чение, то указывается опция ro
# zfs set sharenfs=ro pool/name 
Если у ресурса установлен признак sharenfs, то его можно включать и отключать командами share и unshare.
# zfs share -a
# zfs unshare pool/name
# zfs unshare -a
Как только опция sharenfs меняется, служба mountd перезагружается автоматически.

Если нужно разрешить доступ только конкретным сетям или адресам, то так


# zfs set sharenfs="-maproot=root -alldir -network 10.0.0.0 -mask 255.255.255.0 192.168.15.2 192.168.10.5" zroot/share
Посмотеть все расшаренные ресурсы
# zfs get sharenfs 
На стороне клиента ресурс монтируется следующим образом
# mount -t nfs server_ip:/pool/name /mnt
Для втоматического монтирования в /etc/fstab нужно добавить
server_ip:/pool/name /mnt nfs rw 2 2
Еще бывает полезно посмотреть активность дисков в реальном времени.
# gstat -a 

22 октября 2014

SFTP, FTPЕS и тонкая настройка ProFTPD

    Традиционный способ передачи файлов по протоколу FTP уже считается устаревшим и небезопасным. Есть более совершенные альтернативы, например, SFTP, SCP, FTPS и WebDAV.  Но тем не менее для анонимного доступа обычный FTP вполне сгодится. Еще одна причина, по которой отказаться от FTP полностью пока нельзя, отсутствие в windows встроенной поддержки безопасных FTP. 

В этой статье описываются принципы правильной настройки сервера ProFTPD с виртуальными пользователями, перекодировкой в cp1251 и поддержкой протоколов FTPS (FTP Secure) и SFTP (Secure File Transfer Protocol). Как вы можете видеть из названий, один - безопасность протокола, а другой - безопасный протокол. В этом их кардинальное отличие!

FTPS является обычным FTP поверх SSL/TLS, как HTTPS. Есть две его разновидности: Implicit FTPS - соединение устанавливается через дополнительный порт SSL 990 и Explicit FTPS или сокращенно FTPES, это уже более новая версиякоторый сейчас всеми и ипользуется, соединение и управление по одному стандартному порту 21.

А вот SFTP это абсолютно новый протокол, разработан с нуля, основан на SSH2 и не имеет с FTP ничего общего. У него больше возможностей, например есть докачка файлов после разрыва соединения. В рамках SSH шифруется все. Конечно скорость передачи у SFTP будет меньше чем у чистого FTP или FTPS.

Я провел сравнение на 100 Мбитной сетке: FTP ~ 10 МБ/с, SFTP ~ 3 МБ/с. У FTPS такая же скорость, как и у обычного FTP. Еще для сравнения я проверил SFTP, встроенный в openssh, там скорость оказалась порядка 7 МБ/с. Почему такая разница по сравнению с proftp сказать сложно, видимо в самой реализации sftp. Попробуйте сравнить у себя, будет интересно узнать, как у вас.

Поэтому, наверно все таки, есть смысл использовать sftp-server от OpenSSH. 

Имеем FreeBSD 10, что бы сэкономить время устанавливаем из пакета.
# pkg install proftpd

proftpd.conf
Конфигурационный файл находится в /usr/local/etc/proftpd.conf. Откройте и редактируйте его под себя по ходу чтения статьи.
 
Сервер запускается через inetd или автономно.
ServerType standalone
Рекомендуется создать специального пользователя и группу FTP для запуска службы. Пароль можно сделать пустым.
# adduser ftp
и изменить в конфиге
User ftp
Group ftp
По умолчанию сервер слушает все интерфейсы, что бы указать только заданные адреса, используются директивы
DefaultAddress 192.168.20.1 192.168.30.1
SocketBindTight on
По желанию в виртуальных хостах можно переопределить другой адрес.
  
Для того, что бы включить перекодировку с UTF-8 на CP1251 нужно обязательно задать LangPath
LangEngine   on
LangPath     /usr/share/locale
UseEncoding  UTF-8 WINDOWS-1251
Что бы задать пользователю корневую директорию, за пределы, которой он не должен выходить, используется
DefaultRoot ~ 
знак "~" сообщает, что  будет использоваться домашняя директория пользователя.

Если нужно сделать исключение из правил и дать некоторым пользователям полный доступ к chroot директории, то создаете группу, например admins и пишете
DefaultRoot ~ !admins
Для управления анонимным доступом в конфигурациооном файле есть секция
<Anonymous ~ftp>
  User ftp
  Group ftp
  UserAlias anonymous ftp
  <Limit WRITE>
    DenyAll
  </Limit>
</Anonymous>
Если у вас используются виртуальные хосты, то эту секцию лучше вынести в <Global>, что бы анонимный вход был доступен на всех ip, а не только на основном!

Виртуальные пользователи
По умолчанию для аутентификации пользователей proftp смотрит файл /etc/passwd.  Но использование виртуальных пользователей безопаснее, поскольку это не позволяет злоумышленнику перехватить системные аккаунты, которые передаются в открытом виде! Для этого используются директивы AuthUserFile и AuthGroupFile в конфигурационном файле.
AuthUserFile /usr/local/etc/proftpd/ftpd.passwd
AuthUserFile используется в дополнение к passwd и не исключает его. Но если все таки нужно его запретить, то используйте AuthOrder.
AuthOrder mod_auth_file.c
Форматы файлов AuthUserFile и AuthGroupFile такие же, как /etc/passwd и /etc/group соответственно.
username:password:uid:gid:gecos:homedir:shell
groupname:grouppasswd:gid:member1,member2,...memberN
Для создания и изменения этих файлов используется специальный скрипт ftpasswd. Первый параметр, который надо задать, это --passwd или --group. Потом --name, --uid, --home и --shell. Например,
# ftpasswd --passwd --name=bob --uid=1001 --home=/home/bob --shell=/bin/false
Uid должен быть от реального пользователя, например от ftp, таким образом из одного реального пользователя создается много виртуальных.

После выполнения ftpasswd создается файл ftpd.passwd. Для создания файла с другим именем и расположением используется опция --file.

Аналогично для групп
# ftpasswd --group --name=group-name --gid=group-id --member=user-member1 \ --member=user-member2 ... --member=user-memberN
Так же можно использовать параметр --hash для вычисления хэша либо пароля.
По умолчанию proftp не пускает пользователей у которых шел не перечислен в файле /etc/shell. Поэтому, если вы используете недействительный шел, например /usr/sbin/nologin, то обязательно задайте директику RequireValidShell off. 

Ограничение доступа
У proftpd есть удобный механизм ограничения доступа. Создаются различные правила для клиента на выполнение FTP команд. Это может быть запрет на переименование, удаление, запись файлов в определенную папку и др. (полный список можно посмотреть на сайте).

Для создания правил в конфигурационном файле указывается секция <Limits>... </Limits> с нужными командами. Их можно просто перечислить или использовать группы ALL, DIRS, LOGIN, READ и WRITE.

Затем внутри секции определяется действие: разрешить или запретить: DenyAll, AllowAll, AllowUser, AllowGroup, Deny from, Allow from. Их порядок играет имеет значение, если порядок "Allow,Deny", то разрешающее правило важнее, если наоборот "Deny,Allow", то запрет.

Например,  следующие команды разрешают смену директории и загрузку файлов в эту директорию, при условии, что файловая система так же имеет соответствующие разрешения.
<Limit ALL>
  DenyAll
</Limit>
<Limit CDUP CWD PWD XCWD XCUP>
  AllowAll
</Limit>
<Limit STOR STOU>
  AllowAll
</Limit>  
Для этой цели можно использовать группу WRITE, но тогда пользователь сможет так же создавать и удалять поддиректории.

Или еще один пример, разрешается авторизация только двум пользователям и группе.
<Limit LOGIN>
  AllowUser barb
  AllowUser dave
  AllowGroup ftpuser
  DenyAll
</Limit>
Поскольку активный режим работы FTP-сервера не безопасен, это когда сервер должен сам подключиться к клиенту. То его можно отключить средствами <Limits>.
<Limit EPRT PORT>
  DenyAll
</Limit>
Обычно <Limits> удобно использовать внутри секции <Directory>, тогда все вложенные поддиректории будут наследовать свойства. Следующий пример описывает папку, у которой нельзя увидеть содержимое, но можно загружать и скачивать файлы.
<Directory /path/to/dir>
  <Limit LIST NLST MLSD MLST STAT>
   DenyAll
  </Limit>
</Directory>
Если в пути вы указываете  суффикс /*, то это означает, что конфигурация применяется только для содержимого, но не для самой папки.

Пример, назначается папка для загрузок для анонимного доступа.
<Anonymous ~ftp>
 User ftp
 Group ftp
 UserAlias anonymous ftp
 <Limit WRITE>
  DenyAll
 </Limit>
 <Directory upload/*>
  <Limit STOR>
    AllowAll
  </Limit>
 </Directory>
</Anonymous>
В ftp протоколе команда STOR служит для аплоада файлов клиентом.

Еще можно использовать классы для группировки пользователей.
<Class internal>
  From 192.168.0.0/16
  From *.example.com
</Class>
А потом назначить действия сразу целым классам с помощью AllowClass и DenyClass.
<Limit ALL>
  AllowClass internal
  DenyAll
</Limit>
По умолчанию proftpd слушает все интерфейсы, но если надо только один, то используйте параметр DefaultAddress.

Сервер за NAT
Особый случай, если ваш ftp-сервер находится за NAT и вы хотите предоставить к нему доступ извне. Для этого вам надо задать опцию MasqueradeAddress с ip-адресом nat-сервера. А на NAT-сервере настроить форвардинг порта 21 и диапазона портов для пассивного режимакоторые задаются в конфиге PassivePorts 40000-45535. 

Но как только вы зададите опцию MasqueradeAddress, пользователи из локальной сети не смогут больше подключаться! Выходом из этой ситуации будет использование данной опции не в глобальных настройках, а на виртуальном хосте.
<VirtualHost your_local_ip>
  MasqueradeAddress nat_ip
  Port 1121
</VirtualHost>

Теперь FTP-сервер, кроме 21, еще будет работать на 1121 порту. На NAT-сервере настраиваем перенаправление портов. В моем случае это ядерный NAT.
nat 1 config log if rl0 reset same_ports deny_in redirect_port tcp 192.168.15.2:1121 21 redirect_port tcp 192.168.15.2:40000-45535 40000-45535
add 1085 nat 1 ip from any to any via rl0
Один важный момент, в списке правил перед строкой nat не должно быть явно разрешающих правил для используемых портов, т.е. таких
1030 allow tcp from any to me 21, 20, 40000-45535 
Иначе пакеты не дойдут до nat и соответственно не будут перенаправляться. Была у меня такая проблема, долго не мог понять почему не работает ftp через nat, а они просто напросто не доходили до редиректа.

Еще, если вы пытаетесь таким же способом редиректить штатный фряшный ftpd через ipfw, то ничего не получится! У него нет такой замечательной опции MasqueradeAddress. В этом случае надо использовать ftp-proxy.

Теперь внутри локальной сети FTP сервер будет работать, как обычно на 21 порту. Из вне доступ так же будет по 21 порту через nat-сервер, благодаря форвардингу  redirect_port tcp 192.168.15.2:1121 21.

Виртуальные хосты
Это возможность организовать одновременно несколько ftp-серверов на одном. Они называются виртуальными. Но имейте в виду, что протокол FTP не поддерживает виртуальные хосты на основе имен. Например, нельзя создать soft.server.ru и video.server.ru, как в Apache. FTP виртуальные хосты могут быть основаны только на уникальности пары IP/порт.

Поэтому, если ваш сервер имеет несколько ip-адресов, например, локальная сеть и внешняя, то для каждой из них нужно настроить виртуальные хосты. Это делается с помощью секции  <VirtualHost>.

<VirtualHost 10.0.0.1>
   ServerName "My local FTP server"
</VirtualHost>
<VirtualHost 1.2.3.4>
   ServerName "My
external FTP server"
</VirtualHost>
 
Так же можно использовать виртуальные хоcты с одинаковым ip-адресом, но на разных портах.
<VirtualHost myhost.mydomain.com>
  Port 2001
  ...
</VirtualHost>
  
 
Все глобально установленные параметры в конфигурационном файле не относятся к виртуальным хостам, их нужно задавать отдельно для каждого! Поэтому ради удобства, что бы не дублировать общие параметры в каждом виртуальном хосте, их можно вынести в секцию  <Global>, тогда они будут доступны для всех.

В <Global> так же следует вынести секцию <Anonimous ~>

Таким образом, с помощью виртуальных хостов, мы одновременно запустим ftp, sftp и ftps на разных портах.

Но для этого сначала нужно перекомпилировать ptoftpd с дополнительными модулями.
#./configure --with-modules=mod_sftp:mod_tls:mod_sql:mod_sql_mysql \
--with-includes=/usr/local/include/mysql \
--with-libraries=/usr/local/lib/mysql
# make
# make install
Выяснилось, что в портах Freebsd, начиная c версии 1.3.4 Proftpd стал использовать динамически подключаемые модули. Поэтому пересборка не требуется, достаточно указать директиву LoadModul в proftpd.conf.

Выносим общие параметры в секцию
<Global>
   PassivePorts 40000 45535
   AuthUserFile /usr/local/etc/proftpd/ftpd.passwd
   RequireValidShell no
   MaxLoginAttempts 6
   LangEngine on
   UseEncoding UTF-8 WINDOWS-1251
   DefaultRoot ~ !admins
</Global>
Подгружаем SFTP модуль
LoadModule mod_sftp.c
И добавляем виртуальный хост
<VirtualHost 192.168.10.1>
  MasqueradeAddress myhost.mydomain.com
  SFTPEngine on
  Port 8022
  SFTPHostKey /etc/ssh/ssh_host_dsa_key
  SFTPHostKey /etc/ssh/ssh_host_rsa_key
  SFTPHostKey /etc/ssh/ssh_host_ecdsa_key
  SFTPLog /var/log/sftp.log
  SFTPCompression off
</VirtualHost>
Подгружаем TLS модуль
LoadModule mod_tls.c
Добавляем виртуальный хост
<VirtualHost 192.168.10.1>
MasqueradeAddress
myhost.mydomain.com
TLSEngine on
Port 1021
TLSLog /var/log/tls.log
TLSProtocol SSLv23
TLSRequired auth
TLSOptions NoCertRequest
TLSRSACertificateFile /usr/local/etc/proftpd/ssl/cert.pem
TLSRSACertificateKeyFile /usr/local/etc/proftpd/ssl/key.pem
TLSVerifyClient off

</VirtualHost>
Параметр TLSRequired определяет политику безопасности, когда использовать SSL/TLS и может иметь несколько значений:
  • off - Клиенты могут подключаться, как по обычному FTP, так и используя шифрование,
  • ctrl - шифруется только управляющий канал, поэтому пароли будут спрятаны,
  • data - шифруются только данные (не рекомендуется),
  • on - шифруются оба канала,
  • auth - шифрование управляющего канала, но только в момент авторизации,
  • auth+data - шифрование авторизации и данных, клиенту разрешается использовать команду CCC (Clear Command Channel), что позволяет лучше работать через фаервол.

Для FTPS еще нужно сгенерировать сертификат OpenSSL и положить в /usr/local/etc/proftpd/ssl/
# openssl req -new -x509 -days 365 -nodes -out /usr/local/etc/proftpd/ssl/cert.pem -keyout /usr/local/etc/proftpd/ssl/key.pem
Добавим автозапуск в rc.conf 
# echo 'proftpd_enable="YES"' >> /etc/rc.conf
Не забываем про ротацию логов
# vi /etc/newsyslog.conf
/var/log/proftpd.log 600 7 * @T00 JC
Чтобы запустить Proftpd используем команду
# service proftpd start
По умолчанию сервер пытается связать ip-адрес и имя хоста. Поэтому, если они не соответствуют действительности,  вы получите следующее сообщение при старте.
warning: unable to determine IP address of 'hostname'
Тут либо правильно настройте DNS, либо добавьте имя в файл /etc/hosts.
# vi /etc/hosts
192.168.10.5 your_domain_name 
Проверим, что слушаются 21, 1021 и 8022 порты.
# sockstat
USER COMMAND PID FD PROTO LOCAL ADDRESS FOREIGN ADDRESS
ftp proftpd 87980 0 tcp4 *:21 *:*
ftp proftpd 87980 1 tcp4 *:8022 *:*
ftp proftpd 87980 2 tcp4 *:1021 *:*
Теперь можно подключаться любым клиентом, например, Filezilla, он понимает ftps, ftpes и sftp. Так же удобно использовать ftps/ftpes через Total Commander, но к нему еще нужно скачать OpenSSL библиотеки. Их можно взять тут, просто запустите установщик и он сам скопирует нуждные dll в системную папку. После этого в свойствах ftp-соединения станет доступной галочка SSL/TLS.

Что бы  посмотреть активных пользователей есть команда ftpwho.

Mysql
Кто хочет можно хранить пользователей в базе mysql. Для этого нужно поставить порт proftpd-mod_sql_mysql. Он автоматически установит mysql-client. Но mysql-server вам надо поставить самим.Кстати хороший мануал на русском языке есть на сайте mysql.ru. После установки нужно создать конфигурациооный файл my.cnf и положить его в /var/db/mysql/my.cnf. Шаблоны лежат тут /usr/local/share/mysql/. Можно восползоваться, например my-medium.cnf. В него я добавил такие параметры.
[client]
character_set_client=utf8

[mysqld]
character-set-server=utf8
init-connect="SET NAMES utf8"
skip-networking
#log-bin=mysql-bin
#binlog_format=mixed
Еще необходимо проинициализировать таблицы привилегий. 
# cd /usr/local
# ./bin/mysql_install_db
# chown -R mysql:mysql /var/db/mysql
Скрипт mysql_install_dbсоздает две базы данных: одна mysql, она обеспечивает привилегии доступа и другая test для тестирования.  Для пользователя root устанавливается  пустой пароль.
Добавляем в rc.conf строчку
# echo 'mysql_enable="YES"' >> /etc/rc.conf
Запускаем MySQL сервер
# service mysql-server start
Убеждаемся, что он запустился
# ps ax | grep mysql
15840 - Is 0:00,17 /bin/sh /usr/local/bin/mysqld_safe --defaults-extra-file
16374 - I 0:01,01 /usr/local/libexec/mysqld --defaults-extra-file=/var/db/
Устанавливаем пароль для пользователя root.
# /usr/local/bin/mysqladmin -uroot password 'password'
Заходим
# mysql -uroot -p'pasword'
Позднее пароль можно поменять так
mysql> use mysql;
mysql> update user set password=PASSWORD('my_password') where user='root' and host='localhost';
mysql> flush privileges;
mysql> quit
Чтобы каждый раз не вводить пароль его можно сохранить в файле .my.cnf
# touch /root/.my.cnf
# chmod 0600 /root/.my.cnf
# vi /root/.my.cnf
  [client]
  password=passwd
И для входа просто писать из под руда # mysql

Теперь нужно создать таблицы users и groups, где будут храниться пользователи. Но сначала создадим базу данных proftpd и пользователся ftp для подключения к базе.
mysql> CREATE DATABASE proftpd;
mysql> grant select,insert,update,delete on proftpd.* to ftp@localhost identified by 'password';
mysql> USE proftpd;
mysql> CREATE TABLE users (
userid VARCHAR(30) NOT NULL UNIQUE,
passwd VARCHAR(80) NOT NULL,
uid INTEGER,
gid INTEGER,
homedir VARCHAR(255),
shell VARCHAR(255) );
mysql> CREATE TABLE groups (
groupname VARCHAR(30) NOT NULL,
gid INTEGER NOT NULL,
members VARCHAR(255) );
Добавим нового пользователя для доступа к ptoftpd
mysql> insert into users values('new_user',ENCRYPT('passwd'),'5001','5001','/home/new_user','/sbin/nologin');
mysql> exit;
Изменить можно так
mysql> UPDATE users SET passwd=ENCRYPT('new_pass'), gid=14 WHERE userid='user';
Удалить так
mysql> DELETE FROM users WHERE userid='user';
Создаем домашний каталог пользователя
# mkdir /home/new_user 
# chown 5001:5001 /home/new_user
Настраиваем proftpd для авторизации через mysql
AuthOrder mod_sql.c
SQLConnectInfo proftpd@localhost:3306 ftp password
SQLAuthTypes Crypt
SQLUserInfo users userid passwd uid gid homedir shell
DefaultRoot ~
RequireValidShell off
SQLGroupInfo groups groupname gid members
SQLAuthenticate users groups

SQLLogFile /var/log/proftpd.log
Опцию SQLLogFile включается только на момент отладки, потом не забудьте ее закомментировать! 

Логирование
Еще, что касается логов. По умолчанию proftpd ведет логирование используя  syslog. Размещение определяется согласно /etc/syslog.conf в /var/log/xferlog.

Можно настраивать различные уровни логирования: err, notice, warn, info и debug, но они распространяются только на syslog.
SyslogLevel notice
Если хочется иметь отдельные файлы логов, то можно прописать:
TransferLog /var/log/proftpd-transfer.log
SystemLog /var/log/proftpd-error.log
ExtendedLog /var/log/proftpd-extended.log
Детализация варьируется от 0 до 9 - самая подробная.

DebugLevel 9
Можно перезагружать proftpd и проверять.
# service proftpd restart
Удачных, Вам, настроек!

15 октября 2014

Кодировка UTF-8



На вопрос какую кодировку лучше использовать? Ответ простой - выбирайте unicode, не ошибетесь! Это универсальный стандарт, символы выглядят одинаково везде и вы навсегда избавитесь от проблемы подбора правильной кодовой страницы и кракозябр.

А для совместимости со старыми однобайтовыми кодировками придуман формат UTF-8 (Unicode transformation format). 

По сути это ничто иное, как 8-битная форма записи юникода. Но позвольте, скажете вы, как же так? В юникоде около 110 000 разных символов, как они кодируются одним байтом? Давайте разбираться.

На самом деле не одним байтом. Здесь разные символы кодируются разным числом байтов, в зависимости от их кода или порядкового номера.  Как мы знаем, символы ASCII, кодируется всего 7 битами. И в юникоде они располагаются первыми. Поэтому, если байт начинается с 0, то это является признаком ASCII и символ кодируется только одним байтом.
0aaa aaaa
Но если символ имеет код больше 7 битов (128), то для его кодирования приходится использовать второй байт. Для этого в начале первого байта ставится признак "110" - две единицы, это значит два байта и ноль, как признак завершения кода размера. Второй байт обязательно начинается с "10" - это признак продолжения.
110x xxxx 10xx xxxx
Пример, имеем двухбайтовый символ  [11010000] [10011110], отбрасывая признаки, получаем 10000011110 = 0x41E, это символ большая кирилическая О.

Если код символа занимает больше 11 бит (2048), то ставится признак "1110" и используют третий байт, в начале которого так же ставят признак продолжения "10".
1110 xxxx 10xx xxxx 10xx xxxx
И так далее до 6 байт.
Вот такой простой принцип кодирования.

Но на Freebsd почему то все еще используется KOI8-R. Поэтому после того, как вы осознали пользу от Unicoda, давайте установим ее в качестве локали.  Но пользоваться ею нормально можно будет только в удаленной консоли, например по ssh. В системной это не будет работать!

Если вы используете шелл по умолчанию, то для обычных пользователей это sh, а для root - csh.

Что бы узнать свое окружение дайте команду
# echo $shell
или посмотрите в /etc/passwd

Для смены кодировки csh достаточно в файле /etc/csh.cshrc прописать переменные
setenv LANG ru_RU.UTF-8
setenv LC_CTYPE ru_RU.UTF-8
setenv LC_COLLATE POSIX
setenv LC_ALL ru_RU.UTF-8
Для  bash в файле /etc/profile дописываем

LANG="ru_RU.UTF-8"; export LANG
LC_CTYPE="ru_RU.UTF-8"; export LC_CTYPE
LC_COLLATE="POSIX"; export LC_COLLATE
LC_ALL="ru_RU.UTF-8"; export LC_ALL'
 Переподключайтесь и любуйтесь русскими символами!

23 сентября 2014

АОН и Caller ID

Имеется у меня старенький аон (определитель номера) в виде специальной приставки для телефона, называется ЛАРТ-Евро. Приобретался он относительно давно и предназначался для адаптации зарубежных телефонов с функцией Caller ID к российским импульсным телефонным линиям. Сейчас, в свете последних достижений телефонии, дело с этим обстоит иначе и я озадачился вопросом, а нужен ли он вообще?

Для определения номеров входящих вызовов на стационарных телефонах в России используются два стандарта: аналоговый "русский АОН" и цифровой "Caller ID". Естественно они отличаются алгоритмом работы и способом кодирования информации.

Первый является элементом советского наследия. В то время передача номера вызывающего абонента использовалась чисто для служебных целей, для тарификации междугородних вызовов и спецслужб.  И до 2001 года применение АОН вообще было нелегальным.
Тем не менее такие устройства все еще работают, но определяют уже все меньшее количество номеров. Поскольку они зависит от технической возможности АТС выдавать такую информацию. А многие из них уже отказываются от аналогового и полностью переходят на цифровой стандарт.

Стандарт Caller ID специально разрабатывался, что бы предоставлять абонентам услугу по получению входящего номера. И большинство современных импортных телефонов поддерживают этот стандарт де факто. На сегодняшний день все цифровые АТС уже предоставляют такую услугу за отельную плату.

Caller ID несомненно удобнее: 
  1. Он показывает полностью все цифры номера в международном 10-значном формате. Отечественный АОН максимально только 7 цифр. 
  2. Абонент идентифицируется до установления соединения,  между первым и вторым сигналами вызова. Для АОН необходимо снятие трубки или автоматическая имитация этого с фиктивными длинными гудками. И в этом случае идет оплата за звонок.
  3. Точность определения номера составляет 100%. У АОН это сильно зависит от линии связи и часто номера определяются с ошибками.
Таким образом можно сделать вывод, что отечественный АОН является устаревшим стандартом, как и импульсный набор номера. Поэтому, если ваша АТС поддерживает цифровой режим, то использование ЛАРТ-Евро не целесообразно. Поскольку он определяет номер звонящего по технологии аналогового АОН и преобразовывает в стандарт Caller ID.
Пожалуй единственным оправданием использования будет отсутствие дополнительной платы.

Обратите внимание, что в отличии от ЛАРТ-202, у которого имеется перемычка для задания 6 или 7-значных номеров, ЛАРТ-Евро полностью программируемое устройство и никаких перемычек у него нет.
Его можно настраивать на работу в АТС с номерами от 4 до 7 цифр, отображение даты и времени звонков, срабатывание после определенного числа звонков. Адаптер питается он телефонной линии и при отключении все параметры стираются и требуется повторная настройка!
Поэтому для тех, кто все еще продолжает его использовать, выкладываю инструкцию, возможно у кого-то она уже потерялась (нажмите, чтобы увеличить).

17 сентября 2014

Контакты Google на iPhone


Большинство пользователей айфонов послушно синхронизируют свои контакты с iCloud. Но  у активных пользователей Google есть потребность использовать их сервис Контакты. Ведь с тех пор, как они добавили поддержку протокола CardDAV, синхронизация стала более универсальной. С его помощью вы так же можете обмениваться контактами и с другими не яблочными устройствами. 

Теперь главный вопрос, как перенести контакты с iphone на google?

Если в Настройках в разделе "Почта, адреса, календари" вы добавите новую учетную запись Google, то увидите, что там есть возможность синхронизировать Контакты.

Еще в разделе "Почта, адреса, календари" есть пункт "Стандартная уч. зап.", нужно выбрать Google.

Вот теперь синхронизация заработает в полную силу. И когда вы будете создавать новые контакты, они автоматом появятся в контактах гугл.

Но только уже существующие контакты автоматически не добавятся! Айфон упорно разделяет их на разные группы: Все Gmail и Все iCloud и не хочет объединять.

Поэтому перенести контакты из iCloud в Google придется вручную с помощью vCard.

Для этого вам нужно зайти на сайт icloud.com под своей учетной записью, в левом нижнем углу выбрать все контакты и нажать экспорт vCard.
Затем зайти на сайт gmail.com, на панели справа переключиться в режим Контакты и выбрать импорт контактов.
И в предложенном окне загрузить сохраненный файл из icloud.
Поздравляю вы перенесли все контакты из icloud в google.
Теперь чтобы не путаться, контакты icloud лучше отключить. Поскольку синхронизация сразу на двух сервисах  пока не возможна
Еще один момент, фотографии в карточках vCard не хранятся,  их придется добавлять по новой.

К сведению обратная процедура переноса контактов из google в icloud с помощью vcard тоже возможна.

05 сентября 2014

Шлюз для VPN на Freebsd

Данная статья является руководством, как организовать VPN-соединение, используя протоколы pptp, l2tp и настроить общение сервера с клиентом на Freebsd .

Многие из вас, конечно, знают о пользе VPN (Virtual Private Network). Эту технологию используют всякий раз, когда требуется связать удаленные подсети через Интернет так, как будто бы они находились рядом, в одной локальной сети.

Еще она полезна тем, что обеспечивает безопасный канал данных. А этот вопрос сейчас актуален, как никогда. Мы повсюду пользуемся открытыми wi-fi сетями, в офисах, отелях или кафе. И кто сможет гарантировать нам, что какой-нибудь злоумышленник не сможет перехватить наши персональные данные? Поэтому используйте vpn-клиенты и на ваших мобильных устройствах.

Приступая к вопросу создания vpn-сервера надо сказать, что единого стандарта VPN не существует. Ее можно построить с использованием разных протоколов. Самым распространенным по сей день остается PPTP (Point to Point Tunneling Protocol), в нем используется алгоритм шифрования MPPE (Microsoft Point-to-Point Encryption) с 40, 56 и 128 битным шифрованием. Для проверки аутентификации применяются MS-CHAPv2 или EAP-TLS. Но в этих алгоритмах были обнаружены серьёзные уязвимости. Поэтому использование pptp с точки зрения безопасности крайне не желательно!

Усовершенствованным протоколом является L2TP (Layer 2 Tunneling Protocol). Это совместное детище Microsoft и Cisco, комбинация PPTP и L2F. Но в отличие от PPTP для шифрования PPP-датаграмм здесь используется IPsec. Хотя l2tp  хорошо работает и без шифрования. Имейте в виду, что в windows по умолчанию оно используется! Что бы отключить, правим в реестре

REGEDIT4
[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Rasman\Parameters]
«ProhibitIpSec»=dword:00000001

И так, перейдем ближе к делу.
На VPN-сервере мы будем использовать демон mpd5 (Netgraph multi-link PPP daemon). Он крайне надежен, не требователен к ресурсам и обладает высокой производительностью, на современном оборудовании может справиться с несколькими гигабит PPP-трафика в секунду.
Он манипулирует подсистемой Netgraph и если ее нет в ядре (а по умолчанию ее нет), то сам заботливо подключает все необходимые модули. Проверить какие модули подключаются можно после запуска mpd командой 

# kldstat

Для начала мы потренируемся и настроим PPTP. Это очень быстро и просто!

Дополнительно у него есть механизм сжатия данных, но что бы им воспользоваться, нужно перекомпилировать модуль ng_mppc.ko. По умолчанию он собран без поддержки компрессии! Но сперва хорошенько подумайте, оно вам надо? Как показала практика, без нее vpn работает быстрее и стабильнее.
Если надо, то придется дополнительно скачать проприетарную библиотеку MPPC. Взять ее можно на сайте Alternative MPPC compression/decompression library.
# fetch http://mavhome.dp.ua/MPPC/mppc-1.0.tgz
# tar -xvf mppc-1.0.tgz -C /usr/src/sys/net/
Далее в файле /usr/src/sys/modules/netgraph/mppc/Makefile поправьте
NETGRAPH_MPPC_COMPRESSION?= 1
И соберите модуль
# cd /usr/src/sys/modules/netgraph/mppc
# make && make install && make clean
Так же компрессию для PPTP можно включить прямо в ядро. Но я буду собирать его без компрессии и только с нужными опциями netgraph. Сборка займет около 40 минут, в зависимости от мощности вашего компьютера.
options NETGRAPH 
options NETGRAPH_ETHER 
options NETGRAPH_SOCKET 
options NETGRAPH_TEE 
options NETGRAPH_MPPC_ENCRYPTION 
# options NETGRAPH_MPPC_COMPRESSION
options NETGRAPH_BPF 
options NETGRAPH_IFACE 
options NETGRAPH_KSOCKET 
options NETGRAPH_PPP 
options NETGRAPH_PPTPGRE 
options NETGRAPH_TCPMSS 
options NETGRAPH_VJC 
options NETGRAPH_ONE2MANY 
options NETGRAPH_RFC1490 
options NETGRAPH_TTY 
options NETGRAPH_UI
options NETGRAPH_L2TP
Копирую конфиг ядра из шаблона, добавляю опции, собираю и устанавливаю.
# cd /usr/src/sys/amd64/conf
# cp GENERIC mykernel
# cd /usr/src
# vi mykernel
# make buildkernel KERNCONF=mykernel
# make installkernel KERNCONF=mykernel
После перезагрузки проверяем, что новое ядро успешно загрузилось командой uname -a

Теперь ставим mpd5 из пакета
# pkg install mpd5
или из порта
# portsnap fetch update
# cd /usr/ports/net/mpd5
# make config install clean
Возьмем за основу файл конфигурации из шаблона
# cd /usr/local/etc/mpd5
# cp mpd.conf.sample mpd.conf
Для примера, представим, что у нас есть офисная подсеть 192.168.10.0/24, в ней имеется шлюз  с внутренним адресом 192.168.10.1 и внешним 1.2.3.4, на котором запущен mpd.

Тогда согласно этой топологии отредактируем mpd.conf. Для настройки pptp находим в нем секцию pptp_server и меняем там только такие строчки, остальные оставляем без изменения:
# задаем логин к web-интерфейсу
set user username pass admin
# комментируем эту строчку за ненадобностью
#set user foo1 bar1
# по умолчанию прописываем старт pptd-сервера
default:
load pptp_server
pptp_server:
# пул адресов
set ippool add pool1 192.168.10.200 192.168.10.220
# указываем mpd-сервер и назначаем для подсети пул
set ipcp ranges 192.168.10.1/32 ippool pool1
# указываем dns провайдера или свой
set ipcp dns 192.168.10.1
# если нет WINS, то комментируем
#set ipcp nbns 192.168.1.4
# принимать PPTP подключения на всех интерфейсах или указываем конкретный
set pptp self 0.0.0.0
Если ваш сервер выполняет роль маршрутизатора и раздает интернет при помощи NAT, то  клиенты подключившиеся через vpn так же смогут выходить в интернет.  Правильно укажите адреса dns в mpd.conf. Используйте те, которые выдал провайдер, либо ставьте локальный кеширующий dns, например bind.

Создаем файл с логинами и паролями
# touch mpd.secret
Добавляем в него пользователей
#login password ip
user1 pass1 192.168.10.193
user2 pass2 
Mpd слушает 1723 TCP-порт и после удачной аутентификации с помощью протокола GRE устанавливается PPP-сессия, при этом создаются виртуальные ng* интерфейсы. Поэтому в фаервол нужно добавить правила разрешающие gre по всем интерфейсам и 1723 TCP-порт для управления соединением.   
allow tcp from any to me 1723
allow gre from any to any
Настроим логирование mpd  в файл mpd.log. Для этого в конец /etc/syslog.conf добавим строчки
!mpd 
*.* /var/log/mpd.log 
И еще не забудем про ротацию. В /etc/newsyslog.conf добавим
/var/log/mpd.log 600 7 * @T00 JC
Создадим лог-файл и перезапустим сервис
# touch /var/log/mpd.log
# service syslogd reload
или так /etc/rc.d/syslogd reload Это одно и тоже.

Для автозапуска добавим в /etc/rc.conf параметр
mpd_enable="YES"
mpd_flags="-b"
И запускаем mpd5
# service mpd5 start
Проверяем, слушается ли порт:
# netstat -an | grep 1723
Подключаемся любым клиентом, радуемся! 
Так же для проверки заходим в веб-админку http://server:5006 и смотрим параметры.

mpd5 pptp-client
Что бы настроить mpd, как клиента pptp, в конфигурацонном файле mpd.conf должна быть секция (взято из шаблона).
default:
load pptp_client
pptp_client:

create bundle static B1

# одно из двух, либо это 
set iface route default
set ipcp ranges 0.0.0.0/0 0.0.0.0/0 
# либо это 
#set iface up-script /usr/local/etc/mpd5/up.shset 
#set iface down-script /usr/local/etc/mpd5/down.sh

create link static L1 pptp
set link action bundle B1
set auth authname login_name
set auth password password
set link max-redial 0
set link mtu 1460
set link keep-alive 20 75
set pptp peer ip_pptp_server
set pptp disable windowing
open
И правила для фаерволов. Со стороны сервера 1723 порт, на клиенте произвольный больше 1000. И для установления соединения протокол gre.
 
Еще хочу дать небольшое пояснение. 
Предположим, что соединение происходит по следующей схеме.


После того, как ваш pptp-клиент подключится к серверу, он присоединиться к его локальной сети и будет иметь доступ ко всем подсетям, которые маршрутизирует сервер. Кроме того, если сервер имеет NAT, то вы так же получите доступ к сети интернет через его интерфейс, если пропишете на клиенте в качестве шлюза внутренний адрес pptp-сервера.
route delete default
route add default 192.168.10.1
Но при этом нужно сохранить прежний маршрут для поддержания pptp-канала через основной шлюз, которым вы пользовались по умолчанию, в нашем случае это, например, 1.2.3.1
route add 1.2.3.5 1.2.3.1
Но локальные сети pptp-клиента и сервера по прежнему не имеет доступа друг к другу, поскольку pptp-сервер ничего о них не знает. Для этого на сервере вручную нужно указать  маршрут до сетей клиента. 
route add -net 192.168.20.0/24 192.168.10.5
Теперь все сети видят друг друга, а сети клиента даже могут выходить в интернет через pptp-сервер.

Что бы эти маршруты создавались автоматический можно оформить их в виде отдельных скриптов и прописать в mpd.conf.
set iface up-script /usr/local/etc/mpd5/up.sh
set iface down-script /usr/local/etc/mpd5/down.sh
Они будут срабатывать при установлении соединения. Важный момент, в каком месте mpd.conf их расположить. Если это клиент, то правильно в начале секции заместо "set iface route default", тогда ее нужно закомментировать (см. пример выше), иначе не запускаются. Если сервер, то так же в начале, после "create bundle template BL".

Пример up.sh
#!/bin/sh
route delete default
route add 1.2.3.5 1.2.3.1
route add default 192.168.10.1
В down.sh надо все вернуть обратно как было.
#!/bin/sh
route delete default
route delete
1.2.3.5 1.2.3.1
route add default 192.168.15.1


Настройка l2tp на mpd выполняется по аналогии с pptp. В конфиг mpd.conf нужно добавить секцию l2tp_server с точно такими же параметрами, где все буквосочетания pptp заменяются на l2tp. Жирным выделено то, чем отличается от шаблона.
default:
load pptp_server
load l2tp_server
l2tp_server:
# Define dynamic IP address pool.
set ippool add pool1 192.168.10.200 192.168.10.220
# Create clonable bundle template named B
create bundle template BB
set iface enable proxy-arp
set iface idle 1800
set iface enable tcpmssfix
set ipcp yes vjcomp
# Specify IP address pool for dynamic assigment.
set ipcp ranges 192.168.10.1/32 ippool pool1
set ipcp dns 192.168.10.1
#set ipcp nbns 192.168.1.4
# The five lines below enable Microsoft Point-to-Point encryption
# (MPPE) using the ng_mppc(8) netgraph node type.
set bundle enable compression
set ccp yes mppc
set mppc yes e40
set mppc yes e128
set mppc yes stateless
# Create clonable link template named L
create link template LL l2tp
# Set bundle template to use
set link action bundle BB
# Multilink adds some overhead, but gives full 1500 MTU.
set link enable multilink
set link yes acfcomp protocomp
set link no pap chap eap
set link enable chap-msv2
# We can use use RADIUS authentication/accounting by including
# another config section with label ‘radius’.
# load radius
set link keep-alive 10 60
# We reducing link mtu to avoid GRE packet fragmentation.
set link mtu 1460
# Configure PPTP
set l2tp self 0.0.0.0
# Allow to accept calls
set link enable incoming
Перезапускаем mpd и проверяем, что у нас слушается 1701 udp порт.
# netstat -an | grep 1701
Далее добавляем поддержку IPsec и пересобрать ядро.
# ядерная поддержка IP security
options IPSEC
# изменение и восстановление заголовков пакетов за NAT
options IPSEC_NAT_T
# поддержка криптографии
device crypto
Начиная с версии 11.0 IPSEC_NAT_T включен в ядро по умолчанию, поэтому ее можно закомментировать!

После того как вы установите IPsec, его надо настроить. Вам нужно будет указать какой трафик и как следует шифровать. Для этого в IPsec есть специальная база SPD (Security Policy Database), где хранятся политики безопасности. Ее можно заполнить статически, скриптом setkey.conf, который будет срабатывать при инициализации системы. Для этого в rc.conf нужно добавить строчки
ipsec_enable=”YES”
ipsec_program=”/usr/local/sbin/setkey”
ipsec_file=”/usr/local/etc/racoon/setkey.conf”
IPsec может шифровать любой трафик, но нам надо только канал l2tp. Весь шифрованный трафик будет передаваться по протоколу esp. И есть два варианта настройки, транспортный режим или туннельный. В первом случае в ip-пакет встраиваются только шифрованные данные, а заголовок остается неизменным и содержит оригинальные ip. Во втором, изменяется ip-заголовок и в шифрованную часть esp-кадра помимо данных еще встраиваются оригинальные адреса источника и отправителя. Таким образом скрывются реальные ip-адреса внутренних подсетей и обеспечивается их безопасность. Но естественно это требует дополнительных вычислительных мощностей.

Поэтому, если вы организуете vpn между двумя подсетями и НЕ хотите, чтобы в Интернете курсировали их ip-пакеты, то надо настраивать туннельный режим.  А если у вас подключение хост-хост, то только транспортный!

Для наглядности хочу приложить датаграмму, поясняющую отличия транспортного режима от туннельного.


Настройки для шифрования трафика между сервером и произвольным узлом будут выглядят следующим образом. В файле /usr/local/etc/racoon/setkey.conf
flush;
spdflush;
spdadd 0.0.0.0/0[0] 1.2.3.4/0[1701] udp -P in ipsec esp/transport//require;
spdadd 1.2.3.4/0[1701] 0.0.0.0/0[0] udp -P out ipsec esp/transport//require;
А между двумя подсетями, например, 10.246.38.0/24 и 10.0.0.0/24, в каждой есть свой шлюз  с внешним адресом 172.16.5.4 и 192.168.1.12.
spdadd 10.246.38.0/24 10.0.0.0/24 any -P out ipsec esp/tunnel/172.16.5.4-192.168.1.12/require;
spdadd 10.0.0.0/24 10.246.38.0/24 any -P in ipsec esp/tunnel/192.168.1.12-172.16.5.4/require;
После того, как настроете политики безопасности, посмотрите, как они будут выгляднть до и после подключений клиентов, это делается командой
# setkey -DP
Настройка Racoon
Далее клиенту и серверу нужно договорится о алгоритме и ключах шифрования. Это делается с помощью специального демона по протоколу IKE (Internet Key Exchange protocol). Мы будем использовать Racoon из порта security/ipsec-tools.  

Но перед установкой мы внесем в код небольшие изменения, что бы можно было подключаться с динамических ip-адресов, которые заранее не известны.
# cd /usr/ports/security/ipsec-tools
# make fetch
# make checksum
# make depends
# make extract
# cd /usr/ports/security/ipsec-tools/work/ipsec-tools-0.8.1/src/racoon
Там открываем файл localconf.c и находим функцию getpsk(str, len). В ней строку
if (strncmp(buf, str, len) == 0 && buf[len] == '\0') {
заменяем на
if(strcmp(buf, "*")==0||(strncmp(buf,str,len)==0&& buf[len]=='\0')){
И еще в файле ipsec_doi.c находим функцию ipsecdoi_checkid1(iph1), в ней условный оператор
if (iph1->etype == ISAKMP_ETYPE_IDENT &&
iph1->approval->authmethod == OAKLEY_ATTR_AUTH_METHOD_PSKEY)
{ if (id_b->type != IPSECDOI_ID_IPV4_ADDR &&
id_b->type != IPSECDOI_ID_IPV6_ADDR)
{ plog(LLV_ERROR, LOCATION, NULL,
"Expecting IP address type in main mode, "
"but %s.\n", s_ipsecdoi_ident(id_b->type));
return ISAKMP_NTYPE_INVALID_ID_INFORMATION;
} }
 
Меняем здесь LLV_ERROR на LLV_WARNING и комментируем return используя /* */.
Сохраняем, собираем и устанавливаем порт.
# cd /usr/ports/security/ipsec-tools
# make build
# make install clean
Теперь настроим файл конфигурации recoon. Возьмем из шаблона и скопируем его в каталог /usr/local/etc/racoon
# cp /usr/local/share/examples/ipsec-tools/racoon.conf.sample /usr/local/etc/racoon/racoon.conf
Редактируем, он должен содержать следующие строчки. 
path include "/usr/local/etc/racoon";
path pre_shared_key "/usr/local/etc/racoon/psk.txt";
log info;
listen {
        isakmp 1.2.3.4 [500];
        isakmp_natt 1.2.3.4 [4500];
}
remote anonymous {
                  exchange_mode main;
                  proposal_check obey;
                  lifetime time 24 hour;
                  generate_policy on;
                  nat_traversal on;
proposal {
          encryption_algorithm 3des;
          hash_algorithm sha1;
          authentication_method pre_shared_key;
          dh_group 2;
}}
sainfo anonymous {
                  lifetime time 1 hour ;
                  encryption_algorithm aes;
               authentication_algorithm hmac_sha1, hmac_md5;
                  compression_algorithm deflate;
}
Справку по всем опциям можете смотреть здесь.

Обратите внимание, что в конфигурационном файле racoon.conf есть опция generate_policy on. Благодаря ей демон динамически генерирует политики безопасности в соответствии с нуждами клиента и обновляет базу SPD.

Благодаря этому особой нужды в setkey.conf  нет. Но в процессе эксплуатации выяснилось, что если клиент находится за NAT, то по каким то причинам одних динамических политик не достаточно и он не может подключиться. Если без NAT, то все  работает на ура.

Поэтому специально для таких клиентов обязательно настройте статические правила безопасности SPD, как было описано выше.

Аутентификация в IPsec может происходить по паролю или сертификату. Сейчас мы будем использовать пароли, только здесь они называются открытыми ключами. Они должны находится в файле /usr/local/etc/racoon/psk.txt и быть в формате "ip  пароль" для каждого клиента отдельно.
Но благодаря тому, что мы внесли изменения в код, теперь у нас задается один пароль для всех подключений!
* password
Так же для этого файла нужно задать права доступа
# chmod 600  /usr/local/etc/racoon/psk.txt
Для записи логов racoon добавляем в /etc/syslog.conf строчку
!racoon 
*.* /var/log/racoon.log
И прописываем в rc.conf автозагрузку
racoon_enable="YES"
racoon_flags=”-l /var/log/racoon.log”
Еще не забудьте добавить правила для фаервола, разрешающие IKE трафик, это порты 500 и 4500 UDP.
allow udp from me isakmp to any
allow udp from any to me isakmp
allow udp from any to me 4500
allow udp from me 4500 to any
Так же потребуются правила для ESP и IPENCAP в обе стороны. 
allow esp from me to any
allow esp from any to me
allow ipencap from me to any
allow ipencap from any to me
 Все настроили, поздравляю! Теперь для теста запускаем racoon в фоновом режиме
# /usr/local/sbin/racoon -F -f /usr/local/etc/racoon/racoon.conf
У вас должно появиться следующее сообщение приветствия
Foreground mode.2014-09-06 09:49:44: INFO: @(#)ipsec-tools 0.8.1 (http://ipsec-tools.sourceforge.net)
2014-09-06 09:49:44: INFO: @(#)This product linked OpenSSL 1.0.1e-freebsd 11 Feb 2013 (http://www.openssl.org/)
2014-09-06 09:49:44: INFO: Reading configuration from "/usr/local/etc/racoon/racoon.conf"
2014-09-06 09:49:44: INFO: 1.2.3.4[4500] used for NAT-T
2014-09-06 09:49:44: INFO:
1.2.3.4[4500] used as isakmp port (fd=5)
2014-09-06 09:49:44: INFO:
1.2.3.4[500] used for NAT-T
2014-09-06 09:49:44: INFO:
1.2.3.4[500] used as isakmp port (fd=6)
Это означает, что демон начал слушать. Теперь подключаетесь клиентом и смотрите какие сообщения он будет вадавать.

Что бы настроить racoon в качетве клиента потребуется следующий конфиг
path pre_shared_key "/usr/local/etc/racoon/psk.txt";
log info;

listen {
        isakmp client_ip;
        strict_address;
}

remote server_ip {
        exchange_mode main;
        lifetime time 24 hour;
        my_identifier address;
        peers_identifier address;
        passive off;
        generate_policy off;
        proposal {
                encryption_algorithm 3des;
                hash_algorithm sha1;
                authentication_method pre_shared_key;
                dh_group 2;
        }
}

sainfo anonymous {
        encryption_algorithm aes;
        authentication_algorithm hmac_sha1, hmac_md5;
        lifetime time 1 hour ;
        compression_algorithm deflate;
}
И в файле psk.txt должен быть такой же ключ, как на сервере.
server_ip password
Так же нужны политики безоппасности для определения какой трафик шифровать.
flush; 
spdflush; 
spdadd client_ip[0] server_ip[1701] udp -P out ipsec esp/transport//require; 
spdadd server_ip[1701] client_ip[0] udp -P in ipsec esp/transport//require;
На стороне сервера политики можно не определять, достаточно опции generate_policy on;
Пробуйте подключиться
racoonctl vpn-connect 192.168.15.1

Если все пройдет удачно, то по команде
# setkey -D
увидите установленные соединения
192.168.15.2 192.168.15.1
        esp mode=transport spi=237603062(0x0e2988f6) reqid=0(0x00000000)
        E: rijndael-cbc  c63f1e8a ec2e5696 b4d11f49 43808d67
        A: hmac-sha1  216134ff 88b7f5e4 2ba8636c 6bce456c bcc5be04
        seq=0x0000002a replay=4 flags=0x00000000 state=mature
        created: Nov 22 09:48:53 2014   current: Nov 22 09:54:44 2014
        diff: 351(s)    hard: 3600(s)   soft: 2880(s)
        last: Nov 22 09:54:40 2014      hard: 0(s)      soft: 0(s)
        current: 4176(bytes)    hard: 0(bytes)  soft: 0(bytes)
        allocated: 42   hard: 0 soft: 0
        sadb_seq=1 pid=6713 refcnt=2
192.168.15.1 192.168.15.2
        esp mode=transport spi=143240586(0x0889ad8a) reqid=0(0x00000000)
        E: rijndael-cbc  677283ac fe29513a 9a2718c9 4ce0cd7f
        A: hmac-sha1  ce28280f c819ae0e 99601510 bb99bda8 767bfefe
        seq=0x00000028 replay=4 flags=0x00000000 state=mature
        created: Nov 22 09:48:53 2014   current: Nov 22 09:54:44 2014
        diff: 351(s)    hard: 3600(s)   soft: 2880(s)
        last: Nov 22 09:54:40 2014      hard: 0(s)      soft: 0(s)
        current: 2154(bytes)    hard: 0(bytes)  soft: 0(bytes)
        allocated: 40   hard: 0 soft: 0
        sadb_seq=0 pid=6713 refcnt=1
Если что то пойдет не так, смотрите в логи /var/log/racoon.log на клиенте и сервере, там сразу все сразу станет ясно!
Желаю успехов!