惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

IT之家
IT之家
C
CXSECURITY Database RSS Feed - CXSecurity.com
V
Visual Studio Blog
D
Darknet – Hacking Tools, Hacker News & Cyber Security
小众软件
小众软件
L
LangChain Blog
Cyberwarzone
Cyberwarzone
美团技术团队
The Register - Security
The Register - Security
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
T
Tor Project blog
V
V2EX
Security Archives - TechRepublic
Security Archives - TechRepublic
Hacker News: Ask HN
Hacker News: Ask HN
L
LINUX DO - 最新话题
Recent Announcements
Recent Announcements
H
Hackread – Cybersecurity News, Data Breaches, AI and More
酷 壳 – CoolShell
酷 壳 – CoolShell
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
aimingoo的专栏
aimingoo的专栏
人人都是产品经理
人人都是产品经理
F
Full Disclosure
V2EX - 技术
V2EX - 技术
The Cloudflare Blog
博客园 - 叶小钗
T
Threat Research - Cisco Blogs
阮一峰的网络日志
阮一峰的网络日志
G
GRAHAM CLULEY
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Latest news
Latest news
S
Security @ Cisco Blogs
Spread Privacy
Spread Privacy
Project Zero
Project Zero
K
Kaspersky official blog
MyScale Blog
MyScale Blog
Attack and Defense Labs
Attack and Defense Labs
云风的 BLOG
云风的 BLOG
博客园 - 【当耐特】
Hacker News - Newest:
Hacker News - Newest: "LLM"
大猫的无限游戏
大猫的无限游戏
P
Privacy International News Feed
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
C
Cybersecurity and Infrastructure Security Agency CISA
Webroot Blog
Webroot Blog
罗磊的独立博客
Vercel News
Vercel News
N
News and Events Feed by Topic
A
Arctic Wolf
C
CERT Recently Published Vulnerability Notes

Все публикации подряд на Хабре

