В RouterOS из коробки есть WireGuard, OpenVPN, SSTP и IPsec, но нет SoftEther и OpenConnect-сервера. Начиная с RouterOS 7 в MikroTik можно запускать контейнеры, и этого хватает, чтобы поднять оба VPN прямо на маршрутизаторе, без отдельной Linux-машины. Разбираем установку SoftEther с SecureNAT и каскадом, ocserv с маршрутами для клиентов и грабли, на которые пришлось наступить по пути. Читать далее
Уровень сложностиСредний
Время на прочтение8 мин
Охват и читатели4.6K
Туториал
Хочу поделиться опытом запуска серверов SoftEther VPN и ocserv (OpenConnect/AnyConnect) прямо на MikroTik. В RouterOS из коробки есть WireGuard, OpenVPN, SSTP, L2TP/IPsec и IKEv2, но нет сервера OpenConnect или SoftEther. Иногда нужен именно такой протокол: для клиентов Cisco Secure Client или для каскада с уже работающим сервером SoftEther.
Поднимать отдельную Linux‑машину ради пары VPN‑сервисов не хотелось. Начиная с RouterOS 7 в MikroTik есть поддержка контейнеров, совместимых с образами Docker Hub и Quay. Этим и воспользуемся.
Всё ниже проверено на MikroTik CHR 7.24.5 (x86_64) на KVM, 768 МБ памяти и 7 ГБ диска. На железных маршрутизаторах я не проверял, но, скорее всего, порядок тот же, только нужен образ под их архитектуру (arm/arm64) и внешний накопитель.
Краткое содержание статьи:
включение контейнеров и подготовка сети для них;
поднятие SoftEther VPN с SecureNAT или каскадом на другой сервер;
поднятие ocserv и настройка маршрутов для него;
грабли на которые наступил в процессе.
Итак, приступим.
Подготовка RouterOSДля начала включаем пакет container. В Winbox: System → Packages → container → Enable → Apply Changes. Маршрутизатор уйдёт в перезагрузку.
Пакета мало: запуск контейнеров закрыт device‑mode. Разрешаем их:
/system/device-mode/update container=yesИзменение нужно подтвердить физически в течение 5 минут. На железе это кнопка reset, на CHR — выключение и включение из панели провайдера: Power off, затем Power on. /system reboot и кнопка Reboot в панели не подойдут.
Проверяем:
/system/device-mode/printДолжно быть container: yes. Если там no и attempt-count: 1, попытка была, но не подтвердилась. Повторяем.
Далее готовим сеть. Каждому контейнеру нужен свой veth‑интерфейс, а все veth мы соберём в один bridge. Адреса берём из свободной подсети, у меня это 10.10.4.0/24:
/interface/bridge add name=br-containers
/ip/address add address=10.10.4.1/24 interface=br-containers
/ip/firewall/nat add chain=srcnat src-address=10.10.4.0/24 action=masquerade
/interface/veth add name=veth-softether address=10.10.4.2/24 gateway=10.10.4.1
/interface/veth add name=veth-ocserv address=10.10.4.3/24 gateway=10.10.4.1
/interface/bridge/port add bridge=br-containers interface=veth-softether
/interface/bridge/port add bridge=br-containers interface=veth-ocservRouterOS сам назначит контейнеру адрес и шлюз из настроек veth: внутри он станет eth0. DHCP здесь не участвует.

