Основы IPv6

Предисловие

Пост является кратким конспектом Wiki, Technet’a, FreeBSD’шного handbook’a, Serverfault’a, множества RFC и документов IANA, а также курсов от Специалист.Ру для сотрудников Яндекса.

Пост можно рассматривать как копилку ссылок по актуальной на 2012 год спецификации IPv6. Однако он никак не описывает возможные способы установки IPv6 соединения с интернетом и не привязан к какой-либо определённой ОС.
Учтите, что прочтение данной хабрастатьи займёт у вас не более получаса, однако крайне рекомендуется ознакомиться со всеми приведёнными в статье ссылками… Последнее может занять несколько недель.

Prerequisites
Хоть статья и называется «Основы IPv6» она всё-таки подразумевает наличие базовых знаний о IP сетях и хотя бы небольшой практический опыт работы с IPv6, в противном случае хабрастатья будет даваться очень не легко.
Так же рекомендуется к прочтению документ Implementing IPv6 Addressing and Basic Connectivity от Cisco.
Ещё стоит заметить, что приведённые на википедию ссылки зачастую более примечательны разделом References нежели своим содержанием.

IPv6 Адреса

Анатомия IPv6 адресов
В первой версии этого хабрапоста тут было много текста, но с того момента на википедии выросла отличная статья: IPv6 Address.

Маски подсетей
Маски теперь задаются только /prefix’ами (CIDR), классовой адресации и стандартной decimal dotted нотации в IPv6 нет. Так же теперь первый и последний адрес сети не являются зарезервированными под идентификатор сети и broadcast соответственно.

Выделение IPv6 адресов
Как и в случае с IPv4, IPv6’ые адреса выделяются через целую иерархию организаций:
RIR(/12-/23) -> NIR(??) -> LIR(/19-/32) -> ISP(/48-/56) -> LAN(=>/64)
ISP уже выделяют адреса сетям как хотят. Однако и тут есть Best-Practice от IPv6 Task Force: Guidelines for ISPs on IPv6 Assignment to Customers.
В общем пожелания по выделению IPv6 адресов описаны в RFC5375 IPv6 Unicast Address Assignment Considerations
Также интересная деталь: Таблицы маршрутизации в IPv6 планировали изначально делать как можно более «агригабельными», что подразумевало отсутствие Provider-Independent (PI) адресов. Однако крупные копрорации (видимо желающие делать BGP-failover) в 2009 году всё-таки «продавили» RIPE, так что получить PI-адреса в IPv6 теперь реально.

Типы адресов и их префиксы
Об IPv6 адресации подробно рассказано в RFC4291. Далее я опишу самые распространённые типы IPv6 адресов, их назначения и префиксы.

::/128 — Unspecified — не должен принадлежать ни одной ноде в сети;
::/0 — Default route;
::1/128 — Loopback;

fe80::/10 — Link-Local — адреса уникальные на линке. Создание IPv6 link-local адреса из префикса fe80:: и MAC адреса сетевой карты, как и многое другое описано в презентации от Microsoft и в документе Introduction to IP Version 6, также процедура создания модифицированного EUI-64 идентификатора на пальцах разъяснена в Приложении А RFC4291);
fec0::/10 — Site-Local — устарели судя по RFC3879;
fc00::/7 — Unique Site-Local— пришли на замену Site-Local в RFC4193. В данный момент разбит на две части: fc00::/8 и fd00::/8. Уникальные в пределах организации, е роутящиеся в интернет адреса. Однако могут роутиться внутри site’a и между site’ами;
ff00::/8 — Multicast — о мультикасте подробнее расскажу чуть ниже. Полный список мультикаст адресов можно посмотреть тут: IANA IPv6 Multicast Addresses;
::0000/96 — IPv4-Compatible IPv6 Addressустарели;
::ffff/96 — IPv4-Mapped IPv6 Address — Адреса предназначенные в основногм для Socket API. Более подробно их назначение описано в RFC4038. рочтение этого RFC будет полезно программистам которые собираются писать Dual-Stack приложения;

Все «не специальные» адреса относятся к:
Global Unicast — глобальные адреса, уникальные во всем интернете. Пока, впрочем, судя по этому документу, доступно только глобальное пространство 2000::/3 (Адреса от 2000:: до 3fff:ffff:ffff:ffff:ffff:ffff:ffff:ffff)

Виды трафика
Unicast — Старый добрый юникаст;
Multicast — Мультикаст теперь необходимое расширение, а не опциональное как в IPv4. IGMP был заменён на MLD. А процедура получения глобального мультикаст префикса стала тривиальной — теперь при получении /64 префикса провайдер автоматически получает 4.2 миллиарда глобальных мультикаст групп. Процедура подробно описана в RFC3306, а также дополнена внедрением адреса RP прямо в IPv6 адрес в RFC3956. Получение глобального мультикаст префикса для IPv4 и IPv6 описано в RFC6308. Стоит также заметить, что в IPv4 Multicast link-layer префикс был 01:00:5e, в IPv6 он стал 33:33:ff (посмотреть список групп для интерфейсов во FreeBSD можно через ifmcstat или же через ip maddr в Linux);
Anycast — Такой же anycast как и в IPv4. Этот тип адреса обычно анонсируется протоколом динамической маршрутизации (например BGP), сразу из нескольких мест. Это обеспечивает оптимальный, с точки зрения протокола маршрутизации, роутинг;
Broadcast — в IPv6 broadcast’а не существует. В место него можно использовать All Nodes Address. Пакеты посланные на него будут рассылаться только на хосты с настроенным IPv6 адресом (при включеном MLD snooping’е); Также часть протоколов раньше использовавших Broadcast в IPv6-версии всёже обзавелись собственной multicast группой;

