Хочу поделиться опытом запуска серверов 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-ocserv
RouterOS сам назначит контейнеру адрес и шлюз из настроек veth: внутри он станет eth0. DHCP здесь не участвует.

Внешний трафик попадает в контейнеры только через dst‑nat, а наружу они выходят через masquerade роутера. Осталось указать реестр и папку для распаковки образов:
/container/config set registry-url=https://registry-1.docker.io tmpdir=pull
SoftEther 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=yes
root-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
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
У меня уже был сервер 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
Маршрутизация и NAT
RouterOS должен знать, что сеть клиентов 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.0
no-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. Контейнеры имеют смысл, когда нужен конкретный протокол или совместимость с уже работающей инфраструктурой.
Источники:
MoscowStyle
Amnezia отлично крутится с лета на микроте