Как стать автором
Обновить

Двухфакторая аутентификация VPN/Mikrotik – просто и масштабируемо

Время на прочтение13 мин
Количество просмотров21K
Всего голосов 11: ↑11 и ↓0+11
Комментарии41

Комментарии 41

Интересное решение с прослойкой из PHP.
Только с масштабированием "«1хN» – 1 SMS-шлюз на неограниченное количество роутеров" возникает проблема единой базы логинов и паролей. Она имеет два быстрых решения:
1. Реплекация /ppp secrets на неограниченное количество роутеров при помощи скриптов/API.
2. Установка некоего дополнительно стороннего Radius-сервера. Тогда будет логин будет всегда по номеру телефона.

Для обеспечения принципа "Не важно какое устройство инициировало VPN-соединение, авторизация по ссылке из SMS", сервис авторизации нужно выставить в Интернет. Это может быть нежелательно в ряде случаев.

p.s. если VPN-соединение сможет провисеть час, то не прошедший проверку клиент всё равно получит доступ к внутренним ресурсам сети.
1хN подразумевает именно использование одного SMS-шлюза для авторизации на N-vpn, а не сервиса/сервера авторизации (usb-модем в одном роутере, а не в каждом).
– Репликация /ppp secrets не имеет смысла, т.к пользователю должен быть выдан ip из внутренней адресации роутера.
– Использование стороннего радиуса не рассматривалось в данной задаче, как усложняющее «уровень входа» (проще уже было использовать usermanager)
– Данное решение несет функцию защиты внутренней сети компании, а не способы авторизации, а учитывая, что сервис не предназначен для авторизации широкого круга лиц, эти логины добавляются на необходимый MikroTik системным администратором.

p.s. если VPN-соединение сможет провисеть час, то не прошедший проверку клиент всё равно получит доступ к внутренним ресурсам сети.

Не сможет. Через 59 минут соединение будет разорвано по тайм-ауту. Если боязно, то можно не удалять его ip из адресного листа по тайм-ауту (удалив скрипт из On Down). В этом случае адресный лист будет действовать даже после отключения пользователя.
Если же пользователь инициирует новое подключение, то в текущем листе просто обновится код авторизации и все продолжит работать как и запланировано.

Чтобы соединение было разорвано по таймауту, жто должно быть явно указано в PPP-PROFILE. По-умолчанию, ограничения на длителтность ppp-соединения нет.

Ну это то как раз и указано и описано подробно какое значение там должно быть
/ppp profile
add dns-server=10.10.0.1 idle-timeout=59m local-address=10.10.1.100 name=2F-VPN use-compression=no use-encryption=no use-mpls=no

Я бы еще "sessino-timeout=00:59:00" добавил, т. к. в сессии будут какое-то время ходить пакетики, idle-timeout обнулится.
Да, клиенту придется при этом переустанавливать соединение один раз в час. Но это даже полезно от "брошеннных и забытых" пользователями vpn-соединений.

session-timeout не хорошо использовать по нескольким причинам:
1. необходимость переподключения раз в час будет бесить сотрудников
2. ненужная нагрузка на модемы
3. очень плохо на каналах сервер-mikrotik / mikrotik-mikrotik
… сервис авторизации нужно выставить в Интернет. Это может быть нежелательно в ряде случаев.


Да, но мы делаем все возможные проверки на предмет неверного запроса. Во вторых, чтобы взломать защиту на этапе авторизации нужно обладать верным номером ruid и верным кодом авторизации. Вариант подбора очень низок.
Ну и самое главное – это единственные способ, который пришел в голову для авторизации соединения Сервер -> Mikrotik

PS в скриптах везде указан http (т.к откатывался в локальной сети), но в жизни нужно https (меняется в 3х местах)

Если у вас есть какие-то подозрения, где можно что-то перехватить, то пишите, покопаем в этом направлении.

Перехватывать можно содержимое туннеля при использовании в профиле "use-encryption=no". Со своей стороны склонен использовать "use-encryption=required" или, как минимум "yes".