Ловим музу за клавиатуру: как айтишнику стать автором Что умеет Midjourney в 2026? Мой немного грустный разбор этого шикарного инструмента Никто не любит писать тесты, но ИИ может исправить это IPv8 выглядит как мечта. Поэтому почти наверняка не взлетит Производители вернули в продажу материнки с DDR3. Что происходит? Управление агентом с телефона через Telegram теперь в KodaCode От координации к лидерству: как меняется роль руководителя разработки Я сделала родителям бизнес вместо пенсии: зарабатываем 70 тысяч, мама не даёт продать В три раза быстрее приемка товара и оптимизация трудозатрат на 73%: как «РСТ-Инвент» помог Gulliver Group ИИ-шечный мир победил? О влиянии искусственного интеллекта на игропром Кремль снижает давление на Телеграмм пока Европа строит интернет по паспорту Как CEO, CTO и CIO за 8 часов собрали ИИ-директора, который умеет держать позицию под давлением Как (не) потерять домен за выходные Вместо 8 разных VPS: как я организовал практику студентам на одном сервере Почему твой Open Source проект не замечают? R&D: искусство управления неопределенностью в разработке AI-дефляция: вакансий для разработчиков больше, а рост зарплат — худший за 15 лет Мы отдали управление роботами OpenClaw. Что из этого вышло Галактический ID: система идентификации для всех форм разумной жизни Шесть основ бизнес-анализа: начинаем с вопроса «Кто в игре?» Код-ревью, в котором дело не в коде Данные переехали. Команда — нет Системной подход к сдаче OSWE в 2025 Почему комната управления реактором покрашена в цвет морской пены 4 YAML-файла вместо PySpark: как аналитикам строить пайплайны без разработчиков LLM-агент для поиска свободных доменов: автоматизируем подбор Когда, зачем и как правильно начинать новую сессию в Claude Code? Как я заставил нейросеть писать макросы для FreeCAD Анатомия ИИ‑агента для подбора персонала. От тысячи резюме к топ‑10 за минуты Опыт разработчика как экономика внимания Автономность как точка невозврата: кто будет субъектом в цифровом будущем Обучение ИИ в «диких» условиях: как рутинные действия превращаются в датасеты Как измерить LLM для задач кибербеза: обзор открытых бенчмарков Где хранить код? Сравнение GitHub, GitLab и Bitbucket Математика объясняет, почему нормальное распределение встречается повсюду Почему ваш FinOps не работает: 12 тезисов от практиков Как подписать проектную документацию УКЭП с использованием бесплатных лицензий Pilot Адаптивное администрирование Sigla Vision Я грузил уран в бочки, а потом 20 лет строил ИТ в атомной отрасли Чем позвонить с Эвереста? История и обзор спутниковой связи. Часть 2 Как языковая модель помогает контролировать качество инструктажей по охране труда в металлургии Как не передать на desktop свой IP в РКН Анатомия SAP Privileges: как устроено управление правами в macOS MoneyDev: Сказка про три главных слова Обновлённый токенизатор видео K-VAE 2.0 от Сбера Как сделать диспетчеризацию дома на 1284 квартиры почти бесплатно Как мы разогнали железную дорогу Мы дали агентам рутину. Теперь надо решить — что делать с освободившимся временем Токсичный контент, промпт-хакинг и защита ИИ — всё о Guardrails для LLM Умный город начинается с точного взгляда: как «Фалькон Тех» меняет пространство к лучшему Навайбкодил приложение для анализа графов Почему Дюну так интересно читать? Упрощаем работу с рутиной или как стать Гендальфом Белым Деконструкция Go: CPU, RAM и что там происходит. Go Assembler база. Часть 1.1 Какие профессии исчезнут из-за ИИ, а какие появятся? И что с этим делать Как мы построили IT-отдел, где хочется расти: архитектурные встречи, прозрачные метрики и книжные подарки Rufler: Делаем из Claude Code автономный рой через один YAML-конфиг Sing-box и белый список приложений Как построить надёжный обмен сообщениями в микросервисах: лучшие практики для enterprise OpenAI строит MLM-пирамиду, а McKinsey и Accenture помогают ей в этом Дом, который не построил Фишер (Часть 2) «Сверхзвуковой математик» против «Вдумчивого логиста»: битва алгоритмов 3D-упаковки Мультимодальные модели – грубый и дорогой инструмент Разговоры ничего не стоят. Код тоже Проверки физических лиц: с кого начнет ФНС Топ-10 бесплатных нейросетей для создания видео в 2026 году Первые слои кода: как наши решения сегодня определяют архитектуру ИИ на десятилетия Разработка нового статического анализатора: PVS-Studio JavaScript Поиск уязвимостей ПО: базовый минимум или роскошный максимум Почему оценка персонала не работает как инструмент управления Как мы разработали ИИ-ассистента и сократили рутину продуктовой команды на 50% Как я ушел из найма, нажарил косточек и продал на маркетплейсах на 168 млн в год Когда 1С:ERP уже внедрена, а нормального производственного плана всё ещё нет Как я сделал Claude мультимодальным, подключив к нему Qwen Omni Как приглашение на вакансию мечты превращается в атаку Infrastructure as Code: философия и лучшие практики IaC Тестируем Yandex Code Assistant на задаче, в которой нужно хранить секреты nxs-universal-chart v3.0: новое поколение универсального Helm-чарта Callback Injection: Техника, которая отправила Microsoft Defender в глухой нокаут «Все идеи на стол»: митап как способ вывести проект из тупика Сегодня я узнал нечто новое о GPU благодаря багу в своей игре Как заставить LLM ̶ ̶г̶а̶л̶л̶ю̶ ̶ эволюционировать Карта событий как фундамент аналитики: практический кейс для E-commerce Что выбрать для AI: x86, ARM или RISC-V? Дайджест железа за март Роль соматических мутаций в развитии аутоиммунных заболеваний: путь к избирательной терапии Mythos от Anthropic — тревожный сигнал для всех, а не только для банков Guardrails для LLM на Java: как приручить промпт‑инъекции и токсичные ответы Green-VLA: как мы собрали VLA-модель для реального антропоморфного робота и не потеряли обобщение Финансовая гонка вооружений: почему умные люди добровольно в ней участвуют Эра ИИ-агентов наступила: выбираем лучшего цифрового сотрудника # Практический опыт внедрения WinCC Redundancy на производственном предприятии Сделал MVP за 3 дня, а потом неделю прикручивал оплату. Оно того стоило? Физика против Маска: почему Starship V3 может оказаться ещё одной катастрофой Нефть Венесуэлы: крупнейшие запасы в мире, но не крупнейшая нефтяная держава JPA 4. Переосмысление Hibernate Почему зеркальная фотокамера Nikon D5 десятилетней давности идеально подошла для миссии «Артемида-2» Проект «Уровень-Спутник» или как мы сделали платформу для гидрологов «Замедлиться, чтобы ускориться»: почему ИИ повышает цену ошибок в требованиях и архитектуре Как с нуля поднять трафик IT-компании на 1657% при бюджете 55 тыс. и выжить Pixel-perfect Downsampling — идеальная отрисовка 50 миллионов точек без потерь
Я написал свой DNS-резолвер на Go вместо того, чтобы взять Unbound. Вот почему и что из этого вышло
cyberscoper · 2026-05-15 · via Все публикации подряд на Хабре