Address Scope
В IPv6 появилось такое понятие как Scope , он же Zone ID терминологии Microsoft. На самом деле оно было и в IPv4, однако не было задано явно: сети 10/8, 172.16/12 и 192.168/16 яркие тому примеры.
В случае Unicast/Anycast адресов приминимо следующее:
У каждого IPv6 enabled интерфейса есть свой Link-local адрес. Его scope, внезапно, local. Эти адреса уникальны в пределах линка, но не обязаны быть актуальными в пределах одного хоста. Так, например, VLAN созданный на интерфейсе будет иметь такой же link-local адрес, что и родительский интерфейс (так как без использования IPv6 Privacy Extensions он будет генериться из тогоже Link Layer адреса). Для того, чтобы явно указать интерфейс которому принадлежит IPv6 адрес нужно или указывать в ручную интерфейс для исходящих пакетов или использовать специальный суффикс при записи адреса: %ИндексИнтерфейса в Windows (fe80::2b0:d0ff:fee9:4143%3) или %ИмяИнтерфейса в *BSD/Linux (fe80::2b0:d0ff:fee9:4143%em0).
В случае Multicast адресов scope указан в последних четырёх битах вторго октета IPv6 адреса: ff0s:: и может быть interface-local, link-local, admin-local, site-local, organization-local или же global.
Дополнительно стоит ознакомиться с RFC4007 IPv6 Scoped Address Architecture

Жизненный цикл IPv6 адреса
Возможны следующие state’ы IPv6 адреса на протяжении его жизненного цикла:
086f45b60d689ed6a45a0f8fdaacf658[1]
Tentative — Адрес ещё проверяется на уникальность;
Valid — Траффик на этот адрес будет получатся хостом, делится на 2 подсостояния:
Prefered state — Основное состояние, неограниченное использование адреса;
Deprecated state — Адрес ещё можно использовать для старых соединений, но нельзя создавать новые соединения;

Invalid — Адрес нельзя использовать для получения/отправки пакетов.

IPv6 Пакет
Заголовок IPv6 пакета
Значительные изменения в формате заголовка пакета
Фиксированный размер заголовка;
Отсутствует Checksum заголовка, соответственно, его не надо проверять, а также пересчитывать для каждого пакета при изменении TTL Hop Limit. Так как checksum больше нет, то вся ответственность за целостность информации должна лежать на протоколе более низкого уровня, так например у Ethernet фреймов есть свой честный CRC32. Так же у UDP пакетов наличие checksum теперь обязательно и UDP/IPv6 пакеты с Checksum 0000 будут просто отбрасываться принимающим хостом;
Сам TTL теперь именуется Hop Limit (скорее всего потому, что раньше одним из условий у роутера было уменьшать TTL на один каждую секунду прибывания пакета в очереди, поэтому и TIME-to-live). В связи с последним трендом с повсеместным введением MPLS/TE стоит заметить, что при прохождении IP-пакета через MPLS облако его TTL/HopLimit может не и меняется;
Роутеры теперь не занимаются фрагментацией пакетов. Хосты должны сами проводить Path MTU discovery и разбивать пакеты. Минимальный MTU теперь равен 1280.
Были добавлены Метки потоков, служат для разгрузки роутеров, более точной приоритезации трафика и балансировки. Более подробно можно почитать в RFC6437 — IPv6 Flow Label Specification. До сих пор ходят баталии об использовании этого поля IPv6 заголовка на практике. Эпик-треды можно почитать в RFC6294 — Survey of Proposed Use Cases for the IPv6 Flow Label, RFC6436 — Rationale for Update to the IPv6 Flow Label Specification и RFC6438 — Using the IPv6 Flow Label for Equal Cost Multipath Routing and Link Aggregation in Tunnels. Единственная операционная система(из протестированных нами) которая на выставляет по умолчению flow label’ы это FreeBSD;
Изначально(в obsoleted RFC1883) поле Traffic Class называлось Priority и занимало 4 бита, а flow label был 24 бита. В RFC2460 они стали 8 и 20 бит соответственно. Если кому интересна никрофилия можно почитать остальные Historical notes на вики;
Поддержка IPSec теперь является обязательной;

Extension Headers
Заголовок пакета теперь фиксированной длинны и заметно упрощённый, однако благодаря Extension Header’ам обеспечивается гибкость большая нежели у IPv4 Options, которые благодаря ограничению на размер в 40 байт были вообще не юзабельны. Подробно структура IPv6 пакета описана в RFC2460, тут я опишу лишь самое основное.
Каждый пакет содержит восьми битное поле называемое Next Header, в нём содержится идентификатор следующего заголовка. Extension Headers могут идти сразу после заголовка IPv6 (между заголовком и payload’ом IPv6 пакета) и включают в себя дополнительную информацию сетевого уровня. На данный момент имеются следующие типы Extension Header’ов:
Hop-by-Hop Options — любой роутер на пути следования пакета должен просматривать только IPv6 заголовок, все остальные заголовки предназначены эксклюзивно для получателя пакета. Однако Hop-By-Hop заголовок является исключением — его просматривают все роутеры и если он есть, то должен идти сразу за IPv6 заголовком.
Routing — RFC5095 отменяет Type 0 Routing Headers, которые содержат в своём определении DoS уязвимость (ещё серьёзнее нежели source routing в IPv4). Подробнее тема безопасности в IPv6 обсуждается в RFC4942 и в презентации Security Implications of IPv6.
Fragment — Заголовок фрагментированного пакета. Как я уже упоминал, роутеры больше не занимаются фрагментацией, так что отправитель сам должен позаботится об оптимальном размере пакета, иначе получит Packet too big от одного из роутеров на пути. Кстати, MTU для работы IPv6 не должен быть менее 1280.
Destination Options — Опции предназначенные только получателю.

Так же в имеются заголовки IPSec аунтефикации и шифрования:
Authentication — RFC4302
Encapsulating Security Payload — RFC4303

IPv6 Протоколы
ICMPv6
ICMP в IPv6 был заменён на ICMPv6. О ICMPv6 можно прочитать в RFC4443 Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification.
Сам по себе ICMPv6 довольно прост, однако на его основе сделано множество довольно не тривиальных протоколов, о которых мы поговорим чуть ниже.

MLD
ICMP в IPv6 был заменён на ICMPv6. О ICMPv6 можно прочитать в RFC4443 Internet Control Message Protocol (ICMPv6) for the Internet Protocol Version 6 (IPv6) Specification.
Сам по себе ICMPv6 довольно прост, однако на его основе сделано множество довольно не тривиальных протоколов, о которых мы поговорим чуть ниже.

MLD
Multicast Listener Discovery — протокол на основе ICMPv6. Аналог IGMP для IPv6. Подробнее в RFC3810 — Multicast Listener Discovery Version 2 (MLDv2) for IPv6.

NDP
Описание Neighbor Discovery Protocol, заменившего протокол ARP, доступно в RFC4861. Теперь это не отдельный протокол, а надстройка над ICMPv6 добавляющая несколько новых типов сообщений.
Основное предназначение NDP — производить мапинг между link-layer и IPv6 адресами, однако это лишь небольшая часть функциональности.

Что ещё умеет NDP:
Neigbour Unreachability Detection, позволяющая определить доступность хоста одним из двух методов:
С помощью протокола более высокого уровня;
С помощью unicast solicitation, на который хост должен ответить Neighbor Advertisement сообщением;
Duplicate Address Detection
Отсылка и обработка redirect’ов
Определение пааметров линка (например MTU)
Определение сервисов в сети (например DNS: RFC6106 IPv6 Router Advertisement Options for DNS Configuration)
Stateless автоконфигурация (об этом чуть ниже)

Также есть криптографически защищённый аналог NDP — SEcure Neighbor Discovery (SEND) описаный в RFC3971. SEND, в свою очередь, использует Cryptographically Generated Address описанные рядом в RFC3972.

Автоконфигурация
Zeroconf

Как уже было упомянуто выше, хосты умеют автоматически генерировать себе IPv6 link-local адрес из адреса канального уровня. Так что без какой либо настройки любой IPv6-enabled хост подключённый к сети выдаёт сам себе адрес сетевого уровня.
В IPv4 эта технология использует зарезервированный IPv4 диапазон 169.254/16. Подробно технология описана в RFC3927 Dynamic Configuration of IPv4 Link-Local Addresses (Заметьте, что этот RFC вышел после IPv6’ого 2462).

Stateful

В IPv4 автоконфигурация возможна только с использованием DHCP сервера. В IPv6 эту возможность оставили: можно конфигурировать сеть с помощью DHCPv6 сервера и клиента. Однако, поддержка со стороны вендоров DHCPv6 пока не блещет, так например, dhclient во FreeBSD из коробки не умеет IPv6.

Stateless

Кроме stateful-конфигурации в IPv6 имеется также stateless автоконфигурация, которая позволяет хостам автоматически получать IPv6 адреса в сети без DHCP сервера через использование NDP. Роутеру достаточно задать префикс который он будет анонсировать через Router Advertisement всей остальной сети. Хосты будут получать RA и формровать на основе префикса и своего link-layer адреса IPv6 адрес.
Пара замечаний:
Stateless определение адреса возможно только при наличии роутера/ротеров рассылающего RA;
Каждый роутер имеет приоритет: high/medium/low. Операционная система должна его учитывать при выборе default route;
RFC6106 — IPv6 Router Advertisement Options for DNS Configuration объясняет как встраивать адреса DNS-серверов прямо в RA, что позволяет избавиться от использования DHCPv6 для этого дела. Однако это поддерживается не всеми вендорами;
Генерировать IPv6 адрес используя свой link-layer не очень безопасно с точки зрения privacy. Ваши перемещения по миру а иногда и модель оборудования будет доступна всему интернету. Решение проблемы было описано в RFC4941 — Privacy Extensions for Stateless Address Autoconfiguration in IPv6. Все современные операционные системы поддерживают Privacy Extensions;

Комбинированая

Могут использоваться одновременно оба вида автоконфигурации, например stateless для получения IPv6 префикса и stateful для получения адресов DNS-серверов и/или других параметров, которые нельзя передать с помощью Router Advertisement.

DNS
Этому моменту в документации по IPv6 уделено достаточно мало внимания, однако судя по количеству RFC на эту тему, изменения колоссальны.
Для полноценной поддержки IPv6 в DNS систему было введено множество изменений (RFC3152, RFC3226, RFC3363) и всё равно остаётся некоторое количество нерешённых проблем — RFC4472.
Некоторое время даже существовало два стандарта для описания IPv6 адресов в DNS: A6 и AAAA, плюсы и минусы каждого из них описаны в RFC3364. Если вкратце, то A6 предоставляет большую гибкость и меньшую зависимость зоны от префикса, а AAAA являются лишь частным случаем A6 с длинной префикса 0. A6 в последствии был переведён в статус Experimental в RFC3363 — Representing Internet Protocol version 6 (IPv6) Addresses in the Domain Name System (DNS)
Для минимальной поддержки IPv6 требуется только одна AAAA запись. Также может потребоваться наличие PTR записи. Обратные DNS записи для IPv6 выглядят ужасающе. Так, например, обратка для адреса 4321:0:1:2:3:4:567:89ab будет выглядеть как b.a.9.8.7.6.5.0.4.0.0.0.3.0.0.0.2.0.0.0.1.0.0.0.0.0.0.0.1.2.3.4.IP6.ARPA.. Это зрелище не для слабонервных, однако, это скорее всего сподвигнет людей к автоматической генерации обраток. Для ручной генерации я бы рекомендовал sipcalc с ключом -r или что-либо аналогичное.

Прочее
Протоколы более высокого уровня
Часть протоколов, использующих адрес сетевого уровня в своей работе требовали внесения в них определённых изменением для того, чтобы начать работать по IPv6. Ярким примером такого протокола является FTP.

Тунелирование IPv6 трафика поверх IPv4 сетей
Тут совсем вскользь про некоторые возможные технологии:
Статические point-to-point MCT/GRE тунели;
6to4. Использует 2002::/16 диапазон. Есть ещё его разновидность для customer devices у которых с «той» стороны нет выделенного сервера для деинкапсуляции пакетов: они шлют инкапсулированые пакеты на anycast адрес 192.88.99.1 который анонсируется со множества 6to4 шлюзов с помощью протоколов динамической маршрутизации;
Teredo/Miredo. Работает не со всеми видами NAT’ов;
ISATAP — Intra-Site Automatic Tunnel Addressing Protocol. Обычно завязано на использовании DNS (Через резолв isatap.example.com);

Mobile IPv6
Про него не знаю нечего, так что просто оставлю это здесь: Mobile IP.

IPv6 адрес как хранилище информации
Согласитесь 128бит — это огромный простор для фантазии. Существует множество технологий которые пытаются использовать эти самые 128бит. От кодирования туда IPv4 адреса и криптографических сигнатур до определения растояний между нодами (тут кстати даже мы думали в этом направлении, но пока присмтриваемся к ALTO: Application-Layer Traffic Optimization (ALTO) Problem Statement).

Socket API
Хабратопик описывает IPv6 с точки зрения NOC / системного администратора, но не с точки зрения программиста. Если кому-то интересны особенности программирования под IPv6, то рекомендую обратиться к RFC3493 — Basic Socket Interface Extensions for IPv6 и книжке IPv6 Network Programming