Внешний трафик попадает в контейнеры только через dst‑nat, а наружу они выходят через masquerade роутера. Осталось указать реестр и папку для распаковки образов:
/container/config set registry-url=https://registry-1.docker.io tmpdir=pullSoftEther VPNИспользуем официальный образ softethervpn/vpnserver. У него есть нюанс: тег stable — это ветка 4.x, и настройки она хранит в /mnt. Ветка 5.x (теги вида 5.2.5188) хранит их в /var/lib/softether. Путь в mount должен соответствовать тегу, иначе пароли и пользователи будут пропадать при пересоздании контейнера. Я брал stable.
Папку для настроек заранее не создаём: если её нет, RouterOS заполнит её содержимым образа. Создаём mount и контейнер:
/container/mounts/add list=SE_DATA src=softether/data dst=/mnt
/container add remote-image=softethervpn/vpnserver:stable interface=veth-softether root-dir=softether/root mountlists=SE_DATA name=softether logging=yes start-on-boot=yesroot-dir — это файловая система самого контейнера, она заменяется при обновлении образа. Настройки живут отдельно, в mount.
Ждём, пока образ скачается (status=stopped в /container print), и запускаем:
/container start softetherВ логах должна появиться строка started /usr/local/bin/vpnserver execsvc. Ошибка dmesg: klogctl: Operation not permitted говорит, что сервер пытается прочитать журнал ядра, а контейнеру это запрещено.
После первого запуска пароля администратора нет. Задаём пароль до того, как откроем порт наружу:
/container shell softether
vpncmd localhost /SERVER /CMD ServerPasswordSet
ls -la /mnt
exitВ /mnt должен появиться конфиг файл vpn_server.config. Затем пробрасываем порт. Берём 444 для примера:
/ip/firewall/nat add chain=dstnat in-interface-list=WAN protocol=tcp dst-port=444 action=dst-nat to-addresses=10.10.4.2 to-ports=443Дальше удобнее работать через SoftEther VPN Server Manager: подключаемся к IP:444 с паролем администратора и создаём пользователей в хабе (Manage Users → New). Как клиенты получат IP‑адреса и выход в интернет, зависит от режима.
SecureNAT — встроенный в хаб DHCP и NAT, который работает полностью в userspace. TUN, iptables и дополнительные права ему не нужны, поэтому в контейнере RouterOS он работает сразу. Включаем в Manage Virtual Hub → Virtual NAT and Virtual DHCP Server (SecureNAT) → Enable SecureNAT. Клиенты получат адреса из 192.168.30.0/24, а DNS будет пересылаться в DNS маршрутизатора.
У меня уже был сервер SoftEther на Linux с Local Bridge на TAP‑интерфейс и dnsmasq в роли DHCP. Cascade Connection соединяет хабы SoftEther на уровне L2 в одну логическую сеть.
Порядок действий:
На удалённом сервере SoftEther создаём отдельного пользователя для каскада.
На SoftEther в MikroTik выключаем SecureNAT в хабе. Иначе его DHCP через каскад начнёт раздавать адреса устройствам удалённой сети.
Manage Cascade Connections → New: адрес и порт удалённого сервера, имя его хаба, пользователь из первого шага.
Нажимаем Online. Статус должен смениться на Online (Established).
Важно: каскад настраиваем только в одну сторону, иначе каскад с обеих сторон даст петлю.
ocservС ocserv сложнее: ему нужны TUN, ip_forward и iptables. В Docker их даёт cap_add: NET_ADMIN, а в RouterOS такого параметра нет. На практике контейнер RouterOS спокойно создаёт TUN и меняет сетевые настройки внутри своего сетевого пространства. Режим privileged=yes мне не понадобился.
Берём образ aminvakil/ocserv. Актуальные версии лежат на Quay: на Docker Hub есть образ с таким же именем, но он не обновлялся с 2 020 года.
Сеть для VPN‑клиентов задаём переменными окружения. У меня это 10.10.5.0/24. Всю папку /etc/ocserv монтируем наружу: там конфиг, сертификаты и пользователи.
/container/envs/add list=OC_ENV key=OC_IPV4_NETWORK value=10.10.5.0
/container/envs/add list=OC_ENV key=OC_IPV4_NETMASK value=255.255.255.0
/container/mounts/add list=OC_DATA src=ocserv/conf dst=/etc/ocservРеестр в RouterOS задаётся одной общей настройкой на все контейнеры. Временно переключаем его на Quay и создаём контейнер:
/container/config set registry-url=https://quay.io
/container add remote-image=aminvakil/ocserv:latest interface=veth-ocserv root-dir=ocserv/root envlist=OC_ENV mountlists=OC_DATA name=ocserv logging=yes start-on-boot=yesКогда образ скачался, возвращаем Docker Hub, иначе SoftEther потом не обновится. Запускаем:
/container/config set registry-url=https://registry-1.docker.io
/container start ocservПри первом запуске образ сам создаёт самоподписанный сертификат и тестового пользователя test с паролем test. Создаём своего пользователя и не забываем удалить тестового:
/container shell ocserv
ocpasswd -c /etc/ocserv/ocpasswd user1
ocpasswd -c /etc/ocserv/ocpasswd -d test
exitПробрасываем порт. ocserv работает по TCP и по UDP (DTLS), поэтому нужны оба протокола:
/ip/firewall/nat add chain=dstnat in-interface-list=WAN protocol=tcp dst-port=8443 action=dst-nat to-addresses=10.10.4.3 to-ports=443
/ip/firewall/nat add chain=dstnat in-interface-list=WAN protocol=udp dst-port=8443 action=dst-nat to-addresses=10.10.4.3 to-ports=443Маршрутизация и NATRouterOS должен знать, что сеть клиентов ocserv находится за контейнером. Добавляем маршрут и masquerade:
/ip/route add dst-address=10.10.5.0/24 gateway=10.10.4.3
/ip/firewall/nat add chain=srcnat src-address=10.10.5.0/24 out-interface-list=WAN action=masqueradeЕсть тонкий момент. Скрипт образа при каждом старте добавляет свой MASQUERADE для сети клиентов. Тогда RouterOS видит трафик с адреса контейнера 10.10.4.3, а не с адресов клиентов. Для интернета это не важно, но правила firewall и маршрутизации по адресам клиентов срабатывать не будут.
Правило строится по переменной OC_IPV4_NETWORK, а сам ocserv берёт сеть из уже созданного ocserv.conf. Поэтому после первого запуска перенаправляем правило на документационную сеть TEST‑NET-1, пакетов из которой не бывает:
/container/envs/set [find list=OC_ENV key=OC_IPV4_NETWORK] value=192.0.2.0
/container stop ocserv
/container start ocservЕсли когда‑нибудь удалите ocserv.conf, сначала верните переменную на 10.10.5.0. Иначе клиенты начнут получать адреса 192.0.2.x.
Следующая проблема: с клиента не открывалась внутренняя сеть 172.31.0.0/16, хотя маршрутизация на RouterOS была в порядке. Образ добавляет в конфиг исключения для всех частных сетей, чтобы у клиентов не пропадал доступ к домашним сетям:
route = default
no-route = 192.168.0.0/255.255.0.0
no-route = 10.0.0.0/255.0.0.0
no-route = 172.16.0.0/255.240.0.0
no-route = 127.0.0.0/255.0.0.0no-route говорит клиенту не отправлять этот трафик в VPN. Убираем нужное исключение и добавляем явный маршрут:
/container shell ocserv
sed -i '/^no-route = 172.16.0.0\/255.240.0.0/d' /etc/ocserv/ocserv.conf
echo "route = 172.31.0.0/255.255.0.0" >> /etc/ocserv/ocserv.conf
exit
/container stop ocserv
/container start ocservМаршруты передаются клиенту только при подключении, поэтому переподключаемся и проверяем.
ГраблиСобрал в одном месте всё, что отняло время.
Симптом | Причина | Решение |
|---|---|---|
| мягкая перезагрузка не считается подтверждением | Power off и Power on из панели VPS в течение 5 минут |
Winbox не сохраняет контейнер: | Winbox не читает своё же значение по умолчанию | стереть поле или создавать контейнер из терминала |
Образ не скачивается | по умолчанию реестр — | задать |
После ocserv не обновляется SoftEther |
| вернуть Docker Hub после скачивания |
Настройки SoftEther сбрасываются | mount не совпадает с веткой образа |
|
Ошибки iptables про | ядро RouterOS может не поддерживать nft‑вариант iptables | NAT делает RouterOS, самому ocserv iptables не нужен |
Правила по адресам клиентов ocserv не срабатывают | MASQUERADE внутри контейнера подменяет адрес клиента |
|
С клиента не видно внутреннюю сеть |
| удалить исключение и добавить |
Режим privileged=yes в RouterOS 7.24 есть, но включать его ради VPN не стоит. Privileged‑контейнер может менять firewall и форматировать диски маршрутизатора, а в том, что описано выше, он не нужен.
Оба VPN‑сервера работают на MikroTik без privileged и без отдельной Linux‑машины. SoftEther заводится проще, ocserv требует больше внимания к маршрутизации.
SoftEther VPN | ocserv | |
|---|---|---|
Образ |
|
|
Настройки |
|
|
Клиенты | SoftEther Client, OpenVPN, SSTP, L2TP/IPsec | Cisco Secure Client, OpenConnect |
Адреса клиентам | SecureNAT или DHCP удалённой стороны через каскад | пул из |
Управление | Server Manager (GUI) и |
|
Порты у меня | 444/tcp | 8443/tcp и 8443/udp |
Если нужен просто надёжный VPN, сначала стоит посмотреть на встроенные в RouterOS WireGuard или OpenVPN. Контейнеры имеют смысл, когда нужен конкретный протокол или совместимость с уже работающей инфраструктурой.
Источники: