Owl's minds

Последние несколько дней я занимаюсь довольно странным видом разработки – пишу не столько код, сколько инструкции машинам, которые пишут код, после чего отдаю результат другой машине, чтобы та объяснила первой, почему она опять всё сделала не так.

Звучит как менеджмент.

Собственно, в какой-то момент у меня одновременно оказались Claude и Codex, достаточно большой инфраструктурный проект, некоторое количество оплаченных токенов и совершенно естественное желание выяснить, можно ли заставить двух дорогих электронных идиотов работать друг против друга с пользой для общества.

Спойлер: можно.

Но, как обычно, есть нюанс.

Якодзуна номер один против якодзуны номер два

Изначальная схема была предельно примитивной.

Берём задачу. Отдаём её одной модели:

Вот тебе архитектура на сто страниц, вот код, вот тесты, вот история проекта, прочитай всё и реализуй.

Она читает.

Долго читает.

Потом думает.

Потом ещё думает.

Потом пишет код.

После этого берём вторую модель:

А теперь прочитай архитектуру на сто страниц, код, тесты, историю проекта, результат работы предыдущего деятеля и проведи независимый review.

Она тоже читает.

Долго читает.

Потом думает.

Потом находит BLOCKER.

После чего мы возвращаемся к первой:

Вот review. Прочитай всё ещё раз и почини.

В какой-то момент status у Codex начал показывать контекст больше 185 тысяч токенов, и стало понятно, что мы изобрели не разработку при помощи AI, а очень дорогой способ заставить два трансформера по очереди читать «Войну и мир».

При этом подход работал.

Что особенно обидно.

Модели действительно находили ошибки друг у друга. Причём не только банальное «забыли проверить None», а вполне неприятные вещи на границах API: потерю фактического состояния, неверную интерпретацию отсутствующего поля, aliasing входных provider objects, исключения из hostile Mapping, уничтожающие evidence соседних записей, и прочие радости, которые обычно обнаруживаются примерно через полгода после запуска системы в production.

Один агент реализовывал. Второй пытался сломать. Первый чинил. Второй снова пытался сломать.

Иногда второй находил ошибку в исправлении ошибки.

Например, у нас была совершенно прекрасная цепочка:

implementation
    ↓
review
    ↓
finding
    ↓
remediation
    ↓
rereview
    ↓
новая дырка в remediation
    ↓
remediation remediation
    ↓
rereview remediation remediation

В какой-то момент это начало напоминать сертификаты TLS, где очень хочется спросить, кто сертифицировал сертификатора сертификатора.

Зато результат действительно становился лучше: в одном из таких циклов reviewer воспроизвёл ситуацию, когда кастомный Mapping, у которого keys() кидает RuntimeError, мог выбить целиком чтение quota вместе с нормальными соседними записями.

Исправление потом отдельно проверялось adversarial cases, включая особенности dict() в CPython.

То есть это уже не «AI написал мне Flask todo application».

Машины натурально срались из-за семантики collections.abc.Mapping.

Моё почтение.

Проблема оказалась не в моделях

Достаточно быстро стало понятно, что главный расход здесь вообще не генерация кода.

Главный расход – восстановление состояния мира.

Каждый новый агент приходил как сотрудник в первый рабочий день:

Здравствуйте. А что мы тут вообще строим?

И мы давали ему:

architecture.md
implementation-spec.md
17 ADR
8 implementation reports
11 reviews
6 remediation reports
tests/
source/
README
CHANGELOG
и на всякий случай всё остальное

После чего удивлялись, почему он полчаса размышляет.

Причём хуже всего было то, что огромный контекст не обязательно делал результат лучше.

В нём одновременно находились:

  • текущая архитектура;
  • старая архитектура;
  • решение проблемы;
  • review решения проблемы;
  • старый review старого решения проблемы;
  • Proposed ADR, который ещё ничего не разрешает;
  • отчёт трёхдневной давности, который уже частично устарел.

И модель должна сама понять, кто из них папа.

Это очень человеческая проблема. Если посадить разработчика перед двадцатью противоречащими друг другу документами, он тоже не станет умнее от того, что прочитает их все.

READ ALL оказался антипаттерном

Особенно смешно, что некоторое время мы сами буквально называли задания READ_ALL.

Логика была понятна: пусть модель знает максимум контекста и не пропустит важную архитектурную деталь.

На практике получалось примерно:

READ ALL EVERYTHING AND THEN DO ONE SMALL THING.

После чего агент действительно читал всё.

Машина инструкции выполнила. Какие к ней вопросы.

Постепенно родилась противоположная идея:

агент должен получать не максимальный контекст, а минимальный достаточный авторитетный контекст.

Это довольно важная разница.

Не:

прочитай историю проекта

а:

прочитай AGENTS.md
прочитай CURRENT_PROJECT_STATE.md
прочитай спецификацию текущего slice
открой только файлы, непосредственно связанные с ним
историю трогай только если обнаружилось конкретное противоречие

И внезапно модели перестали начинать каждую задачу с раскопок Трои.

AGENTS.md как BIOS для электронного сотрудника

Вторая полезная штука – вынести повторяющиеся правила из prompt'ов.

Раньше каждый prompt выглядел примерно так:

не трогай production
не читай секреты
не делай provider mutations
не начинай следующий milestone
не меняй архитектуру
не решай Proposed ADR самостоятельно
не ходи за пределы repository
не коммить
не пушь
не ешь жёлтый снег

Причём это повторялось снова.

И снова.

И снова.

В итоге prompt на исправление одной функции мог быть размером с небольшую кандидатскую диссертацию.

Теперь большая часть постоянного контракта живёт в AGENTS.md: границы filesystem, секреты, правила live access, разделение read/write capabilities, порядок завершения milestone и так далее.

А task prompt начинается с простого:

READ AGENTS.md FIRST.

Это оказалось неожиданно важным.

Потому что одно дело – иметь файл с правилами.

Другое – эксплицитно сказать машине его прочитать.

Да, мы пришли к необходимости напоминать компьютеру прочитать инструкцию к компьютеру.

Будущее наступило.

Не передавать контекст. Передавать решение

Следующий шаг оказался ещё полезнее.

Предположим, один агент несколько часов исследовал API и выяснил:

  • где именно теряются HTTP headers;
  • почему существующий abstraction нельзя безопасно менять;
  • какой минимальный новый interface нужен;
  • какие варианты были рассмотрены и отвергнуты;
  • что доказано кодом;
  • что наблюдалось live;
  • что пока неизвестно.

Раньше следующему агенту мы говорили:

Теперь сам всё это исследуй и реализуй.

Зачем?

У нас уже есть результат исследования.

Например, сегодняшний pagination research выяснил вполне конкретную вещь: ovh.Client.call() уничтожает requests.Response после JSON decode, поэтому текущий OvhApiReader.get() физически не может увидеть X-Pagination-*.

При этом менять общий OvhApiReader ради одного endpoint – слишком большой blast radius, поэтому предложен узкий OvhNetworkV2ApiReader с дополнительным raw_call.

Следующему агенту больше не надо заново доказывать это.

Ему надо сказать:

Вот authoritative design.
Реализуй §11.
Если repository reality ему противоречит — остановись.
В остальных случаях не переизобретай архитектуру.

То есть handoff между моделями должен содержать не весь мыслительный процесс предыдущей модели, а сжатое доказанное состояние задачи.

По сути мы независимо пришли к тому же принципу, на котором построены нормальные distributed systems:

не реплицировать весь журнал событий каждому участнику, если ему достаточно актуального materialized state.

Разделение ролей

Очень полезным оказалось и то, что модели перестали быть взаимозаменяемыми «сделай всё».

Теперь работа естественно делится примерно так:

research
   ↓
design
   ↓
implementation
   ↓
independent review
   ↓
bounded remediation
   ↓
bounded rereview
   ↓
closure

И каждый агент получает только свою роль.

Research-agent не пишет код.

Implementation-agent не устраивает повторный архитектурный симпозиум.

Reviewer не исправляет найденную ошибку.

Remediation-agent не начинает следующий milestone, потому что «ну я уже тут».

Это кажется бюрократией, пока reviewer не находит реальную проблему.

Тогда становится понятно, зачем она нужна.

Если reviewer одновременно исправляет собственную находку, то проверяет он в итоге самого себя. Гораздо интереснее дать результат обратно другому якодзуне.

Пусть дерутся.

Review тоже не должен читать Вселенную

Тут мы сначала наступили на те же грабли второй ногой.

После небольшой реализации запускался:

FINAL COMPREHENSIVE READ-ALL INDEPENDENT CLOSURE REVIEW.

И reviewer снова читал всё.

Теперь review стараемся строить от falsification targets.

Например, design прямо говорит, что в следующем изменении опасны четыре вещи:

  • raw_call случайно превратится в универсальную дырку к provider API;
  • supplementary probe сможет уронить основной успешный read;
  • счётчик API requests начнёт врать;
  • кто-нибудь радостно объявит pagination COMPLETE, хотя доказательств этому нет.

Вот их reviewer и должен пытаться сломать в первую очередь.

Не «проведи философский анализ всего репозитория».

А:

Вот invariants. Вот diff. Докажи, что хотя бы один из них нарушен.

Это гораздо более продуктивная форма агрессии.

Машины очень любят расширять задачу

Есть ещё одна особенность LLM, которая особенно хорошо проявляется на больших проектах.

Они хотят помочь.

Очень хотят.

Ты просишь:

Добавь наблюдение двух pagination headers.

Модель думает:

А не построить ли нам generic pagination framework для всех будущих provider APIs?

Нет.

Сядь.

Именно поэтому у каждой задачи появились explicit stop conditions:

no cursor following
no completeness promotion
no v1 changes
no generic HTTP abstraction
no next slice
STOP

Причём STOP – возможно, одна из самых полезных инструкций во всём prompt engineering.

Потому что хороший человеческий разработчик тоже иногда смотрит на соседний код и думает: «ой, тут заодно можно красиво переделать».

Но человеку хотя бы можно сказать это голосом.

Машине приходится писать капсом.

Доказательство важнее уверенности

Ещё одна вещь, которую пришлось достаточно жёстко прибить к проекту: различие между:

я думаю, что API работает так

и:

мы видели, что API работает так

В документах появились довольно скучные, но полезные категории:

LIVE_OBSERVED
CODE_PROVEN
DERIVED_INFERENCE
UNVERIFIED

Например, реальный live-read показал, что OVH действительно отдаёт X-Pagination-Elements, рекламирует X-Pagination-Cursor и X-Pagination-Size, а X-Pagination-Cursor-Next в конкретном ответе отсутствовал.

Из этого не следует, что отсутствие Cursor-Next всегда означает конец коллекции.

Очень хочется, конечно.

Но не следует.

И модель не должна превращать удобное предположение в архитектурный факт только потому, что оно красиво ложится в код.

