{"id":48440148,"url":"https://github.com/addspin/hllb","last_synced_at":"2026-04-06T15:03:52.477Z","repository":{"id":349427170,"uuid":"1152397869","full_name":"addspin/hllb","owner":"addspin","description":"High load DNS server for load balancing between balancers or other systems","archived":false,"fork":false,"pushed_at":"2026-04-05T21:19:02.000Z","size":4700,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-05T23:21:43.923Z","etag":null,"topics":["balancing","checker","dns","forward","high-load","upstream"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/addspin.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-02-07T20:18:00.000Z","updated_at":"2026-04-05T21:15:23.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/addspin/hllb","commit_stats":null,"previous_names":["addspin/hllb"],"tags_count":2,"template":false,"template_full_name":null,"purl":"pkg:github/addspin/hllb","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/addspin%2Fhllb","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/addspin%2Fhllb/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/addspin%2Fhllb/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/addspin%2Fhllb/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/addspin","download_url":"https://codeload.github.com/addspin/hllb/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/addspin%2Fhllb/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31477014,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-06T14:34:32.243Z","status":"ssl_error","status_checked_at":"2026-04-06T14:34:31.723Z","response_time":112,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["balancing","checker","dns","forward","high-load","upstream"],"created_at":"2026-04-06T15:03:20.061Z","updated_at":"2026-04-06T15:03:52.471Z","avatar_url":"https://github.com/addspin.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# HLLB - High load DNS сервер с проверкой хостов для балансировки нагрузки\n\n\n\n## Быстрый старт\n\nДля балансировки нагрузки:\n- Добавьте несколько одинаковых \"A\" записей в зоне с разными ip адресами.\n- В файле `check.yaml` добавьте список этих ip для проверки.  \n- Запустите сервер.\n- curl на запись к которой вы закрепили ip ареса в зоне будет чередовать выдачу ip адреса из списка `check.yaml`.\n\n---\n### Некторые варианты работы\n\n```\n┌──────────────────────────────────────────────────────────────────┐\n│                         ИНТЕРНЕТ                                 │\n│                                                                  │\n│  Пользователь ──────▶ DNS Провайдер                              │\n│         │                │                                       │\n│         │                │ NS: ns1.your-domain.com.              │\n│         │                │     → 203.0.113.1 (hllb)              │\n│         │                ▼                                       │\n│         │         ┌─────────────────┐                            │\n│         │         │   Ваш hllb      │                            │\n│         │         │   203.0.113.1   │                            │\n│         │         │                 │                            │\n│         │         │  check.yaml:    │                            │\n│         │         │  - 198.51.100.1 │ ← внешний IP               │\n│         │         │  - 198.51.100.2 │ ← внешний IP               │\n│         │         │  - 198.51.100.3 │ ← внешний IP               │\n│         │         │                 │                            │\n│         │         │  zone/your-domain.com:                       │\n│         │         │  lb  A  198.51.100.1                         │\n│         │         │  lb  A  198.51.100.2                         │\n│         │         │  lb  A  198.51.100.3                         │\n│         │         └─────────────────┘                            │\n│         │                  │                                     │\n│         │                  │ Health Check (TCP)                  │\n│         │                  │ по внешним IP                       │\n│         ▼                  ▼                                     │\n│  ┌──────────────────────────────────┐                            │\n│  │  Firewall / NAT Gateway          │                            │\n│  │  (прозрачно для hllb)            │                            │\n│  │  198.51.100.1:443 → 10.0.1.1:80  │                            │\n│  │  198.51.100.2:443 → 10.0.1.2:80  │                            │\n│  │  198.51.100.3:443 → 10.0.1.3:80  │                            │\n│  └──────────────────────────────────┘                            │\n│                                                                  │\n└──────────────────────────────────────────────────────────────────┘\n\n\n┌─────────────────────────────────────────────────────────────────┐\n│                    Закрытый контур (VPN)                        │\n│                                                                 │\n│  ┌──────────────┐   ┌──────────────┐   ┌──────────────┐         │\n│  │  Клиент #1   │   │  Клиент #2   │   │  Клиент #3   │         │\n│  │  10.100.1.10 │   │  10.100.1.11 │   │  10.100.1.12 │         │\n│  └──────┬───────┘   └──────┬───────┘   └──────┬───────┘         │\n│         │                  │                  │                 │\n│         └──────────────────┼──────────────────┘                 │\n│                            │                                    │\n│                            │ DNS запрос (внутри VPN)            │\n│                            ▼                                    │\n│                  ┌─────────────────┐                            │\n│                  │   Ваш hllb      │                            │\n│                  │   10.100.1.1    │                            │\n│                  │   :53 (DNS)     │                            │\n│                  │                 │                            │\n│                  │  check.yaml:    │                            │\n│                  │  - 10.200.1.1   │                            │\n│                  │  - 10.200.1.2   │                            │\n│                  │  - 10.200.1.3   │                            │\n│                  │  port: 80       │                            │\n│                  │                 │                            │\n│                  │  zone/internal: │                            │\n│                  │  lb  A  10.200.1.1                           │\n│                  │  lb  A  10.200.1.2                           │\n│                  │  lb  A  10.200.1.3                           │\n│                  └────────┬────────┘                            │\n│                           │                                     │\n│                           │ Health Check (TCP)                  │\n│                           │ по внутренним IP                    │\n│                           ▼                                     │\n│         ┌─────────────────┼─────────────────┐                   │\n│         ▼                 ▼                 ▼                   │\n│  ┌────────────┐   ┌────────────┐   ┌────────────┐               │\n│  │Balancer #1 │   │Balancer #2 │   │Balancer #3 │               │\n│  │10.200.1.1  │   │10.200.1.2  │   │10.200.1.3  │               │\n│  │   :80      │   │   :80      │   │   :80      │               │\n│  └────────────┘   └────────────┘   └────────────┘               │\n│                                                                 │\n└─────────────────────────────────────────────────────────────────┘\n```\n\n### Сборка\n\n```bash\ngo build -o hllb .\n```\n\n### Первый запуск\n\nПри первом запуске автоматически создаются отсутствующие файлы: \n- `config.yaml` — конфигурация сервера (порт 53, forward на 8.8.8.8)\n- `check.yaml` — список хостов для health check\n- `zone/example.com` — тестовая зона\n\n```bash\n./hllb\n```\n\n### Запуск на порту 53\n\nПорт 53 — привилегированный (\u003c 1024), для работы на нём требуются дополнительные права.\n\n#### Linux\n\n```bash\n# Рекомендуемый способ — дать бинарнику право на привилегированные порты\nsudo setcap 'cap_net_bind_service=+ep' ./hllb\n./hllb\n\n# Или запуск от root (не рекомендуется)\nsudo ./hllb\n```\n\nЕсли порт 53 уже занят `systemd-resolved`:\n```bash\nsudo ss -tlnp | grep :53\nsudo systemctl disable --now systemd-resolved\n```\n\n#### macOS\n\n```bash\n# Запуск от root\nsudo ./hllb\n```\n\nАльтернатива — слушать на высоком порту и пробросить через pfctl:\n```bash\n# В config.yaml: port: 1053\necho \"rdr pass on lo0 inet proto {tcp, udp} from any to 127.0.0.1 port 53 -\u003e 127.0.0.1 port 1053\" | sudo pfctl -ef -\n```\n\n#### Windows\n\nПорты ниже 1024 в Windows не привилегированные — дополнительных прав не требуется. Убедитесь, что порт 53 не занят службой DNS Client:\n```powershell\nnetstat -ano | findstr :53\nnet stop \"DNS Client\"\n```\n\n### Проверка работы\n\n```bash\ndig @127.0.0.1 -p 53 example.com A\n```\n\n---\n\n## Возможности\n\n### DNS-сервер\n- Слушает входящие запросы одновременно по **UDP и TCP** на настраиваемом порту\n- Обрабатывает типы запросов **A** и **NS**\n- Флаг **Authoritative** устанавливается только для ответов из собственных зон\n- **Форвардинг** — запросы, не найденные в зонах, пересылаются на внешний DNS (настраивается в `config.yaml`)\n\n### Зоны и записи\n\nФайлы зон хранятся в директории `./zone/`. Имя файла — имя зоны (например `test.ru`), оно же становится `ORIGIN` — корневым доменом, подставляемым к относительным записям внутри файла.\n\nПоддерживаемые типы записей в зонах:\n| Тип | Пример в zone-файле | Описание |\n|-----|---------------------|----------|\n| `A` | `www IN A 10.13.1.34` | IPv4-адрес |\n| `NS` | `@ IN NS ns1.test.ru.` | Сервер имён |\n\n### Wildcard-матчинг (три уровня)\n\n| Паттерн | Пример запроса | Описание |\n|---------|----------------|----------|\n| `*` (корень зоны) | `any.test.ru` | Любой поддомен зоны |\n| `*.suffix` | `x.info.test.ru` | Любой поддомен для `*.info.test.ru` |\n| `*.sub.domain` | `a.b.msg.admin.test.ru` | Любая вложенность субдоменов |\n| `exact.domain` | `sub.admin.test.ru` | Точное совпадение записи |\n\nПорядок приоритета обработки запроса:\n1. Точное совпадение\n2. Wildcard-записи зоны (`*.suffix`)\n3. Wildcard-фолбэк (`*.zone`)\n4. Форвардинг на внешний DNS (если `forward: true`)\n5. `NXDOMAIN`\n\n### Горячая перезагрузка зон\n- Каждый zone-файл отслеживается в отдельной горутине\n- Изменение файла обнаруживается через **SHA-256 хеш**\n- При изменении — зона атомарно перезагружается без перезапуска сервера\n- Интервал проверки настраивается: `checkZoneInterval` + `checkZoneIntervalType`\n\n### Активная проверка хостов (Health Check)\nВключается параметром `activeCheck: true` в `config.yaml`.\n\n- Выполняет **TCP-проверку** порта для списка хостов из `check.yaml`\n- При изменении - список хостов для провери и порт перезагружаются `check.yaml` (также через SHA-256)\n- Алгоритм балансировки **Round Robin** применяется только к записям, чьи IP находятся в пуле `check.yaml`\n- Записи, не относящиеся к пулу, отдаются напрямую из зоны\n- Интервалы настраиваются отдельно: `repeatCheckInterval` и `repeatCheckFileInterval`\n\n### Форвардинг\nВключается параметром `forward: true` в `config.yaml`.\n\n- Запросы, не найденные ни в одной зоне, пересылаются на указанный внешний DNS-сервер\n- Настраивается адрес (`forwardDNS`) и порт (`forwardDNSPort`)\n\n---\n\n## Конфигурация\n\n### `config.yaml`\n```yaml\napp:\n  port: 53                            # Порт DNS-сервера\n  checkZoneInterval: 5                # Интервал проверки изменений зон\n  checkZoneIntervalType: seconds      # Единица: seconds / minutes / hours\n  activeCheck: true                   # Включить активную проверку хостов\n  algorithmCheck: RR                  # Алгоритм балансировки (RR — Round Robin)\n  repeatCheckInterval: 3              # Интервал TCP-проверки хостов\n  repeatCheckIntervalType: seconds\n  repeatCheckFileInterval: 3          # Интервал проверки изменений check.yaml\n  repeatCheckFileIntervalType: seconds\n  forward: true                       # Включить форвардинг для неизвестных зон\n  forwardDNS: 8.8.8.8                # Адрес upstream DNS\n  forwardDNSPort: 53                  # Порт upstream DNS\n```\n\n### `check.yaml`\n```yaml\nhostCheck:\n  - 10.13.1.36        # IP хоста (должен совпадать с A-записью в зоне)\n  - 176.125.254.184\nportCheck: 22          # TCP-порт для проверки\n```\n\n---\n\n## Benchmark\n\n### Стенд\n\n| | Машина | Роль |\n|---|--------|------|\n| Клиент | Mac mini M2, 16 GB | Генератор нагрузки (dnsperf / resperf) |\n| Сервер | MacBook Air M4, 16 GB | hllb на порту 1053 |\n| Сеть | Wi-Fi | Без оптимизации сетевого стека |\n\n### resperf (поиск точки насыщения)\n\n```\nresperf -P 20260325-1333.gnuplot -s 10.13.1.18 -p 1053 -d test.info -R -C 10\n```\n\n| Метрика | Значение |\n|---------|----------|\n| Запросов отправлено | 673 250 |\n| Запросов завершено | 608 827 (90.4%) |\n| Потеряно | 64 423 (9.6%) |\n| **Пиковый throughput** | **35 790 qps** |\n| Потери на пике | 16.61% |\n\n### dnsperf (стабильная нагрузка)\n\n```\ndnsperf -s 10.13.1.18 -m udp -p 1053 -d test.info -c 10 -l 30\n```\n\n| Метрика | Значение |\n|---------|----------|\n| Запросов отправлено | 202 632 |\n| Запросов завершено | 202 632 (100%) |\n| Потеряно | 0 (0%) |\n| **QPS** | **6 752** |\n| Средняя латенция | 14.1 ms |\n| Мин / Макс латенция | 3.1 ms / 145 ms |\n\n### Выводы\n\n- При стабильной нагрузке (10 клиентов) — **0% потерь**, ~6 750 qps\n- Пиковый throughput по resperf — **~35 800 qps** (с потерями 16%)\n- Предположительно Узкое место — UDP syscall ядра macOS (если опираться на pprof)\n\n---\n\n## Структура проекта\n\n```\n.\n├── main.go                    # Точка входа, запуск DNS-сервера\n├── config.yaml                # Основная конфигурация\n├── check.yaml                 # Список хостов для health check\n├── zone/                      # DNS zone-файлы (стандартный формат RFC 1035)\n│   └── test.ru\n├── algorithm/\n│   └── rr.go                  # Round Robin балансировка\n├── checks/\n│   └── tcpCheck.go            # TCP health check\n├── handles/\n│   ├── handleDNS.go           # Обработчик DNS-запросов\n│   └── forwardDNS.go          # Форвардинг на upstream DNS\n└── utils/\n    ├── initFiles.go           # Создание файлов/папок при первом запуске\n    ├── zoneParser.go          # Парсинг zone-файлов\n    ├── watchZoneFile.go       # Слежение за изменениями zone-файлов\n    ├── watchCheckFile.go      # Слежение за изменениями check.yaml\n    ├── hashFile.go            # SHA-256 хеширование файлов\n    ├── readConfig.go          # Чтение и кэширование config.yaml\n    ├── readCheck.go           # Чтение check.yaml\n    └── selectTime.go          # Конвертация единиц времени\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faddspin%2Fhllb","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faddspin%2Fhllb","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faddspin%2Fhllb/lists"}