Уровень сложностиСредний

Время на прочтение6 мин

Охват и читатели338

Кейс

Привет, Хабр!

Три месяца назад я начал делать NextDNS-clone для Европы. Рекурсивный DNS с фильтрацией рекламы, трекеров и malware. Первый день: открываю Unbound, читаю man, всё понятно. К вечеру понимаю, что не подходит. Через неделю пишу свой резолвер на Go и вспоминаю поговорку про человека, который решил написать почтовый сервер. Никогда такого не было, и вот опять.

Сейчас в проде: 10 нод по миру, отвечает на DoH/DoT, фильтрует по миллионам доменов, RAM 60 МБ на ноду. Расскажу, почему ушёл от готового, что было больно, и где Unbound всё ещё быстрее. Спойлер: почти везде, но в наших условиях это не имеет значения.

В конце ссылки на open-source ядро резолвера и наш бесплатный тариф, можно потыкать.

Зачем вообще свой резолвер, если есть Unbound

Unbound — отличный софт. PowerDNS Recursor тоже. Я их обожаю как обожают старого кота: за то, что они есть и не требуют объяснений. В обычной ситуации просто бы поставил один из них и пошёл пить чай. Но у меня было три требования, которые ни тот, ни другой не закрывают штатно.

Миллионы DoH-эндпойнтов с разными правилами фильтрации

В NextDNS-like продукте каждый юзер получает свой config_id, короткий публичный токен в URL: https://dns.vantagedns.com/<config_id>/dns-query. У одного юзера может быть профиль «дом», «дети», «офис», у каждого свои блок-листы и whitelist. Это не «один резолвер с одним конфигом», это десятки тысяч логических резолверов на одной ноде.

В Unbound views есть, но они не масштабируются на десятки тысяч независимых наборов правил без боли с конфиг-генерацией и SIGHUP’ом каждые пять минут. Я как-то видел подобную конструкцию в одной телекомовской конторе в 2014-м. Там админ носил с собой бумажку с порядком действий, чтобы не забыть. Не хотелось в это ввязываться.

In-memory query log без записи на диск

Edge-нода не должна писать на диск ничего, что относится к юзеру. Это часть позиционирования. Поэтому query log живёт в кольцевом буфере в памяти, async-шипится в ClickHouse в Хельсинки, и всё. Unbound пишет логи в файл; для async-shipping надо городить tail+парсер.

Retention: 24 часа на free, до 30 дней на платных, дальше ClickHouse TTL чистит.

Bloom-фильтры для блок-листов с шарингом между профилями