В результате текущая модель честно говорит:

UNVERIFIED_PAGINATION

Хотя на реальном запросе мы получили все 59 сетей.

Это, пожалуй, одна из самых полезных привычек при AI-разработке вообще: заставлять машину отдельно маркировать факт, вывод и предположение.

Она прекрасно умеет писать убедительный текст для всех трёх.

В этом и проблема.

Тестов скоро будет больше, чем программы

Есть, правда, побочный эффект.

Каждый раз происходит примерно следующее:

нашли edge case
    ↓
написали regression test
    ↓
reviewer придумал более мерзкий edge case
    ↓
ещё test
    ↓
remediation обнаружила соседний случай
    ↓
ещё пять tests

В какой-то момент мы дошли до полутора тысяч unit tests, а потом бодро пошли дальше.

И есть серьёзное подозрение, что тестовая база в итоге будет в разы больше кодовой.

Но если подумать, это довольно забавный способ использовать LLM.

Генерировать boilerplate они умеют прекрасно.

Значит можно тратить человеческое время не на написание двадцатого assertEqual, а на вопрос:

Каким максимально уёбищным объектом можно сломать вот эту границу?

И тут второй якодзуна иногда проявляет настоящее вдохновение.

Deep nested JSON до recursion limit?

Держи.

Custom Mapping, который кидает исключение из keys()?

Почему бы и нет.

Hostile subclass?

Конечно.

Mutation after capture?

Сейчас проверим.

Обычный разработчик в пятницу вечером до некоторых из этих вещей просто не доберётся.

У машины пятницы нет.

Самое смешное – стало быстрее

И вот тут случилась неожиданная часть эксперимента.

После всей этой дополнительной бюрократии:

  • current state;
  • authority chain;
  • bounded slices;
  • handoff;
  • отдельные research/design artifacts;
  • implementation report;
  • independent review;
  • remediation;
  • rereview;

работа ускорилась.

Потому что исчезло главное пожирающее время действие:

заново понять весь проект.

Раньше новый агент мог потратить огромную часть контекста просто на восстановление того, что предыдущий уже выяснил.

Теперь implementation prompt иногда помещается буквально в несколько абзацев:

READ AGENTS.md FIRST.

Implement R1-S3-D.

Authoritative design:
docs/.../R1_S3_PAGINATION_ENVELOPE_DESIGN.md

Implement §11 exactly.

Here are hard stops.
Here are review risks.
Run validation.
Write report.
STOP.

И всё.

Не потому что задача стала проще.

А потому что контекст уже скомпилирован предыдущим этапом.

Контекст – тоже ресурс

Наверное, главный вывод из всей этой истории оказался довольно банальным.

LLM context надо воспринимать примерно как RAM.

Если у тебя её много, это не означает, что туда обязательно надо загрузить весь диск.

Можно.

Linux даже постарается сделать из этого cache.

Но приложение от этого не обязано стать быстрее.

Большой контекст полезен, когда задача действительно требует большого количества одновременно доступной информации.

Но огромный исторический контекст – это ещё и:

  • больше времени на чтение;
  • больше токенов;
  • больше конкурирующих инструкций;
  • больше старых решений;
  • больше возможностей зацепиться за уже неактуальную ветку рассуждений.

Поэтому сейчас наша цель не «дать модели всё».

Наша цель:

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

Это очень похоже на проектирование API.

И, наверное, неудивительно.

А кто из якодзун победил?

Никто.

И в этом весь смысл.

Один периодически лучше исследует большую область и строит связный design.

Другой неожиданно хорошо включает режим параноика и начинает искать способы заставить Python сделать какую-нибудь совершенно противоестественную хуйню.

Потом они меняются местами.

Попытка выбрать «лучшую модель» вообще оказалась менее интересной, чем попытка построить процесс, в котором ошибка одной модели становится входом для другой.

Потому что две модели, согласные друг с другом, – это просто две модели.

А две модели, которым поручили доказать, что другая облажалась, – уже какой-никакой engineering process.

Человек при этом постепенно превращается из автора каждой строчки кода в странную смесь архитектора, арбитра, диспетчера и организатора подпольных боёв сумоистов.

Сидишь такой утром.

С одной стороны Claude.

С другой Codex.

Посередине репозиторий.

Говоришь:

Так, этот утверждает, что всё PASS.

И передаёшь diff второму.

Через некоторое время оттуда:

CHANGES_REQUIRED

BLOCKER findings: 1

Ну.

Погнали ещё кружочек.

Сегодня (вчера) у меня немного пригорело, но обо всём по порядку.

Предприятие Mikrotik позиционирует себя как производитель SOHO (small-office/home-office) оборудования для масс. Однако в линейке продукции данного предприятия также есть железки с замахом на инсталляции в датацентрах. Ну есть и есть, нормальные люди ими не пользуются. Есть же всякие juniper/cisco и прочее промышленное оборудование. Но как же вы ошибаетесь в своих предположениях... Достаточно большое количество дноминистраторов, в числе которых, каюсь, был и ваш покорный слуга привыкли для решения задач использовать инструменты, которые им знакомее, чем другие знакомые. В общем сложно выйти из зоны комфорта. И вот лет 5 назад я решил, что Mirktoik CCR1036 или что-то такое будет отличным решением под пограничный маршрутизатор в датацентре. Однако я же сейчас занимаюсь проектом кросс-сайтового соединения, одной большой красивой приватной сетью и тому подобными запчастями. И в очередной раз я столкнулся с тем какой же некротик неповоротливый.

Вкрации, есть таблицы маршрутизации (vrf на умном). По сути можно представить себе это как отдельные виртуальные маршрутизаторы внутри физического. Соответственно есть основная vrf таблица – main и можно создать что-то типа до 2 или 3 тысяч своих. И вроде бы всё хорошо, vrf работают, изолируют маршруты друг от друга, но что делать, когда возникает потребность ходить из одной vrf в другую? В микротике возникает коллапс, поскольку утекание маршрутов (routing leaks) из/в таблицу main просто нормально (никак) не реализовано. Господа из некротик сообщают, что вот вот мы уже всё это починим. Начиная с версии 7.14... Сейчас на дворе 7.20.1.

В общем хочешь сделать хорошо – посмотри как у других и сделай это сам. И тут второй раз у меня пригорело, но уже по другому поводу.

Есть такое понятие как LLM (большие языковые модели) – обывателю продаются под соусом искуственного интеллекта. И вот эти замечательные модели, якобы, улучшают нашу жизнь и сокращают время доступа к искомой информации. Но (!) есть нюансы, как и во всём вокруг, а именно – LLM не серебрянная пуля и чтобы получить ответ именно о том, о чём ты спрашиваешь – нужно самому понять вопрос, иначе можно нарваться на галлюцинации модели и прочий бред. Ещё есть опасность того, что вместо решения какой-то одной конкретной задачи могут начаться длительные поэтические изыскания на различные темы с уходом в сторону от проблемы. Поэтому все вот эти исследования на тему того, что AI помощники для программистов – ухудшают качество кода + уменьшают производительность труда вполне реальны, я провёл личное исследование в течении месяца и да, всё так и есть. Основная причина, как мне кажется, кроется в психологии людей – мозг штука хитрая и ищет возможности решать проблемы самым малозатратным способом, а тут джинн в банке, который даёт ответы на всё вокруг. Но джинны, как известно, хоть и выполняют желания своего нанимателя, но не всегда таким образом, которым он хотел, чаще даже наоборот.

Так вот, продолжая про микротик. Проблему мы определили, vrf main у нас “неутекаемый”. Определяли мы это с ChatGPT вчера 3 часа, он предлагал разные варианты, с бриджами, с veth, с macvlan (которые к бриджам вообще не применимы) и прочие “обходные пути”, но ни один из них не работал. Штош, я по-старинке пошёл в гугель и уже оттуда узнал о проблемах с main таблицей, множетсво жалоб пользователей, обещаний разработчиков и прочем, о чём LLM тактически умолчал (ну его же не спрашивали напрямую, вот он и решал задачу, которую, как он считал, перед нима поставили)

В конечном итоге после прочтения документации, опыта пользователей и куче другой инфы “постаринке” я пришёл к выводу, что на Mikrotik оборудовании для работы с vrf лучше всего и чище всего таблицу main не трогать вообще. И тогда всё красиво можно утекать. Две пользовательские таблицы нормально стекуются через внутренний BGPVPN (тоже костыль, но рабочий) и всё нормально (наверное, вот сейчас допишу и буду пробовать) “утекает” друг в друга по фильтрам, которые сам настроишь. В общем моё решение на текущий момент создать две vrf – upstream (для всех приходящих ко мне провайдеров, в ней конечно же сделать все анонсы агрегатов и отправлять их наверх) и transit (для моей транзитной оверлей сети, которая будет впоследствии растянута между сайтами) Из transit в main будут утекать только специфики + в main будут анонсируемые префиксы в блэкхол, которые я и буду отдавать апстримам. Из плюсов такого подхода – если в transit (по сути на серверах) нет такого адреса – бордер сразу же отрежет весь входящий траффик по маршруту blackhole, что в свою очередь снизит количество arp траффика внутри сайта и тому подобные флуктуации со сканнерами. Из main же утечёт только маршрут по умолчанию, причём аггрегированный (0.0.0.0/0), что позволит не тянуть fullview, при наличи такового в main таблице и сократит количество обсчитываемых маршрутов в других vrf, (опять же каинд оф оптимизация)

Какие выводы мы сделали:

  1. Никаких

  2. У firefox очень большие боли с рендерингом больших страничек с разметкой, так что лучше писать в отдельном редакторе, а потом вставлять готовый текст, иначе можно потерять всё собою написанное.

  3. Mikrotik не подходит для использования в датацентрах (ну то есть как, подходит, но только в роли временной затычки, и памяти мало, и скорость небольшая, и много архитектурных особенностей, которые привносят боль в жизнь сетевого инженегра)

  4. LLM не является серебряной пулей и не стоит думать, что он всеведущ. Он отвечает только на заданные вопросы, причём прямо и топорно, не учитывая в большинстве случае контекст и/или подводные камни, которые лежат вот совсем на поверхности. В целом его можно использовать как дополнение к гуглежу, однако не более.

Дальше думать и решать только вам самим, здесь я могу лишь поделиться своим печальным опытом, который всё равно мало кому интересен.

И снова у нас будет увлекательная история о том, как я женил ужа с ежом. В целом тут будет много специфической информации о тезнологиях, с которыми каждый ИТ-специалист среднего уровня сталкивается ежедневно, посему сей опус может быть сложноват для восприятия неподготовленным читателем, однако как известно я пишу больше для себя заметки, но и с вами всегда рад поделиться. За сим начнём.