Послесловие
Не смотря на все мои попытки всё структурировать статья получилась довольно сумбурной. Возможно это из-за её сугубо теоретической направленности, возможно из-за того что сам ещё не всё устаканил у себя в голове. В любом случае, я надеюсь, она будет служить хорошей памяткой и катологом ссылок по IPv6, как для меня, так и для всего хабрасообщества.
Однако, возможно, перед тем как зарываться с головой в RFC и tcpdump’ы можно сначала почитать книжки, например, IPv6 Essentials от O’Reilly должна сильно помочь усвоению материала описанного в этой статье.

Корпоративный VPN c ACCEL-PPP+IPsec и авторизацией в Freeradius через AD

В этой заметке я хочу показать пример быстрой реализации корпоративного VPN сервера с поддержкой PPTP, L2TP (как с IPsec так и без), IPSec vpn с единой базой, который сможет работать с пулами адресов, разными группами пользователей, авторизировать пользователей как из LDAP, так и из локальной базы, опциональная настройка шейпирования как для групп, так и для отдельных пользователей с поддержкой windows, linux, osx, ios, android клиентов и все это на открытых решениях.
P.S. В данной заметке аспекты сетевой безопасности затронуты не будут, иначе она разрастется в огромный документ, с кучей нюансов в реализации, возможно о защите периметра и сетевой безопасности отдельно расскажу в следующий раз.
Кому интересно, добро пожаловать под кат.

В результате мы планируем получить примерно такую схему:
749a7c8ce75244a09db1e7f92ee7a012[1]

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

0)Подготовительные работы.
Перед тем как приступить непосредственно к настройке VPN, проведем некоторые подготовительные работы.
И так у нас есть свежеустановленный сервер с Debian 7 (не принципиально, аналогично будет работать на любом другом linux) в минимальной конфигурации. Логинимся на него по ssh или в локальной консоли, затем:
Ставим правильный часовой пояс (в примере я ставлю MSK)

mv /etc/localtime /etc/localtime_org && ln -s /usr/share/zoneinfo/"Europe/Moscow" /etc/localtime && date

Отключаем IPv6, если не планируете использовать на данном сервере

echo net.ipv6.conf.all.disable_ipv6=1 > /etc/sysctl.d/disableipv6.conf

В репы подключаем бэкпорты(чтоб не ставить древние samba и strongswan в которых есть ряд проблем), для этого добавляем в /etc/apt/sources.list следующие строки:

deb http://http.debian.net/debian wheezy-backports main contrib non-free
deb http://mirror.yandex.ru/debian/ wheezy-backports main contrib non-free

Устанавливаем минимально необходимые на данном этапе пакеты

apt-get update
apt-get install cmake make libssl-dev libpcre3-dev libnet-snmp-perl libtritonus-bin bzip2 checkinstall ntpdate

Синхронизируем время на сервере, лучше сразу с доменными часами, самый простой вариант через

ntpdate DC.DOMAIN.COM

Указываем DNS сервер домена в /etc/resolv.conf

Настройки фаирвола специфичны для компании и тут не публикую, но на основе его мы привязываем разные подсети клиентов VPN к разным запретам и разрешениям.

Тут и далее
ХХ.УУ.1.99 — внешний IP вашего сервера.

1) Accel-PPP — основной сервис для работы с L2TP и PPTP
Скачиваем и кидаем на сервер.
http://downloads.sourceforge.net/project/accel-ppp/accel-ppp-1.9.0.tar.bz2

разархивируем
tar -xjf accel-ppp-1.9.0.tar.bz2
mkdir accel-ppp-build
cd accel-ppp-build

собираем
cmake -DBUILD_PPTP_DRIVER=FALSE -DLOG_PGSQL=FALSE -DNETSNMP=FALSE -DRADIUS=TRUE -DSHAPER=TRUE /root/accel-ppp-1.9.0/
make
checkinstall -D

Создаем скрипт автозапуска из примера.
cd ../accel-ppp-1.9.0/contrib/debian
cp accel-ppp-init /etc/init.d/accel-ppp

Определяем дирректорию с демоном
which accel-pppd

Скорее всего для deb будет /usr/local/sbin/accel-pppd
В стартовом файле меняем пути на полученный выше.
nano /etc/init.d/accel-ppp

Добавляем в автозапуск
insserv -v accel-ppp

Создаем дирректорию для логов
mkdir /var/log/accel-ppp/
Создаем фаил с доступами для проверки коннектов, в дальнейшем заменим его на radius авторизацию
touch /etc/ppp/chap-secrets

Формат:
login * password ip_для выдачи(если надо брать из пула, то просто *)

Создаем конфигурационный фаил /etc/accel-ppp.conf

[modules] path=/usr/local/lib64/accel-ppp
#Данный модуль предназначен для записи журнала событий в файл.
log_file
#Данный модуль записывает события в syslog.
#log_syslog

#Рабочие протоколы
pptp
l2tp

#Методы аутентификации
auth_mschap_v2
auth_mschap_v1
auth_chap
auth_pap
#модуль поддержки файла CHAP-secrets конфликтует с radius
#chap-secrets
#модуль поддержки файла RADIUS конфликтует с chap-secrets
radius

#Назначение IPv4 адреса из статического пула.
ippool
sigchld
#Данный модуль запускает скрипты ip-up/ip-down при старте сессии и обработки RADIUS CoA запрос.
#pppd_compat
#Модуль управления пропускной способностью.
shaper
#Модуль управления частотой подключений.
#connlimit

[core] log-error=/var/log/accel-ppp/core.log
thread-count=4

[ppp] verbose=0
min-mtu=1280
mtu=1480
mru=1480
#ccp=1
check-ip=1
# Если эта опция управления отсутствует контроль количество сессий на пользователя выключен.
# Если эта опция replace — accel-ррр прекращает первую сессию, когда вторая выполяет подключение.
# Если эта опция deny accel-ррр будет сбрасывать попытки авторизации второй сессии
#single-session=replace
#Задаё политику шифрования MPPE (Microsoft Point-to-Point Encryption)
# prefer – Не разрывает соединение при отрицании шифрования клиентом
mppe=prefer
ipv4=prefer
#Если эта опция задана, и больше 0, то PPP модуль будет отправлять LCP пакеты эхо-запроса каждые n секунд.
lcp-echo-interval=300
#Определяет максимальное количество эхо-запросов без ответа, по достижению значения n сессия будет сброшена.
lcp-echo-failure=6