В данной статье не говорится про настройку VPN сервера.
Настройка PPP/L2TP/SSTP – это на ответсвенности администратора сети, также как и настройка firewall, которую каждый делает на свой вкус и потребности, на функционале авторизации и её защищенности это никак не сказывается.
Мой скрипт работает при любом типе туннеля, а, например, SSTP не работает use-encryption
Лично я вообще люблю L2TP, вот просто люблю :)

Но спасибо, добавлю пояснения к статье

А как l2tp на смарт поднять так чтобы он не оказался основным шлюзом? Правильно, ни как. А микрот не умеет ovpn в udp. Что тоже в минус.

Не совсем понял как это относится к теме двухфакторной авторизации, но да, на смартфоне не получится и не только l2tp, но и все остальные, а на MacOS не получится PPTP/SSTP.
Но это решение для рабочего процесса:
– у меня оно используется для авторизации туннелей сервер-микротик и между микротиками, а дальше поднимаю адресацию по OSPF.
– достаточно хорошо будет для авторизации сотрудников работающих на удаленке с компьютера. Я полагаю с телефона никто не работает.
– При соединении офисов в единую сеть данное решение также позволит получать информацию о «падении/подъеме» туннеля. Но это больше вторично, но тоже полезно

И, что не маловажно, если вы/компания строите защищенную сеть и заморочились с 2FA, то шлюз у вас должен быть один, в противном случае в вашу сеть запросто можно зайти, что называется «со двора» – с того устройства у которого основной шлюз не через vpn
Вопрос был в любви к l2tp. И сразу камень в огород микрота где ovpn позволяет не задавать основной шлюз, но tcp портит всю малину.
Без предъяв. Статья понравилась, в избранное затулил не знаю зачем )))
Это не камень в огород МТ, а камень в протокол. Вы же не говорите, что на другом оборудовании l2tp можно сделать так, чтобы работало.
Тут «от каждого по желаниям, каждому по потребностям». Лично для меня отсутствие OVPN UDP не является причиной, чтобы отказываться от столь мощного оборудования.
Это из разряда извечных споров типа «Android/iOS», «Windows/MacOS», «Huyndai/VW» etc…
Вы же не говорите, что на другом оборудовании l2tp можно сделать так, чтобы работало.

Ну начнем с того что в той же винде легко можно снять галочку с основного шлюза и все проблемы исчезают сами по себе. Ну кроме того что надо маршруты теперь дописать. ))) В том же микроте это сделать вообще не проблема. Так что… Но к примеру в том же android этого не завезли и как не крутись после соединения с l2tp сервером весь трафик идет через сервер l2tp. А к примеру у меня канал ограничен. Представь 10 клиентов соединятся с сервером, забудут отключить и будут ютубчик через меня гонять? Или работа у них эпизодическая не клацать же каждый раз «соединится/разъединиться», да и опять же трафик в этот момент либо через меня, либо на маршрутизаторе я его рублю и клиент получается без инетрнета…
Это не камень в огород МТ, а камень в протокол.

Далее Вы не верно поняли. Камень был не в l2tp, а микрот + ovpn. Ведь там можно из коробки считай для любого устройства сделать как default gateway, так и отказаться от него вовсе, а можно отдавать клиенту конфиги с сервера с скажем правилами маршрутизации которые клиент (приложение) ovpn пропишет в систему. И мне пользователю надо дать только адрес сервера и логин/пароль. Дальше произойдет «чудо»! И по идее даже не надо вдаваться в подробности что за система у клиента, и обойтись одним конфигом. Но отсутствие возможности пользоваться UDP у OVPN полностью отбивает желание пользоваться им. К примеру у меня у многих клиентов не очень широкий интернет канал. И забивать его лишним трафиком TCP, когда внутри и так TCP… сами понимаете )
И да по итогу мне пришлось отказаться от микрота именно по этой причине. Домой имея микрот в качестве основного маршрутизатора я поднял l2tp, проблем нет на микроте поиграться с основными шлюзами, но вот клиентам которым надо доступ к нашему ПО и иногда со смартов пришлось поднимать ovpn на отдельном сервере. Когда поднял на микроте, то столкнулся с тем что служебные пакеты очень быстро забили мой канал. Перешел с микрота TCP на отдельный сервере с UDP и прям сильно полегчало.