Итак, есть замечательный язык программирования go lang от небезиветсной корпрации добра Google. Сам язык имеет как свои плюсы, так и минусы, о которых я конечно же рассказывать не буду. В одном из своих предыдущих высеров я как-то упоминал, что для ускорения разработки в целом и сокращения количества написанного программного кода принято использовать так называемые библиотеки функций. В go lang данный феномен называется модулями. Соответственно программист пишет какой-то модуль, складывает его куда-то и после этого все желающие, у кого есть доступ до этого куда-то, могут не писать этот самый код, а использовать уже готовые функции и методы, предоставляемые этим модулем. Всё просто и прозрачно. На первый взгляд.

Однако диавол, как все знают, кроется в деталях. И такой деталью является то, что люди между собой делятся не всем, что они написали и некоторые модули могут находиться где-то в приватной системе хранения, куда требуется аусвайз любого толка. В своё время компания Oracle придумала для именования пакетов такую схему <доменное имя>/<пакет>/<подпакет>/.... например example.com/api/auth. Google решила, что это как-будто бы здорово и переняла опыт, попутно добавив внутри компилятора возможность эти самые пакеты скачивать из интернета базируясь на вышеописанное схеме. Так, в случае с примером выше, при запуске команды go get example.com/api/auth компилятор отправится по данному пути, магическим образом в конце добавит все интересующие его адреса и скачает к себе готовый модуль, если таковой имеется.

Первая из интересных особенностей – go lang модули распространяются просто упаковкой исходных кодов, соответственно мы можем просто упаковать наши тексты в zip и спокойно распространять их архивом. Однако это много ручной работы, каждый раз собирать архив. И тут нам на помощь приходит особенность современных систем управления версиями по типу Gitlab. Если спросить у последнего по определённому адресу – вместо самого git репозитория можно получить готовый zip со всеми исходными кодами, актуальными на дату запроса. Удобно? Удобно конечно, роботы работыют за нас. Но доступ в эту самую систему контроля и управления версиями чаще всего закрыт тройной авторизацией, а которой go компилятор не знает ничего. И тут возникает вторая особенность, связанная с форматом модуля. Мы хотим получить example.com/api/auth, а он доступен либо через https://git.example.com/test/api/auth либо вообще через ssh://git@git.example.com/test/api/auth. Сам по себе go lang не умеет работать с таким формато импортов, однако спасибо разработчикам – компилятор имеет костыль. Если по адресу пакета вместо данных будет специальным образом сформированная строка с тегом meta – go компилятор возьмёт её и попытается с локально указанными секретами сходить куда его послали. Итак, магический тег выглядит условно следующим образом

И в целом всё, компилятор сам спросит метадату, сам сходит в git репозиторий и сам же заберёт все данные для сборки модуля, при этом не надо явно нигде указывать пути.

И в целом это всё прекрасно работает в рамках локальных машин пользователей и даже некоего CI/CD проекта, который имеет на борту ssh ключ для скачивания всех нужных зависимостей.

Но тут мы сталкиваемся с тем, что качать одно и то же 100500 раз и нагружать конечный сервер это как-то не комильфо и задумывается о некоем промежуточном гноилище, которое будет в себе хранить уже готовые для использования артефакты. Долго ли, коротко ли – нашёлся проект Athens. Простейшая прокся, у которой можно спросить какой-то модуль. В случае если в кеше его нет – он куда-то сходит и скачает к себе, если в кеше есть – просто отдаст никуда не ходя. И пока ты работаешь с публичными модулями – всё замечательно, но как только тебе нужно проксировать ещё и приватные – начинаются приседания.

Итак, перво-наперво нужно для себя решить как Athens будет эти модули забирать и откуда. В нашем случае есть условный Gitlab где-то в интернете. Забирать можно, как водится, по ssh и https. В примере выше метатег говорит, что исходники модуля находятся по адресу ssh://git@git.example.com/test/api/auth, но мы не хотим иметь на сервере, например, ключ ssh для клонирования исходников, а хотим сделать gitlab token, по которому обезьянка будет забирать всё, что её интересует.

Соответственно перво-наперво настраиваем git для пользователя, от которого запущен athens:

~/.gitconfig

[url "https://git.example.com/"]
  insteadOf git@git.example.com:
  insteadOf ssh://git@git.example.com/
[credential "https://git.example.com"]
  username = gitlab-token
[credential]
  helper = store

~/.git-credentials

https://gitlab-token:gplat-XXXXXXXXX@git.example.com

После этого настраиваем сами афины

~/.env