[dns] dns1=8.8.8.8
dns2=8.8.4.4

[auth] #any-login=0
#noauth=0

[pptp] bind=ХХ.УУ.1.99
echo-interval=300
echo-failure=6
verbose=0

[l2tp] bind=ХХ.УУ.1.99
#ppp-max-mtu=1300
dictionary=/usr/local/share/accel-ppp/l2tp/dictionary
hello-interval=300
#timeout=60
#rtimeout=5
retransmit=3
host-name=vpn.mydomain.ru
#dir300_quirk=1
#secret=
verbose=0

[radius] dictionary=/usr/local/share/accel-ppp/radius/dictionary
nas-identifier=cisco
nas-ip-address=127.0.0.1
gw-ip-address=ХХ.УУ.1.99
auth-server=127.0.0.1:1812,Radius-Sicret
acct-server=127.0.0.1:1813,Radius-Sicret
server=127.0.0.1,Radius-Sicret,auth-port=1812,acct-port=1813,req-limit=0,fail-time=0
dae-server=127.0.0.1:3799,Radius-Sicret
timeout=5
max-try=3
acct-timeout=600
acct-delay-time=1
verbose=0

[shaper] attr=Filter-Id
#down-burst-factor=1.0
#up-burst-factor=1.0
#latency=50
#mpu=0
#time-range=1,7:00-00:59
#time-range=2,1:00-3:59
#time-range=3,4:00-6:59
#leaf-qdisc=sfq perturb 10
up-limiter=htb
down-limiter=htb
cburst=1375000
ifb=ifb0
r2q=10
quantum=1500
verbose=0

# Указывает диапазон IP-адресов, с которых клиенты могут подключиться к серверу в виде: x.x.x.x/mask (for example 10.0.0.0/8)
[client-ip-range] #192.168.0.0/18
disable

[log] log-file=/var/log/accel-ppp/accel-ppp.log
log-emerg=/var/log/accel-ppp/emerg.log
log-fail-file=/var/log/accel-ppp/auth-fail.log
log-debug=/var/log/accel-ppp/debug.log
#syslog=accel-pppd,daemon
#log-tcp=127.0.0.1:3000
copy=1
color=1
#per-user-dir=per_user
#per-session-dir=per_session
#per-session=1
level=0

# Раскоментировать во время теста, пока не настроен радиус
#[chap-secrets] #gw-ip-address=ХХ.УУ.1.99
#chap-secrets=/etc/ppp/chap-secrets

[ip-pool] attr=Framed-Pool
gw-ip-address=ХХ.УУ.1.99
10.65.16.129-254,fullaccess
10.65.17.129-254,mobila
10.65.18.129-254,office

[cli] telnet=127.0.0.1:2000
tcp=127.0.0.1:2001
#password=123

#[connlimit] #limit=10/min
#burst=3
#timeout=60

Запускаем
service accel-ppp start

Если что-то не так, увеличиваем в конфиге уровень логирования и смотрим логи.

Для работы под нагрузкой необходим небольшой тюнинг, если у вас менее 500 одновременных клиентов на VPN, можно не делать, кроме пункта net.ipv4.ip_forward=1, он обязателен.

Добавляем в /etc/sysctl.conf

############################
net.ipv4.ip_forward=1
net.ipv4.neigh.default.gc_thresh1 = 1024
net.ipv4.neigh.default.gc_thresh2 = 2048
net.ipv4.neigh.default.gc_thresh3 = 4096

net.ipv4.netfilter.ip_conntrack_max=9548576
net.netfilter.nf_conntrack_max=9548576

# turn off selective ACK and timestamps
net.ipv4.tcp_sack = 0
net.ipv4.tcp_timestamps = 0

# memory allocation min/pressure/max.
# read buffer, write buffer, and buffer space
net.ipv4.tcp_rmem = 10000000 10000000 10000000
net.ipv4.tcp_wmem = 10000000 10000000 10000000
net.ipv4.tcp_mem = 10000000 10000000 10000000

net.core.rmem_max = 524287
net.core.wmem_max = 524287
net.core.rmem_default = 524287
net.core.wmem_default = 524287
net.core.optmem_max = 524287
net.core.netdev_max_backlog = 300000
net.core.netdev_tstamp_prequeue = 0
############################

Применяем:
sysctl -p

Пробуем подключиться с PPTP и L2TP без IPsec с логином и паролем, указанным в /etc/ppp/chap-secrets

На самом сервере список подключенных клиентов можно посмотреть командой
accel-cmd show session

Очень рекомендую прочитать справку по accel-cmd, имеет много возможностей, включая изменение метода авторизации пользователей на лету без обрыва сессий

Если все ОК, переходим к следующему пункту

2) IPsec
устанавливаем
apt-get -t wheezy-backports install strongswan libcharon-extra-plugins

Конфиги приводим к виду:
nano /etc/ipsec.conf

# ipsec.conf - strongSwan IPsec configuration file

config setup
# Нужно ли требовать неистекший лист отзывов для проведения аутентификации клиента
strictcrlpolicy=no
include /var/lib/strongswan/ipsec.conf.inc

conn %default
ikelifetime=1440m
keylife=60m
rekeymargin=3m
keyingtries=1
keyexchange=ikev1
authby=xauthpsk
# включает механизм Dead Peer Detection (DPD) и указывает, что нужно забывать о клиенте, если он не отзывался дольше таймаута
dpdaction=clear
# задержка до включения DPD
# dpddelay=35s
# таймаут для DPD
# dpdtimeout=300s
#включение внутренней фрагментации пакетов. Позволяет использовать IPsec с провайдерами, у которых сломана IP-фрагментация пакетов
fragmentation=yes
# выключение инициации смены ключей со стороны сервера. Windows это не любит.
rekey=no
# перечень ciphersuites для использования с IKE
ike=aes256gcm16-aes256gcm12-aes128gcm16-aes128gcm12-aesxcbc-sha256-sha1-modp4096-modp2048-modp1024,aes256-aes128-sha256-sha1-modp4096-modp2048-modp1024!
# перечень ciphersuites для шифрования трафика
esp=aes128gcm12-aes128gcm16-aes256gcm12-aes256gcm16-modp4096-modp2048-modp1024,aes128-aes256-sha1-sha256-modp4096-modp2048-modp1024,aes128-sha1-modp1024,aes128-sha1!