Я вас правильно понял. На маке тоже можно не ставить галочку "отправлять весь трафик через vpn".
Но речь у вас изначально была про невозможность на смартфонах пустить трафик не over vpn, вот я говорю, что проблема локальная для l2tp и его реализации в смартфонах. И проблема тут не в микротах.

Опять же вы не до конца поняли. Проблема глобальная и универсального решения на микроте не заиметь. Ладно, оставим этот разговор. Удачи!
НЛО прилетело и опубликовало эту надпись здесь
Спасибо большое. Начал изучать, все так красиво, а потом… мтс режет IKE2, мегафон режет… И выходит что вообще не универсальное решение…
НЛО прилетело и опубликовало эту надпись здесь
Да именно.
НЛО прилетело и опубликовало эту надпись здесь
Лично у меня ovpn, l2tp не режут. ipsec и IKE2 режут. Тот же ovpn с шифрованием и в путь, что захочу, то и будет внутри, хоть 1000 офисов… короче глупости на ровном месте сделали и все.

Один вопрос — почему вместо нестабильного модема, который может отключить оператор (по вашим же словам) не использовать например тот же AWS SNS для рассылки SMS сообщений? Выйдет и дешевле и надежнее.
Вместо php скрипта можно использовать AWS Cognito и/или Lambda.
Ну и лично я бы подобную задачу решил путем установки опенсорсного pritunl — vpn сервера на базе openvpn — он поддерживает 2fa на базе OTP кодов из коробки. Ну и займет подобный сетап минут 10. Но это конечно же имхо.

Вопрос в цене. У того же Тинькофф.мобайл симка с безлимитными sms стоит 49 руб./мес.
Прикрутить к скрипту отправку через платный сервис, тот же smsc.ru / AWS SNS не проблема, но сразу считайте на одну авторизацию -2,5-3 рубля. Поэтому дешевле точно не выйдет.

нестабильного модема, который может отключить оператор
– не совсем правильно поняли. У меня была такая мысль на начальном этапе создания, т.к не было понимания как относятся к этому операторы и какую нагрузку испытывает модем. И исходя из этого были заложены «страховки»

По факту решение оказалось достаточно стабильное если модем использовать нормальный. У меня установлена Sierra Wireless на pci-e в BaseBox2 и уже более полутора лет работает безотказно примерно по 1200 авторизаций в месяц. Плюс через него я отправляю уведомления умного дома, synology и пр… эдакий домашний sms-шлюз. Модемы пробовал разные (Alcatel, 3272, 3372, SIM800L, …)

AWS Cognito / Lambda – другой уровень вхождения и опять таки цена каждой авторизации…
Pritunl – это облачное решение, для его работы нужно либо VPS в облаке, либо выделять сервер/ВМ + стоимость на каждую авторизацию

Мое решение подходит тем, у кого в парке есть физические маршрутизаторы MT. Сайт, на который можно кинуть скрипт и так у всех (почти у всех) есть.

Ок, оставим вопрос с смс сообщениями. На AWS тарифы для смс сообщений зависят от страны и оператора получателя и колеблятся от 0.001$ до 0.1$ за сообщение — надо считать. Например, 1200 смс в РФ на оператора МТС обойдутся в 69$ примерно. Согласен, значительно дороже 49 рублей) Но если цель используя 2fa авторизовать пользователя, то AWS Cognito это то что доктор прописал.
1200 авторизаций в месяц даже близко не подходит к месячному бесплатному (Free tier) лимиту (который по моему 50000 в месяц, точно не вспомню, надо смотреть прайсинг).
С лямбдами тоже никаких вопросов — если смогли написать php скрипт, то и на каком-нибудь nodejs / python наваяете, там сложного ничего нет.
И без всяких сомнений такое решение будет надежнее чем использовать модем за 49 рублей)
Просто присмотритесь к такому варианту решения, сервисы AWS крайне хорошо документированы, а API интерфейсы я бы даже сказал user-friendly.
И облака при правильном использовании не всегда дорого, иногда даже бесплатно)

С лямбдами тоже никаких вопросов — если смогли написать php скрипт, то и на каком-нибудь nodejs / python наваяете, там сложного ничего нет.

