
Начальные параметры:
- Головной офис предприятия с двумя пограничными прокси Kerio Control v.9.2.9 build 3171 (за Kerio расположен свич Cisco 3550, определяющий конфигурацию локальной сети офиса).
- На каждом Kerio организовано по два канала с балансировкой нагрузки до ISP (на схеме — ISP #1 и ISP #2) со статичными белыми IP.
- Со стороны удалённого офиса установлен MikroTik 951G-2HnD (OS v.6.43.11).
- На MikroTik приходят два ISP (на схеме — ISP #3 и ISP #4).
На момент написания статьи и в головном и в удалённом офисе соединение с провайдерами было по витой паре.
Список задач:
- Организовать IPSec VPN-соединение между MikroTik и Kerio Control, где инициатором будет выступать MikroTik.
- Обеспечить отказоустойчивость VPN-соединения, т.е. кроме того, что MikroTik должен отслеживать работоспособность своих ISP(статья здесь), он также должен мониторить доступность каждого сервера Kerio и определять, доступ по какому каналу (через какого ISP со стороны Kerio) будет производиться подключение.
- Обеспечить возможность изменения адреса сети, с которым MikroTik подключается к Kerio. Это обусловлено тем, что в головном офисе «на границе» стоят Kerio, а не маршрутизатор.
Что получим на выходе?
- При запуске MikroTik (scheduleStartup) будет организован канал к сети предприятия (инициатором организации канала выступит MikroTik), позволяющий удалённому пользователю работать с корпоративными ресурсами без запуска Kerio Client и без настройки дополнительного VPN-подключения средствами операционной системы;
- В MikroTik будет реализован Failover, позволяющий автоматически переключаться на «живой» ISP;
- Вы сможете настроить приоритеты для точек подключения к сети предприятия, изменяя в MikroTik принадлежность peers, настроенных на подключение к Kerio Control, к той или иной Policy Template Group;
- MikroTik сможет в автоматическом режиме отслеживать работоспособность Kerio Control серверов, и, в случае, если связь с приоритетной точкой разорвана, самостоятельно переключиться на «живой» канал;
- Если ваши Kerio Control серверы опубликованы на внешних DNS-серверах, MikroTik сможет отслеживать изменения их IP-адресов (напр. в случае, если у вас поменяется провайдер) и самостоятельно вносить изменения в свою конфигурацию (scriptSetIPSecSADstAddrFromDNS).
Сразу оговорюсь, что эта статья не является учебным пособием (с маршрутизаторами в принципе, и с MikroTik в частности я познакомился всего за два месяца (конец 2017 года) до начала создания конфигурации) и в ней не рассматриваются вопросы «почему?», здесь будет приведено описание рабочей конфигурации MikroTik, которая используется на реальном предприятии.
Примечание:
- Чтобы при переносе кода скриптов в MikroTik сохранились русскоязычные комментарии, перед тем как скопировать текст в буфер и перед вставкой из буфера проверьте, чтобы была включена русская раскладка клавиатуры;
- Если вы посчитаете, что логирование работы скриптов — это лишнее, вы можете закомментировать или удалить строки с «log warning» и «log error»;
- Также вы можете заметить в коде закомментированные «log warning» и «log error», это попытка добавить возможность использовать логирование на английском языке...
Итак, приступим:
Базовые параметры:
- Сеть головной организации (за Kerio) — 192.168.77.0/24 (здесь используем адрес сети, в которой находится Kerio в сети предприятия)
- Сеть филиала (за MikroTik) — 192.168.11.0/24
- Сеть, в которую будет мапиться сеть филиала при подключении к Kerio Control #1 — 192.168.22.0/24
- Сеть, в которую будет мапиться сеть филиала при подключении к Kerio Control #2 — 192.168.33.0/24
- IP-адрес из пула ISP #1 (Kerio #1) — 11.11.11.111
- IP-адрес из пула ISP #2 (Kerio #1) — 22.22.22.111
- IP-адрес из пула ISP #1 (Kerio #2) — 11.11.11.222
- IP-адрес из пула ISP #2 (Kerio #2) — 22.22.22.222
- IP-адрес из пула ISP #3 (MikroTik) — 33.33.33.111
- IP-адрес из пула ISP #4 (MikroTik) — 44.44.44.111
Первое, что необходимо сделать, это включить на MikroTik использование DDNS:
/ip cloud set ddns-enabled=yes
В связи с тем, что на MikroTik не будет статического белого IP-адреса, дальнейшая работа конфигурации и скриптов построена на использовании DDNS.
Также IP ---> Cloud используется для определения внешнего IP-адреса MikroTik, с которого он смотрит в интернет.
Теперь произведём настройку Kerio Control #1, чтобы потом к нему уже не возвращаться:
Заходим в раздел «Интерфейсы» и добавляем новый интерфейс «VPN-туннель»…
Настройка туннеля в Kerio Control
1. В поле имя присваиваем имя интерфейсу;
2. Ставим переключатель в положение «Пассивное — только принимает входящие подключения»;
3. Тип оставляем «IPSec»;
4. Закладка «Аутентификация»:
5. Закладка «Удалённые сети»:
Здесь мы вводим IP-адрес локальной сети, который будет использовать MikroTik при подключении к этому конкретному серверу Kerio Control (в примере — 192.168.22.0/24).
Важно! Во всех остальных (в моём случае определяется количеством ISP со стороны Kerio) туннелях на MikroTik, на этом сервере Kerio, должен быть указан этот же IP-адрес!
Напомню, что это связано с необходимостью настройки маршрута на эту сеть из сети головного офиса.
6. Закладка «Локальные сети»:
Повторяем все вышеуказанные действия для второго туннеля на этом же сервере Kerio.
Отличаться настройка второго туннеля будет только использованием другой ключевой фразы (п.4.1) и другого внешнего IP-адреса, из пула адресов ISP #2 (п.4.2) (в примере — 22.22.22.111).
Настройки Kerio Control #2 идентичны вышеописанным, за исключением адреса сети, указываемого на закладке «Удалённые сети» (п.5) (в примере — 192.168.33.0/24) и, соответственно, IP-адресов в поле «Локальный ИД:» (п.4.2), которые должны быть выбраны из IP-адресов присвоенных WAN-интерфейсам Kerio Control #2 (в примере — 11.11.11.222 и 22.22.22.222).
2. Ставим переключатель в положение «Пассивное — только принимает входящие подключения»;
3. Тип оставляем «IPSec»;
4. Закладка «Аутентификация»:
- 4.1 В поле «Предопределённый ключ:» вводим ключевую фразу, которая будет использована для соединения;
- Примечание:
Категорически рекомендую на все VPN-туннели, создаваемые на одном конкретном сервере Kerio, задавать разные ключевые фразы!
Обусловлено это тем, что замечено, что у Kerio присутствует плавающий баг, который выражается в следующем.
Представим, что в конфигурации Kerio, как в моём случае, присутствует несколько интерфейсов «VPN-туннель», настроенных на соединение с MikroTik, которые отличаются друг от друга только настройками в поле «Локальный ИД:» (будут рассмотрены ниже).
Так вот, при создании (назову его так) входящего туннеля, вне зависимости от того, на какой внешний IP-адрес Kerio будет обращаться MikroTik, Kerio (почему-то) активирует первый попавшийся интерфейс, и, если IP-адрес, указанный в настройках туннеля со стороны Kerio, отличается от того, на который обращается MikroTik, туннель не организуется.
А в случае, когда для всех туннелей указаны разные ключевые фразы, это проблема купируется. - 4.2 В поле «Локальный ИД:» вводим IP-адрес из пула адресов ISP #1 (в примере — 11.11.11.111), присвоенных WAN-интерфейсу Kerio Control #1, на который будет обращаться MikroTik;
- 4.3 В поле «Отдалённый ИД:» вводим FQDN, который был получен нашим MikroTik из DDNS (IP ---> Cloud ---> DNS Name). Эта настройка позволяет нам не заботиться о том, через какого ISP MikroTik обращается к Kerio;
- 4.4 В поле «Шифр фазы 1 (IKE):» выбираем из списка aes128-sha1-modp2048;
- 4.5 В поле «Шифр фазы 2 (ESP):» выбираем из списка 3des-sha1-modp2048;
- Примечание:
Редактирование используемых настроек по умолчанию через кнопку «Изменить...»;
Оба шифра подобраны «методом научного тыка».
5. Закладка «Удалённые сети»:
Здесь мы вводим IP-адрес локальной сети, который будет использовать MikroTik при подключении к этому конкретному серверу Kerio Control (в примере — 192.168.22.0/24).
Важно! Во всех остальных (в моём случае определяется количеством ISP со стороны Kerio) туннелях на MikroTik, на этом сервере Kerio, должен быть указан этот же IP-адрес!
Напомню, что это связано с необходимостью настройки маршрута на эту сеть из сети головного офиса.
6. Закладка «Локальные сети»:
- 6.1 Снимаем флажок «Использовать автоматически определённые локальные сети»;
- 6.2 Устанавливаем флажок «Использовать пользовательские сети:», а в список сетей добавляем адрес сети «накрывающий» весь диапазон адресов, используемых в локальной сети за Kerio Control (в примере — 192.168.0.0/16).
Повторяем все вышеуказанные действия для второго туннеля на этом же сервере Kerio.
Отличаться настройка второго туннеля будет только использованием другой ключевой фразы (п.4.1) и другого внешнего IP-адреса, из пула адресов ISP #2 (п.4.2) (в примере — 22.22.22.111).
Настройки Kerio Control #2 идентичны вышеописанным, за исключением адреса сети, указываемого на закладке «Удалённые сети» (п.5) (в примере — 192.168.33.0/24) и, соответственно, IP-адресов в поле «Локальный ИД:» (п.4.2), которые должны быть выбраны из IP-адресов присвоенных WAN-интерфейсам Kerio Control #2 (в примере — 11.11.11.222 и 22.22.22.222).
Далее создаём разрешающее правило на пингование наших Kerio со стороны MikroTik…
Правило пинга в Kerio Control
Заходим в раздел «Правила трафика» и создаём новое правило со следующими параметрами:
Сохраняем правило с понятным для вас именем и «перетаскиваем» его в самый верх списка правил.
Эту же процедуру повторяем на втором Kerio-сервере.
- источник — указываем FQDN, который был получен нашим MikroTik из DDNS;
- назначение — Брандмауэр;
- служба — Ping;
- также можно указать версию IP (IPv4), но это не обязательно.
Сохраняем правило с понятным для вас именем и «перетаскиваем» его в самый верх списка правил.
Эту же процедуру повторяем на втором Kerio-сервере.
Не забываем прописать маршруты на сети за MikroTik в свичи или маршрутизаторы на стороне головного офиса, чтобы сеть головного офиса знала куда направлять трафик (в моём случае это два статических маршрута на сети 192.168.22.0/24 и 192.168.33.0/24).
Со стороны головного офиса мы всё сделали, теперь переходим к MikroTik.
Начнём с того, что создадим базовые объекты конфигурации для организации и проверки VPN-туннеля.
Первым делом создадим список адресов «Local subnet». Его мы будем использовать в правилах Firewall.
/ip firewall address-list # адрес основной локальной сети за MikroTik, # IP-адреса из которой он раздаёт через DHCP add address=192.168.11.0/24 list="Local subnet" # адрес сети, в которую будет мапиться основная локальная сеть MikroTik # при организации VPN-туннеля с Kerio Control #1 # (мы её определили когда настраивали VPN-интерфейсы на Kerio Control #1, # на закладке "Удалённые сети") add address=192.168.22.0/24 list="Local subnet" # адрес сети, в которую будет мапиться основная локальная сеть MikroTik # при организации VPN-туннеля с Kerio Control #2 # (мы её определили когда настраивали VPN-интерфейсы на Kerio Control #2, # на закладке "Удалённые сети") add address=192.168.33.0/24 list="Local subnet"
Далее создадим разрешающее правило для IKE-трафика и поместим его в самый верх списка правил.
add action=accept chain=input comment="VPN Allow IKE" dst-port=500 protocol=udp
Затем добавим два правила в Firewall Filter для работы с VPN-трафиком…
/ip firewall filter add action=accept chain=forward comment="VPN In IpSec" dst-address-list=\ "Local subnet" ipsec-policy=in,ipsec src-address=192.168.0.0/16 \ src-address-list="!Local subnet" add action=accept chain=forward comment="VPN Out" dst-address=192.168.0.0/16 \ dst-address-list="!Local subnet" src-address-list="Local subnet"
… и переместим их в позицию сразу над drop-правилом, запрещающим входящий трафик не из LAN. В моей дефолтной конфигурации оно было с комментарием «defconf: drop all not coming from LAN»
Идём в Firewall Mangle и создаём следующие правила:
/ip firewall mangle # перехватываем входящий трафик из головного офиса, # маркируем соединение... add action=mark-connection chain=prerouting comment="VPN In" \ new-connection-mark=VPN_conn_in passthrough=no src-address=192.168.0.0/16 \ src-address-list="!Local subnet" # ...и обратный маршрут add action=mark-routing chain=output comment="VPN In" connection-mark=\ VPN_conn_in new-routing-mark=VPN_route_in passthrough=yes # перехватываем исходящий трафик с MikroTik в головной офис и маркируем соединение. # Этот маркер используется в NAT. add action=mark-connection chain=postrouting comment="VPN Out" dst-address=\ 192.168.0.0/16 dst-address-list="!Local subnet" new-connection-mark=\ VPN_conn_out passthrough=no
Далее отметимся в Firewall NAT:
/ip firewall nat # мапим весь исходящий с MikroTik в головной офис трафик # по маркеру соединения на адрес сети, # определённый для используемого Kerio-сервера (напоминаю: для Kerio Control #1 - 192.168.22.0/24, для Kerio Control #2 - 192.168.33.0/24) # Внимание! # comment=KerioVpnNatOut используется в скриптах! add action=netmap chain=srcnat comment=KerioVpnNatOut connection-mark=\ VPN_conn_out to-addresses=192.168.22.0/24 # мапим весь входящий на MikroTik из головного офиса трафик # по маркеру соединения на адрес основной локальной сети за MikroTik add action=netmap chain=dstnat comment=KerioVpnNatIn connection-mark=\ VPN_conn_in to-addresses=192.168.11.0/24 # разрешаем MikroTik пинговать Kerio-сервера add action=accept chain=srcnat comment=KerioVpnNatPing out-interface-list=WAN protocol=icmp
Важно! Эти правила должны размещаться выше правила маскарадинга.
Теперь переходим в раздел IP ---> IPSec, где нам потребуется создать политику, peer, policy template groups (об их назначении я расскажу позже) и proposal для настройки шифра фазы 2.
ip ipsec proposal
/ip ipsec proposal add enc-algorithms=3des name=KerioVPNProposal#01 pfs-group=modp2048
ip ipsec policy group
/ip ipsec policy group add name=1 add name=2 add name=3 add name=4
ip ipsec peer
/ip ipsec peer add address=11.11.11.111/32 comment=vs01-i01-01.domain.ru exchange-mode=\ main-l2tp local-address=33.33.33.111 my-id=\ fqdn:mikrotik.sn.mynetname.net policy-template-group=1 profile=\ profile_4 secret=pass1111
ip ipsec policy
/ip ipsec policy add comment=KerioVPNPolicy dst-address=192.168.77.0/24 proposal=KerioVPNProposal#01 \ sa-dst-address=11.11.11.111 sa-src-address=33.33.33.111 src-address=\ 192.168.22.0/24 tunnel=yes
Комментарий:
1. /ip ipsec proposal — вводим те же параметры шифрования, которые были нами указаны при настройке Kerio Control, в поле «Шифр фазы 2 (ESP):».
Примечание:
Обратите внимание на параметр «name=KerioVPNProposal#01».
Использовать конкретно это имя не обязательно, но в случае, если вы решите использовать другое, то после его изменения вам необходимо проверить и, при необходимости, изменить настройку связанной IPSec-политики, а также изменить присваиваемое значение переменной DefKerioPropName в скрипте scriptCheckActiveVpnServer, о котором пойдёт речь далее.
(Собственно, большинство имен и комментариев объектов, в описываемой конфигурации, используются в скриптах, поэтому их переименование может доставить вам некоторые неудобства в связи с необходимостью внесения изменений в код скриптов. Я постараюсь далее по тексту делать соответствующие пометки для облегчения поиска таких объектов.)
2. /ip ipsec policy group
Создание групп обусловлено тем, что в дальнейшем мы будем обрабатывать их имена (1, 2, ...n) в скриптах и использовать для определения приоритетности IP-адресов серверов Kerio, к которым мы будем обращаться.
Я создаю сразу четыре группы т.к. у меня два ISP, с двумя внешними IP на каждом со стороны Kerio. На данном этапе мы пока используем только одну группу.
3. /ip ipsec peer
В peer указываем:
- Address — IP-адрес Kerio, на который будет производиться обращение с MikroTik. Должен быть указан тот же адрес, который мы ввели в /ip ipsec policy sa-dst-address, только с маской "/32";
- Local Address — IP-адрес MikroTik, с которого будет производиться обращение к Kerio. Должен быть указан тот же адрес, который мы ввели в /ip ipsec policy sa-src-address;
- Auth. Method — выбираем из списка «pre shared key»;
- Exchange Mode — выбираем из списка main-l2tp;
- Если установлен, снимаем флажок «Passive»;
- Secret — вводим парольную фразу, которую мы вводили, когда настраивали VPN-интерфейс на Kerio, на закладке «Аутентификация», в поле «Предопределённый ключ:»;
- Policy Template Group — выбираем из списка созданную ранее нами группу с именем «1»;
- Снимаем флажок NAT Traversal;
- My ID Type — выбираем из списка значение «fqdn»;
- My ID — вводим FQDN, присвоенное MikroTik в DDNS;
- На закладке «Encryption» выбираем параметры шифрования, которые мы вводили, когда настраивали VPN-интерфейс на Kerio, на закладке «Аутентификация», в поле «Шифр фазы 1 (IKE):»;
- Comment (Внимание! Используется в скриптах!).
В комментарии я указываю полный технический FQDN своих серверов, которые опубликованы на DNS-серверах, обслуживающих мою внешнюю зону.
Кроме применения в этой конфигурации, это позволяет мне поддерживать в актуальном состоянии информацию об используемых внешних IP-адресах Kerio-серверов (мне достаточно изменить IP-адрес на внешнем DNS-сервере и он будет автоматически изменён на MikroTik (статья здесь)).
Для тех, кому лень разбираться привожу рабочий код:
/system script add dont-require-permissions=no name=scriptSetIPSecSADstAddrFromDNS owner=\ admin policy=read,write
Листинг скрипта scriptSetIPSecSADstAddrFromDNS
:if ([:len [/system script job find script=SetIPSecSADstAddrFromDNS]]>1) do={ :error } :local DnsNameFromComment :local ResolvedIpFromComment :local ResolvedIpWithMaskFromComment :local IpPeerAddr :foreach IpSecPeerCount in=[/ip ipsec peer find] do={ :set DnsNameFromComment [/ip ipsec peer get $IpSecPeerCount comment] :if ($DnsNameFromComment!="") do={ :do { :set ResolvedIpFromComment [:resolve $DnsNameFromComment] :set ResolvedIpWithMaskFromComment ($ResolvedIpFromComment . "/32") :set IpPeerAddr [/ip ipsec peer get $IpSecPeerCount address] :if ($ResolvedIpWithMaskFromComment!=$IpPeerAddr) do={ :log warning ("[SetIPSecSADstAddrFromDNS] В пире на сервер " . DnsNameFromComment . " изменён IP-адрес с " . $IpPeerAddr . " на " . $ResolvedIpFromComment) #:log warning ("[SetIPSecSADstAddrFromDNS] In the peer to the server " . DnsNameFromComment . " changed IP address from " . $IpPeerAddr . " on " . $ResolvedIpFromComment) /ip ipsec peer set $IpSecPeerCount address=$ResolvedIpWithMaskFromComment } } on-error={ :set ResolvedIpFromComment "unknown" :log error ("[SetIPSecSADstAddrFromDNS] Не удалось разрешить имя " . $DnsNameFromComment) #:log error ("[SetIPSecSADstAddrFromDNS] Cant resolve name " . $DnsNameFromComment) } } } :log warning ("[SetIPSecSADstAddrFromDNS] Проверка IP-адресов VPN-серверов произведена") #:log warning ("[SetIPSecSADstAddrFromDNS] The IP-addresses of the VPN-servers are checked")
Основное правило, применяемое к комментарию в peers — имя должно начинаться с любых букв и/или цифр, без пробелов, за которыми ОБЯЗАТЕЛЬНО следует дефис ("-"), после которого может располагаться любое количество произвольных символов.
Я использую следующий формат:
vsNN-pNN-NN.domain.ru
Где:
vsNN — vpn-server #NN (Эта часть комментария обрабатывается в скриптах и используется в IP ---> Firewall ---> Address Lists (см. далее));
pNN — ISP #NN;
NN — порядковый номер внешнего IP-адреса в пуле адресов, выданных мне провайдером на Kerio;
4. /ip ipsec policy
В политике определяем:
- Dst. Address — адрес сети за Kerio (dst-address);
- Src. Address — адрес сети, в который MikroTik будет маскировать (см. далее настройку IP ---> Firewall ---> NAT) свою локальную сеть (src-address). Этот адрес сети будет виден со стороны Kerio (его мы указывали, когда настраивали VPN-интерфейс на Kerio, на закладке «Удалённые сети»);
- Protocol — 255 (all);
- Action — encrypt;
- Level — require;
- IPSec Protocols — esp;
- устанавливаем параметр tunnel=yes;
- SA Src. Address — Внешний IP-адрес MikroTik, с которого будет производиться обращение к Kerio (sa-src-address);
- SA Dst. Address — IP-адрес Kerio, на который будет производиться обращение с MikroTik (sa-dst-address);
- Proposal — Вводим значение, присвоенное параметру name в разделе /ip ipsec proposal (в данной конфигурации — KerioVPNProposal#01);
- Comment (Внимание! Используется в скриптах!) — KerioVPNPolicy.
Если всё сделано правильно, то после сохранения политики, в поле «PH2 State» должно появиться значение «established», что говорит об установке VPN-канала между MikroTik и Kerio.
Убедиться в этом можно проверив состояние VPN-интерфейса в Kerio Control. Там в поле «Сведения», напротив того интерфейса, к которому произведено подключение, должна появиться надпись «Соединение с IP_адрес_вашего_MikroTik установлено».
Продолжаем…
Теперь создадим пиры на все оставшиеся у нас IP-адреса Kerio-серверов (в моей конфигурации необходимо создать ещё три пира).
Для этого нам необходимо повторить все действия указанные в п.3 (/ip ipsec peer), но обратить внимание на следующие изменения:
- Address — изменяем IP-адрес Kerio;
- Secret — вводим парольную фразу относящуюся к создаваемому соединению (pass2222, pass3333, ...passNNNN);
- Policy Template Group — выбираем из списка следующую по порядку группу (2, 3, ...n).
Примечание:
Потом вы можете в любой момент изменить приоритетность своих серверов, изменив группу в настройках пира.
- Comment — в моём случае изменяется на другой FQDN Kerio-сервера.
Все остальные параметры вводим такие же, как и в первом пире. Те, которые необходимо будет изменять, обрабатываются скриптами и вы можете пока их копировать без изменений.
Завершающий штрих конфигурирования перед подключением в работу скриптов — заставим MikroTik работать хранилищем констант, которые мы будем использовать в скриптах…
Добавим два списка в Firewall Address Lists (Внимание! Используется в скриптах!):
/ip firewall address-list add address=192.168.22.0/24 list=vs01 add address=192.168.33.0/24 list=vs02
в них указываем адреса сетей с привязкой к префиксам имен Kerio-серверов, в которые мы будем мапить исходящий VPN-трафик.
Ну и для того, чтобы автоматизировать работу всего этого безобразия добавим два скрипта и три расписания (если решите переименовать скрипты, не забудьте внести соответствующие изменения в код).
/system script add dont-require-permissions=no name=scriptFunctionsList owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon
Листинг скрипта scriptFunctionsList
# Процедура синхронизации IP --> Cloud с внешними DNS-серверами # входящий параметр: # # $start (true/false); # # возвращает "" или "updated" :global subUpdateCloudDns do={ put ($start); :if ($start=false) do={ set $CloudDnsStatus; # Определяем переменную для счётчика set $m 1; log warning ("[subUpdateCloudDns] ---> DDNS статус ---> ЗАПУЩЕНА ПРОВЕРКА"); #log warning ("[subUpdateCloudDns] ---> DDNS status ---> CHECK STARTED"); do { log warning ("[subUpdateCloudDns] ---> DDNS проверка, попытка ---> " . $m); [/ip cloud force-update]; delay 30000ms; set $CloudDnsStatus ([/ip cloud get status]); set $m ($m+1); :if ($CloudDnsStatus="updated") do={ log warning ("[subUpdateCloudDns] ---> DDNS статус ---> " . $CloudDnsStatus); #log warning ("[subUpdateCloudDns] ---> DDNS status ---> " . $CloudDnsStatus); } else={ log error ("[subUpdateCloudDns] ---> DDNS статус ---> " . $CloudDnsStatus); #log error ("[subUpdateCloudDns] ---> DDNS status ---> " . $CloudDnsStatus); } } while=(($CloudDnsStatus!="updated") and ($m<10)); return ($CloudDnsStatus); } } # Процедура проверки состояния IP --> Cloud # возвращает код состояния: # # 0 - деактивировано; # 1 - активно, но не обновлено; # 2 - активно и обновлено :global subCheckCloudDDNS do={ set $CloudDnsActive ([/ip cloud get ddns-enabled]); # Значение по-умолчанию ( $m=0 ) set $m 0; :if ($CloudDnsActive=yes) do { # Если IP--->Cloud активировано ( $m=1 ) set $m ($m+1); set $CloudDnsStatus ([/ip cloud get status]); # Проверяем синхронизацию внешних IP-адресов (сохранённого в IP--->Cloud и на внешних DNS) set $CloudDnsIP ([/ip cloud get public-address]); set $CheckIpAddr ([resolve [/ip cloud get dns-name]]); :if ($CloudDnsIP!=$CheckIpAddr) do={ # Если IP разные (изменилось подключение MikroTik к провайдеру)... set $CloudDnsStatus "updating..."; } :if ($CloudDnsStatus="updated") do { # Если IP--->Cloud активировано и обновлено ( $m=2 ) set $m ($m+1); } } return ($m); } # Процедура повторного вызова скрипта на выполнение # входящий параметр: # # $ScriptName (имя скрипта) :global subRepeatScript do={ put ($ScriptName); :if ($ScriptName!="") do { [/system script run $ScriptName]; } } # Процедура формирования списка внешних VPN-серверов из пиров # # возвращает список IP-адресов VPN-серверов с привязкой к группам :global subGetVpnServers do={ # Получаем группы и IP-адреса VPN-серверов из пиров и считаем общее количество пиров :foreach IpSecPeerId in=[/ip ipsec peer find passive!=yes] do={ set $CheckIpAddr [/ip ipsec peer get $IpSecPeerId address]; :if ($CheckIpAddr!="") do={ set $MaskPos [find $CheckIpAddr "/"]; set $GroupFromPeer ([/ip ipsec peer get $IpSecPeerId policy-template-group]); set $IpFromPeer ([pick $CheckIpAddr 0 $MaskPos]); set $VpnServersList ($VpnServersList, {{$GroupFromPeer; $IpFromPeer}}); } } return ($VpnServersList); } # Процедура выключения активных пиров и связанных политик # # процедура возвращает список ID всех политик :global subDisableIpSecPeers do={ # ...выключаем все включённые, активные (passive=false) пиры... :foreach IpSecPeerId in=[/ip ipsec peer find passive!=yes] do={ log warning ("[IP IPSec Peer] ---> обрабатывается пир на ---> " . [/ip ipsec peer get $IpSecPeerId comment]); #log warning ("[IP IPSec Peer] ---> processed peer on ---> " . [/ip ipsec peer get $IpSecPeerId comment]); # Получаем address из текущего пира... set $CheckIpAddr [/ip ipsec peer get $IpSecPeerId address]; :if ($CheckIpAddr!="") do={ # Если address не пустой, отрезаем IP-адрес от маски... set $MaskPos ([find $CheckIpAddr "/"]); set $CheckIpAddr ([pick $CheckIpAddr 0 $MaskPos]); # ...и выключаем связанные IPSec-политики :foreach IpSecPolicyId in=[/ip ipsec policy find sa-dst-address=$CheckIpAddr] do={ :if ($IpSecPolicyId!="") do={ :if ([/ip ipsec policy get $IpSecPolicyId disabled]!=yes) do={ [/ip ipsec policy disable $IpSecPolicyId]; log warning ("[IP IPSec Policy] ---> политика " . [/ip ipsec policy get $IpSecPolicyId comment] . " деактивирована"); #log warning ("[IP IPSec Policy] ---> policy " . [/ip ipsec policy get $IpSecPolicyId comment] . " deactivated"); } # Заполняем массив списком ID политик для дальнейшего изменения set $IdList ($IdList, $IpSecPolicyId); } } } # Примечание: пиры выключаются после деактивации политик, чтобы не возникали системные ошибки :if ([/ip ipsec peer get $IpSecPeerId disabled]!=yes) do={ [/ip ipsec peer disable $IpSecPeerId]; log warning ("[IP IPSec Peer] ---> " . [/ip ipsec peer get $IpSecPeerId comment] . " ---> деактивирован"); #log warning ("[IP IPSec Peer] ---> " . [/ip ipsec peer get $IpSecPeerId comment] . " ---> deactivated"); } } return ($IdList); } # Процедура включения активных пиров и связанных политик # входящие параметры: # # $PeerID (ID пира на VPN-сервер); # $PolIdList (список ID из $subDisableIpSecPeers); # $CloudIP (IP MikroTik из DDNS); # $SrcIP (src-address для обращения к VPN-серверу) :global subEnableIpSecPeers do={ put ($PeerID); put ($PolIdList); put ($CloudIP); :if (($PeerID!="")&&($PeerID!=nil)&&($PolIdList!="")&&($PolIdList!=nil)&&($CloudIP!="")&&($CloudIP!=nil)) do={ # Получаем адрес VPN-сервера set $ActiveVPN [/ip ipsec peer get $PeerID address]; :if ($ActiveVPN!="") do={ # Если найден, отрезаем IP-адрес от маски set $MaskPos [find $ActiveVPN "/"]; set $ActiveVPN ([pick $ActiveVPN 0 $MaskPos]); } # Если пир выключен, делаем задержку исполнения и включаем :if ([/ip ipsec peer get $PeerID disabled]=yes) do={ delay 5000ms; [/ip ipsec peer enable $PeerID]; log warning ("[IP IPSec Peer] ---> активирован peer на ---> " . [/ip ipsec peer get $PeerID address]); #log warning ("[IP IPSec Peer] ---> activated peer on ---> " . [/ip ipsec peer get $PeerID address]); } # Ищем политики по ID из массива PolIdList, проверяем, при необходимости изменяем Src. Address, SA Src. Address и SA Dst. Address, и активируем :foreach IpSecPolicyId in=$PolIdList do={ :if ($IpSecPolicyId!="") do={ :if ([/ip ipsec policy get $IpSecPolicyId src-address]!=$SrcIP) do={ [/ip ipsec policy set $IpSecPolicyId src-address=$SrcIP]; log warning ("[IP IPSec Policy] ---> изменён src-address"); #log warning ("[IP IPSec Policy] ---> src-address changed"); } :if ([/ip ipsec policy get $IpSecPolicyId sa-src-address]!=$CloudIP) do={ [/ip ipsec policy set $IpSecPolicyId sa-src-address=$CloudIP]; log warning ("[IP IPSec Policy] ---> изменён sa-src-address"); #log warning ("[IP IPSec Policy] ---> sa-src-address changed"); } :if ([/ip ipsec policy get $IpSecPolicyId sa-dst-address]!=$ActiveVPN) do={ [/ip ipsec policy set $IpSecPolicyId sa-dst-address=$ActiveVPN]; log warning ("[IP IPSec Policy] ---> изменён sa-dst-address"); #log warning ("[IP IPSec Policy] ---> sa-dst-address changed"); } :if ([/ip ipsec policy get $IpSecPolicyId disabled]=yes) do={ delay 3000ms; [/ip ipsec policy enable $IpSecPolicyId]; log warning ("[IP IPSec Policy] ---> политика активирована"); #log warning ("[IP IPSec Policy] ---> policy activated"); # Очищаем DNS-кэш [/ip dns cache flush] } } } } } # Процедура формирования списка политик по ID пира # входящие параметры: # # $PeerIP (IP из пира БЕЗ МАСКИ); # $CloudIP (IP MikroTik из DDNS); # $action (enable/disable/skip) # # процедура возвращает список ID, связанных с пиром, политик :global subGetPoliciesByPeer do={ put ($PeerIP); put ($CloudIP); put ($action); :if (($action="")||($action=nil)) do={ set $action "skip"; } :foreach IpSecPolicyId in=[/ip ipsec policy find sa-dst-address=$PeerIP] do={ :if ($IpSecPolicyId!="") do={ # Если политика включена И $action=disable, выключить политику :if (([/ip ipsec policy get $IpSecPolicyId disabled]!=yes)&&($action="disable")) do={ [/ip ipsec policy disable $IpSecPolicyId]; log warning ("[IP IPSec Policy] ---> политика деактивирована"); #log warning ("[IP IPSec Policy] ---> policy deactivated"); } # Если получен не пустой $CloudIP И sa-src-address!=$CloudIP (изменился ISP), выключить политику и изменить sa-src-address :if (($CloudIP!="")&&($CloudIP!=nil)&&([/ip ipsec policy get $IpSecPolicyId sa-src-address]!=$CloudIP)) do={ [/ip ipsec policy disable $IpSecPolicyId]; [/ip ipsec policy set $IpSecPolicyId sa-src-address=$CloudIP]; log warning ("[IP IPSec Policy] ---> политика деактивирована ---> новый sa-src-address ---> " . $CloudIP); #log warning ("[IP IPSec Policy] ---> policy deactivated ---> new sa-src-address ---> " . $CloudIP); # Делаем задержку исполнения, чтобы Kerio разорвал канал delay 30000ms; } # Если политика выключена И $action=enable, включить политику :if (([/ip ipsec policy get $IpSecPolicyId disabled]=yes)&&($action="enable")) do={ [/ip ipsec policy enable $IpSecPolicyId]; log warning ("[IP IPSec Policy] ---> политика активирована"); #log warning ("[IP IPSec Policy] ---> policy activated"); # Очищаем DNS-кэш [/ip dns cache flush] } # Заполняем массив списком ID политик для дальнейшего изменения set $IdList ($IdList, $IpSecPolicyId); } } return ($IdList); } # Процедура проверки local-address пира # входящие параметры: # # $PeerID (ID пира на VPN-сервер); # $CloudIP (IP MikroTik из DDNS) :global subCheckPeerLocalIp do={ put ($PeerID); put ($CloudIP); :if (($PeerID!="")&&($PeerID!=nil)&&($CloudIP!="")&&($CloudIP!=nil)) do={ # Проверяем изменение DDNS-IP :if ([/ip ipsec peer get $PeerID local-address]!=$CloudIP) do={ [/ip ipsec peer set $PeerID local-address=$CloudIP]; log warning ("[IP IPSec Peer] ---> изменён local-address"); #log warning ("[IP IPSec Peer] ---> local-address changed"); } } }
/system script add dont-require-permissions=no name=scriptCheckActiveVpnServer owner=admin policy=ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon
Листинг скрипта scriptCheckActiveVpnServer
:if ([:len [/system script job find script=scriptCheckActiveVpnServer]]>1) do={ :error } # Библиотеку процедур инициализируем в скрипте scheduleStartup # и объявляем процедуры, которые будут использованы в этом скрипте :global subCheckCloudDDNS :global subCheckPeerLocalIp :global subDisableIpSecPeers :global subEnableIpSecPeers :global subGetPoliciesByPeer :global subGetVpnServers :global subUpdateCloudDns :local CheckIP :local CheckPeer # Заполняем переменную статусом активации DDNS (внешняя процедура) :local CloudDnsStatus ([:put [$subCheckCloudDDNS]]) :local Exit false :local DefMikroTikSrcNet 192.168.11.0/24 :local DefKerioDstNet 192.168.77.0/24 :local DefKerioPropName KerioVPNProposal#01 :local DefKerioPolName KerioVPNPolicy :local IpSecPolicyId :local KerioName :local KerioVpnNatRuleName KerioVpnNatOut :local m :local n 1 :local PeerCount 0 :local PeerDisabled :local PingCount 3 :local PingResult :local PoliciesList :local PublicIp :local VpnServersList # Проверяем активацию DDNS и, если активирован, считываем активный внешний IP-адрес MikroTik :if ($CloudDnsStatus=0) do={ # Если Cloud DDNS не активно, записываем сообщение в журнал и выходим из скрипта :log error ("[schedule CheckActiveVpnServer] ---> для подключения к VPN-серверу требуется активировать Cloud DDNS! (IP -> Cloud)") # :log error ("[schedule CheckActiveVpnServer] ---> to connect to the VPN server, you need to activate Cloud DDNS! (IP -> Cloud)") :error } :if ($CloudDnsStatus=1) do={ # Если Cloud DDNS активно, но не обновлено, запускаем обновление (внешняя процедура) :set CloudDnsStatus [:put [$subUpdateCloudDns start=false]] :if ($CloudDnsStatus="updated") do={ :set CloudDnsStatus 2 } } :if ($CloudDnsStatus=2) do { # Если Cloud DDNS активно и обновлено ... # Получаем IP из DDNS :set PublicIp [/ip cloud get public-address] # Получаем список VPN-серверов с группами, определяющими приоритет подключения (внешняя процедура) :set VpnServersList ([:put [$subGetVpnServers]]) # Считаем общее количество пиров :foreach VpnIpId in=$VpnServersList do={ :set PeerCount ($PeerCount+1) } # Ищем активный VPN-сервер пингом с внешнего DDNS-IP (для этого, на стороне VPN-сервера необходимо создать разрешающее правило) :while (($Exit!=true)&&$n<=$PeerCount) do={ :foreach VpnIpId in=$VpnServersList do={ # Перебираем IP-адреса VPN-серверов с учётом приоритета :if (($VpnIpId->0)=$n) do={ :set CheckIP ($VpnIpId->1) :if ($CheckIP!="") do={ # Проверяем доступность найденного IP :set PingResult ([:put [/ping address=$CheckIP count=$PingCount src-address=$PublicIp]]) :if ($PingResult=$PingCount) do={ :log warning ("[schedule CheckActiveVpnServer] ---> DDNS-IP ---> " . $PublicIp . " ---> VPN-IP ---> " . $CheckIP . " ---> Ping Result ---> " . $PingResult) # Если IP доступен, ищем пир на этот IP-адрес :set CheckPeer (:put [/ip ipsec peer find address=($CheckIP . "/32")]) :if ($CheckPeer!="") do={ # Если пир найден, проверяем наличие в конфигурации src-адреса (IP ---> Firewall ---> Address Lists), использующегося для соединения с Kerio # Получаем имя сервера Kerio из комментария пира :set KerioName [/ip ipsec peer get $CheckPeer comment] # Обрабатываем полученное имя (ИЗМЕНИТЬ АЛГОРИТМ обработки, если FQDN сервера Kerio отличается от KerioName-Parameter1-...-Parameter_n :if ($KerioName!="") do={ # Находим первый дефис :set m ([find $KerioName "-"]) # Отрезаем KerioName от всего остального :set KerioName ([pick $KerioName 0 $m]) # Ищем адрес в Firewall -> Address List (соответственно там должны быть необходимые записи в формате: # Name ---> KerioName (eg srv1) # Address ---> DefMikroTikSrcNet (eg 192.168.99.0/24)) :set m [/ip firewall address-list find list=$KerioName] :set DefMikroTikSrcNet ([/ip firewall address-list get $m address]) } # ... проверяем наличие в конфигурации политик настроенных на соединение с Kerio :set IpSecPolicyId (:put [/ip ipsec policy find comment="$DefKerioPolName"]) # Если ни одной политики не найдено, создаём политику с настройками по умолчанию # (задаются в разделе объявления переменных) и размещаем её в самом верху списка политик :if ($IpSecPolicyId="") do={ [/ip ipsec policy add disabled=yes dst-address=$DefKerioDstNet proposal=$DefKerioPropName sa-dst-address=$CheckIP sa-src-address=$PublicIp src-address=$DefMikroTikSrcNet tunnel=yes comment=$DefKerioPolName place-before=0] :log warning ("[schedule CheckActiveVpnServer] ---> создана политика " . $DefKerioPolName . " ---> использованы параметры по умолчанию") #:log warning ("[schedule CheckActiveVpnServer] ---> created policy " . $DefKerioPolName . " ---> default parameters used") } else={ # Если политика есть, проверяем указанный в ней src-address, при необходимости меняем. :if ($DefMikroTikSrcNet!=[/ip ipsec policy get $IpSecPolicyId src-address]) do={ [/ip ipsec policy set $IpSecPolicyId src-address=$DefMikroTikSrcNet]; :log warning ("[schedule CheckActiveVpnServer] ---> политика " . $DefKerioPolName . " изменена ---> src-address изменён на ---> " . $DefMikroTikSrcNet) #:log warning ("[schedule CheckActiveVpnServer] ---> policy " . $DefKerioPolName . " changed ---> src-address changed to ---> " . $DefMikroTikSrcNet) } } # очищаем переменную :set m # ищем NAT-правило для мапинга исходящего в сторону Kerio трафика :set m [/ip firewall nat find comment=$KerioVpnNatRuleName] :if ($m!="") do={ # Если изменился src-address в политике ipsec, изменяем правило мапинга исходящего в сторону Kerio трафика :if ([/ip firewall nat get $m to-addresses]!=$DefMikroTikSrcNet) do={ [/ip firewall nat set $m to-addresses $DefMikroTikSrcNet] :log warning ("[IP Firewall NAT] ---> изменено правило мапинга ---> " . $KerioVpnNatRuleName) #:log warning ("[IP Firewall NAT] ---> netmap rule changed ---> " . $KerioVpnNatRuleName) } } # ...сравниваем local-address найденного пира с текущим внешним IP MikroTik, при необходимости изменяем (внешняя процедура) :put [$subCheckPeerLocalIp PeerID=$CheckPeer CloudIP=$PublicIp] # ...проверяем состояние найденного пира :set PeerDisabled ([/ip ipsec peer get $CheckPeer disabled]) :if ($PeerDisabled=true) do={ # Если пир выключен... # Выключаем все другие пиры и политики (внешняя процедура) :set PoliciesList ([:put [$subDisableIpSecPeers]]) # Находим пир на активный VPN-сервер и включаем (внешняя процедура) :put [$subEnableIpSecPeers PeerID=$CheckPeer PolIdList=$PoliciesList CloudIP=$PublicIp SrcIP=$DefMikroTikSrcNet] } else={ # Если пир включен... # Находим все связанные с пиром политики, проверяем и включаем (внешняя процедура) :set PoliciesList ([:put [$subGetPoliciesByPeer PeerIP=$CheckIP CloudIP=$PublicIp SrcIP=$DefMikroTikSrcNet action="enable"]]) } :set Exit true } } else={ :log error ("[schedule CheckActiveVpnServer] ---> DDNS-IP ---> " . $PublicIp . " ---> VPN-IP ---> " . $CheckIP . " ---> Ping Result ---> " . $PingResult) } } } } :set n ($n+1) } }
/system scheduler add interval=1h name=scheduleCheckIPSecSADstAddrFromDNS on-event=\ "/system script run scriptSetIPSecSADstAddrFromDNS" policy=read,write \ start-date=oct/30/2017 start-time=00:10:00 add name=scheduleStartup on-event=":global StartupScript true :global RepeatRun false /system script run scriptFunctionsList" policy=\ ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ start-time=startup add interval=5m name=scheduleCheckActiveVpnServer on-event=\ "/system script run scriptCheckActiveVpnServer" policy=\ ftp,reboot,read,write,policy,test,password,sniff,sensitive,romon \ start-date=nov/29/2017 start-time=00:00:00
Листинг расписания scheduleStartup
:global StartupScript true :global RepeatRun false /system script run scriptFunctionsList
Листинг расписания scheduleCheckIPSecSADstAddrFromDNS
/system script run scriptSetIPSecSADstAddrFromDNS
Листинг расписания scheduleCheckActiveVpnServer
/system script run scriptCheckActiveVpnServer
Завершающий штрих:
для корректного обращения MikroTik к DNS-серверам предприятия, находящимся за Kerio Control, необходимо добавить статические записи с их адресами в MikroTik, в раздел IP ---> DNS ---> Static…
Ну вот где-то так!
Надеюсь, нигде не ошибся и ничего не забыл…
Спасибо за внимание!
p.s.
История правок и изменений:
- Добавлен раздел «Что получим на выходе?:»;
- Добавлен комментарий к адресу сети головного предприятия;
- Изменены IP-адреса сетей, из пулов ISP, использующиеся в описании конфигурации;
- Добавлен пункт «Завершающий штрих:»;