conn L2TP_Accel-PPP
authby=psk
rekey=no
type=transport
esp=aes128-sha1,null-sha1,md5
ike=aes128-sha-modp1024,null-sha1,md5
left=194.135.1.99
leftprotoport=17/%any # при 1701 не пашет на iOS
right=%any
rightprotoport=17/%any
rightsubnetwithin=0.0.0.0/0
auto=add
compress=no
dpddelay=30
dpdtimeout=120
dpdaction=clear
forceencaps=yes

conn IPsec
authby=secret
rekeymargin=3m
keyingtries=1
keyexchange=ikev1
leftfirewall=yes
rekey=no
left=XX.YY.1.99
leftsubnet=0.0.0.0/0
leftauth=psk
rightsourceip=%radius
rightdns=8.8.8.8
right=%any
rightauth=psk
rightauth2=xauth-radius
dpdaction=clear
dpdtimeout = 5s
auto=add

Далее указываем наш приватный ключ
nano /etc/ipsec.secrets
: PSK «Sicret-Test-Key»

Для дальнейшей интеграции с Freeradius также правим
nano /etc/strongswan.d/charon/eap-radius.conf

eap-radius {
accounting = yes
load = yes
nas_identifier = StrongSwan
#Наш секрет для Radius
secret = Radius-Sicret
server = 127.0.0.1
dae {
enable = yes
listen = 127.0.0.1
port = 3799
secret = Radius-Sicret
}
forward {
}
servers {
}
xauth {
}
}

Запускаем
service ipsec start

Статус можно посмотреть так:
ipsec statusall

3) FreeRadius
Устанавливаем стандартно
apt-get install freeradius freeradius-ldap

Правим фаил /etc/freeradius/clients.conf в нем содержатся настройки для пользователей FreeRadius, у нас такими выступают локальные демоны Accel-PPP и Strongswan, минимально достаточно следующего содержимого:
client localhost {
ipaddr = 127.0.0.1
secret = Radius-Sicret
nastype = cisco
shortname = MY_TEST_VPN
}

Теперь подготовим профиль для запуска, стандартный находится тут /etc/freeradius/sites-enabled/default
, нам необходимо привести его к виду:
*пока не настроена интеграция с LDAP необходимо закомментировать все опции связанные с ldap и ntlm_auth, в дальнейшем раскоментируем одну из них, но не обе сразу, они конфликтуют, если нам не нужны группы из LDAP проще использовать ntlm_auth, если группы нужны, тогда ldap, в примере рабочий конфиг уже с группами.
authorize {
preprocess
chap
mschap
ldap
# ntlm_auth
digest
suffix
eap {
ok = return
}
files
expiration
logintime
pap
}
authenticate {
Auth-Type PAP {
pap
}
Auth-Type CHAP {
chap
}
Auth-Type MS-CHAP {
mschap
}
Auth-Type LDAP {
ldap
}

# Auth-Type ntlm_auth {
# ntlm_auth
# }
digest
unix
eap
}
preacct {
preprocess
acct_unique
suffix
files
}
accounting {
detail
unix
radutmp
exec
attr_filter.accounting_response
}
session {
radutmp
}
post-auth {
exec
Post-Auth-Type REJECT {
attr_filter.access_reject
}
}
pre-proxy {
}
post-proxy {
eap
}

Теперь создадим фаил локальных пользователей, а также описание настроек для различных групп из LDAP
/etc/freeradius/users

#Указываем что пользователь берется из локального файла, его имя и пароль,
# можно откртым текстом либо зашифровать через
#perl -e 'print(crypt("testpassword","abrakadabra")."\n");'
#Тогда указываем сразу зашифрованно
#testuser Crypt-Password := "abA5hjwYqm1.I"

testuser Cleartext-Password := "testpassword" , MS-CHAP-Use-NTLM-Auth := 0
Service-Type = Framed-User,
Framed-Protocol = PPP,
# Можно не указывать конкретный IP, тогда он возьмется автоматически из пула, переданного в Framed-Pool
Framed-IP-Address = 10.65.18.12,
Framed-IP-Netmask = 255.255.255.255,
# Пул из которого берем адреса для клиентов, описан в секции ip-pool конфига accel-ppp
Framed-Pool = "office",
# Скорость шейпера в килобитах на пользователя.
Filter-Id = "100000/100000",
# В ответе указываем что авторизация взята из локального файла, удобно для тестов
Reply-Message = "Accepted from local file"
# Можно указать дополнительно любые другие параметры соединения
# такие как Idle-Timeout, Acct-Interim-Interval и т.п.

# Описываем привязку к различным группам LDAP, например привязываем доменную группу
# remote-connection к группе office, описанной в секции ip-pool конфига accel-ppp
DEFAULT Ldap-Group == "remote-connection"
Service-Type = Framed-User,
Framed-Protocol = PPP,
Framed-Pool = "office",
Filter-Id = "100000/100000"

# Остальные группы по аналогии
DEFAULT Ldap-Group == "full-access"
Service-Type = Framed-User,
Framed-Protocol = PPP,
Framed-Pool = "fullaccess"
# Админская группа уберем для нее шейпер
# Filter-Id = "100000/100000"

DEFAULT Ldap-Group == "mobile-access"
Service-Type = Framed-User,
Framed-Protocol = PPP,
Framed-Pool = "mobila",
Filter-Id = "100000/100000"

Перезапустим радиус
service freeradius restart

*Для отладки можно запускать в режиме вывода лога на терминал freeradius -X
Если все ОК и ошибок в запуске нет, проверим тестового пользователя:

radtest testuser testpassword 127.0.0.1 0 Radius-Sicret

мы должны получить ответ вида:

Sending Access-Request of id 238 to 127.0.0.1 port 1812
User-Name = "testuser"
User-Password = "testpassword"
NAS-IP-Address = XX.YY.1.99
NAS-Port = 0
Message-Authenticator = 0x00000000000000000000000000000000
rad_recv: Access-Accept packet from host 127.0.0.1 port 1812, id=238, length=105
Service-Type = Framed-User
Framed-Protocol = PPP
Framed-IP-Address = 10.65.18.12
Framed-IP-Netmask = 255.255.255.255
Framed-Pool = "office"
Filter-Id = "100000/100000"
Reply-Message = "Accepted from local file"