У нас 10+ блок-листов от 50K до 5M доменов каждый. Если хранить их per-profile в виде set’ов, это сотни МБ RAM на ноду. С Bloom: 8 МБ на лист, шарится между всеми профилями, false-positive rate < 0.1%. В Unbound такого нет, там либо local-zone (медленно на больших списках), либо RPZ (тоже не совсем то).

Долго смотрел на варианты «допилить Unbound через модули» и отказался. Модульный API на C, миллионы конфигов через unix-сокет — это путь в ад дебага, причём сразу пятый круг. У меня нет на это ни нервов, ни жизни.

Почему Go, а не Rust/C++

Короткий ответ: я знаю Go и не знаю Rust на уровне «писать сетевую системную программу под нагрузкой». А C я в последний раз писал в университете, когда ещё думал, что segfault — это интересная диагностическая проблема. Сейчас я знаю, что это просто наказание за гордыню.

Длинный ответ:

Критерий

Go

Rust

C/C++

Скорость старта

✅ < 1 с

✅ < 1 с

✅ < 1 с

Memory safety

✅ GC

✅ borrow check

Время до прототипа

✅ дни

⚠️ недели

❌ месяцы

Library: DNS

miekg/dns (де-факто стандарт)

⚠️ trust-dns ок, но беднее

✅ много

Gorout./async

✅ goroutine на запрос — норма

⚠️ async runtime

❌ epoll руками

miekg/dns решал 80% задач из коробки: парсинг wire-format, сериализация, EDNS, DNSSEC. Я писал поверх неё recursive resolution, кеш, фильтрацию.

С Rust я бы выиграл 10-15% по latency и какие-то МБ по RAM. Но потерял бы 2 месяца на rewriting. Для бутстрап-проекта 1-человека это не выгодно.

Что было больно

Рекурсивная резолюция — это не просто «спросить .com NS, потом NS зоны»

Когда впервые пишешь recursive resolver, кажется: ну подумаешь, рекурсивно ходим по NS, кешируем, всё. Любой первокурсник напишет за вечер. Реальность, как водится, побила меня палкой по голове и обозвала наивным.

Параллельные NS lookups. У зоны обычно 2-4 авторитетных NS. Если последовательно дёргать каждый при таймауте, на холодном кеше один резолв example.com может занять 5+ секунд. Параллельные goroutines, race-to-first-response, отсев медленных.

Glue records. Когда запрашиваешь ns1.example.com для зоны example.com, это chicken-and-egg. Авторитетный сервер отдаёт A-запись для NS прямо в additional section. Если её игнорировать, рекурсия зацикливается. Был баг, где резолвер упирался в loop, потому что пропускал additional.

Negative caching. RFC 2308 (1998 год, между прочим, привет из эпохи, когда DNS ещё считался простым). Если NS вернул NXDOMAIN, надо кешировать с TTL из SOA, а не из ответа. Иначе при первом таймауте кешируем «домен не существует» на стандартный час и юзер ругается, а я смотрю в логи и не понимаю, почему GitHub лежит только у меня одного.

QNAME minimisation. Должно быть включено по умолчанию, это privacy. Запрашиваешь mail.google.com → у . спрашиваешь только com, у com только google.com, у google.com уже полный mail.google.com. Не «у всех NS на пути показываем full qname». Реализовать аккуратно отдельная история: некоторые корявые NS отвечают NODATA на минимизированный запрос, и ты сидишь, ловишь их в логах.

EDNS Client Subnet — отдельный ад

Без ECS Google отдаёт IP CDN из той страны, где стоит твоя нода. Юзер в Берлине через нашу ноду в Хельсинки получает финский IP googlevideo.com. Пинг 80 мс вместо 5 мс. YouTube тормозит, юзер пишет, что у нас «всё сломано».

С ECS публикуешь /24 подсеть юзера авторитетному NS. И вот тут начинается. Часть NS на ECS плюёт. Cloudflare принципиально не использует, потому что anycast. Часть отдаёт «правильный» IP. Часть выдаёт неправильный, а потом ты неделю выясняешь, почему. RFC 7871 формально опционален, и каждый сервер интерпретирует «опционально» по-своему, как бывшие супруги интерпретируют «давай останемся друзьями».