http_proxy=http://proxy:3128
https_proxy=http://proxy:3128
no_proxy=127.0.0.1,localhost,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,10.233.0.1,.local,.svc,.monitoring.svc
ATHENS_GONOSUM_PATTERNS=example.com/*
GO_ENV=production
GO111MODULE=on
ATHENS_GLOBAL_ENDPOINT=https://athens.local

~/config.toml

GoBinary = "go"
GoEnv = "production"
GoBinaryEnvVars = ["GOPROXY=direct","GOROOT=/usr/local/go","GOSUMDB=sum.golang.org"]
GoGetWorkers = 10
GoGetDir = ""
ProtocolWorkers = 30
LogLevel = "debug"
LogFormat = "plain"
CloudRuntime = "none"
EnablePprof = false
PprofPort = ":3001"
FilterFile = ""
RobotsFile = "robots.txt"
Timeout = 300
StorageType = "disk"
Port = ":3000"
UnixSocket = ""
GlobalEndpoint = "http://localhost:3000"
BasicAuthUser = ""
BasicAuthPass = ""
HomeTemplatePath = "/var/lib/athens/home.html"
ForceSSL = false
ValidatorHook = ""
PathPrefix = ""
NETRCPath = ""
GithubToken = "" 
HGRCPath = ""
TraceExporter = ""
TraceExporterURL = "http://localhost:14268"
StatsExporter = "prometheus"
SumDBs = ["https://sum.golang.org"]
NoSumPatterns = ["example.com/*"]
DownloadMode = "sync"
NetworkMode = "strict"
DownloadURL = ""
SingleFlightType = "memory"
IndexType = "none"
ShutdownTimeout = 60

[SingleFlight]
[Storage]
  [Storage.Disk]
    RootPath = "/athens-data/"

Теперь ставим перед всем этим nginx, заворачиваем ssl и пробуем что у нас получается на уже локальной тачке

export GOPROXY="https://athens.local"
export GOSUMDB="off"
export GO111MODULE="on"
cd /tmp
mkdir t
cd t
go mod init example.in/test
go get -v -u example.com/api/auth@0.0.1

В случае успеха athens сходит в наш вымышленный gitlab с паролями, которые мы ему указали, скачает в себя нужную версию, отмеченную тегом в репозитории и отдаст готовые данные пользователю. Если что-то пошло не так – добро пожаловать в удивительный мир программирования, друг, изучай что там в логах и почему так произошло. Возможно к конфигурации git ещё потребуется добавить файлик ~/.netrc, но о нём ты можешь уже узнать из интернета.

Очень давно в моей голове, ещё года с 14го витает идея сделать свой собственный хостинговый проект. Чтобы что? Чтобы то. По сути потому что могу, ну и так, поиграться в целом.

Всё начинается с регистрации нашего уютного предприятия в главном управляющем публичной адресацией сети интернет по европейскому региону – RIPE. Сложностей минимум – регистрируемся, заливаем пачку документов и платим мзду в размере нескольких тысяч евро за членство. Получаем подтверждение с той стороны и вот мы уже официальный член партии.

Как говорил Билли Гейтс – 640 килобайта хватит всем (интересный факт, что данное высказывание, которое сейчас является культовым, было исключительно ошибкой журналиста, поскольку сам Билли сказал фразу – “Когда мы установили верхний лимит PC-DOS на 640 килобайт, мы думали, что никому никогда столько памяти не понадобится”, но журналист, как водится, не уточнил что именно имел в виду Гейтс. Так и повелось.) Так и в компьютерных сетях при их организации в стародавние времена было сделано смелое предположение, что 4 миллиарда уникальных адресов в интернете будет достаточно, однако оказалось не казалось, в связи с чем в дополнение к протоколу ipv4, ограниченного этими самыми 4 миллиардами, родился протокол ipv6, с разительно большим адресным пространством (для понимающих в ipv4 используется всего 32 бита для адреса, в свою очередь в ipv6 используется уже 128, а 2 в степени 128 это очень и очень много)

Однако отступление выше было предусмотрено для того, чтобы описать следующие шаги после регистрации. Итак, мы уже входим в сообщество. Каждый партнёр имеет право на одну бесплатную ipv4 сеть размера /24 (256 адресов) и одну бесплатную ipv6 сеть размера /32 (это очень очень много адресов). Но есть один нюанс. Пару-тройку лет назад свободные блоки ipv4 окончательно закончились, благодаря активному развитию интернета, а так же киберсквоттерам, которые в своё время накупили подсетей где могли и теперь втридорога продают их всем страждущим по 30-60 евро за адрес (путём несложных математических исчислений имеем цену за /24 префикс от 7 тысяч евро и в космос) Со своей стороны RIPE придумал хитрую схему с очередью на выдачу. После того, как свободные блоки закончились предприятие пришло к выводу, что стоит начать распаковывать зарезервированные блоки и ставить в очередь всех страждущих, дабы в случае освобождения уже существующих сразу же выдавать им. На момент получения моего личного блока я провёл в очереди около 500 дней. ipv6 же выдали сразу после запроса без каких-либо проблем.

По завершению второго шага на руках имеем два блока буличных ip адресов – классический ipv4 (185.227.77.0/24) и новомодный ipv6 (2a13:a1c0::/32).

Сам по себе интернет не является какой-то одной большой центральной точкой, а состоит из множества различного оборудования, которое сообщает по цепочке друг другу как к нему добраться, а уже внутри себя управляет присвоенными ему блоками адресов. Соответственно для того, чтобы весь интернет узнал как попасть на route 66 – мы должны через кого-то, кто уже поключен к глобальной системе, рассказать остальным, что наши блоки лежат вот тут вот и к ним ходить через вот тут вот. По историческим сведениям мы знаем, что в стародавние времена для распространения маршрутов использовался протокол RIP, который уже R.I.P. и ему на замену пришёл очаровательный и неповоротливый BGP. Для удобства распространения информации все выданные блоки адресов должны быть ассоциированы с виртуальным номером автономной системы (здесь и далее ASN), однако дополнительно регистратор уведомляет, что у каждой автономной системы должно быть как минимум два канала, через которые анонсируются в сеть её блоки адресов. Сказано – сделано, ищем двух оперторов связи, которые готовы предоставить нам услугу IP Transit, договариваемся с ними на BGP пиринг и подаём прошение в RIPE, указывая данных операторов связи как своих контрагентов. В случае успеха получаем заветный номер (AS214507 в нашем случае).

Дальше дело техники, закупаем тонну оборудования, пограничный маршрутизатор, свитч, сотню серверов, устанавливаем всё это где-то, настраиваем пиринг и радуемся жизни громко хлопая в ладоши. Но жизнь, как известно, чуть сложнее, чем могла бы быть. Поскольку с теоретической частью мы околозакончили – можно переходить к практике.

Итак, поскольку я люблю сети и компудахтерные технологии, плюс, как я упоминал вначале, у меня в душе сидит идея об организации своего собственного хостинга – было принято решение купить шкаф и вот тут вот под ногами строить что-то прям в доме.

Первая проблема, с которой я столкнулся была в отсутствии хоть какого-то внятного интернета в моём селе. Путём долгих вдумчивых рассуждений был закуплен набор Starlink, протестирован и введён в эксплуатацию с небольшими ограничениям в плане скорости (например Starlink выдаёт 250 мегабит на скачивание и до 25 мегабит на загрузку в интернет, ну и задержка от 50 до 150 мс в зависимости от погодных условий и прочих флуктуаций в сети интернет) Меня это “устраивает”, однако где-то фоново происходит проект кибердеревни. Я уже обнаружил идущиё вдоль моря магистральнй оптический кабель корпорации ТЕТ и веду переговоры по строительству отвода в помещение школы неподалёку от кабеля. Вообще была идея стерменировать интернет вот тут вот дома, но строительство 800 метров оптического кабля должно было встать в 40000 евро, когда 350 метров в околоподъёмные 17000, что тоже очень дорого, но решаемо. В общем ТЕТ предприятие большое и неповоротливое, да и я в целом не флеш, так что вялотекуще общаемся и думаем про строительство, радиолинки и прочие страсти христовы.

Возвращаясь к сказанному выше с дырочкой в интернет мы определились, однако теперь нам нужно две вещи – оборудование и провайдеры, которые готовы дать нам ту самую рукопожатость с системой интернет. По оборудованию были произведены изыскания и выбраны Juniper SRX1500 как пограничный роутер в силу его производтельности и удобства настройки, как свитч для будущих клиентов тут на месте был выбран Juniper QFX5000-какой-то там, с 48 SFP портами и 6 QSFP. Вряд ли, конечно, получится утилизировать всю пропускную способность, выдаваему этой железкой, но почему бы и да. Попутно в процессе эксплуатации было выявлено, что для внутренних нужд дома категорически мало 8 портов ethernet, да ещё и некоторым требуется Power-over-ethernet решение, в связи с чем был дозаказан Juniper EX3400-48P. (пока вместо него стоит 8-портовый некротик с двумя десяточными аплинками, странное, конечно, решение от Mikrotik, поскольку имея 8 гигабитных портов ты даже один десяточный сильно не утилизируешь, но есть как есть)

Собираем всё это в гирлянду, подключаем, настраиваем и вот уже дома есть интернет, вайфай раздаётся через некротиковскую тарелку и все счастливо живут. Однако мы тут не про личный комфорт, а про публичный, поэтому продолжаем реализацию нашего проекта. У starlink есть несколько тарифных планов как для частных лиц, так и для бизнеса. Сначала я жил на простом residental подключении за 50 евро в месяц, однако в данном случае невозможно получить один статический внешний ip адрес и всех клиентов Starlink выпускает через богомерзкий CGNAT. (технология трансляции внутренних блоков ip-адресов клиентов в адреса из публичных блоков, поскольку, как мы помним, количество публичных ip-адресов органичено и закончилось, соответствено по определённой логике несколько клиентов для выхода в интернет могут использовать один и тот же публичный ip-адрес даже не зная об этом. Для провайдера это плюс, однако для конечного клиента это минус, поскольку запросы из сети интернет не могут быть доставлены напрямую клиенту с приватным адресом) По результатам исследования starlink был перерегистрирован как business клиент с ценником в три раза дороже, однако из бенефитов мы получаем 2 терабайта приорити траффика (я даже боюсь себе представить что такое не приорити с текущими потерями периодическими и временем задержки) и условно статический публичный ip-адрес, который приземляется непосредственно на мой пограничный маршрутизатор, что даёт мне возможность получать прямые запросы из интернета на моё оборудование минуя обработку на стороне Starlink. (но конечно же со своими ограничениями по протоколам и блокировками некоторых сайтов согласно регулам ЕС)

Соответственно – дырочка в интернет найдена, прямой доступ до оборудования настроен, можно идти калядовать до пиринг партнёров с целью установления IP Transit. Чаще всего в больших датацентрах используется прямое подключение корневого или не очень оборудования между участниками сети. Т.е. например при покупке услуги IP Transit у корпорации RETN и нахождении оборудования в точке присутствия последнего просто организовывается прямое соединение порт в порт минуя всевозможное промежуточное оборудование. Но наш случай сложный.

Пока оптическая трасса находится в процессе обсуждения у нас имеется только дырочка в интернет через космос. Сам по себе starlink не предоставляет для клиентов услуги IP Transit, в связи с чем было принято решение временно использовать GRE туннели до партнёров. Это даже не VPN или тому подобное, скорее инкапсуляция траффика для удобства целенаправленной передачи данных. Соответственно находим парочку партнёров, договариваемся с ними, настраиваем туннели и видим как траффик успешно течёт в их сторону и возвращается обратно.

А дальше начинается прекрасное общение с вышестоящими провайдерами. Например у того же RETN все анонсы от их партнёров фильтруются по данным, находящимся в описании автономной системы. Обычно там указывается откуда данная автономная система может получать анонсы и анонсы кого в какую автономную систему может присылать. И всё было очень просто, когда твоя автономная система является конечной. Т.е. ты просто указываешь свои данные и данные партнёров и полетели. Однако когда ты сам становишься транзитным оператором приходится изучать новые уровни дна. И в наше описание автономной системы добавляется новая запись типа AS-SET, которая по сути является списком номеров автономных систем, которые наша автономная система желает анонсировать своим партнёрам.

Долго ли, которотко ли, однако за сутки удалось с некоторыми ограничениями завести всё это дело. Конечно RETN в Таллинне почему-то не хочет принимать мои личные префиксы на своём оборудовании, однако через Ригу всё завелось и вот уже довольный и счастливый дед, радостно потирая ручонки может из любой точки интернета достучаться до NanoPi Neo 2, лежащего вот тут вот в шкафу, без каких либо ограничений. Причём не только по ipv4 (185.227.77.2), но и по ipv6 (2a13:a1c0:77:2::1).

В процессе настройки всего этого было много интересного как с настройкой gre туннелей, так и с routing instances, да и прочие приседания с попытками подружить Juniper и Mirkotik, однако всё получилось. Возможно я расскажу об этом, но это уже совсем другая история.

Я обещал – я собрался с мыслями. Ну почти. Или не собрался, но очень очень стараюсь это сделать.

Итак, последний раз я разглаголствовал по поводу Rust и Python. Честно говоря за давностью событий я уже не очень помню в чём же всё-таки было пригорание, но попробую вспомнить.

Итак – Rust. Всё ещё никому толком не нужный язык, который даже в ядре линукса задепрекейтили, но который усиленно продолжают пропихивать в массы. В общем и целом в чатике я уже писал, что основная проблема была в том, что для сборки компилятора и рантайма этого самого Rust требуется уже больше 16 гигабайт места, что, как по мне, какой-то сюр. Меня тут поправили недавно, что Rust использует тот самый пресловутый llvm в процессе своей сборки и сравнение с последним по занимаемому пространству было как минимум неверно. Штош – как есть. Но всё же я хочу заметить, что у меня ВСЯ операционка на диске занимает 44 гигабайта (в том числе с docker мусором, с базами в postgres и вообще), а также хочу заметить, что при пересборке мира в gentoo (полная пересборка всех пакетов) я ни разу не сталкивался с тем, чтобы кому-то не хватило 16 гигабайт. Делаем выводы, работаем дальше.

Теперь про петухон. Есть для администраторов набор утилит и шаблонизаторов, который называется ansible. Написан он полностью на петухоне с использованием петухонных же библиотек. Но есть один нюанс – некоторые **петухонные** библиотеки написаны **не** на петухоне. В общем и целом идея здравая – для того, чтобы что-то работало быстро – лучше всего написать это на компилируемом языке. Так вот, люди взяли и написали, но сделали это без уважения. Ansible для работы с серверами использует SSH подключение (удалённое подключение по зашифрованному каналу для исполнения команд на сервере) и есть у этого подключения несколько способов авторизации, как то по паролю, по секретному ключу, другое. В современном мире люди наизобретали большое количество способов шифрования данных и каждый день появляются новые, какие-то уходят в стандарты, какие-то тихонько умирают. Соответственно для шифрования секретных ключей, которые можно использовать при подключении к удалённому серверу есть также несколько стандартов шифрования, новые и старые. Для каждого стандарта есть свой собственный модуль (ну или общий моуль, который по мере добавления/удаления изменяется) Одним из стандартов является bcrypt. Там снизу много математики, но сейчас не будем углублять в детали. И вот модуль петухона для этого метода шифрования написан на Rust. Единственный модуль из базовой поставки ansible, который написан на Rust. А теперь возвращаемся к началу и собираем паровозик рассуждений:

  1. Нам нужен ansible, чтобы управлять серверами, мы его устанавливаем
  2. Он за собой тянет и компилирует модули
  3. В модулях этот сраный bcrypt
  4. Для bcrypt он тянет целый rust

Короче у меня пригорело и я пошёл писать cbcrypt, на чистеньком С. И даже написал, но естественно его никто в апстрим принимать не собирается. В общем и целом петухонные модули на отличных от петухона языках программирования это тоже интересный люк с гадостями, кучей биндов и кривых дефиниций, но об этом как-нибудь в другой раз.

Ещё последние несколько дней/недель погружаюсь глубоко во flask, это такой набор модулей и функций для быстрого запуска web-приложений и относительно простой их разработки. В целом всё было бы хорошо, если бы было не так плохо. ORM (flask-alchemy, модуль для работы с базой данных), никаких оптимизаций нет, на каждое движение запрос к базе. В общем очень большой модуль с одной стороны с попытками охватить все возможные варианты использования. Пришлось писать своё, с оптимизациями. Даже что-то прикольное получилось, осталось дописать. Следующим идёт локализация@интернационализация. Здесь предлагается модуль babel. Очень прикольный и забавный, медленный и своенравный. Особенно мне понравилось то, что для создания переводов требуется запустить 3 команды, потом поправить 18 файлов и запустить ещё две команды, чтобы он из промежуточных файлов сделал готовы в своём собственном ведомом ему формате. Видимо и это придётся переписывать. Штош, за удобство платим скоростью, но чот сильно дорого, поскольку сам петухон уже тормоз бесконечный.

Штош, с чистой совестью и спокойной душой можно рассказать новую эпопею по уже завершённой задаче с подключением к провайдеру через древние технологии.

Всё началось полгода назад, когда провайдер сообщил нам, что для взаимодействия с ним потребуется настроить ни много, ни мало – несколько IPSec туннелей, которые позволят поверх интернета “безопасно” обмениваться траффиком с ними. У меня под рукой была прекрасная железка Juniper SRX380, которая по всем параметрам должна была справиться с задачей и спокойно принять на себя весь удар шифрования траффика, но, как это часто бывает, что-то пошло не совсем по плану и мы потратили огромное количество времени чтобы понять что же.

Но я сильно забежал вперёд, поэтому обо всём по порядку.

По сути IPSec (IP Security) это достаточно старая реализация VPN туннелей, которая позволяет организовывать частные виртуальные сети поверх публичных и в траффик которых никто кроме соединившихся сторон не должен иметь возможности заглянуть. Для организации данных туннелей производятся всевозможные числодробления, зашифровки, расшифровки, в общем куча всякой математики, к которой предрасположено сетевое оборудование. Но как это часто бывает – каждый производитель этого самого сетевого оборудования видит стандарты по-своему, откуда возникает множество проблем. Есть возможность настроить туннель в двух режимах – policy-based (когда траффик, выходящий из определённого интерфейса, внутри железки по определённым параметрам будет выбираться, шифроваться и дальше передаваться куда шёл) и route-based (когда в устройстве есть виртуальный интерфейс с какой-то адресацией и весь траффик, проходящий через этот интерфейс, независимо от параметров, шифруется и отправляется к строго указанной дестинации) По очевидным причинам разные режимы подходят для разных методов использования – в основном через ipsec туннели можно передавать IP траффик, а остальные протоколы могут работать, а могут не работать, но и тут ребята не растерялись и придумали, что внутри вот этого вот ipsec туннеля можно запустить ещё один протокол, под названием GRE, который уже может спокойно обслуживать любые протоколы, обходя ограничения чистого ipsec. Так вот, для обычного траффика TCP/IP вполне достаточно использовать route-based ipsec, всякие bgp, icmp и прочие нормально в него пролазят, однако для того, чтобы засунуть GRE нужно использовать policy-based ipsec, посколько партнёры на той стороне решили, что и сам ipsec туннель и gre интерфейс должны утилизировать одну и туж е связку source-destination. Т.е. по сути весь траффик, который уходит в GRE туннель сначала должен упаковываться в GRE, а уже потом шифроваться на ipsec и отправляться на ту сторону.

Суть да дело – начал я погружаться в это. основные туннели были подняты примерно в тот же день без каких-либо проблем (впрочем проблемы были, поскольку для апстрима у нас используется отдельный виртуальный роутер, но там быстро всё порешалось. Вкрации – для того, чтобы ipsec туннель нормально работал – его внешний интерфейс – адрес, на который терменируется ipsec – должен находиться в том же виртуальном инстансе, что и внешний интерфейс, в который выходит траффик до партнёра), а вот с GRE over IPsec возникли проблемы. Продолжительный гуглёж и игрища на стенде ничего не дали, пока я не обнаружил на просторах интернета, что у Juniper SRX есть органичение – GRE over IPSec возможно запустить только с route-based IPSec. Запрос на использование route-base IPSec со стороны партнёра был отклонён со словами – всю жизнь так паркуемся, ради вас менять ничего не будем.

По советам проверенных комрадов было решено взять циску, во избежание каких-либо неточностей между разными производителями оборудования. Сказано – сделао, за гроши приобретене Cisco ASA 5508-X, всё настроено, но беда подкралась откуда не ждали – ASA, как впоследствии оказалось, не умеет в этот самый GRE. Т.е. все ipsec туннели успешно завелись, но соединиться так и не удалось.

В конечном итоге было принято решение перестать пытаться поженить сетевое оборудование и прямо на сервере было развёрнуто решение strongswan+bird, которое после непродолжительных приседаний и бесконечного гуглежа было-таки приведено в рабочее состояние. Правда пришлось дополнительно поприседать с policy-based routing. Зато мы узнали много нового, как то:

  • strongswan для работы в режиме route-based требует чтобы в настройках было указано add=route
  • так же для того, чтобы знать куда какой туннель (vti) цеплять в настройках каждого пира должен быть указан уникальный mark, который впоследствии при создании виртуального интерфейса должен совпадать с key
  • для gre же настройка пира должна быть стандартной, без всяких там хитрых mark, там уже xfrm сам разберётся что шифровать, а что нет

Рабочий конфиг для route-based ipsec получился таким

conn route-based
  left=1.2.3.4
  leftsubnet=0.0.0.0/0
  right=4.3.2.1
  rightsubnet=0.0.0.0/0
  type=tunnel
  keyexchange=ikev1
  auto=route
  authby=secret
  ike=aes256-sha1-modp1024
  esp=aes256-sha1
  lifetime=24h
  lifetime=1h
  mark=10

После того как в ipsec status подключение будет успешно установлено можно создавать интерфейс

ip tunnel add rb1 mode vti local 1.2.3.4 remote 4.3.2.1 key 10
ip link set up rb1
ip a add 10.0.0.2/31 dev rb1

и о чудо – ping 10.0.0.3 успешно проходит, bgp сеесия успешно устанавливается и все полученные с той стороны сети нормально работают. Тут ещё предлагают в интернете подкручивать sysctl -w net.ipv4.conf.rb1.disable\_policy=1, но у меня без этого заработало, впрочем стоит иметь в виду.

Попутно для route-based ipsec в интернете советуют настраивать /etc/strongswan.d/charon.conf

install_routes = no
install_virtual_ip = no

В свою очередь для GRE over IPSec процесс немного иной. Подключение выглядит проще

conn grx
  left 1.2.3.4
  right 4.3.2.2
  type=tunnel
  keyexchange=ikev1
  auto=add
  authby=secret
  ike=3des-sha1-modp1024
  esp=3des-sha1
  ikelifetime=24h
  lifetime=1h

А сам GRE туннель уже поверх этого накорячивается следующим образом

ip tunnel add grx mode gre local 1.2.3.4 remote 4.3.2.2
ip link set up grx
ip a add 10.0.0.4/31 dev grx

И вот уже GRE over IPSec работает как задумано.

Очевидно ещё нужно настроть /etc/ipsec.secret, но тут уже вы сами с усами. Эндой ёр трип.

Давненько я не графоманил, получается время пришло. Как раз всякого накопилось. Начнём с последних событий.

Поскольку я во-IT (а также вы-IT), мне желательно быть на связи с интрнетом ну не то, чтобы всё время, но очень часто. Публичные WiFi точки попадаются не всегда, да и сложно их найти когда ты в тех же полях (да-да, на фазенде у меня есть StarLink, но моя фазенда пока не по всей Латвии) Как одно из решений можно конечно же предложить HotSpot на телефоне, но он жрёт батарейку так, что лучше бы нет. Как временная замену интернету подойдёт, но на постоянку использовать такое я бы не стал, мне телефон звонить-писать, а не вот это вот всё.

Изучая интернет на тему LTE мы натыкаемся на несколько вариантов, основными из которых являются USB to M.2 WWAN adapter и нативный WWAN модем в ноутбук. С первым всё понятно, ты таскаешь в дополнение к ноуту чёрную коробоку с двумя достаточно массивными антеннами, на которую все вокруг, а особенно всякие службы безопасности, смотрят с подозрением. В целом оно работает. С песнями и плясками, но работает. Второй же вариант более предпочтительный, один девайс, один интернет, один фюр^W^W но и тут всё оказалось непросто.

Так сложилось исторически, что мне импонируют ноутбуки производства Lenovo. Сначала был E480, потом всратый E485, потом E490, так я жил, не тужил, но оказалось, что в линейке E отсутствуют девайсы с возможностью воткнуть WWAN. Долго-ли, коротко-ли, проведя исследования был обнаружен L14 Gen 4, который и в WWAN может, и AMD хороший на борту несёт, да и в целом неплохой девайс (не считая того, что у него максимально ублюдский форм-фактор nvme и все-лишь один M.2 слот под него) Соотнеся все плюсы и минусы берём железку, начиняем её памятью под завязку, ставим NVME на 1 терабайт, собираем Gentoo, живём, радуемся, ждём когда же Lenovo произведёт под эту модель WWAN карточки (да-да, ноутбук выпустили, а карточки забыли, так бывает) Но почему же мы ждём? А ждём мы потому, что Lenovo, как мама, заботится об окружающей среде и в BIOS своих ноутбуков зашивает коды WWAN карточек, которые можно использовать. Т.е. ты не можешь пойти, купить какую-нибудь Sierra карточку и просто её воткнуть, ноут тупо не загрузится с ошибкой YOUR MODEM IS NOT WHITELISTED. Вся эта замечательная забота о человечестве в широких массах называется FCC Lock и навязана как самими производителями (кто занёс денег за то, чтобы их карточки работали, того и пропустят), так и всевозможными чинушами, которым только дай волю, они дышать разрешат через раз.

Но мы отвлеклись. Через N месяцев, таки, Lenovo потрудилось и прислало мне сие чудо – Fibocom L860-GL-16, стильный, модный, новейшее изобретение человечества, практически сразу с завода. Штош, вставляем мы этот чудо-девай, ноут нормально загружается, но при попытке подключения к сети нам сообщают, что девайс Software Locked. Т.е. по сути вы платите 100+ евро за то, чем можно пользоваться только тогда когда вам позволят третьи лица.

Приступаем к погружению в пучины этой бездны и на просторах интернета обнаруживаем, что данная напасть постигла людей давно и люди даже нашли несколько способов с этой напастью бороться. Ах да, ещё один интересный момент – поскольку данные модули шли с завода, то в стоковой прошивке, как это часто бывает, были баги и недочёты, которые не позволяли разбллокировать даже официальным вирусным ПО от Lenovo, на что последние пообещали выпустить обновление, но как его устанавливать никто конечно же не удосужился рассказать. На сайте Lenovo для обновления есть даже какие-то зайчатки в виде пары deb пакетов под Ubuntu 22, но они тоже особо не работают, я пытался.

В конечном итоге после продолжительных исследований я смирился и остановился на том, что время от времени для разблокирования модема приходилось по нескольку раз перезагружать ноутбук ибо никаким иным образом перезапустить модем не представлялось возможным (да-да, в стоковой прошивке не работала AC+CFUN=15, модем намертво вис и досвидули)

Через некоторое время я пообщался со знающими людьми, почитал интернет и пришёл к выводу, что пора бы обновляться, но как обычно – информации как это сделать нигде нормальной нет. Потратил я на это дело около суток, пока разобрался что куда засовывать.

Мои исследования начались с того, что, якобы, обновить модем можно очень просто и быстро с помощью Windows, типа скачай инсталлятор и он сам всё сделает. Я скачал – инсталлятор обновил мне ВСЮ железную начинку, которую нашёл, за исключением WWAN модуля (спасибо хоть загрузочные записи EFI не затёр, а то у меня после обновления BIOS было и такое, очень увлекательно было восстанавливаться через raspbery pi, пушо больше ничего под рукой не было)

Продолжились исследования тем, что я случайно наткнулся на ветку про эти Fibocom на 4pda. Многобукав, совершенно непонятные процессы, инструкции написанные нердами для нердов. В общем классика. Вот вам набор серых фломастеров, раскрашивайте пейзаж заката.

Первым подходом к снаряду было скачать все эти запчасти и попытаться запустить. На официальном сайте Lenovo есть конечно же EXE файлы для винды и пара deb пакетов, которые толком не работают. Погружаемся в инструкцию, и находим, что есть интересная поделка Flash Tool Light от интел, в упаковке с которой идёт тот самый downloadTool. Без каких-либо описаний, в справке по приложению многабукав, которые не рассказывают как именно этим приложением пользоваться.

Возвращаемся к статье и понимаем, что кроме прошивальщика нам требуется ещё и сама фирмварь, которую надо залевать на ноутбук (шёл 2024 год, люди уже лет 10 как придумали Update Over The Air – OTA, но мы не такие, мы так делать не будем). На этом этапе мы с удивлением для себя узнаём, что человечество придумало такую замечательную утилиту как innoextract, которая позволяет выковыривать файлы из Windows EXE инсталляторов. Но я немного забежал вперёд. на 4pda люди усиленно советовали скачивать cab файлы с официального сайта microsoft, которые содержат в себе прошивки и обновления для WWAN модемов, но и тут подкралась засада. Заключалась она в том, что версия прошивки выглядит примерно как 18601.5001.00.00.01.16.32_GC или что-то подобное. Есть как минимум три версии WWAN модуля от Fibocom – L580, L680-GL, L680-GL-16 и по логике вещей номер версии должен содержать указание на то для какой версии он предназначен, однако всё на том же 4pda местные кулибины утверждают, что успешнр зашивают 18600 на L680-GL-16 и всё работает, однако если почитать тред дальше – становится понятно, что умельцы умудряют зашивать версию 18601 на L680-GL и разблокировать достижения^W дополнительные возможности.

Итак, на данном этапе у нас есть непонятно работающий downloadTool и россыпь всевозможных cab и exe файлов с прошивками, правда уже распакованными. Читая дальше обнаруживаем команду, которой с помощью downloadTool можно прошить модем. Запускаем, получаем “Reboot your modem” и сталкиваемся с проблемой описанной ранее – при перезагрузке модема в отрыве от самого девайса он намертво зависает, а попутно получаем вторую проблему downloadTool не умеет обновлять модемы, которые подлючены в ноутбук напрямую через M.2 разъём, только через USB. По счастливой случайности у меня под рукой оказался переходник USB to WWAN, в который я запихнул бедный модуль. Но и тут оказалось всё не слава богу – downloadTool при подключении модема увидел последний, однако даже прошивка с официального сайта не накатывалась со словами “Wrong partition table. Abort”

Кое-как, с такой-то матерью, мне удалось в итоге обновить модем на версию, которая начиналась с 18600. Да-да, это прошивка от другой модели модема, но мне нужно было двигаться хоть куда-то. Соответственно модем прошит, работает через переходник. Выключаем ноут, раскручиваем, отключаем батарею, вставляем модем, собираем всё обратно, не забыв подключить батарею и после включения видим – YOUR DEVICE IS NOT WHITELISTED.

Разбираем всё обратно, засовываем модем в переходник, идём читать дальше, распаковываем ещё десяток exe-шников, пока в треде (на 300+ страниц) не натыкаемся на то, что нужно не только зашивать саму прошивку, но ещё и секретные файлы от Lenovo, которые прописывают идентификаторы модема для сравнения их с whitelist в BIOS. Суть да дело, зашиваем вместодвух файлов четыре, выбрав один из файлов, в названиие которого есть PSI и 00000000 (куча нолей). Меня это не смутило, мы же экспериментаторы. Прошивка 18601 от Lenovo наконец успешно встала. Разборка, интеграция, сборка, загрузка – YOUR DEVICE IS NOT WHITELISTED.

Чтение форума ничего особо не дало, поскольку там велось общение в основном о том как использовать WWAN модули с Kinetik и прочим сетевым оборудованием, Lenovo там никто не интересовался от слова совсем. Покумекав ещё я решил попробовать залить в модем другой PSI файл, у которого вместо 0000000 было что-то бесмысленное, но отличное от этого самого 0000000. И о чудо, BIOS пропустил модем к загрузке, система радостно отрапортовала, что версия теперь новая, но проблема с fcc unlock никуда не ушла, впрочем модем после обновления стал разблокироваться утилитами без каких-либо перезагрузок, а также заработала возможность перезагружать сам модем без перезагрузки всего устройства. В дополнение ко всему вышеперечисленному в модеме разблокировался слот под вторую сим-карту, вангую это eSIM, но в этот люк я уже не нырял.

Подводя итоги хочется пожелать всего плохого производителям, которые блокируют нормальную работу устройств по своей прихоти и запрещают конечному пользователю использовать те устройства, которые ему хочется, ограничивая их узким кругом дорогостоящих девайсов. Позиция Apple, не иначе.

В дополнение скажу, что я также приобрёл queltek модем, который по спецификациям совместим с моим ноутбуком, но по факту оказалось, что Lenovo не просто заблокировали во всё своём оборудовании использование модемов отличных от разрешённых, они ещё и в разных моделях ноутбуков (даже внутри однйо серии L14 Gen 3 и L14 Gen 4) разрешили использовать только те модемы, часть серийного номера которых совпадает с разрешёнными в BIOS.

До прошивки Queltek руки пока не дошли, может в будущих сериях и промелькнёт, но на сколько я знаю там те же проблемы с fcc_unlock, а менять рабочую железку на такую же, но от другой компании я смысла не вижу.

За сим спешу откланяться, я тут и так уже наклякал длинный пост о своих приключениях. Спасибо, что потратили ваше время и, как водится, хоть иногда смотрите на небо.

Искренне ваш, *49-кун

Накопилось у меня тут всякого по поводу работы с SRX и думаю я, что пора бы это куда-то вылить, чтобы не забыть.

Работаю я с Juniper SRX плюс-минус полгода, за это время я успел накупить себе целых два SRX300 и один SRX320. Чуть позже мне достался в обслуживание SRX380 с 10G портами. Забавная штука, но обо всём по порядку.

Итак, что же такое juniper – это предприятие, которое ориентировано на оборудование для глобальных сетей. У него достаточно большое коммьюнити, но чтобы к нему примкнуть нужно либо заплатить бесконечное количество денег через неопределённых лиц, поскольку нормальных партнёров в прибалтике я так и не нашёл, либо страдать. Если у вас на руках есть железка купленная с рук или восстановленная – вы можете долго регистрироваться на сайте juniper, ругаться с их техподдержкой, но в конечном итоге вас завернут и сообщат – покупай честную железку или путешествуй. Соответственно ни обновлений, ни ответов на вопросы, ничего не получить из официальных источников.

Конечно же есть всякие обходные пути, которые позволяют получить пусть и не последние, но обновления для Juniper железок. (Например я нашёл tg канал, но чтобы подобрать правильный пароль от архива нужно сломать себе весь мозг и пальцы) Дополнительно, как недавно оказалось, на Reddit достаточно живое коммьюнити по Juniper, которое может давать вполне дельные ответы. В общем я уже и забыл даже, что существуют форумы и вот это вот всё, а тут вдруг такое открытие.

Первая, да и, пожалуй, основная проблема, с которой я столкнулся настраивая Juniper это группы безопасности (security groups). Суть этой запчасти в том, что мы можем настраивать внутри маршрутизатора зоны безопасности и правила, по которым либо пропускать траффик, либо отбрасывать. Приключения начинаются, когда ты настраиваешь что-то сложнее офисного интернета.

Практический пример – чтобы быть автономной системой в интернете требуется не менее двух соседей, которые будут дальше по цепочке транслировать остальным в интернете как до вас добраться. По логике вещей хочется, чтобы каждый партнёр обслуживался своим виртуальным маршрутизатором и это можно организовать – вы просто рассовываете их в конфигурации и полетели... До того момента, пока у вас не начнёт появляться асимметричный траффик (это когда от нас сообщения уходят через одного соседа, а возвращаются через другого) В этот момент SRX начинает сходить с ума со своими группами безопасности и весь обратный траффик просто отбрасывать. Я даже нашёл несколько статей по поводу того как это починить на сайте джунипера, но увы, это никак не помогло. В конечном итоге было принято решение сгрузить всех соседей в один инстанс виртуального роутера, что, впрочем, впоследствии упростило настройку других запчастей.

Второй замечательной проблемой, которая больше относится к неосведомлённости о настройке оборудования, чем к самому оборудованию, хотя с другой стороны производитель мог бы по умолчанию и не включать функционал, который его никто не просил включать. У Juniper SRX есть прекрасная вещь под название ALG (Application Layer Gateway). Суть этой вещи в том, что Juniper сам залезает внутрь траффика, определяет к какому протоколу он относится и уже по своим внутренним правилам устанавливает ограничения на различные аспекты (количество соединений, скорость передачи данные, максимальное количество пакетов в секунду и тому подобное) Так мы столкнулись с тем, что переключив SIP траффик внутрь своей автономки ALG ограничил нас 100 одновременными подключениями к телефонной станции, а все остальные он просто втихаря отбрасывал. В конечном итоге всё дошло до того, что сам SRX был переведён из flow-mode в packet-mode, что превратило железку в тупой маршрутизатор, отключив все защитные фишки ради которых он и брался.

Прошло время, я поигрался со стендами, понастраивал разные топологии и в какой-то момент включил обратно flow-mode, что привело к частичному отключению автономки, но впоследствии всё вернулось на круги своя и я наконец настроил огненную стену как требовалось.

Поскольку мы тут интегрируемся со всякими партнёрами – нам понадобилось поднять несколько IPSec (VPN) подключений, чтобы иметь возможность взаимодействовать с партнёрами. В целом ничего сложного. Организовываем отдельную группу безопаности, чтобы сегрегировать основной траффик автономки и gsm траффик для клиентов. Далее пытаемся настроить IPSec туннели, но они почему-то не поднимаются. Включаем debug логи и видим, что траффик с улицы приходит на Juniper, обрабатывается им, но при отправле оборудованием обратного траффика мы получаем странную ошибку: Can not send UDP datagram. В интернете этой ошибки нет от слова совсем, гугл ничего про неё не знает. И тут я открыл для себя reddit. После недолгого общения было сделано предположение, что интерфейс, на котором будет терменироваться IPSec должен быть в той же группе безопасности, в которой находятся интерфейсы с внешним траффиком.

Заводим lo0.0 интерфейс, вешаем на него /32 адрес, засовывем его в группу безопасности untrust к интерфейсам соседей и voila – траффик ходит, туннели устанавливаются, всё работает.

Единственная проблема, которая у меня сейчас осталась – Telia подаёт нам 1gbps интернет по оптике, попутно предоставив нам SFP модуль на 1 гигабит. В нашем SRX380 SFP+ порты, которые поддерживают 10 гигабит модули, но имеют возможность переключаться в скорость модуля (судя по документации). Вся проблема в том, что интерфейс в режим 1 гигабит не переходит от слова совсем, каких-то настроек, взятых с интернета, просто нет, какие-то не работают. В общем я пока так и не понял, как заставить SFP+ порт в SRX380 работать в режим 1 гигабит, соответственно пиринга с Телией опять нет, но это не конец. Я уже даже смотрю в сторону медиа конвертера, но прибалтика это прибалтика – только на заказ, доставка когда-нибудь и то не факт.

Дада, я опять потерялся, хотя обещал, но так бывает иногда, а иногда не бывает. Не стоит воспринимать это на свой личный счёт. Сегодня я здесь и сегодня я поделюсь с вами что же и ге же происходило всё это время.

Январь закончился, некоторые трудовые отношения закончились, межличностные отношения тоже закончились, в общем конец января и начало февраля окзались временем чтобы собирать камни и делать выводы. Вплоть до 21го числа я занимался в основном тем, что возил н асвоём сарае вещи с одной квартиры на другую и знаете что – переезд хуже трёх пожаров, я даже не все вещи вывез, но меня это так утомило, что в последний заход я просто забил болт на оставшееся. Возможно если бы я был чуть поумнее – то делал бы всё это не водиночку, но мы сильны задним умом и слишком самостоятельны чтобы прям попросить кого-то о помощи.

Также в феврале, внезапно, в моей жизни появился нарвский кот. Тут особо нечего рассказать, хороший, интересный человек, с желанием уйти обратно в художку, 3д и прочими гуманитарными увлечениями. Сейчас, правда, её немного анноит сдача диплома, но я уверен, что к сроку всё получится и этот стресс закончится. Как я и писал – ездим туда-сюда, потихоньку перемешиваем вещи, ругаемся, миримся, в общем всё как у всех. 31го летим в Милан, посмотрим что там у этих итальянцев, поедим пасты, сходим на озеро Комо.

В начале марта я наконец раскидал все свои проблемы, беды с башкой, рабочие вопросики и вынырнул на полшишечки из пучины. Появилось немного свободного времени и я наконец собрал и подключил свой компутер дома. Решил изучить что же такое WSL (Windows Subsystem for Linux). В общих чертах, как я понимаю, это виртуальная машина с Linux, которая достаточно глубоко интегрирована в Windows, вплоть до возможности запускать X11 приложения.

Первое столкновение с WSL произошло ещё в окружении Windows 10, но как оказалось, WSL 1 имеет большие ограничения и пришлось обновляться до Windows 11, чтобы получить new, shiny technology в свою копилочку. Долго я ковырялся с TPM 2.0, чтобы всё подготовить для работы 11ой винды, настраивал BIOS и так, и сяк, но в итоге заборол проблему. Итак, нововведения – у windows, внезапно, появился новый удобный терминал Windows Terminal (до urxvt, конечно, не дотягивает, но намного лучше, чем cmd/powershell), в который дополнительное завезли ни много, ни мало – прозрачность. В общем я не то, чтобы влюбился, но жить в винде стало определённо веселее.

Дальше WSL – стильно, модно, молодёжно – три команды и вот мы уже в системе. Из удобств – нативные Linux приложения, ssh, telnet, tcpdump (бесполезен в виду особенностей работы WSL), mpv (внезапно X11 приложения нативно работают в Windows, моё уважение), pass (таки rofi тоже вполне себе работает, рисует менюшки, предлагает выбор, местами, правда кривовато, но работает) и многое, многое другое.

Но, как это часто бывает, у WSL есть множество проблем, которые по мнению разработчиков этой технологии наоборот делают жизнь рядового пользователя лучше (ведь мама знает лучше, да), но по факту руинят всё до чего только можно дотронуться. Лезем под капот и обнаруживаем, что WSL это по сути Hyper-V виртуальная машина, запущенная в каком-то своём совершенно отдельном окружении и которая даже в интефрейсе управления VM (Hyper-V Manager) не светится никаким образом. Причиной же, по которой мы начали погружаться в эту пучину боли и отчаяния является то, что из linux окружения, например, я никаким образом не мог достучаться до других виртуальных машин в том же инстансе Hyper-V.

Но зачем мне другие виртуалки, спросите вы – а я вам отвечу – поскольку я последнее время плотно занимаюсь сетями и всем с ними связанным – я немного подсел на GNS3 – это такое opensource решение, которое позволяет запускать виртуальные роутеры, фаерволы, свитчи и просто оконечные виртуалки, перевязывать их портами и строить виртуальные сети, чтобы понимать как и что будет работать в боевых условиях. В общем это некий виртуальный тестовый стенд для ленивых, но я в очередной раз для себя убедился, что иметь физический шкаф, набитый разного рода оборудованием является лучшим решением, чем вот эта вот виртуализация, но мы отвлеклись.

Итак, на Linux GNS3 работает очень классно и удобно, используя libvirt+qemu в системе он не требует больше ничего для своей работы, всё красиво, удобно, сверкает лампочками и гоняет терабиты трафика. Но Windows... У Windows всегда свой путь. Для начала немного теории – есть в современных процессорах набор инструкций, которые позволяют выполнять инструкции виртуальных машин так, будто эти самые виртальные машины запущены на реальном железе. Соответственно всё работает быстрее, выселее и лучше. Название этой подсистемы в ядре Linux – KVM (kernel virtual machine). В свою очередь у Microsoft своя виртуализация, которая называется Hyper-V и которая, при включении, монополизирует доступ к этим KVM инструкциям не позволяя другим системам виртуализации (Virtualbox, VMWare) получать доступ к инструкциям виртуализации. Libvirt для Windows не существует родного, соответственно чтобы GNS3 работал нормально требуется запустить какую-то дополнительную виртуалку, в которой будет доступен KVM и в которой будет libvirt.

Открываем первый люк и ныряем в него – как сделать так, чтобы VirtualBox получил доступ к KVM – получается самый простой вариант отключить Hyper-V. Отключаем, перезагружаемся и на этом этапе мы узнаём, что WSL2 работает на основе Hyper-V. Получается на данном этапе у нас либо GNS3, либо WSL. Нас это совершенно не устраивает. Включаем Hyper-V обратно, перезагружаемся, теряем сеть, никакие команды её не восстанавливают. Как починить Windows – переустановить. Сказано – сделано. Открываем второй люк – видим, что у многих пользователей GNS3 тоже проблемы с Hyper-V и виртуалкой для запуска роутеров. Гуглим, гуглим, читаем тонны информации и находим, что на самом деле GNS3 умеет кое-как работать с Hyper-V + рядом приложен образ виртуальной машины для последней. Долго ли, коротко ли – машина заливается, запускается и работает, но в конечном итоге GNS всё равно рассказывает о том, что у него какие-то проблемы с доступами. Гуглим дальше и обнаруживаем, что для управления Hyper-V виртуальными машинами пользователю нужно выдать некие неопределённые администраторские права через POLICY EDITOR. Читаем, ищем xml файл с этими полиси, а его нет, тупо нет. Нигде. Штош, вспоминаем бурную молодости и то, что в винде есть ещё такое понятие как группы, ищем группу связанную с Hyper-V, докидываем туда себя, перезагружаемся и voila! GNS3 видит виртуалку, сам её запускает, останавливает, подключается, в общем мечта – лекарство найдено, можно снимать халаты, мыть руки и идти домой.

Мжно было бы, если бы не одно но – GNS3 и правда заработал, образы роутеров и фаерволов и правда начали загружаться на эту виртуалку, я даже смог через telnet подключаться к этим роутерам, но juniper, с которыми я и работаю последний год плотно, так и не соизволил загрузиться на всём этом сетапе. Сначала он очень медленно жуёт ядро, а потом выпадает в coredump. Занавес, аплодисменты, поклоны.

Делая выводы из всего этого действа не могу не отметить, что Microsoft со всеми их нововведениями делает очень интересные и правильные вещи, но, как это обычно и бывает, совершенно не дожимает до конца в критических местах. Да, Windows 11 стала намного дружелюбнее к продвинутым пользователям, но к сожалению для меня она всё так же остаётся исключительно лаунчером для требовательных игр, sad, but true.

Раз пошла такая пьянка, расставляйт, брат, стаканы (с) Юрий Хой

Штош, получается в конце декабря я вернулся в Европу и всё было вроде бы неплохо, не считая того, что за последний месяц я был дома около 4 дней, ну может 6, не более.

Вернувшись в Маарду я заселился к своим хорошим друзьям, где потусил несколько дней и отправился домой в Ригу, посмотреть как люди там живут, как квартира себя чувствует ну и вообще, негоже долго находиться за пределами страны, которая выдала тебе ВНЖ, ещё миграционка расстроится. В Риге я потусил со знакомцами, а также обнаружил прекрасную бричку, которую и купил в подарок на новый год своей хорошей подруге из Эстонии. Хонда Аккорд 200-какого-то там года, я уже не помню, на механике, с классным звуком и шумоизоляцией, я аж преисполнился от того на сколько она классная. Плюс я очень соскучился по механической коробке передач и если бы не мой аурис, который тупо не ломается, да ещё и жрёт около 4.5 литров на 100 км – я бы себе такую же взял.

Самый смак был, когда я на этой тачке покатился в Эстонию, чтобы её подарить. Эти 4 часа были увлекательным путешествием, которые так или иначе выявили ещё пару недостатков, но в общем и целом я остался под впечатлением. Прикатился в Таллинн, провели с ребятами пенсионерский новый год, причём 30го числа плясали в квартире так, что на утро болели колени, но я ни о чём не жалею. 31го, как водится, в 23:00 ласнамяэ взорвался салютами, а к полуночи уже и остальные районы подтянулись, но поскольку новый год был пенсионерский – то в районе часа ночи мы уже раскатились по кроваткам и отправились в страну морфея. 1го числа я приболел, а 2го мы выяснили, что у меня говнид. Штош, моя хорошая подруга сразу раскидала вопросы про лечение по своим широчайшим сетям и мне подогнали кучу медикаментов, различные ингалляции, которые уже к третьему числу поставили меня на ноги. За это время я успел откатить тачку на СТО, где ей поменяли задние ступичные подшипники и доделали по мелочи, чтобы пройти ТО в Эстонии и 2го числа машина была перерегистрирована на нового владельца в Эстонии. Как оказалось процесс переимпорта машин между странами ЕС достаточно просто и незамысловатый, а техосмотр вообще можно не проходить, пока действует ТО из страны экспорта. В общем одни плюсы.

3го числа я покатился домой, потому что уже у моей машинки начались проблемы с задними тормозами и я был записан к знакомым на замену и починку, поскольку 10го мне предстояло путешествовать снова в Москву, а без тормозов как-то страшновато кататься, как ни крути. Заменили быстро, недорого, спасибо знакомым, всё сделали качественно, ну разве что проблема была с плановым техобслуживанием. Я должен был поменять масло и фильтры на 88000 км, но как-то так вышло, что моё СТО, где я постоянно всё это делаю, ушло на праздники 25го декабря, а выходить собиралось 8го января. Соответственно на счётчике километров уже 95000, а масло так и не поменяно, однако я надеюсь в начале февраля всё-таки сделать уже большое ТО, как на 100000 предписывает производитель. В общем типичные проблемы автолюбителей, ничего особо интересного.

За время пребывания в Риге я успел ещё купить 40” телевизор и преисполнился от того на сколько это кртая тема, организовал дома ещё нормальный звук и теперь у меня есть целая отдельная тусильная комната, где можно чилить под кинцо и делать всякие штуки, не занимая при этом спаленку. В общем всё организовал и 8го числа укатился обратно в Таллинн, где протусил до 10го числа и двинулся брать штурмом уже Нарву на этот раз. И вот оно, приключение, которое я сам себе придумал.

10го января 2024 года у меня была запись на границу, о которой я упоминал в предыдущим лонгриде, на 11 утра. Как обычно никто ничего не рассказывает, но к счастью у меня в смске про запись был адрес “стоянки ожидания”. Я добрался до Нарвы к 10 утра и поехал искать стоянку. Стоянка оказалась огороженной промзоной с огромной площадью, где тусил с десяток машин, ожидающих своей очереди. Разговорился с мужиками – сказали, что стоят с двух ночи и на границе какие-то задержки. Подошёл в будку и получил примерно те же указания – ожидайте когда вызовут, вам придёт смс. Ну штош, делать нечего, я выкотился со стоянки и поехал изучать что же там в Нарве происходит, попутно выяснять как же проехать на границу, поскольку указания были очень расплывчатыми. Приехал к границе, нашёл эту маленькую улочку, где можно встроиться в очередь и ожидать, когда позовут. И тут начинается приключение. На этой маленькой улочке два знака (как потом оказалось) Первый знак стоит в начале улицы и гласит, что зона остановка и стоянка запрещена заканчивается прямо перед въездом на улице, а второй знак, который я проскипал, находился посередине этой улицы и гласил, что данный участок дороги приспособлен для живой очереди заезжающих на границу и остановка/стоянка здесь и далее запрещены. Но знак я проскипал, увидел как там стоят машинки без водителей, вклинился в свободное место и пошёл пешком покорять Нарву.

Вернулся я через пару часов, смотрю все меня обхезжают и ругаются. Ну я сел в машинку и сидел ждал когда же уже наконец вызовут. Через некоторое время недовольные люди начали на меня нападать, мол чего ты тут стоишь, зачем загораживаешь проезд. А я был в полной уверенности, что знак на всей дороге один, посему отвечал хамством на хамство. Меня пугали штрафами, полицией, народной расправой, но я если я уверен в своей правоте – меня очень сложно вывести на эмоции. Однако через полтора часа ругани я вс же решил пойти посмотреть что же там за мифические знаки на дороге. И вы не поверите, я нашёл второй знак, под которым стоял. Соответственно ошибку свою осознал, отъехал и перепарковался, проблем нет.

Время приближалось к 18:00 и вот наконец пришла заветная смска – будьте добры проследовать на границу, мы Вас ожидаем. Сказано – сделано, подъезжаю в очередь и стоим ждём по одному когда запустят. Запустили, подъезжаю к домикам, подходит полицейская и такая – А вы знаете, что нарушили закон, затрудняли движение и вообще нехорошо себя вели. – Ответил, что да, знаю, посмотрел знаки, вину признаю, 20 евро штрафа, так 20 евро штрафа, ничего не поделать. Полицейская посмотрела мне в глаза и сообщила, что ладно, раз уж так, то на первый раз прощаем, но больше так не делайте. Люблю я в общем эстонскую полицию, они няшки. Дальше всё стандартно, штамп в паспорт, беглый осмотр и выпустили на ничейную территорию, 10 минут и вот я уже стою в очереди на российской стороне. И самое гадкое, что я попал на пересменку. Мы около двух часов смотрели как погранцы бегают туда сюда, ссаживаются с автобуса, засаживаются, в общем граница тупо стояла в ожидании чуда, которое в конечном итоге и произошло. Начали потихоньку проходить машинки. Я, будучи уже наученный горьким опытом предыдущей границы побежал сразу к таможенникам и затребовал выдать мне бланки декларации о временном ввозе, чтобы заполнить пока сижу. На меня посмотрели с уважением и дали сразу 5 бланков, на всякий случай. Паспортный контроль прошёл быстро, как и досмотр, а вот с бланками вышла лажа, меня заставили заниматься чистоисанием аж три раза. Помарки нельзя, адреса нужно указывать реальные (хотя я написал от балды где буду жить в Москве), то, это, короче потратил я час пока бегал к будке и обратно. Разговорились с таможенницей, похихикали о моём прошлом пересечении границы, она позвонила куда-то и сообщила, что в этот раз я освобождён от рентгена, однако латышские машины почему-то любят досматривать с пристрастием. В конечно итоге оставив 6 часов на границе я счастливый и довольный выкатился с границы, заехал на первую попавшуюся заправку, но зелёной карты там не оказалось, однако на том блокпосте, который на подъезде к Иван-городу была целая удобная будка с нормальным интернетом, где мне спокойно сделали страховку на месяц. В целом я болле-менее доволен процессом в этот раз.

Время приближалось к полуночи и я пришёл к выводу, что ехать в ночь 600 км я не хочу, в Питер смысла соваться нет и придумал очередное приключение, а именно – попробовать заночевать в мотеле, как это делают настоящие пацаны с фур. Мотелей по объездной как-то не оказалось и пришлось мне ехать до самой трассы Питер-Москва (старой) Недалеко от схезда с объездной обнаружился очень уютный мотель, рядом с церковью. Прям классное место, всё по-домашнему. Правда пришлось выхзванивать администратора, но всё получилось и в 2 часа ночи по местному времени я уже укладывал голову на подушку. Собирался поспать пока не станет плохо, но увы, организм в 7 утра сообщил, что достаточно, время отправляться в путь. Сказано – сделано, но и тут не обошлось без приключений. Ехать назад к объездной же не по-людски, ехать надо только вперёд, а следующий съезд на платку был километров через 100, при это километров 50 пришлось ехать по грунтовой дороге, которую никто не чистит от снега. Классное место, если бы меня ещё не носило как собаку на поворотах. Где-то даже валяются видосики этой зимней сказки. Доехал до платки, съехал и дело пошло на лад, впрочем в Москве я оказался только к 6 вечера. Как-то очень сложно всё это было, я так и не понял как это вышло.

Приехал, заселился и приступил к делишкам, которые планировал. С 11го до 14ое из дома особо не выходил, в основном работал, разбирал вещички, как новые, так и старые и вообще происходило всякое интересное. 14го числа 2024го года отправился в МФЦ, где получил завтное свидетельство о разводе и тут же подал его на апостиль. Девочка в окошке сказала, что для Латвии апостиль конечно не нужен, но я не первый раз готовлю документы и потребовал мне его проставить. В итоге в документах написали для Германии (на апостиле всё равно не указывается страна назначения). Получил бумагу – срок проставления 5 рабочих дней, готовность услуги – 23е января. Прикинув в уме, что это больше 5 рабочих дней я так и не понял как МФЦ считает, но мы люди маленькие и повлиять никак не можем на это. Вернулся домой и продолжил заниматься всякими делишками.

В понедельник посетил театральное выступление Тарас Бульба в отличной компании, мне очень понравилась хореография ну и в целом это произведение прошло как-то мимо меня, так что я остался очень доволен происходящим. Дальше во вторник расторг, таки, договор с одним из партнёров, с которым очень долго собирался это сделать и освободилось большое количество времени, хотя на собесы меня до сих пор таскают, но я не жалаюсь, это даже интересно. Возможно я бы с ними и продолжил работать на почасовой основе, но что-то не хотят ребята. Тут моё дело маленькое, я могу только предложить.

Дальше была куча разъездов, встреч, даже была встреча бывших коллег, увидел много старых новых лиц, пообнимался, пили хреновуху, в общем и целом было весело. На выходных добрался до родственников в Шереметьево, пообнимался, пообщался и 24го рано утречком засобирался до дому (ну как до дому, до Таллинна, тут есть ещё пара делишек, которые надо закрыть)

До питерской объездной я каким-то чудом от МКАДа долетел за 6 часов, впрочем если топить 140 всю дорогу удивляться нечего, но машинке такое не очень понравилось, всё же средняя скаорость, на которую она рассчитана 100 км/ч, поэтому получилось чот типа 7.7 литров на 100 км, но я ни о чём не жалею. С ценами на бензин в России можно и пятилитровый мустанг гонять туда сюда – не разоришься. Дальше всё так же как и в первый раз – разбитая дорога вокруг Питера, городки до Иван-города. Быстро прошёл границу, где-то за полчаса и вот я снова в Европе. Долго думал остановиться в Нарве или доехать уже до Маарду и пришёл к выводу, что терять уже нечего, собрался и покатился в сторону Таллинна. Дорога прошла незаметно и уже в районе 10 вечера я был на месте. Обратная дорога от Мск до Маарду заняла около 12 часов, на удивление быстро и спокойно.

Теперь сижу в Таллинне, работаю закрываю делишки, которые накопились за время моего отсутствия, готовим всякие новые проектики к запуску по телефонии, в общем всячески развиваем тут предприятие, как можем. Интересно, увлекательно, очень круто.

За сим, пожалуй и всё, что я могу адекватно рассказать о происходившем за поледние два месяца в моей жизни, не считая моих личных моментов, в которые кто-то из вас посвящен, а кому-то никогда об этом не узнать, но тут ничего не поделать, у всех должны быть личные моменты и переживания.

А, ну был ещё один переживательный момент, где я не подрассчитал при обгоне колонны тайминги и чуть не отправился сразу в рай в лобовом столкновении, но всё обошлось, встречный жигуль и я сориентировались и все пролезли, так что я всё ещё жив, цел, бодр, орёл.

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