Кстати, хочу поблагодарить сообщество за обратную связь по EvertyDesk. Я увидел огромное количество замечаний, идей и реальных проверок. Много ребят запускали проект у себя, ковыряли его, находили проблемы, и вместе мы дотащили всё до версии 2.0.1. Да, я перепрыгнул с 0.0.1 почти сразу. Иногда нумерация версий тоже хочет жить быстрее разработчика.
Нейросети очень помогают добивать мелкие и очевидные баги. Это невозможно сравнить с тем, как я работал раньше, и с тем, как работаю сейчас.
Некоторые спрашивали про Contributor в виде cloud. Ребят, было бы стыдно этого не указать. Значительная часть работы действительно идёт в диалоге с нейросетями. Я фанат технологий, и иногда меня в хорошем смысле удивляет, насколько круто они умеют делать рутинную работу.
В целом я считаю, что мы живём в удивительное время.
Меня можно за это хейтить. Можно не хейтить. Я просто качусь по общей технологической волне и не особенно жду признания. Сегодня я могу делать вещи, которые раньше даже в виде заказной разработки выглядели безумными идеями.
Поэтому я решил начать параллельную серию статей. Помимо своего VST3-плагина для сведения я хочу наконец сделать то, о чём мечтал годами, пока работал ведущим инженером у частного интернет-провайдера.
Сначала была вышка
Я начинал обычным системным администратором.
Потом наступил момент, когда я остался один, а меня отправили на вышку «МегаФона» примерно в трёхстах километрах от базы. Задача звучала просто: построить VLAN-туннель.
Просто — это когда задачу формулирует человек, который никуда не едет.
На вышке я провёл всю ночь.
Тут, наверное, должна быть фотография. Я пока не решил, можно ли её публиковать, поэтому заблюрю лица, пропуска, экраны, координаты, номера объектов и всё, что может превратить техническую ностальгию в разговор с безопасниками.
Но задача стояла, и я её решил.
Со старым ноутбуком, RouterOS Torch и администраторами «МегаФона» мы справились. Спасибо тем ребятам — у них была действительно крутая команда.
Хотя в то время любой человек, который мог отличить служебный пакет от пользовательского, автоматически казался мне существом более высокого инженерного порядка.
Наверное, именно тогда во мне появилось безумное желание взять под контроль всё это сетевое хозяйство.
Сейчас я могу посмотреть на двадцать строк конфигурации Cisco или Eltex и примерно понять, как устроена топология. Тогда для меня было немыслимо даже разобраться, чем trunk отличается от access.
И проблема была не в отсутствии интеллекта.
Проблема была в том, что сети почти всегда объясняют через текст, таблицы, консоль и чужую уверенность. Перед тобой сотни строк конфигурации, но никто не показывает, куда именно пойдёт пакет и почему он вообще должен туда пойти.
В моем хозяйстве была CCR
MikroTik CCR1036-8G-2S+.
Это был серьёзный для своего времени маршрутизатор: 36 ядер по 1,2 ГГц, два SFP+ и RouterOS Level 6 — характеристики до сих пор можно посмотреть на странице MikroTik.
Но биллинг был заточен под MikroTik и простые очереди. Абонентов у нас было чуть больше тысячи.
Те, кто работал с большим количеством Simple Queue, уже понимают, куда я веду. В официальной документации MikroTik прямо написано, что простые очереди проверяются последовательно: если нужная очередь стоит последней среди тысячи, пакет может пройти через 999 предыдущих проверок. Это не мой художественный образ, а особенность механизма Simple Queue.
В нашей конфигурации добавление даже небольшого количества дополнительной обработки через mangle могло отправить загрузку процессора в потолок.
И тогда я снова вспомнил о желании разгрузить весь этот кошмар. Я слишком чокнутый, чтобы просто купить железку и успокоиться. Да и кто-то бы дал денег на крутую ASIC железяку?)
У нас был сервер с двумя сетевыми картами Intel X520, от скуки я начал копать в DPDK.
Многим, наверное, интересно, зачем мне мой EVRTCK. Отвечу честно: писать кодек иногда проще, чем разбираться с пакетами на аппаратном уровне.
Но идея меня выкупила полностью.
Я представлял такой стек:
Ubuntu ServerHugepagesvfio-pciDPDKFD.io VPPVPP NAT44VPP DHCP
На существующем x86-сервере с i7-8700K мне тогда хотелось похоронить CCR1036-8G-2S+.
Именно хотелось. Полноценного честного сравнительного теста, который можно было бы защищать перед суровым человеком с Хабра, я не закончил.
По производительности software data plane мог выглядеть безумно убедительно. По надёжности, предсказуемости, эксплуатации и восстановлению после аварии — уже совсем другой разговор.
Там, где работает ASIC, всё твёрдо и понятно. А в DPDK ты сначала прописываешь интерфейс, потом разбираешься с IOMMU, NUMA, очередями, памятью, драйверами и внезапно понимаешь, что уже три часа ночи.
DPDK действительно использует hugepages для больших пулов памяти и снижения нагрузки на TLB, а vfio-pci даёт доступ к устройствам с защитой через IOMMU. Но даже официальная документация DPDK довольно быстро напоминает, что за высокой скоростью стоит сложная системная настройка. СТОП:
|
Параметр |
Intel Core i7-8700 |
MikroTik CCR1036-8G-2S+ |
|---|---|---|
|
Архитектура |
x86-64 Coffee Lake |
Tilera TILE |
|
Ядер / потоков |
6 / 12 |
36 / 36 |
|
Частота |
3.2 GHz base / 4.6 GHz turbo (Intel) |
1.2 GHz (mikrotik.com) |
|
Время 1 такта |
0.313 нс @3.2 GHz / 0.217 нс @4.6 GHz |
0.833 нс |
|
Разница по времени такта |
≈2.7–3.8× быстрее на ядро |
1× |
|
L3 cache |
12 MB (Intel) |
— |
|
CCR routing, 64B FastPath |
— |
41.67 Mpps ≈ 24 нс/пакет* (mikrotik.com) |
|
CCR routing, 64B + 25 queues |
— |
7.64 Mpps ≈ 131 нс/пакет* (mikrotik.com) |
|
CCR routing, 64B + 25 firewall rules |
— |
3.05 Mpps ≈ 328 нс/пакет* (mikrotik.com) |
|
X520 10G, 64B, 1 порт line-rate |
14.88 Mpps → 67.2 нс между пакетами |
10G SFP+ тоже ограничен физическим портом |
|
2×10G X520, оба RX line-rate |
29.76 Mpps → 33.6 нс между пакетами aggregate |
CCR заявляет до 41.5 Mpps / ~28 Gbit/s суммарно (mikrotik.com) |
|
Для VPP/DPDK |
Очень сильный single-core |
Не применимо |
|
Для тяжёлого NAT/ACL |
Вероятно i7-8700 + VPP заметно интереснее, но нужен реальный тест |
RouterOS: производительность сильно падает при фильтрах |
|
Победитель по single-core latency |
🏆 i7-8700 |
|
|
Победитель как готовый appliance |
|
🏆 CCR1036 |
https://mikrotik.com/product/CCR1036-8G-2Splus
https://cdn.mikrotik.com/web-assets/product_files/CCR1036-8G-2S-r2_210536.pdf
https://doc.dpdk.org/dts/test_plans/nic_single_core_perf_test_plan.html
У меня по коже мурашки пошли, выходит можно по задержке выехать? Да, можно.
Я долго мучился. Это был огромный труд, и я точно не первый человек, который пытался собрать из обычного сервера маршрутизатор мечты.
В какой-то момент мечта частично исполнилась. Когда появились современные нейросети, я начал использовать чужие открытые наработки как черновики и строительные леса вокруг своей идеи. Какие-то результаты появились.
Но это не стало production-продуктом.
Мои бывшие боссы вряд ли простили бы такие авантюры. Хотя мне всё ещё хочется верить, что BGP full view моя конструкция прожевала бы как низковисящий карагач для кролика.
Годы летят, а пакет всё ещё хочет пройти
Потом я разработал кодек, долго работал на несколько крупных компаний и в итоге ушёл из провайдерской жизни.
Теперь у меня нет стойки с тысячей абонентов. Есть небольшой MikroTik hEX, простой коммутатор Cisco — та самая «киска» — и старая идея.
Я хочу сделать управление сетью визуально понятным.
Не превратить сеть в детскую игрушку. Не спрятать реальные правила под красивыми картинками. Не нарисовать зелёную стрелку там, где программа ничего не поняла.
Я хочу, чтобы инженер видел одновременно и конфигурацию, и физический смысл происходящего.
Так появился проект Visual IDE for Networks, или VI4N.
Сейчас доступна альфа-версия 1.0.1. Это приложение на C#, .NET 10 и Avalonia. Оно умеет подключаться к MikroTik в режиме наблюдения или загружать экспорт RouterOS для полностью локального анализа.
Но началось всё не с красивых карточек.
Сначала пришлось научиться читать RouterOS export.
Разумеется с моим характером мне пришлось подготовить целый аттракцион развлечений для разного комьюнити:
Конфигурация — это не просто текст
Экспорт RouterOS выглядит обманчиво просто:
/interface bridgeadd name=bridge-lan vlan-filtering=yes/interface bridge portadd bridge=bridge-lan interface=ether2 pvid=10add bridge=bridge-lan interface=sfp-sfpplus1 \ frame-types=admit-only-vlan-tagged/interface bridge vlanadd bridge=bridge-lan tagged=bridge-lan,sfp-sfpplus1 \ untagged=ether2 vlan-ids=10
Человек видит здесь bridge, access-порт и trunk. Программа сначала видит строки, кавычки, переносы, комментарии и набор аргументов.
Поэтому первым слоем стал парсер:
public static RouterOsExportDocument Parse(string sourceName, string text){ ArgumentException.ThrowIfNullOrWhiteSpace(sourceName); ArgumentNullException.ThrowIfNull(text); var entries = new List<RouterOsExportEntry>(); var diagnostics = new List<RouterOsParseDiagnostic>(); var currentSection = string.Empty; foreach (var statementInfo in ReadStatements(text)) { var statement = statementInfo.Text; if (statement.StartsWith('/')) { currentSection = statement.Trim(); continue; } if (statement.StartsWith('#')) continue; if (string.IsNullOrWhiteSpace(currentSection)) { diagnostics.Add(new( statementInfo.LineNumber, "", "Команда находится вне раздела RouterOS")); continue; } var tokens = Tokenize(statement); var arguments = new Dictionary<string, string>( StringComparer.OrdinalIgnoreCase); foreach (var token in tokens.Skip(1)) { var equals = token.IndexOf('='); if (equals <= 0) continue; arguments[token[..equals]] = Unquote(token[(equals + 1)..]); } entries.Add(new RouterOsExportEntry { Section = currentSection, Command = tokens[0], Arguments = arguments }); } return new RouterOsExportDocument( sourceName, text, entries, diagnostics);}
Здесь нет искусственного интеллекта, который магически понимает роутер.
Есть довольно скучный код, который собирает продолжения строк, сохраняет номера команд, разбирает аргументы и сообщает, если встретил незакрытую кавычку или команду вне раздела.
И это принцип проекта: нейросеть может помочь написать код, но результат должен оставаться детерминированным и проверяемым.
Красное должно означать проблему, а не настроение дизайнера
После разбора конфигурации начинается анализ.
Сейчас проверяются правила firewall, маршрутизация, DNS, открытые сервисы управления и распространённые поля с секретами:
public static IReadOnlyList<ConfigFinding> Analyze( RouterOsExportDocument document){ var findings = new List<ConfigFinding>(); AnalyzeManagementServices(document, findings); AnalyzeFirewall(document, findings); AnalyzeRouting(document, findings); AnalyzeDns(document, findings); AnalyzeSecrets(document, findings); return findings .OrderByDescending(f => f.Severity) .ThenBy(f => f.Category, StringComparer.OrdinalIgnoreCase) .ToList();}
Например, если включён Telnet, FTP, обычный HTTP или незашифрованный API без ограничения по адресам, анализатор показывает критическую проблему.
Если нет запрещающего правила в цепочке input, он предупреждает, что сам маршрутизатор может быть доступен из сетей, которым управлять им совсем не обязательно.
Это пока не аудит уровня большого коммерческого продукта. Проверки не доказывают абсолютную безопасность. Они позволяют быстро увидеть очевидное и не забыть то, что обычно откладывают на потом.
Красное означает: сюда надо посмотреть человеку.
Зелёное означает: конкретная проверка пройдена.
Зелёное не означает: Артур выдал сертификат безопасности всей инфраструктуре.
Trunk или access — теперь видно
Отдельной маленькой победой стала визуализация VLAN.