Тестирование на 30+ доменов руками было самым нудным этапом за все три месяца.

DNSSEC validation

Реализовать с нуля validation chain — две недели чистого времени. Я в итоге включил его опционально: для большинства юзеров он сейчас mostly cosmetic (95% доменов всё равно без подписи), а baggage серьёзный.

Cache poisoning — параноя 24/7

Любой кеширующий резолвер — потенциальная цель для cache poisoning. Source port randomization, txn-id randomization, 0x20 case randomization (да-да, тот самый трюк с регистром букв в qname, который выглядит как костыль и им и является), не доверять additional section без подтверждения через bailiwick. Это всё надо сделать до релиза, не после.

Раз 5 переписывал валидацию ответа. Каждый раз находил новый edge case и думал «ну вот теперь точно всё». Так не бывает. Запомните это, дети.

Цифры: что в итоге получилось

Замеры с одной ноды (Hetzner CPX21, 3 vCPU, 4 GB RAM, Helsinki):

QPS sustained:           ~12 000 cached / ~3 500 cold
P50 latency cached:      0.3 ms
P50 latency cold (.com): 38 ms
P99 latency cold:        180 ms
RAM steady state:        62 MB
Binary size:             14 MB (go build -ldflags="-s -w")
Cold start to ready:     0.4 s

Для сравнения, Unbound на той же ноде с похожим конфигом:

QPS sustained:           ~18 000 cached / ~5 000 cold
P50 latency cached:      0.18 ms
RAM steady state:        85 MB

Unbound быстрее на 30-40% по cached lookups. Это ожидаемо: он на C, код вылизан 20 лет. На холодных запросах разница меньше, потому что упираемся в сеть.

Для нашей нагрузки (~500 QPS на ноду пиково на текущем этапе) этой разницы не существует.

Что бы я сделал по-другому

Включил бы pprof и continuous profiling с первого дня. Первые два месяца дебажил allocations через runtime.ReadMemStats и top как пещерный человек. С pprof + Parca находил бы лики за минуты, а не за вечера. В оправдание скажу, что в три ночи кажется, будто top — это нормальный инструмент.

Не писал бы сразу Bloom-фильтры, взял бы суффиксные деревья. Bloom нужен на масштабе миллионов доменов. На старте у меня было 200K записей в листе, обычный suffix-trie дал бы exact matching без false positives, проще дебажить. Bloom добавил бы потом, когда уже припекает. Это, кстати, главное правило: не оптимизируй то, что не болит. Я его знаю с 2010 года и регулярно нарушаю.

Сделал бы feature flags с первого дня. Сейчас у меня 4 разных пути в коде «если ECS включён — так, иначе так», и они переплетены, как кабели за рабочим столом любого старого админа. С флагами можно было бы тестировать в проде на 1% трафика. Без них тестирую на себе, что довольно унизительно.

Open-source

Edge-резолвер — open source, MIT. Ссылка в конце статьи. Что НЕ open-source: control plane (биллинг, дашборд, blocklist-каталог) — это бизнес.

Зачем open-source edge: я хочу, чтобы юзер мог поднять свой собственный экземпляр и убедиться, что мы не врём про «не пишем на диск». В transparency report — статистика запросов на правоохранителей. Warrant canary обновляем еженедельно.

Что дальше

В следующих постах планирую разобрать конкретику:

  • как делал Bloom-фильтры с шарингом между профилями;

  • почему отказался от anycast в пользу geo-DNS на 10 PoPs и сколько это реально стоит;

  • как async-шипим query log в ClickHouse без потерь и без диска на edge.

Если интересно что-то конкретное — пишите в комментарии, постараюсь приоритизировать.


Ссылки:

Спасибо, что дочитали. Замечания и вопросы пишите в комменты.