Если в ответе есть Access-Accept, то все хорошо и можно переходить к настройке интеграции Freeradius с LDAP, конфиги помещаю в этой секции заранее, нам надо подправить:
nano /etc/freeradius/modules/ntlm_auth
*вместо KR.LOC просто указываем свой домен

exec ntlm_auth {
wait = yes
program = "/usr/bin/ntlm_auth --request-nt-key --domain=KR.LOC --username=%{mschap:User-Name} --password=%{User-Password}"
}

Чуток подправим авторизацию через mschap, т.к. pap использовать не безопасно.
nano /etc/freeradius/modules/mschap
mschap {
#Используем шифрование
use_mppe = yes
# Но разрешаем подключаться и без шифрования, для некоторых клиентов это важно, если таких нет - заменить на yes
require_encryption = no
require_strong = yes
with_ntdomain_hack = no
ntlm_auth = "/usr/bin/ntlm_auth --request-nt-key --username=%{%{Stripped-User-Name}:-%{%{User-Name}:-None}} --challenge=%{%{mschap:Challenge}:-00} --nt-response=%{%{mschap:NT-Response}:-00}"
}

ну и самое важное, непосредственно интеграция с LDAP
nano /etc/freeradius/modules/ldap

*не забываем параметры доступа к ldap сменить на свои, пользовательская учетка должна иметь права на чтение профилей в домене.
ldap {
server = "10.13.205.7" #свой контроллер
identity = "sf-test@KR.LOC" #своя учетка
password = "987654321" # свой пароль
basedn = "dc=KR,dc=LOC" # свой домен
filter = "(sAMAccountName=%{%{Stripped-User-Name}:-%{User-Name}})"
ldap_connections_number = 5
max_uses = 0
#port = 389
timeout = 4
timelimit = 3
net_timeout = 1

tls {
start_tls = no
}
dictionary_mapping = ${confdir}/ldap.attrmap
password_attribute = userPassword
edir_account_policy_check = no

groupname_attribute = cn
groupmembership_filter = "(|(&(objectClass=GroupOfNames)(member=%{control:Ldap-UserDn}))(&(objectClass=GroupOfUniqueNames)(uniquemember=%{control:Ldap-UserDn})))"
groupmembership_attribute = memberOf

access_attr_used_for_allow = yes

chase_referrals = yes
rebind = yes
# set_auth_type = yes

keepalive {
idle = 60
probes = 3
interval = 3
}
}

Еще один важный момент, для того чтоб получать radius атрибуты для конкретного пользователя прямо из ldap атрибутов домена необходимо настроить соответствие их между собой, это делается в файле /etc/freeradius/ldap.attrmap там многое уже заполнено и интуитивно понятно, но для примера покажу несколько своих:

replyItem Framed-IP-Address msRADIUSFramedIPAddress
replyItem Framed-Pool msRADIUSFramedRoute

Таким образом указав в домене у пользователя персональный атрибут msRADIUSFramedIPAddress мы передадим радиусу считать его атрибутом Framed-IP-Address и выдать пользователю конкретно его по VPN, для пулов по аналогии.
Со стороны домена это выглядит так:

761c5ded6a1640d386c9be0673cfa5c7[1]

IP необходимо преобразовать в HEX на любом IP калькуляторе, можно конечно создать и любые свои атрибуты для ldap, через редактор атрибутов, но для ускоренного описания будем использовать стандартные.

*данные опции станут доступны после настройки samba4, необходимо не забыть раскомментировать секцию ldap в /etc/freeradius/sites-enabled/default

4) SAMBA 4
Для начала установим все необходимое:
apt-get install krb5-user libpam-krb5 samba winbind libnss-winbind libpam-winbind -t wheezy-backports

Настройки samba находятся в файле /etc/samba/smb.conf
*не забываем менять имя домена на свое.
[global] obey pam restrictions = Yes
log file = /var/log/samba/log.%m
log level = 1
socket options = TCP_NODELAY SO_SNDBUF=8192 SO_RCVBUF=8192

encrypt passwords = yes

idmap config * : range = 10000-20000
idmap config * : backend = tdb

auth methods = winbind
name resolve order = hosts bcast lmhosts

case sensitive = no
dns proxy = no
netbios name = SAMBA
server string = %v samba
password server = DC02.KR.LOC

# обязательно указывать имя домена в верхнем регистре
realm = KR.LOC
client use spnego = yes
client signing = yes
local master = no
domain master = no
preferred master = no
workgroup = KR
debug level = 2

# ads указывает что авторизация проходит на уровне домена
security = ads
unix charset = UTF-8
dos charset = 866
max log size = 50
os level = 0
follow symlinks = yes

winbind uid = 10000-20000
winbind gid = 10000-20000
winbind enum groups = yes
winbind enum users = yes

Теперь настроим winbind (позволяет Самбе узнавать пользователей AD и общаться с ними как с локальными).
Нам необходимо отредактировать фаил /etc/nsswitch.conf , добавляем в него:
passwd: compat winbind
group: compat winbind
shadow: compat winbind

Осталось настроить Kerberos (используется для интеграции Samba в Active Directory)
Приводим фаил /etc/krb5.conf к виду
*Домен меняем на свой.
[logging] default = FILE:/var/log/krb5.log
kdc = FILE:/var/log/krb5kdc.log

[libdefaults] default_realm = KR.LOC

clockskew = 500
dns_lookup_realm = false
dns_lookup_kdc = true
ticket_lifetime = 324000

[realms] KR.LOC = {
kdc = DC02.KR.LOC
admin_server = DC02.KR.LOC
default_domain = KR.LOC
}

[domain_realm] .kr.loc = KR.LOC

[login] krb4_convert = true
krb4_get_tickets = false

Конфиги поправлены, можно перезапустить сервисы:
service samba restart
service winbind restart

Проверяем для своего доменного пользователя:
kinit sf-test@KR.LOC

Получаем запрос на ввод пароля, вводим.
Password for sf-test@KR.LOC:

Если все ОК, вывода на экран не будет, если все-же что-то выводит, внимательно читаем и правим ошибки в конфиге.
Считаем что у вас все хорошо и вводим сервер в домен
net join –U sf-test@KR.LOC

Проверим работу winbind:
wbinfo -u
wbinfo -g

В выводе должны видеть список доменных пользователей и групп.

Что бы проверить воспринимаются ли доменные пользователи как локальные, можно воспользоваться командой:
id domain_user