Уровень вхождения не мой, а того, кто внедряет мое решение у себя :)
Я изначально делал его не для себя, а для того чтобы отправить ссылку и человек мог скачав два файла все запустить
Спасибо за обратную связь.
Я обновил код добавив возможность отправки SMS через платный шлюз, на примере smsc.ru (цена за одно SMS на 0.5 руб. ниже чем у amazon)
Также выложил код на GitHub
Спасибо за статью. Я правильно понимаю что если надо вместо смс имплементировать TOTP то надо менять в функции autorize()?
В данном случае SMS выступает в виде транспорта для доставки одноразового пароля.
Соответственно если использовать другой тип пароля (генерации пароля и пр), вам нужно его сначала сгенерировать в send_authcode(), потом передать пользователю и потом проверить, что вернулось от него в autorize().
Но необходимости в этом особого не вижу, потому что гораздо легче рвать неподтвержденное, например в течении одной/двух минут, VPN-соединение по таймауту (сейчас стоит 59 минут)

В случае TOTP пользователю ничего отсылать не нужно, у него код уже есть .

А что вы подразумеваете под – «В случае TOTP пользователю ничего отсылать не нужно, у него код уже есть».
TOTP в моем понимании – метод шифрования пароля со сроком действия. Сгенерировать его можно на сервере, в клиентском приложении или на токене (например), куда изначально уже внесен ключ-секрет. Если у клиента нет приложения или токена и пароль генерировался на сервере, то пароль ему в любом случае нужно передать.
Если написать приложение, то это все меняет, но я увы не пишу их.

Буду рад любым разъяснениям. Может это то, что индустрия ждет и я это реализую на благо сообщества :)

TOTP не метод шифрования. Это, проще говоря, алгоритм генерации N-значного цифрового пароля на основе текущего времени и некоего секрета который есть и на сервере и на клиенте. В данном случае надо его просто генерировать и сравнивать с введённым кодом второго фактора.

Ну это то, что я и представлял. Но для генерации у клиента должно быть приложение или токен, правильно? Ну и самое главное на сервере еще должна быть страница куда этот пароль вводить.
Ну или приложение, которое генерирует код и отправляет его на сервер «невидимо».
повторюсь, ничего посылать не нужно. одноразовый код вычисляется по формуле:
OTP = TOTP* (time+shared secret)

* там hmac и т.п. — подробнее в RFC

у клиента будет генерироваться такой же код без привязки к коду на микротике — главное чтобы время и shared secret совпадали

Да я это понял.
Где он у него будет генерироваться?

Например на аппаратном ключе, или на приложении типа Google Authenticator

Вот про это я и писал, что у пользователя должен быть токен или приложение, а также на сервере должна быть форма в которую будет выводиться этот код. В данном случае код не нужно передавать пользователю, но наоборот сервер его должен получить от пользователя. Экономия на смс, но неудобство для авторизации. На мой взгляд гораздо проще перейти по ссылке из SMS/email и пр.
Решение задачи с ТОТР усложняется, когда один пользователь может авторизовать несколько туннелей на разных роутерах (возможность заложена в скрипте).

Дело не в экономии. СМС легко «взломать» заказав дубликат симки
TOTP хорошая вещь, но конкретно к данному решению оно увы совсем не подходит.
SMS взломать не получится, т.к отправленный код действует ровно столько сколько действует сессия установленная в idle-timeout. Далее код теряет свою актуальность.
Поэтому если нужна очень высокая защищенность, для критических узлов можно установить timeout vpn-соединения равным 60s.
Заказать дубликат симки даже за час не реально, учитывая то, что еще нужно знать на какой номер отправлялось сообщение и как-то решить вопрос с предоставляемыми документами для заказа дубликата.
Второй момент – для компаний которые используют для защищенного общения внутренние чаты, например тот же Synology Chat, скрипт может отправлять код авторизации через его API и в этом случае система авторизации становится изолированной от внешней среды.
Обновлен код:
– Добавлена отправка кодов в Synology Chat и через Telegram Bot
– Возможность отправки различным пользователям по различным каналам
– Упрощен код скрипта для MikroTik
Обновлен код на github.
Два варианта реализации – функциональное и в виде класса
Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации

Изменить настройки темы

Истории