Можно было поступить просто: если у порта много связей, написать TRUNK, а если одна — ACCESS. Выглядело бы красиво и иногда даже совпадало бы с реальностью.
Но такой подход пришлось бы защищать комментариями на Хабре.
Поэтому приложение читает реальные данные:
/interface bridge port/interface bridge vlantaggeduntaggedvlan-idspvidframe-types
А затем классифицирует порт:
var mode = tagged.Count > 0 && untagged.Count > 0 ? SwitchportMode.Hybrid : tagged.Count > 0 || frameTypes.Equals( "admit-only-vlan-tagged", StringComparison.OrdinalIgnoreCase) ? SwitchportMode.Trunk : untagged.Count > 0 || pvid is not null ? SwitchportMode.Access : SwitchportMode.Unknown;
В режиме Артура всё объясняется особенно настойчиво:
ACCESS — одна VLAN без тегаTRUNK — несколько VLAN с тегамиHYBRID — обычный и тегированный трафик одновременноНЕ ЯСНО — данных недостаточно
Последняя метка для меня самая важная.
Если модель не знает — она должна сказать «не знаю». Сетевой эмулятор, который уверенно врёт, опаснее отсутствующего эмулятора. (Мой режим тестируйте сами, скрины тут добавлять не буду.)
Пакет должен пройти глазами
В приложении есть тестовый режим. Пользователь задаёт исходный адрес, адрес назначения, протокол, порт и цепочку.
Модель последовательно проверяет dst-NAT, firewall и маршрут:
var nat = FindNat(document, scenario, "dstnat");var effectiveDestination = scenario.DestinationAddress;if (nat is not null){ effectiveDestination = nat.Get("to-addresses") ?? effectiveDestination; steps.Add( $"2. NAT изменит адрес назначения " + $"на {effectiveDestination}.");}var filter = FindFilter( document, scenario, effectiveDestination);if (filter is not null){ var action = filter.Get("action")?.ToLowerInvariant() ?? "accept"; if (action is "drop" or "reject") { return new TrafficSimulationResult( false, "ЗАБЛОКИРОВАНО", "Пакет остановлен правилом firewall.", steps); }}var route = FindBestRoute( document, effectiveDestination);if (route is null){ return new TrafficSimulationResult( false, "НЕТ МАРШРУТА", "Firewall пропустил пакет, " + "но маршрута до назначения нет.", steps);}
Настоящий packet flow RouterOS гораздо сложнее. Пакет проходит RAW, connection tracking, mangle, NAT, filter, routing и другие этапы. FastTrack вообще может обходить часть стандартной обработки — это хорошо видно на официальной схеме Packet Flow.
Поэтому моя модель не заявляет, что полностью заменила RouterOS или CHR.
Если она встречает неподдержанное условие, результат становится не зелёным и не красным:
var unknownRule = document .InSection("/ip firewall filter") .Where(e => !e.IsDisabled) .Select(e => new { Entry = e, Unknown = e.Arguments.Keys.FirstOrDefault( key => !SupportedRuleArguments.Contains(key)) }) .FirstOrDefault(x => x.Unknown is not null);if (unknownRule is not null){ return new( false, "НЕОПРЕДЕЛЕНО", $"Условие «{unknownRule.Unknown}» " + "пока не поддерживается моделью.", steps, false);}
Неопределённость здесь является функцией, а не багом.
Я хочу постепенно расширять покрытие, добавлять сценарии и сравнивать результаты с CHR и настоящими устройствами. Но пока модель честно показывает границу собственных знаний.
Зачем существует режим Артур
Перед запуском приложение предлагает два варианта: обычный режим и режим Артура.
Функционально это одна и та же программа.
Режим Артура не является демо и не загружает заранее подготовленный файл. Он умеет подключаться к живому MikroTik, открывать топологию, показывать интерфейсы, firewall, NAT, DHCP и запускать проверки.
Разница в языке.
Обычный интерфейс предполагает, что пользователь понимает термины.
Режим Артура объясняет так, будто разработчик устал отвечать на один и тот же комментарий:
Маршрут не найден.Роутер буквально не знает, куда отправить пакет.Даже хейтер теперь знает.
Или:
Интерфейс выключен или кабель не поднялся.Пакет без интерфейса не полетит.Артур разжевал.
Это стёб, но стёб не над новичками.
Новичок не обязан знать разницу между input и forward, tagged и untagged, route и default route. Я сам когда-то не знал.
Стёб направлен на нашу инженерную привычку делать непонятный интерфейс, а потом считать пользователя глупым.
Если инструмент можно объяснить проще, значит, его стоит объяснить проще.
Конфигурация не должна сразу лететь в роутер
Второй режим работы — лаборатория конфигурации.
Пользователь загружает .rsc или текстовый экспорт RouterOS. Приложение создаёт редактируемую копию в памяти. Исходный файл не изменяется, а подключение к маршрутизатору вообще не требуется.
В лаборатории можно:
-
просматривать разделы и команды;
-
открывать схему интерфейсов;
-
смотреть firewall, NAT и DHCP;
-
менять временную копию;
-
запускать проверки;
-
моделировать прохождение трафика;
-
сравнивать изменения;
-
откатывать шаги;
-
создавать задачи;
-
запускать намеренно уязвимый демонстрационный конфиг.
Да, сейчас это ещё не настоящий цифровой двойник RouterOS.
Но для меня важна сама последовательность:
загрузилувиделизменил копиюпроверилпонял последствияи только потом полез в настоящий роутер
Слишком часто в сетях первая проверка гипотезы одновременно является изменением production. Мне хочется разделить эти два события.
Немного про безопасность
Приложение сохраняет адрес, API-порт, имя подключения и пользователя. Пароль существует только в оперативной памяти текущего запуска и не попадает в devices.json.
Сам список устройств записывается атомарно через временный файл:
public void Save( IEnumerable<SavedDeviceProfile> profiles){ var directory = Path.GetDirectoryName(FilePath); if (!string.IsNullOrWhiteSpace(directory)) Directory.CreateDirectory(directory); var temporaryPath = FilePath + ".tmp"; File.WriteAllText( temporaryPath, JsonSerializer.Serialize( profiles, JsonOptions)); File.Move( temporaryPath, FilePath, true);}
Но здесь нужна честная оговорка.
Живое подключение пока использует классический RouterOS API на порту 8728. TLS через API-SSL/8729 ещё не реализован. Поэтому текущую версию следует использовать только в доверенной локальной сети или через VPN.
До фразы «безопасный production-инструмент» проект пока не дорос. Именно так и должно быть написано в статье об альфе.
Что уже собрано
Версия 1.0.1 автоматически собирается через GitHub Actions. Workflow использует закреплённый .NET SDK, lock-файлы NuGet, прогоняет 83 теста, создаёт self-contained сборку Windows x64 и публикует ZIP вместе с SHA-256.
Исходники и релиз лежат на GitHub:
Visual IDE for Networks — релиз v1.0.1
Приложение пока не подписано сертификатом. Нет установщика. Нет TLS для RouterOS API. Нет полноценной эмуляции всего packet flow. Cisco и Eltex не подключаются. Одновременно работает только одна активная сессия с маршрутизатором.
Киска не работает.
Eltex нет.
В целом сыро, да.
Нейрослоп?
Решать вам.
Зачем я всё это делаю
Я хочу, чтобы появился понятный стандарт визуального редактирования сетей. И, да, я знаю что вы скажите что статья не понятная, но пишу та я ее без нейросетей. Порядок странный, но я просто делюсь инструментов где микроток или киска или елтекс может превратится вполне понятную настройку и в базу тестев. Откройте бэкап конфига, протестируйте, запустите пакет, взгляните что не так.
Не очередная панель, в которой таблицу из CLI просто перенесли в DataGrid. Не зелёные кружочки ради зелёных кружочков. А модель, где можно открыть устройство, провалиться внутрь, увидеть физические порты, bridge, VLAN, IP, маршруты и firewall как связанные уровни.
Чтобы access был не словом из документации, а понятной ролью порта.
Чтобы trunk не приходилось угадывать.
Чтобы при нажатии на интерфейс было видно, куда пойдёт пакет.
Чтобы изменение конфигурации сначала становилось гипотезой, потом тестом и только после этого — командой для настоящего оборудования.
И да, я всё ещё хочу закончить историю с DPDK.
Хабр — строгая аудитория. Последняя моя сборка сыпала пакеты, и выдавать её за победителя CCR было бы нечестно. Возможно, с современными инструментами и нейросетями продолжить этот эксперимент станет проще.
Я хочу это проверить.
Но сначала показываю визуальную альфу.
Когда-то я стоял ночью на вышке и не понимал, какой SFP+ нужно поставить, чтобы два конца линии увидели друг друга.
Сегодня я пишу программу как Артур — Нейрослоп, которая должна объяснять такие вещи человеку прямо на схеме.
Наверное, технологии нужны именно для этого. Не чтобы сделать вид, что мы всё знаем. А чтобы следующий человек потратил на понимание немного меньше ночей.
ссылка на оригинал статьи https://habr.com/ru/articles/1068948/