Проверяем работу модуля аутентификации (логин/пароль/домен — естественно свои)
ntlm_auth --request-nt-key --domain=KR.LOC --username=sf-test --password=123456789

Получили OK, значит можно раскомментировать в конфиге радиуса модуль ldap или ntlm_auth (если не нужны доменные группы), перезапускать freeradius и наслаждаться работой VPN сервера с учетками домена, но для успокоения совести проверим что радиус авторизирует доменных пользователей:
radtest -t mschap sf-test 123456789 127.0.0.1 0 Radius-Sicret

Теперь можно создавать VPN подключение у себя и проверять всю связку.

5) Бонус
Пролистывая заметку еще раз посмотрел на схему сети и вспомнил, что у нас есть соединения site-to-site для IPsec — это так-же удобно если пользователям ВПН необходимо давать доступ в другие сети, все это реализовано фаирволом, но пример настройки strongswan для такого соединения привожу ниже.

В /etc/ipsec.conf добавляем в конец секцию:
conn juniper
forceencaps=yes
dpddelay=30 # Dead peer detection - 30 секунд - интервал между keep-alive пакетами
dpdtimeout=120 # dpd таймаут 120 секунд, после которого хост будет объявлен недоступным
# IKE alg 3DES - HASH sha1 - DH group 2 (1024)
ike=3des-sha1-modp1024
# IKE lifetime 86400 seconds (24 hours)
ikelifetime=86400s
# IKE auth method Pre-Shared Key (PSK secret)
authby=secret
# IPSec type tunnel
type=tunnel # режим - туннель
#left side (myside)
left=ХХ.УУ.1.99 # OpenSWAN side
leftsubnet=10.65.0.0/16 #наши локальные сети, которые мы экспортируем удаленному маршрутизатору
right=ХХ.УУ.116.5 #Удаленный маршрутизатор
rightsubnet=192.168.105.0/24 #Сети с удаленного маршрутизатора, которые доступны пользователям нашего VPN
auto=start
esp=3des-sha1,3des-md5
keyexchange=ikev1

Заключение.

Надеюсь все получилось с первого раза и сразу заработало, если это не так — задавайте вопросы в комментариях. Автор паталогически безграмотен, если увидели ошибку, опечатку, не однозначность или любой другой момент, мешающий восприятию заметки — просьба сообщать в личку. Всем спасибо за потраченное время.

Приёмы объектно-ориентированного проектирования. Паттерны проектирования

Design Patterns: Elements of Reusable Object-Oriented Software (Приёмы объектно-ориентированного проектирования. Паттерны проектирования) — книга 1994 года об инженерии программного обеспечения, описывающая решения некоторых частых проблем в проектировании ПО. Авторы книги: Эрих Гамма (Erich Gamma),Ричард Хелм (англ.) (Richard Helm), Ральф Джонсон (англ.) (Ralph Johnson), Джон Влиссидс (англ.) (John Vlissides). Коллектив авторов также известен как «Банда четырёх», Gang of Four[1], GoF. Автор предисловия Гради Буч (Grady Booch). Книга состоит из двух частей, в первых двух главах рассказывается о возможностях и недостатках объектно-ориентированного программирования, а во второй части описаны 23 классических шаблона проектирования. Примеры в книге написаны на языках программирования C++ и Smalltalk.

Читать далее

Понимая Docker

Что такое докер?

Докер — это открытая платформа для разработки, доставки и эксплуатации приложений. Docker разработан для более быстрого выкладывания ваших приложений. С помощью docker вы можете отделить ваше приложение от вашей инфраструктуры и обращаться с инфраструктурой как управляемым приложением. Docker помогает выкладывать ваш код быстрее, быстрее тестировать, быстрее выкладывать приложения и уменьшить время между написанием кода и запуска кода. Docker делает это с помощью легковесной платформы контейнерной виртуализации, используя процессы и утилиты, которые помогают управлять и выкладывать ваши приложения.

Читать далее

Правила хорошего тона при работе с git в многопользовательском окружении

Данное повествование подразумевает знакомство читателей с такими командами git как: add, pull, push, commit.

В случае многопользовательской работы с репозиторием зачастую получается такая ситуация: сделали мы git pull, правим код, коммитим, хотим пропихнуть код в общий репозиторий, а тут-то нам и говорят: фигу вам, а не push — там уже всё поменялось. В итоге приходится делать git pull, получается вынужденный автоматический merge и с этим уродливым merge (который был по сути и необязателен!) мы запихиваем наши изменения обратно в общий репозиторий. История изменений получается не самая красивая.

Читать далее

Бесплатный Wi-Fi, с небольшой изюминкой

Данная статья повествует о небольшом проекте бесплатной Wi-Fi сети, об основных технических проблемах и решениях. Цель – просто рассказать о достаточно оригинальном проекте.

Чуть меньше года назад, моё руководство решило на территории организации развернуть сеть бесплатного Wi-Fi для посетителей. Все было бы просто и прозаично, если бы не одно интересное условие: прежде чем пользователь попадет в Интернет, он должен посмотреть информационную страницу, с нашей «рекламой».

Читать далее

Тестирование программ Perl для начинающих. Test:: Simple

Test::Simple — это базовый, очень простой модуль, который используется для написания тестов.

Модуль дает возможность использовать для тестирования всего одну функцию — ok(). Если возможностей данной функции недостаточно, рекомендуется использовать Test::More. Тесты, написанные с помощью Test::Simple полностью совместимы с Test::More.
Читать далее

Test::More для начинающих

Руководство Test::More

Руководство написано с использованием публикации Test::More. By Michael G Schwern. Copyright 2001-2002, 2004-2006 и является ее частичным переводом. Все примеры созданы автором специально для данного руководства.

Модуль Test::More поставляется со стандартным дистрибутивом Perl начиная с версии 5.8. Модуль для более ранней версии можно взять в CPAN. Модуль работает со всеми версиями Perl, начиная с версии 5.6.

Test::More — это полноценный фреймворк (framework) для написания тестовых скриптов. Имеет множество специализированных функций.

Читать далее

Unbound — настройка кеширующего DNS-сервера

Unbound логотип

В релизе FreeBSD 10.0 DNS-сервер BIND заменен на связку из кеширующего DNS-сервера Unbound и библиотеки LDNS. Разбираясь с нововведениями, решил заодно ознакомиться и с настройкой Unbound.

Читать далее