Commit 8037b7c0 authored by Vitaly Lipatov's avatar Vitaly Lipatov

memory: update infrastructure references and project notes

parent e27dce06
...@@ -6,7 +6,16 @@ PVE-хост в кластере MIAC. CPU: **AMD Opteron 6164 HE** (2010, K10, ...@@ -6,7 +6,16 @@ PVE-хост в кластере MIAC. CPU: **AMD Opteron 6164 HE** (2010, K10,
## Changelog ## Changelog
### 2026-06-26 — с border сняты два VPN-гостя ### 2026-07-19 — создан CT 480 (petrosvyaz.dgw.etersoft.ru)
- **Что:** Клонирован CT 694 (dgw.etersoft.ru) → CT 480. IP 91.232.225.250, routing через Петровсвязь: `ip rule from 91.232.225.250 lookup petrosvyaz` (persistent в `/etc/net/ifaces/ether3/ipv4rule`). PTR добавлен в обратную зону. На egw route-update.sh обработал petrosvyaz группу: google-dns маршруты (8.8.8.8, 8.8.4.4) через 91.232.225.250. Masquerade НЕ нужен — Петровсвязь маршрутизирует ответы до .250 обратно через priv.
- **Зачем:** Изоляция трафика через Петровсвязь — вместо кастомных маршрутов на priv, отдельный контейнер с policy routing. [ses_08605dc7cffeh, ses_077433517ffe]
### 2026-07-15 — запущен CT 706 (gr.egw), восстановлен gvpn Greek-эгресс
- **Что:** CT 706 `ikev2.gr.egw.etersoft.ru` (.139) был остановлен → gvpn (CT 752 на enceladus) терял default-gateway и был offline. `pct start 706` + initiate с parentglobal → SA up, gvpn эгрессит `94.69.12.186` (Греция).
- **Зачем:** CT 706 = IPsec-responder для Greek-эгресса gvpn (аналог fr.egw=CT704). onboot:1, переживает ребут border.
- **Подробности:** [[reference_ikev2_gr_tunnel]].
### 2026-06-26 — с border сняты два VPN-гестя
- **Что:** CT 258 (vpn.eterfund.ru) и VM 292 (vpn.office.etersoft.ru) мигрированы на enceladus (Ryzen, AES-NI). С border ушли полностью. - **Что:** CT 258 (vpn.eterfund.ru) и VM 292 (vpn.office.etersoft.ru) мигрированы на enceladus (Ryzen, AES-NI). С border ушли полностью.
- **Зачем:** Opteron 6164 HE без AES-NI делал OpenVPN-крипту софтовой → упор в ядро. Подробности: [[project_vpn_migrate_enceladus_aesni]]. - **Зачем:** Opteron 6164 HE без AES-NI делал OpenVPN-крипту софтовой → упор в ядро. Подробности: [[project_vpn_migrate_enceladus_aesni]].
- **evpn (CT 264) ОСТАЛСЯ на border** — его не переносили (IKEv2/strongSwan, см. [[lesson_evpn_ikev2_strongswan_cert]]). - **evpn (CT 264) ОСТАЛСЯ на border** — его не переносили (IKEv2/strongSwan, см. [[lesson_evpn_ikev2_strongswan_cert]]).
...@@ -42,6 +42,26 @@ ...@@ -42,6 +42,26 @@
## Changelog ## Changelog
### 2026-07-19 — eterweb.ru: истёк→освобождён→ПЕРЕРЕГИСТРИРОВАН обратно + фикс сертификата gnucheva
**Инцидент: `eterweb.ru` истёк и был освобождён из реестра `.ru`.**
- whois (TCI) первое время: `No entries found` — домен **полностью отсутствовал** (истёк, освобождён). TLD `.ru` отдавал NXDOMAIN+SOA зоны `.ru`, публичные резолверы — NXDOMAIN на все `*.eterweb.ru`. Наши ns1/ns4 хранили зону, но без делегирования мир её не видел.
- **Восстановлено пользователем в тот же день** (~19:36Z): перерегистрация через регистратора `DOMAINSHOP-RU`, `paid-till: 2027-07-19`. Делегирование `state: REGISTERED, DELEGATED, UNVERIFIED`.
- **Набор NS изменился** при перерегистрации: теперь `ns1/ns2.etersoft.ru` + `ns3/ns4.etersoft.com` (раньше было `ns1/ns4.etersoft.ru`). Все 4 синхронно отдают зону (SOA serial `2018011404`, знают `vgnucheva.eterweb.ru`→.9). ТLD `.ru` подхватывает делегирование с задержкой (минуты–десятки минут) — публичные резолверы сразу после регистрации ещё NXDOMAIN.
- **Влияние было:** все `*.eterweb.ru` публично мертвы ~7 недель; сертификаты LE с SAN `*.eterweb.ru` протухли (renew падал на DNS NXDOMAIN): `eterweb.ru` (16.05), `vgucheva.eterweb.ru` (09.05), `anastasia-nikolaeva.eterweb.ru` (09.05), `vgnucheva.eterweb.ru` (30.05).
- **После возврата домена:** renew этих сертификатов снова заработает автоматически, как только TLD распространит делегирование. Ничего удалять не нужно.
- **2026-07-20:** как только DNS `*.eterweb.ru` ожил публично (TLD `.ru` разнёс NS-делегирование), вручную перевыпущены `certbot renew --cert-name {eterweb.ru, vgucheva.eterweb.ru, anastasia-nikolaeva.eterweb.ru}` — все три до 17.10.2026, HTTPS ожил (anastasia-nikolaeva 200, остальные 302-forward). **Грабля:** certbot 0.31 `renew` ставит `random delay` до ~480 c перед каждым cert → пакетный renew 3 сертификатов занял ~10 мин; для скорости можно `--no-random-sleep-on-renew` (но лишает anti-load jitter).
**Фикс: сертификат `vgnucheva.eterweb.ru` (varvara.gnucheva.com и др.).**
- Root cause: в SAN было `vgnucheva.eterweb.ru` (NXDOMAIN публично из-за потери зоны) → роняло весь сертификат → истёк 30.05.2026.
- Перевыпустил с 6 доменами **без** `vgnucheva.eterweb.ru`: `certbot certonly --webroot -w /var/spool/nginx/tmp/client -d gnucheva.com -d gnucheva.ru -d varvara.gnucheva.com -d varvara.gnucheva.ru -d varya.gnucheva.com -d varya.gnucheva.ru --cert-name vgnucheva.eterweb.ru` (cert-name оставлен для сохранения путей).
- Новый cert: `notAfter=2026-10-17`. `--dry-run` auto-renew прошёл.
- certbot при `certonly` **стёр `renew_hook`** из renewal-conf → восстановил вручную (`renew_hook = serv nginx reload`), бэкап `.bak-hook-*`. **Грабли:** всегда проверять renew_hook после ручного certonly.
- Сайт `https://varvara.gnucheva.com` — HTTP/2 200.
- Тестовый challenge-файл `z-claude-test` в webroot создан для диагностики и **удалён**.
**Прочее из mass-renew-failure (04:49, 23 серта):** у каждого своя причина (не только eterweb). Например `ximper.ru` — домен указывает на .173 (другой хост), `www.ximper.ru` NXDOMAIN. Это отдельная задача массового разбора.
### 2026-06-27 — массовые 503 на soulibre.ru (ДОКАЗАННАЯ причина) ### 2026-06-27 — массовые 503 на soulibre.ru (ДОКАЗАННАЯ причина)
- **Симптом:** soulibre.ru плавающе отдаёт 503, реально **1 685 200 ответов 503/сутки** (~60% запросов). Даже 1 запрос в 6 сек ловит 503; wikilivres.ru (тот же движок/хост) и etersoft.ru — чисто. - **Симптом:** soulibre.ru плавающе отдаёт 503, реально **1 685 200 ответов 503/сутки** (~60% запросов). Даже 1 запрос в 6 сек ловит 503; wikilivres.ru (тот же движок/хост) и etersoft.ru — чисто.
- **503 рисует nginx, НЕ бэкенд.** Apache в CT 167 за сутки отдал **0 ответов 503** (200/404/302/301/304), mod_status Load 0.5 — перегрузки нет. Бэкенд ни при чём (важно: первая гипотеза про «маленький CT 167 захлёбывается» оказалась неверной). - **503 рисует nginx, НЕ бэкенд.** Apache в CT 167 за сутки отдал **0 ответов 503** (200/404/302/301/304), mod_status Load 0.5 — перегрузки нет. Бэкенд ни при чём (важно: первая гипотеза про «маленький CT 167 захлёбывается» оказалась неверной).
......
# roundcube.eterhost.ru (CT 366, 10.20.30.66)
## 2026-07-10 — обновление до Roundcube 1.7.0
Обновлено через epm. Breaking changes и исправления:
**Apache** (`/etc/httpd2/conf/sites-enabled/roundcube.eterhost.ru.conf`):
- DocumentRoot: `/usr/share/roundcube``/usr/share/roundcube/public_html` (mandatory в 1.7.0)
- Directory: аналогично
**Патч authres_status** — плагин `pimlie/authres_status` v0.6.3 не обновлён для 1.7.0:
- `/usr/share/roundcube/plugins/authres_status/authres_status.php`
- `src="plugins/authres_status/images/"``src="static.php/plugins/authres_status/images/"`
- `login_history` (выключен) — та же проблема
**Nginx** (на 91.232.225.23, `/etc/nginx/sites-enabled.d/roundcube.eterhost.ru.conf`):
- `location /installer.php { return 403; }` — блокировка установщика
- `listen 443 ssl http2``listen 443 ssl` + `http2 on` (deprecation fix)
**Статика**: `public_html/` содержит только index.php, static.php, installer.php, .htaccess. Вся статика (JS, CSS, шрифты) отдаётся через `static.php`. Прямых файлов для nginx нет. Кеш: `cache-control: public, max-age=604800` (7 дней).
**Плагины**: contextmenu оставлен (встроенное меню 1.7.0 — только список писем). Дубликат image_paster убран. zipdownload отключён (500 на AJAX).
**Безопасность**: directory listing отключён, внутренние файлы не доступны, installer.php заблокирован nginx.
## 2026-07-09 — проверка исходящей связности
- По запросу проверен `ping -c 4 ya.ru` от `root@10.20.30.66`.
- Результат: 4/4 ответа, потерь нет; RTT 13.772–14.003 ms (средний 13.900 ms).
- На момент проверки исходящий IPv4-трафик из CT проходит; изменений на сервере и NAT-шлюзе не выполнялось.
---
# VPN: dvpn/fvpn/gvpn.eterfund.ru — прогресс (2026-07-13)
## Созданные контейнеры (enceladus)
| Контейнер | VMID | IP | Default route | VPN pool | OpenVPN | ocserv |
|---|---|---|---|---|---|---|
| dvpn.eterfund.ru | CT 750 | 91.232.225.182 | via 91.232.225.12 (dgw) | 10.236.0.0/16 | ✅ | ✅ |
| fvpn.eterfund.ru | CT 751 | 91.232.225.183 | via 91.232.225.140 (fr.egw) | 10.237.0.0/16 | ✅ | ✅ |
| gvpn.eterfund.ru | CT 752 | 91.232.225.184 | via 91.232.225.139 (gr.egw) | 10.238.0.0/16 | ✅ | ✅ |
## Сделано
- Клонированы с CT 258 (vpn.eterfund)
- Сеть настроена через /etc/net/ifaces/breth0/ (ipv4address, ipv4route, options)
- IPv6 адреса: ::182/::183/::184 (последняя компонента как IPv4)
- OpenVPN запущен и работает (порт 1195, UDP)
- ocserv запущен и работает (порт 443, TCP/UDP)
- PKI и пароли ocserv скопированы с CT 258
- DNS записи добавлены на ns1
- Let's Encrypt сертификаты получены (dvpn/fvpn/gvpn.eterfund.ru)
- ntpd отключён (не нужен в LXC)
- Старый azbyka отключён и удалён
- iptables на хосте: SNAT добавлен для .182/.183/.184
## Нужно доделать
1. **Мониторинг** — telegraf не установлен на CT 750/751/752
2. **Баг #16295** — отписаться о создании
3. **certbot auto-renew** — настроить на всех трёх
## Грабли
- Клонирование LXC НЕ копирует SNAT-правила на хосте → нужно добавить вручную: `iptables -t nat -A POSTROUTING -s <IP> -j SNAT --to-source <IP>`
- ntpd в контейнере падает с segfault (не нужен в LXC, отключить)
- IPv6 адреса копируются с оригинала → dadfailed конфликт
## Ссылки
- План: `.mimocode/plans/1783569058720-calm-eagle.md`
- Баг: https://bugs.etersoft.ru/show_bug.cgi?id=16295
--- ---
name: project-dchat-telemt-greek-tunnel-down name: project-dchat-telemt-greek-tunnel-down
description: "d.chat.eterfund.ru (telemt Telegram MTProxy на divserver) не работает лежит IPsec-туннель divserver↔parentglobal к греческому exit. Диагноз готов, фикс отложен 2026-06-05" description: "d.chat.eterfund.ru (telemt MTProxy на divserver) Greek exit parentglobal. Туннель divserver↔parentglobal падал 2026-06-05 (фикс 06-06) и РЕЦИДИВ 2026-07-14 (rekey-fail, нет self-heal). Финальный фикс 2026-07-15: runtime re-initiate + watchdog-timer на parentglobal (divserver + site-to-site). РАБОТАЕТ"
metadata: metadata:
node_type: memory node_type: memory
type: project type: project
...@@ -42,5 +42,22 @@ IPsec-туннель **divserver↔parentglobal (10.43.0.0/30) лежит**: ...@@ -42,5 +42,22 @@ IPsec-туннель **divserver↔parentglobal (10.43.0.0/30) лежит**:
Связано: [[lesson-telemt-middle-proxy-egress-match]] (egress=registered IP для ME), [[reference-remote-ssh-access]], [[lesson-anyssh-ru-in-91232225]], [[lesson-etcnet-hooks]]. Связано: [[lesson-telemt-middle-proxy-egress-match]] (egress=registered IP для ME), [[reference-remote-ssh-access]], [[lesson-anyssh-ru-in-91232225]], [[lesson-etcnet-hooks]].
## Рецидив 2026-07-14 → финальный фикс 2026-07-15 (watchdog)
Персистентность 2026-06-06 оказалась **недостаточной**: `start_action=start` срабатывает ТОЛЬКО при загрузке конфига в charon, а **после провала rekey SA умирает и не переинициируется**. strongSwan на parentglobal крутился с 2026-05-26 без рестарта; последний CHILD_SA `div{278}` — 14 июля 06:48, в 12:33 «restarting CHILD_SA div» провалился → тишина до ручного initiate. telemt висел в `No ME connections` (~3 суток ретраев).
**Runtime-фикс 2026-07-15:**
1. `ssh -p10337 etersoft@anyssh.ru 'sudo swanctl --initiate --ike divserver --child div'` (child = **`div`**, НЕ `s2s`) → SA up.
2. divserver responder был полностью здоров (conn `parentglobal` загружен, ipsec1.service active, policy-route table 201 на месте) — проблема была только в отсутствии инициации с parentglobal.
3. `ssh root@div.eterhost.ru 'systemctl restart telemt'` → ME-pool reinit, STUN `94.69.12.186`, 48→126 ESTAB к TG-DC, d.chat обслуживает клиентов.
**Self-heal (настоящий фикс) — watchdog-timer на parentglobal** (как autoheal у fr-туннеля, но systemd, не docker):
- `/usr/local/bin/ikev2-keepalive.sh` — каждые 2 мин (timer) проверяет `swanctl --list-sas | grep -q '^<ike>:.*ESTABLISHED'`; если 0 → `swanctl --initiate --ike <ike> --child <child>`. Логирует в syslog тегом `ikev2-keepalive`.
- Покрывает **оба** туннеля parentglobal: `divserver`/child `div` (этот telemt-эгресс) и `site-to-site`/child `s2s` (gvpn Greek-эгресс, [[reference_ikev2_gr_tunnel]] — у него 2026-07-15 был тот же гэп).
- Юниты: `/etc/systemd/system/ikev2-keepalive.{service,timer}`, `systemctl enable --now ikev2-keepalive.timer`. OnBootSec=2min, OnUnitActiveSec=2min.
- Проверка паттерна: `swanctl --list-sas | grep -c '^divserver:.*ESTABLISHED'` = 1 (up); при падении = 0 → триггер. ✓
Доступ к parentglobal: `ssh -p10337 etersoft@anyssh.ru` (sudo). divserver: `ssh root@div.eterhost.ru`.
## Побочное (отдельно) ## Побочное (отдельно)
Сертификат `/etc/ssl/chat.eterfund.ru/fullchain.pem` на divserver (и на .43/.140) имеет SAN только `chat.eterfund.ru`, без `d.chat.eterfund.ru` → в браузере ошибка имени. Для telemt fake-TLS неважно. Cert раздаётся централизованно на все 3 узла (одинаковый, LE, выпуск 2026-05-08). nginx vhost (`server_name chat.eterfund.ru d.chat.eterfund.ru`) проксирует на web.matrix.etersoft.ru — это камуфляж-бэкенд. Сертификат `/etc/ssl/chat.eterfund.ru/fullchain.pem` на divserver (и на .43/.140) имеет SAN только `chat.eterfund.ru`, без `d.chat.eterfund.ru` → в браузере ошибка имени. Для telemt fake-TLS неважно. Cert раздаётся централизованно на все 3 узла (одинаковый, LE, выпуск 2026-05-08). nginx vhost (`server_name chat.eterfund.ru d.chat.eterfund.ru`) проксирует на web.matrix.etersoft.ru — это камуфляж-бэкенд.
--- ---
name: reference_eterventcontrol name: reference_eterventcontrol
description: "eterventcontrol управление вентиляцией офиса (Modbus + FastAPI), где код, где запущен, порт" description: "eterventcontrol управление вентиляцией офиса (Modbus + FastAPI): где код, где запущен (контейнер vent), порт, Kerberos"
metadata: metadata:
node_type: memory node_type: memory
type: reference type: reference
originSessionId: 127a3012-0746-43d6-89a5-719f3ca01d7d originSessionId: 127a3012-0746-43d6-89a5-719f3ca01d7d
--- ---
**eterventcontrol** — сервис управления вентиляцией офиса (Modbus TCP → приточки, FastAPI/uvicorn API). **eterventcontrol** — сервис управления вентиляцией офиса (Modbus TCP → приточка Zentec 192.168.8.217:502, PID по CO2/температуре, FastAPI/uvicorn API).
## Где код ## Где код
- Репозиторий: `/srv/lav/Projects/git-eter/eterventcontrol` (Python, отдельный git-проект, НЕ в etersoft-admin-essential) - Репозиторий: `/srv/lav/Projects/git-eter/eterventcontrol` (Python, отдельный git-проект, НЕ в etersoft-admin-essential)
- Запуск: `python3 -m eterventcontrol.main loop` (он же `/usr/bin/eterventcontrol loop`) - Запуск: `python3 -m eterventcontrol.main loop`
- Есть `services/eterventcontrol.service` (ExecStart=/usr/bin/eterventcontrol loop), но на server он НЕ установлен как сервис - Свежее дерево лежит и в dev-репо, и в контейнере `/opt/eterventcontrol` (rsync)
## Где запущен ## Где запущен (production)
- Машина **server** = `192.168.0.1` - **Контейнер `vent`** = CT **762** на PVE-хосте **border**, `vent.office.etersoft.ru` = **192.168.0.67**, ALT p11
- **API: http://192.168.0.1:8000** (uvicorn/FastAPI; в коде дефолт `127.0.0.1:8000`, host переопределён на LAN-адрес 192.168.0.1) - **Сетевой мост `vmbr0`** (office LAN). Контейнер — единственное место, где LXC имеет L2-доступ к office LAN и досягаемость до Modbus-устройства.
- Крутится как обычный процесс, НЕ через systemd: `serv eterventcontrol status``not-found`, автозапуск выключен (запущен вручную/из другого места — родитель не уточнён) - **Сервис: system unit `/etc/systemd/system/eterventcontrol.service`** (root), enabled, `Restart=always`, `ExecStart=/usr/bin/python3 -m eterventcontrol.main loop`, `WorkingDirectory=/opt/eterventcontrol`. onboot=1.
- Управление: `ssh root@192.168.0.67 "systemctl {status,restart} eterventcontrol"`; логи `journalctl -u eterventcontrol`.
## Порты (дефолты в коде) - **API: http://vent.office.etersoft.ru:8000** — UI `/`, API под `/api/v1/` (`/api/v1/health`, `/api/v1/rooms`, `/api/v1/status`…). Auth: api_key (`X-API-Key`) ИЛИ Kerberos SPNEGO.
- API: **8000** (`main.py` api_cfg) - DNS: A+PTR `vent.office.etersoft.ru`→192.168.0.67 на dhcp (зона office.etersoft.ru внутренняя, на ns1 нет).
- Modbus TCP к устройству вентиляции: **502** (`vent_device.py`, `modbus_client.py`)
- InfluxDB (метрики): **8086** (`influx_client.py`) ## Сеть в контейнере (грабли шаблона 720)
- Шаблон 720 — etcnet, настроен на `breth0` (10.20.30.246), а PVE создаёт `eth0` и пишет мёртвый `/etc/systemd/network/eth0.network` (networkd **не установлен**).
- Фикс: настроить `/etc/net/ifaces/eth0/` (ipv4address 192.168.0.67/24, ipv4route `default via 192.168.0.1`, options BOOTPROTO=static TYPE=eth ONBOOT=yes), убрать `breth0` и мёртвые networkd .network, **`systemctl enable network`** (в шаблоне active-но-disabled → без enable eth0 не поднимется после ребута). См. [[lesson_lxc_etcnet_to_systemd_networkd]].
- Modbus 192.168.8.217:502 достижим через server (192.168.0.1) как gw.
## Пакеты (p11)
- epm: `python3-module-{toml,requests,fastapi,uvicorn,pydantic,gssapi,influxdb}`, `libmodbus`, `python3-module-cffi`.
- `python3-module-pylibmodbus` **нет в регулярном p11/branch** (только girar-task 402985). Ставят локальным rpm: на server кеширован `python3-module-pylibmodbus_0.6.2-alt1_noarch.rpm` (p11+402985). noarch, зависит только от `python3(cffi)`.
## Kerberos SSO
- AD-аккаунт **`http-vent`** (CN=Users, UAC 512, как `http-builder`), SPN `HTTP/vent.office.etersoft.ru`.
- Keytab `/etc/eterventcontrol/http.keytab` (RC4/enctype 23, KVNO 2). Создание: `samba-tool user create http-vent --random-password` + `spn add HTTP/vent.office.etersoft.ru http-vent` + `domain exportkeytab --principal=HTTP/vent.office.etersoft.ru` (на dc.etersoft.ru, lav+sudo).
- `[auth] fqdn = "vent.office.etersoft.ru"`, `admin_users = ["lav@ETERSOFT.RU","owl2@ETERSOFT.RU"]`.
- Тест acceptor: `gssapi.Credentials(name=HTTP@vent.office.etersoft.ru, usage=accept, store={keytab:...})` — грузится OK. `kinit -k HTTP/...` падает «not found» (SPN-as-client не работает в этом Samba) — это нормально, акцептор-роль работает; реальный тест — `curl --negotiate` с клиентского TGT.
## Порты / внешние сервисы (из config.toml)
- Modbus TCP: 192.168.8.217:502
- InfluxDB: `http://influxdb.k8s.eterfund.ru:80`, БД `co2_levels`
- API: 8000
- Сенсоры (читаются из InfluxDB): `fenix.office.etersoft.ru`, `lav.office.etersoft.ru`
## Важно
- **Два инстанса одновременно запускать нельзя** — оба пишут Modbus control-регистры (конфликт управления, износ EEPROM). Перед миграцией — cutover-свап (stop старого → start нового).
- `cleanup()` восстанавливает initial fan/supply (пишет, только если значение успело измениться).
## История
- До 2026-07-21: крутился как `systemctl --user` сервис у `lav` на `server` (192.168.0.1, шлюз, не PVE). После ребута server 02:49 был down ~12ч (unit с `ConditionHost=server.office.etersoft.ru`). Перенесён в контейнер vent (CT 762 на border), server-side user-service disabled.
---
name: reference_ikev2_fr_tunnel
description: "Обход claude.ai/Anthropic через Францию вся система fr/ikev2.fr (route-update + .140 + rpi). Data path, доступ, диагностика \"egress=.140\", фикс, persistence"
metadata:
node_type: memory
type: reference
originSessionId: e7921933-7fc7-4871-889c-9d5efe71c046
---
Обход `claude.ai` и Anthropic-доменов через французский egress. Вся система = 3 части: группа `fr` в route-update (на igw/egw) → IPsec-туннель `.140` ↔ rpi(Франция). Зафиксировано после инцидента «egress = .140 вместо Франции» (2026-07-05).
## Data path (как идёт трафик)
```
клиент/сервис
│ (claude.ai резолвится в 160.79.104.10 / 2607:6bc0::10)
igw / egw ── ip rule: lookup claude.ai (pref 900) ──▶ table claude.ai (per-list, table 223)
│ gateway 91.232.225.140 (v4) / unreachable (v6)
▼ v6 = ICMP unreachable (fast reject ~2мс) — т.к. туннель IPv4-only
91.232.225.140 «ikev2» (IPsec RESPONDER, strongSwan)
│ ip route get claude.ai → via 10.10.10.6 dev ipsec0
│ XFRM if_id=42 → шифрует (ESP) → NAT-T :4500
rpi (Франция, public 78.193.2.190, Orange/AS3215) — контейнер ikev2-fr (INITIATOR)
│ ipsec0 = 10.10.10.6/30, MASQUERADE → eth0
claude.ai (видит src 78.193.2.190 — Франция, проходит геоблок)
```
## Часть 1. Группа `fr` в route-update (igw + egw)
`routes.d/fr/` (v4) и `routes6.d/fr/` (v6) на обоих шлюзах:
- `gateway` (v4) = `91.232.225.140 metric 50`
- `gateway` (v6) = `unreachable` (route-type keyword, см. [[reference_route_update_sh]])
- `options` = `pref 900` (явный override, **перебивает** `egw/ai` на pref 1210)
- `claude.ai.list` → симлинк на `/root/egw-route/claude.ai.list` (Anthropic-домены)
- таблица `claude.ai` (per-list, №223 на igw)
Симметрично на igw и egw. Подробно механика route-update — [[reference_route_update_sh]]. Сами списки живут в git `eterfund/egw-route.git` (`/root/egw-route/` на хостах).
## Часть 2. .140 «ikev2» (responder)
- Хост `ikev2` = `91.232.225.140`. Доступ: `ssh root@91.232.225.140`.
- strongSwan + swanctl. Конфиг: `/etc/strongswan/swanctl/conf.d/site-to-site.conf`.
- Соединение `site-to-site`: `local_addrs=91.232.225.140:4500`, `remote_addrs=%any` (**responder**, ждёт инициатора). local id `ikev2.fr.egw.etersoft.ru`, remote id `fr.egw.etersoft.ru`. PSK в `secrets`.
- `ipsec0` XFRM if_id=42, `10.10.10.5/30`.
- Перезагрузка конфига: `swanctl --load-all` (или `systemctl restart strongswan`).
## Часть 3. rpi (initiator, Франция)
- **Raspberry Pi** во Франции, public `78.193.2.190` (Orange).
- Доступ через reverse-SSH: `ssh -p 10338 root@anyssh.eterhost.ru` (hostname `rpi`). Reverse-SSH поднят контейнером `tunnel-fr` (autossh `-R 10338:localhost:22`, проект `/root/tunnel-fr/`, пользователь `a338`, ключ `/root/tunnel-fr/etersoft.key` → COPY в образ как `/root/.ssh/etersoft.key`).
- **Альтернативный доступ** (когда reverse-SSH упал): с .140 через IPsec → Docker bridge. `ikev2-fr` = host networking, rpi-хост = `172.17.0.1` (Docker bridge): `ssh root@91.232.225.140 'ssh root@172.17.0.1 "hostname"'`. Примечание: `10.10.10.6` — это контейнер `ikev2-fr`, НЕ rpi-хост.
- IPsec-инициатор = docker-контейнер **`ikev2-fr`** (image `ikev2-fr-client`), проект `/opt/ikev2-fr-docker/` (Dockerfile, swanctl.conf, entrypoint.sh, healthcheck.sh, docker-compose.yml, README.md).
- `swanctl.conf` в образе: `remote_addrs=91.232.225.140:4500`, local id `fr.egw.etersoft.ru`. PSK = тот же, что на .140. `start_action=start`, `close_action=start`, `dpd_action=restart`.
- `entrypoint.sh`: создаёт `ipsec0` (10.10.10.6/30, if_id 42), MASQUERADE на eth0, `exec charon-systemd` (PID 1).
- `ipsec0` = `10.10.10.6/30`.
| | .140 (responder) | rpi / ikev2-fr (initiator) |
|---|---|---|
| public | 91.232.225.140 | **78.193.2.190** |
| local id | ikev2.fr.egw.etersoft.ru | fr.egw.etersoft.ru |
| ipsec0 | 10.10.10.5/30 | 10.10.10.6/30 |
| conf | /etc/strongswan/swanctl/conf.d/site-to-site.conf | /opt/ikev2-fr-docker/swanctl.conf (+в образе) |
## Ключевая диагностика: «egress = .140 вместо Франции»
= **IPsec SA не установлен**. Тогда .140 маршрутизирует claude.ai через свой default (Etersoft uplink 91.232.225.1) и egress'ит как `91.232.225.140` (Anthropic отдаёт 403 на curl).
Проверки:
```bash
# на .140:
ssh root@91.232.225.140 'swanctl --list-sas | grep -i ESTABLISHED' # пусто → SA down
ssh root@91.232.225.140 'ip route get 160.79.104.10' # via ipsec0=OK, via eth0=down
# на rpi:
docker exec ikev2-fr swanctl --list-sas # SA со стороны инициатора
docker ps | grep ikev2-fr # Up (unhealthy)? → SA down
```
AUTH_FAILED в логе .140 от IP типа 164.90.141.172 / 205.210.31.215 — **сканеры**, не наш пир (они до IKE_AUTH не доходят или фейлятся раньше). Реальный пир = rpi (78.193.2.190).
## Фикс
Переинициировать SA:
```bash
ssh -p 10338 root@anyssh.eterhost.ru 'docker exec ikev2-fr swanctl --initiate --child s2s'
```
После этого `swanctl --list-sas` на .140 покажет `ESTABLISHED ... remote 'fr.egw.etersoft.ru' @ 78.193.2.190`, `ip route get 160.79.104.10``via 10.10.10.6 dev ipsec0`, egress claude.ai = 78.193.2.190.
## Persistence (self-healing)
`ikev2-fr` имеет label `autoheal=true``docker-compose.yml`). Контейнер `autoheal` (`willfarrell/autoheal`, проект `/root/tunnel-fr/`) рестартит unhealthy-контейнеры с этой меткой:
```
SA down → healthcheck (swanctl --list-sas | grep ESTABLISHED) fail → unhealthy
→ autoheal рестартит ikev2-fr → entrypoint → charon → start_action=start → SA ↑
```
~60-90с восстановление. На свежем старте SA поднимается сам. **Именно отсутствие autoheal-label** было причиной 7-дневного дауна (контейнер висел unhealthy, никто не рестартил).
Все настройки ikev2-fr в образе `ikev2-fr-client` (== `/opt/ikev2-fr-docker/*`, `docker diff` чист) — пересоздание через `docker compose up -d` ничего не теряет.
## Мониторинг (route-health)
`route-health.sh` (timer на igw/egw) + Telegraf → InfluxDB (`gateways`): по шлюзам собирает ping/iperf3/vpn/proxy, пишет `health.json` (кормит route-web UI).
**ikev2.fr и ikev2.gr — ping-only** (`is_pingonly_gw` в route-health.sh): у rpi-пира нет iperf3-сервера и VPN-status-feed, поэтому судят **только по ping** (loss≥50 или no-data = dead). Раньше они проверялись по iperf3 → success=0 → перманентный false-`down`, что маскировало реальные обрывы (7-дневный даун не заметили). Теперь: туннель up → ping через него идёт → healthy; упал → ping до 10.10.10.6 не идёт → dead (реальная детекция).
Health виден в route-web UI (`health.json`: `groups[].gateways[]` для fr → ikev2.fr). **Push-алертинга пока нет** — состояние видно в UI + rpi восстанавливается через autoheal, но уведомления (Telegram/почта) не настроены.
## Грабли / нюансы
- `claude.ai` на plain-`curl` = **403** (anti-bot по User-Agent). С браузерным UA = **302** (норма). 403 ≠ геоблок.
- Туннель **IPv4-only** → v6 claude.ai = unreachable (fast reject), не пытаться чинить v6 через rpi.
- `docker logs ikev2-fr` пустой (charon-systemd пишет в journald, которого нет в контейнере) — диагностика через `swanctl --list-sas` / `--initiate`.
- PSK хранится в swanctl.conf с обеих сторон (в secrets); при смене — одинаково в `/opt/ikev2-fr-docker/swanctl.conf` (rpi) и `/etc/strongswan/swanctl/conf.d/site-to-site.conf` (.140), потом rebuild/reload.
---
name: reference_ikev2_gr_tunnel
description: "Greek egress для gvpn через gr.egw (CT 706 .139 responder) parentglobal (Греция, initiator). Data path, доступ, фикс 'gvpn offline = CT 706 stopped'. Параллельно [[reference_ikev2_fr_tunnel]]"
metadata:
type: reference
---
Greek egress для **gvpn** (CT 752 на enceladus). Полный аналог французского туннеля ([[reference_ikev2_fr_tunnel]]), только страна/хосты другие. Зафиксировано 2026-07-15 после инцидента «gvpn offline».
## Data path
```
gvpn (CT 752, enceladus) default via 91.232.225.139
gr.egw / CT 706 (.139, PVE-нода border) — IPsec RESPONDER (strongSwan/swanctl)
│ ip_forward=1, route: default via 10.10.10.6 dev ipsec0 metric 50
│ ipsec0 = 10.10.10.5/30, XFRM if_id=42
parentglobal (Греция, Cosmote, dyn 94.69.12.186, за NAT) — INITIATOR
│ IKE id gr.egw.etersoft.ru, ipsec0 = 10.10.10.6/30
инет (эгресс = 94.69.12.186, Греция)
```
gvpn выходит в инет как `94.69.12.186` (проверка: `lxc-attach -n 752 -- curl -s https://icanhazip.com`).
## Узлы
| | gr.egw (responder) | parentglobal (initiator) |
|---|---|---|
| что это | CT 706 `ikev2.gr.egw.etersoft.ru` на **border** | ALT Workstation K 11 дома в Греции (Cosmote) |
| IP | 91.232.225.139 (public) | dyn **94.69.12.186**, за NAT (192.168.1.99 lan) |
| local id | ikev2.gr.egw.etersoft.ru | gr.egw.etersoft.ru |
| ipsec0 | 10.10.10.5/30 | 10.10.10.6/30 |
| conf | `/etc/strongswan/swanctl/conf.d/site-to-site.conf` | `/etc/strongswan/swanctl/conf.d/site-to-site.conf` |
| start_action | none (responder) | **start**, dpd_action=restart, close_action=start (self-heal) |
| PSK | 7f02acba… (id-server ikev2.gr.egw… / id-client gr.egw…) | тот же |
PSK и конфиг — близнецы fr.egw/CT704, только `.139`/`gr` вместо `.140`/`fr`.
## Доступ к parentglobal (за NAT)
- **Reverse-SSH:** `ssh -p 10337 etersoft@anyssh.ru` (anyssh.ru=91.232.225.8), потом sudo. См. [[reference_remote_ssh_access]].
- **Через IPsec (когда SA up):** `ssh -J root@91.232.225.139 root@10.10.10.6`.
## Ключевая диагностика: «gvpn offline»
gvpn (CT 752) имеет `default via 91.232.225.139 dev breth0`. Если **CT 706 остановлен** → у gvpn нет шлюза → offline. Симптом: `ping 91.232.225.139` из gvpn = 100% loss, `lxc-attach -n 752 -- curl` виснет.
```bash
ssh root@border 'pct status 706' # stopped → причина
ssh root@border 'pct start 706' # поднять responder
ssh root@border 'lxc-attach -n 706 -- swanctl --list-sas' # пусто → parentglobal не подключился
```
CT 706 = responder (`remote_addrs=%any`, `start_action=none`) — сам SA не инициирует. Если parentglobal не переподключился сам (редко), инициировать с его стороны:
```bash
ssh -p 10337 etersoft@anyssh.ru 'sudo swanctl --initiate --child s2s'
```
## Фикс 2026-07-15 (этот инцидент)
CT 706 был остановлен (onboot:1, но не бежал; все 5 собратьев ikev2.*.egw бежали) → gvpn offline.
1. `ssh root@border 'pct start 706'` — responder поднялся (ipsec0=10.10.10.5/30).
2. gvpn снова пингует .139, но SA пустой.
3. `ssh -p 10337 etersoft@anyssh.ru 'sudo swanctl --initiate --child s2s'` → SA ESTABLISHED, gvpn эгрессит `94.69.12.186`.
После ручного initiate дальше self-heal (`close_action=start`).
## Различие с fr
- fr.egw (CT 704, .140) обслуживает **обход claude.ai/Anthropic** через igw/egw (группа `fr` в route-update, таблица claude.ai). См. [[reference_ikev2_fr_tunnel]].
- gr.egw (CT 706, .139) обслуживает **только gvpn** (default route). Группы `gr` в route-update НЕТ, route-health ikev2.gr не мониторит (только ikev2.fr/ikev2.gr формально ping-only, но routes.d/gr пуст).
## Смежный туннель на parentglobal: `divserver`
У parentglobal в swanctl **две** conn: `site-to-site` (→.139, этот документ) и `divserver` (→divserver, telemt/Telegram MTProxy, ipsec1 10.43.0.0/30). На 2026-07-15 `divserver` SA **down** — это отдельная deferred-проблема ([[project_dchat_telemt_greek_tunnel_down]]), к gvpn-эгрессу отношения не имеет.
## Грабли
- [[lesson_anyssh_ru_in_91232225]] — НЕ добавлять на parentglobal маршрут `91.232.225.0/24 via ipsec0` до установки SA: перехватит трафик к anyssh.ru (.8), умрёт reverse-SSH, parentglobal недоступен извне.
- Туннель **IPv4-only** (как и fr). gvpn без IPv6 специально ([[lesson_clone_container_iptables]] контекст, fvpn/gvpn v6 убран 2026-07-15).
- `pct start` пишет «failed to connect to monitor socket: Connection refused» — безвредно (QEMU monitor ещё не готов), старт идёт.
---
name: reference-mysql-servers
description: "Инвентарь MySQL/MariaDB-серверов инфры: 4 прод-хоста (auth 5.5 / office 8.0 / fond 5.7 / host03 8.0) + тест-стенды; RT 4.4.x работает с 5.5/5.7 и MariaDB 10/11, но НЕ MySQL 8"
metadata:
type: reference
---
# MySQL/MariaDB серверы в инфре Етерсофт
Версии сняты **pre-auth handshake-баннером** (без credов) — Python `socket`→ HandshakeV10, версия идёт до авторизации. См. `~/tmp/claude/mysql_banner.py`.
## Прод-серверы (4 выделенных, port 3306 открыт в сети)
| Хост | IP | Версия | Назначение |
|---|---|---|---|
| **mysql.auth**.etersoft.ru | 10.20.30.202 | MySQL **5.5.43**-alt2 | shared: `eter_rt` (RT), `mail`, `eter_mnogosearch`, `eter_sales`, `phpmyadmin`. OS **ALT p8** EOL. [[reference-rt-etersoft-ru]], [[lesson-mail-mysql-credentials]] |
| **mysql.office**.etersoft.ru | 10.20.30.191 | MySQL **8.0.16**-alt1 | почти наверняка shared-БД офиса (zabbix CT132, taiga CT152, wiki CT235, collectd CT213, noc CT225). ⚠️ у имени **НЕТ A-записи** (forward не резолвится), только stale PTR. SSH-ключа нет. |
| **mysql.fond**.eterhost.ru | 10.20.30.81 | MySQL **5.7.28**-alt1 | выделенная БД «фонда» (fond). Чужой хост. |
| **mysql.host03**.eterhost.ru | 10.20.30.83 | MySQL **8.0.30**-alt1.1 | выделенная БД хостинга host03. |
| **mariadb.dmz**.etersoft.ru | 10.20.30.195 | MariaDB **11.8.8** | ✅ **NEW (CT 369, border, 2026-07-16)** — выделенный RT-хост. Full-clone шаблона 720 → etcnet убран, **systemd-networkd**. utf8mb4/utf8mb4_unicode_ci, `innodb_buffer_pool_size=4G`, `max_allowed_packet=64M`, bind **10.20.30.195:3306** (skip-networking OFF). Зарегистрирован в phpMyAdmin (mysql.eterhost.ru, CT 240; в массиве `$hosts` в `/var/www/webapps/phpMyAdmin/config.inc.php`). **Юзеры созданы** (пароли = как на mysql.auth): `root`@`10.20.30.%`+`91.232.225.23` (=`6f1XQPLsfd`, pma ходит с **10.20.30.99**), `eter_rt`@`%` (=`Veegi9sh`, боевой — RT переподключится без смены пароля при смене DatabaseHost), `phpmyadmin` controluser (=`CHwJTSr58wwBTYBS`, фикс. в config.inc.php) + 19 `pma__` таблиц. Готов к заливке дампа `eter_rt`. [[plans-rt-update]] |
Все 4 старых — на DHCP (без static ip= в PVE-конфиге). **mariadb.dmz — статический** (10.20.30.195). SSH-ключа к office/fond/host03 нет — к auth (CT 219) и mariadb.dmz (CT 369) есть.
## Тест-стенды
- **rt-test** (CT 183, gefest, 192.168.0.191) — локальная **MariaDB 11.8.8** (дамп боевой `eter_rt`), RT 4.4.7 с ней работает. [[plans/rt-update]]
- **test-mail** (CT 943, border, 10.20.30.246) — MariaDB **bound на 127.0.0.1:3306** (по сети недоступен), копия таблиц `mail`. [[plans/mail-etersoft-ru]]
## Совместимость с RT (для миграции [plans/rt-update])
RT 4.4.x работает с **MySQL 5.5 / 5.7** и **MariaDB 10 / 11**, но **НЕ с MySQL 8** (RT не использует quoted identifiers → `SQL syntax error` на `Groups`/`Principals`, баг 7693#c51-53). Поэтому:
- ✅ RT-совместимые прод-хосты: только **auth (5.5)** и **fond (5.7)**
- ❌ office (8.0) и host03 (8.0) — MySQL 8, RT не заведётся
- Решение по БД для RT: **новый выделенный MariaDB 11 на p11** — ✅ ВЫПОЛНЕНО, это **mariadb.dmz.etersoft.ru (CT 369, 10.20.30.195, MariaDB 11.8.8)**. (office/host03 отлетают по версии, auth — EOL-p8 shared с которого уходим, fond — чужой). Открытый вопрос про БД-хост в [[plans/rt-update]] закрыт.
## ⚠️ Документация
`plans/mail-etersoft-ru.md` (стр. 17) ошибочно пишет `mysql.auth.dmz.etersoft.ru (10.20.30.191)` — mysql.auth реально на **.202**, а .191 = mysql.office (MySQL 8). При ротации/миграции не перепутать.
## 🔜 Будущее: mysql.auth сам требует обновления (отдельная задача, «потом»)
`mysql.auth` (CT 219) = **ALT p8 + MySQL 5.5.43** — глубоко EOL, и это **shared-хост** (`eter_rt` + `mail` + `eter_mnogosearch` + `eter_sales`). Его собственная миграция (p8→p11, MySQL 5.5→MariaDB 10/11) — крупная и рискованная: `mail` критична и тесно связана (Cyrus/Postfix-мапы, cyradm, sec — см. [[lesson-mail-mysql-credentials]]). **Вывод для RT:** не привязывать RT к mysql.auth — иначе его БД-коннекшен переедет ещё раз при будущем апгрейде auth, плюс RT окажется завязан на чужую рискованную миграцию. Дать RT свой выделенный MariaDB-хост сейчас → RT независим.
---
name: reference_pam_limits_desktop_builder64
description: "pam-limits-desktop на builder64: nproc/nofile подняты из-за Chromium + ИИ-агентов (bug 19109)"
metadata:
node_type: memory
type: reference
---
## 2026-07-10 — подняты лимиты на builder64
Причина: Chromium крашился с `pthread_create: Resource temporarily unavailable` (bug https://bugs.etersoft.ru/show_bug.cgi?id=19109). ИИ-агенты (codex+claude+mimo) занимают ~770 потоков, Chromium с 50 вкладками — ещё ~1500-2000. Лимит4096 не хватало.
**Изменён** `/etc/security/limits.d/90-desktop.conf` (pam-limits-desktop-0.1-alt2):
```
nproc: soft 4096 → 16384, hard 5120 → 32768
nofile: soft 8192 → 65536, hard 10240 → 131072
```
**Добавлено** в `/etc/systemd/system.conf`:
```
DefaultLimitNOFILE=65536:131072
DefaultLimitNPROC=16384:32768
```
Требуется полный logout/login графической сессии (systemd user наследует лимиты от PAM при входе).
Серверы не затронуты — pam-limits-desktop не установлен на серверах (chat.eterfund.ru и др.).
---
name: reference_pantum_scanner
description: "Pantum M6700DW сетевой сканер настройка через sane-airscan (eSCL)"
metadata:
node_type: memory
type: reference
---
# Pantum M6700DW — сетевой сканер (192.168.0.134)
## Инфраструктура
- Модель: Pantum M6700DW series, IP 192.168.0.134
- eSCL: http://192.168.0.134:631/eSCL/
- Native (pantum6500): порт 9200 — НЕ работает (Invalid argument)
- Баг: https://bugs.etersoft.ru/show_bug.cgi?id=19196
## Рабочее решение: sane-airscan (eSCL)
- sane-airscan ≥0.99.36 (из Sisyphus)
- Устройство: `airscan:e0:Pantum M6700DW` (или `airscan:e0:Pantum M6700DW Series 6E14A7` при auto-discovery)
## Настройка
Для виртуальных машин (mDNS не работает) — ручная запись в `/etc/sane.d/airscan.conf`:
```
[devices]
"Pantum M6700DW" = http://192.168.0.134:631/eSCL/, eSCL
```
Для физических машин — auto-discovery работает (не нужна ручная запись).
## Конфликт с pantum-бэкендами
Pantum-бэкенды (pantum6500, pantum_bm4200 и т.д.) мешают `scanimage -L`. Решение:
```bash
for f in /etc/sane.d/dll.d/pantum*; do mv "$f" "$f.disabled"; done
```
## Матрица (2026-07-11)
| Машина | ALT | sane-airscan | scanimage -L | сканирование |
|---|---|---|---|---|
| lav (VM) | Sisyphus | 0.99.36 | ✅ (ручная запись) | ✅ |
| statos (phys) | p11 | 0.99.37 (Sisyphus) | ✅ (auto-discovery) | ✅ |
| fenix (VM) | p10 | 0.99.29 | ❌ | ❌ (нужен Sisyphus) |
## Установка на новую машину
```bash
sudo epm install sisyphus/sane-airscan
# Для VM: добавить ручную запись в /etc/sane.d/airscan.conf
# Отключить pantum-бэкенды:
for f in /etc/sane.d/dll.d/pantum*; do sudo mv "$f" "$f.disabled"; done
```
---
type: reference
description: "BIRD2 routing и аплинки на priv конфигурация, preferences, диагностика 8.8.8.8"
---
# BIRD2 и аплинки на priv (91.232.225.1)
## Аплинки
| Интерфейс | IP | Провайдер | AS | Тип | BIRD pref |
|---|---|---|---|---|---|
| ether3 | 109.235.223.53 | Petrosvyaz | AS50538 | default route | 50 |
| ether1 | 85.235.192.190 | Prometey/Severen | — | down (нет ARP) | — |
| enp8s0f0.3210 | 178.18.227.15 | DATA-IX (Peering Ltd) | AS50952 | пиринг | 150 |
| enp8s0f0.3211 | 94.124.183.151 | GlobalNet | AS31500 | транзит | 50 |
## BIRD конфигурация
- Main config: `/etc/bird/bird.conf`
- Import filters: `/etc/bird/bird.d/globalnet.conf`
- Kernel table: 5 (ip rule `from all lookup 5 pref 100` в `/etc/net/ifaces/default/ipv4rule`)
- ECMP: `merge paths yes` в kernel protocol k4/k6
### Import filters
```
import_ix_v4: preference = 150 # IX peering beats transit
import_transit_v4: preference = 50
petrosvyaz4: preference = 50
```
### AS-PATH prepend
- GlobalNet (3211): 1x prepend (`bgp_path.prepend(198324)` в `export_gbl_v4/v6`)
- DATA-IX (3210): без prepend (`export_own_v4/v6`)
- Petrosvyaz (ether3): без prepend
## Проблема с 8.8.8.8 (UDP 53)
**Симптомы:**
- `dig @8.8.8.8` (UDP 53) — timeout с любых хостов Etersoft
- `dig @8.8.8.8 +tcp` (TCP 53) — работает
- `ping 8.8.8.8` — работает
- `dig @1.1.1.1`, `dig @9.9.9.9` — работает (UDP 53)
**Маршрут BIRD:** `8.8.8.8 via 178.18.225.111 dev enp8s0f0.3210 table 5` (DIX, pref 150)
**Traceroute UDP 53:** пакеты доходят до Google (хопы 3-4: 216.239.x, 172.253.x), Google не отвечает на UDP 53.
**iptables на priv:** нет правил блокирующих UDP 53. OUTPUT/FORWARD policy ACCEPT.
**Вывод:** блокировка UDP 53 к 8.8.8.8 на уровне провайдеров/DPI. Специфична для Google DNS, не для других резолверов.
## Диагностика
```bash
# Проверить BIRD маршрут
birdc show route for 8.8.8.8 all
# Проверить import filter preferences
grep -A5 "import_ix_v4\|import_transit_v4" /etc/bird/bird.d/globalnet.conf
# Traceroute UDP 53
traceroute -n -U -p 53 -s 109.235.223.53 -m 15 -w 2 8.8.8.8
# Проверить conntrack
conntrack -L -p udp --dport 53 | grep 8.8.8.8
```
## Миграция БД после обновления пакета
При обновлении пакета roundcube миграции БД НЕ выполняются автоматически.
**Проверить текущую версию:**
```
mysql -h mysql.dmz.etersoft.ru -u eter_roundcube -p4h7dGS2Sp3ruw5Vd eter_roundcube -e "SELECT * FROM \`system\`;"
```
**Запустить миграции:**
```
cd /usr/share/roundcube && php bin/updatedb.sh --dir SQL --package roundcube
```
**Если миграция падает** (таблица/колонка уже существует — бывает от плагинов):
1. Посмотреть что делает миграция: `cat /usr/share/roundcube/SQL/mysql/<VERSION>.sql`
2. Пропустить проблемную миграцию: `UPDATE \`system\` SET value='<VERSION>' WHERE name='roundcube-version';`
3. Запустить updatedb.sh снова
**Важно:** `--dir SQL` (не `--dir SQL/mysql`!) — скрипт сам добавляет `/mysql` к пути.
### Симптом: вложения не прикладываются к письмам
Если при прикреплении файлов к письму Roundcube молча не загружает вложение — проверить наличие таблицы `uploads` в БД. Если таблицы нет — миграции не выполнялись после обновления пакета. Пример: БД на версии 2016112200 (Roundcube ~1.2), пакет — 1.7.2. После `updatedb.sh` создаётся таблица `uploads` и вложения работают. [ses_077433517ffe]
---
name: reference_route_update_sh
description: "route-update.sh на igw архитектура, слои персистентности IP, pref, inotify; баг volatile_ips (fixed 2026-07-05)"
metadata:
node_type: memory
type: reference
originSessionId: e7921933-7fc7-4871-889c-9d5efe71c046
---
`router/route-update.sh` на igw.etersoft.ru — декларативная policy-маршрутизация. Каталоги `routes.d/` (v4) и `routes6.d/` (v6), site-specific (в `.gitignore`), сам скрипт — в git.
**Архитектура**
- **Таблица = per-list**, не per-group. Каждому `.list` — своя таблица 200-250 (автовыделение в `/etc/iproute2/rt_tables`, напр. `ai`=201, `claude.ai`=223). Несколько `.list` в каталоге группы = несколько таблиц, шарящих `gateway`.
- **`ip rule` pref = порядок обработки, НЕ имя/номер таблицы.** Группы обрабатываются **по алфавиту** (`for d in routes*.d/*/`, локаль `ru_RU.UTF-8`**цифры сортируются ПОСЛЕ букв**, так что `0-fr` встанет последним, не первым!), каждой — блок в 100 с 1000, внутри группы `.list` += 10. По умолчанию `egw` (ai=1210) перебивает `fr` (claude.ai=1300).
- **Override приоритета**: `options` файл в группе со строкой `pref N``process_routes` использует N как pref_base вместо алфавитного. `option_value()` в `functions`. Применено: `routes.d/fr/options` + `routes6.d/fr/options` = `pref 900` → claude.ai (fr) перебивает ai. Грабля (fixed): переезд правила на новый pref не происходил при skip-ветке «resolved unchanged» — `_fixup_rule_pref` теперь вызывается и перед этим skip.
- gateway: IP/hostname/`default`, метрики (`metric N`) = failover, multipath если несколько строк без метрики.
- **gateway route-type keywords** (added 2026-07-05): `blackhole`/`unreachable`/`prohibit`/`throw` — скрипт ставит маршруты этого типа (без `via`), `ip route replace <kw> <dst> table N`. `unreachable`/`prohibit` = ICMP назад → мгновенный отказ (curl падает за ~2мс). Применено на `routes6.d/fr` → claude.ai v6 reject (50 unreachable-маршрутов, вкл. covering-подсети). Keyword первым в `gateway` → вся группаrejected. **Почему v6=unreachable**: fr-узел `ikev2.fr` (.140, v4-only gateway группы fr) **не имеет IPv6** — v6-пути во Францию нет, поэтому reject fast вместо попытки шлюза.
**Слои персистентности IP** (для DNS round-robin tolerance)
1. `resolved` — текущий набор IP списка.
2. `resolve_history/{1..20}` — union из `HISTORY_SIZE=20` snapshot'ов, мерджится в `resolved` каждый запуск. Самоочищается за N запусков **только если IP перестаёт поступать**.
3. `volatile_ips/<домен>` (только IPv6) — для volatile-доменов (TTL≤120 / diff-resolvers); `expand_volatile_subnets` собирает IP с нескольких резолверов и добавляет covering-подсети. **Имена файлов = домены.**
**Баг (fixed 2026-07-05):** `expand_volatile_subnets` читал весь `volatile_ips/` как список доменов к ре-резолву, **не удаляя осиротевшие** → удалённый из `.list` домен пожизненно перевпрыскивал свои IP в таблицу. Фикс: prune `volatile_ips/<домен>` если домена нет в текущем `.list` (передан `$_f`). Побочно вычистило кучи стаи в web-bypass (~40 доменов), blocked и др.
**Грабли при очистке state:** после удаления IP из `resolved`+history перезагрузка может пройти мимо stale-removal — если `resolved` совпал сам с собой, load идёт по короткому пути «без изменений» и kernel stale-маршруты не трогает. Добивать вручную: `while ip -6 route del <dst> table <T>; do :; done`.
**Триггеры на igw:** inotify-наблюдатель (PID ~962337) — `route-update.sh` при изменении `/root/egw-route/`, `/root/antifilter/`, `/root/antifilter.network/`; + `route-update.timer` раз в 30 мин. Запуск: `./route-update.sh [--resolve|--force|-v]`, `--flush GROUP`, `--add|--del IP|DOMAIN GROUP`.
См. [[reference_igw_route_api]] (HTTP API поверх тех же списков), [[feedback_route_list_symlink_only]].
---
name: reference_rt_package_requires
description: "Пакет rt (ALT): состояние Requires runtime-условных Perl-модулей в spec 6.0.3-alt1. DateTime::Set, DateTime::Event::Recurrence, CSS::Inliner добавлены как жёсткие Requires. GraphViz2 ПОКА опционален (%filter_from_requires стр.8-9) но фильтр устарел (perl-GraphViz2 уже в Сизифе via #426095) и RT требует его жёстко (RT/Graph/Tickets.pm:61). Решение о Requires: perl(GraphViz2.pm) pending."
metadata:
type: reference
---
# Пакет `rt` (ALT): Requires runtime-условных модулей — состояние spec
RT 6.0 подключает часть Perl-модулей **runtime-условно** (`require`/`use` только в
кодовом пути фичи) → `make testdeps` и авто-detect `perl.req` их видят не всегда.
Spec: `/srv/lav/Projects/git-alt/00-perl/rt/rt.spec` (gear-чекаут на builder64).
Детали/симптомы: [[lesson_rt6_runtime_deps_missed]], план: [[plans/rt-6.0]].
## Что уже в spec 6.0.3-alt1 (girar #426033, test-only, собирается 2026-07-22)
Жёсткие `Requires:` добавлены (совпадает с нашими находками на rt-test):
```spec
Requires: perl(DateTime/Set.pm)
Requires: perl(DateTime/Event/Recurrence.pm)
Requires: perl(CSS/Inliner.pm) >= 4027
```
Модули в Сизифе: DateTime/Set + Event/Recurrence — давно; CSS/Inliner + GraphViz2 —
опубликованы girar **#426095** (Kanban git-alt #297). ✅ Деплой `epm install rt`
подтянет эти три автоматически.
## ⚠️ GraphViz2 — опционален в spec, но RT требует его жёстко (open decision)
Source RT 6.0.3 (локально `rt/lib/`):
```
rt/lib/RT/Graph/Tickets.pm:61 require GraphViz2; # ГОЛЫЙ require, без eval → без модуля падает рендер графа
rt/lib/RT/Graph/Tickets.pm:62 GraphViz2->import;
rt/lib/RT/Graph/Tickets.pm:316 $args{'Graph'} = GraphViz2->new(...
rt/lib/RT/Config.pm:874 return if RT::StaticUtil::RequireModule("GraphViz2"); # мягкая проверка (eval)
```
→ для RT в целом модуль опционален, но **фича графов связей тикетов без него ломается**
(ровно как видели на rt-test).
Spec **оставил GraphViz2 опциональным** через фильтр:
```spec
7: # GraphViz/GraphViz2 is an optional dependency (ticket graphs), not a hard requirement
8: %filter_from_requires /^perl(GraphViz.pm)/d # v1 — оставить (нужна только testsuite, см. стр.441-442)
9: %filter_from_requires /^perl(GraphViz2)/d # ← УСТАРЕЛ
```
Changelog (стр.784-785): фильтр добавлен т.к. *«4.4.7 switched graph rendering to
GraphViz2, **not packaged in Sisyphus**»*. Это обоснование **исчезло** — perl-GraphViz2
теперь в Сизифе (#426095). Без правки в #426033 GraphViz2 останется необязательным →
на чистой `epm install rt` графы тикетов не рендерятся.
### Правка (pending решение мейнтейнера)
- убрать **строку 9** (`%filter_from_requires /^perl(GraphViz2)/d`);
- строку **8** (v1) оставить — v1 нужна только testsuite (стр.441 «testsuite unconditionally
depends upon perl(GraphViz)»), runtime-Requires у неё быть не должно;
- обновить комментарий стр. 7;
- добавить `Requires: perl(GraphViz2.pm)`.
- **graphviz/dot доб. НЕ надо**: `perl-GraphViz2` сам `Depends: graphviz` (проверено:
`apt-cache depends perl-GraphViz2` → graphviz).
## Что НЕ трогать (уже в rpm --requires rt)
`perl(DateTime.pm)`, `perl(DateTime/TimeZone.pm)`,
`perl(DateTime/Format/Natural.pm) >= 0.670`, `perl(DateTime/Locale.pm) >= 0.40`,
`perl(Calendar/Simple.pm)`, `perl(Data/ICal.pm)`, `perl(Data/ICal/Entry/Event.pm)`,
`perl(CSS/Squish.pm)`, `perl(CSS/Minifier/XS.pm)`, `perl(HTML/Gumbo.pm)`.
BuildRequires `perl(GraphViz.pm)` (v1, для testsuite) — отдельно от runtime.
Связанные: [[lesson_rt6_runtime_deps_missed]], [[plans/rt-6.0]],
[[reference_rt_etersoft_ru]], [[lesson_rt6_secure_cookies_http]].
---
name: reference_zclaude_glm_config
description: "Как устроен Claude Code + z.ai GLM на машине lav wrapper zclaude, env-z.conf, tiered routing моделей"
metadata:
node_type: memory
type: reference
originSessionId: 4c8c587c-964b-4433-9a95-0a7682fce282
---
Конфиг Claude Code под z.ai GLM на машине lav:
- **`/usr/local/bin/zclaude`** — shell-wrapper (362 б): source'ит `/etc/opt/claude.ai/env-z.conf` и `~/.claude/env-z.conf` (через `set -a` allexport), затем `exec /opt/claude.ai/claude "$@"`. Штатный `/usr/bin/claude` — отдельный wrapper, source'ит `env.conf` (без z), для др. провайдера.
- **`/etc/opt/claude.ai/env-z.conf`** (root:eterworkers, 640) — тут живут `ANTHROPIC_AUTH_TOKEN`, `ANTHROPIC_BASE_URL=https://api.z.ai/api/anthropic`, `ANTHROPIC_DEFAULT_{HAIKU,SONNET,OPUS}_MODEL`, `CLAUDE_CODE_AUTO_COMPACT_WINDOW`, `API_TIMEOUT_MS`. Лежат 2 токена z.ai (один закомментирован). Пользовательского `~/.claude/env-z.conf` нет — всё из системного.
- Список моделей z.ai: GET `https://api.z.ai/api/anthropic/v1/models` (Bearer или x-api-key). 8 шт: glm-4.5/4.5-air/4.6/4.7/5/5-turbo/5.1/5.2. `[1m]` суффикс = 1M context window.
- Цены/доки: https://docs.z.ai/guides/overview/pricing ; https://docs.z.ai/devpack/faq (5h rolling-квота: Lite ~80 prompts/5h, Pro ~400, Max ~1600).
**Почему квота GLM тает «во много раз быстрее» Anthropic Opus** (подтверждено r/ZaiGLM + z.ai devpack):
1. В Coding Plan **cached tokens считаются как full usage** (у Anthropic cache hits не считаются против rate limit).
2. **glm-5.x имеет множитель 2–3×** (3× пик, 2× внепик) против glm-4.7.
**Tiered routing с 2026-07-06** (бэкап: `env-z.conf.bak.2026-07-06`): HAIKU=`glm-4.7`, SONNET=`glm-4.7`, OPUS=`glm-5.2` (без `[1m]`), `AUTO_COMPACT_WINDOW=200000`. Было: SONNET=OPUS=`glm-5.2[1m]`, compact=1M → квота горела. Менять только через sudo (tee сохраняет права); правки вступают только при новом запуске `zclaude`.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment