Commit 0d5c64d9 authored by Vitaly Lipatov's avatar Vitaly Lipatov

memory: route-health fix + vici-socket lesson, igw changelog

Mark lesson_route_health_flush_hang resolved (bulk flush + 3m window shipped, deployed, timer re-enabled). Add lesson_vici_socket_acl_for_telegraf: the ikev2 churn root cause (check-vpn-status.sh as telegraf can't read the vici socket -> false vpn_status=0), why the sudoers approach is blocked on ALT (sudo is 4710 root:wheel), and the vici-socket ACL fix. Add objects/igw.md changelog. Co-Authored-By: 's avatarClaude <noreply@anthropic.com>
parent 8144abe5
......@@ -6,7 +6,8 @@
- **Docs** (`.claude/docs/`): dhash.ru, nfs, epm, host03, vaultwarden-bridge — справка
- **CLAUDE.md**: таблица skills + общие правила
- **Memory** (тут): feedback / планы / задачи / уроки
- **Changelog объектов** (`memory/objects/<host>.md`) — по дате; см. [feedback_changelog_notes.md](feedback_changelog_notes.md). Есть: vpn.eterfund, vpn.office, enceladus, border, [host03.eterhost.ru](objects/host03.eterhost.ru.md)
- **Changelog объектов** (`memory/objects/<host>.md`) — по дате; см. [feedback_changelog_notes.md](feedback_changelog_notes.md). Есть: vpn.eterfund, vpn.office, enceladus, border, [host03.eterhost.ru](objects/host03.eterhost.ru.md), [gre.hetzner2.egw](objects/gre.hetzner2.egw.md), [igw](objects/igw.md)
- **mimocode** (другой агент на lav): вся история сессий в SQLite `~/.local/share/mimocode/mimicode.db`[reference_mimicode_history.md](reference_mimicode_history.md) (как Querять; грабли NFS/WAL/FTS; искать по контенту, не по title)
## SSH доступы
......@@ -24,6 +25,7 @@
| vpn.office | `ssh vpn.office` (lav, не root) |
| kuma.office | `ssh root@kuma.office.etersoft.ru` |
| border (PVE) | `ssh root@border` |
| **eterhost** (CT 102, общий TLS-фронт) | `ssh -p32 root@91.232.225.23` (**:32**=фронт; :22→gitlab-бэкенд) — [reference_eterhost_front.md](reference_eterhost_front.md) |
| beget.ogw (217.12.37.55) | `ssh root@beget.ogw.eterhost.ru` |
| telemt/e5 (91.232.225.105) | `ssh root@91.232.225.105` — осн. chat.eterfund.ru — [reference_telemt_fleet_ja4_monitoring.md](reference_telemt_fleet_ja4_monitoring.md) |
| telemt.eterfund.ru (91.232.225.3) | `ssh root@91.232.225.3` |
......@@ -33,7 +35,6 @@
| iot.etersoft.ru (91.232.225.104) | `ssh root@iot.etersoft.ru` (fish) / `pv@` (bash) — [reference_create_lxc_container_pve.md](reference_create_lxc_container_pve.md) |
| time.office | `ssh time` (порт 6122, lav+sudo) — [reference_time_office_sessions.md](reference_time_office_sessions.md) |
| matrix (91.232.225.42) | `ssh -p32 root@matrix.etersoft.ru` (нужен ssh-agent) |
| tele.eterfund.ru | ВЫКЛЮЧЕН 2026-06-14 |
| rpi (78.193.2.190, Франция) | `ssh -p10338 root@anyssh.eterhost.ru` (reverse-SSH); fallback: с .140 `ssh root@172.17.0.1` через IPsec→Docker bridge — [reference_ikev2_fr_tunnel.md](reference_ikev2_fr_tunnel.md) |
| parentglobal (94.69.12.186 dyn, Греция/Cosmote) | `ssh -p10337 etersoft@anyssh.ru` (reverse-SSH, потом sudo); через IPsec: `ssh -J root@91.232.225.139 root@10.10.10.6`[reference_ikev2_gr_tunnel.md](reference_ikev2_gr_tunnel.md) |
| rca-gw (10.20.30.250) | `ssh root@10.20.30.250` (fish→heredoc) — [project_rarus_1c_vpn_gateway.md](project_rarus_1c_vpn_gateway.md) |
......@@ -41,6 +42,7 @@
| sec.office (CT 251, 10.20.30.61) | `ssh root@10.20.30.61`[project_mail_password_hash_migration.md](project_mail_password_hash_migration.md) |
| mysql.auth (CT 219, 10.20.30.202) | `ssh root@mysql.auth.etersoft.ru`[lesson_mail_mysql_credentials.md](lesson_mail_mysql_credentials.md) |
| rt.etersoft.ru | **ПРОД CT 412 (10.20.30.196)** с 2026-07-16: `ssh root@10.20.30.196`[reference_rt_etersoft_ru.md](reference_rt_etersoft_ru.md); MariaDB на mariadb.dmz (CT 369, 10.20.30.195). Старый CT 233 (10.20.30.53) снят с прода |
| flathub-proxy (CT 341, 10.20.30.247) | DMZ — только через border: `ssh root@border 'ssh root@10.20.30.247 "..."'`; оболочка **fish** (скрипты через base64→`bash -s`) — [reference_flathub_eterfund_ru.md](reference_flathub_eterfund_ru.md) |
| dc.etersoft.ru | `ssh -p32 dc.etersoft.ru` (lav+sudo), samba-tool через sudo |
| **lav** (192.168.0.55) | `ssh lav` — десктоп (доменный юзер lav uid 502, sss; в wheel→sudo). ⚠️ Claude-сессия обычно крутится на **builder64.office.etersoft.ru** (отдельный хост, тоже sss-auth), НЕ на lav — не путать хост/юзер. См. [lesson_pam_system_check_localuser_uid500.md](lesson_pam_system_check_localuser_uid500.md) |
......@@ -55,8 +57,13 @@
- [reference_igw_route_api.md](reference_igw_route_api.md) — Route API на igw :80 (bypass/direct/geo, `/api/check`, экспорт)
- [reference_route_update_sh.md](reference_route_update_sh.md) — route-update.sh: per-list таблицы, pref по алфавиту, слои персистентности
- [reference_mysql_servers.md](reference_mysql_servers.md) — инвентарь MySQL/MariaDB: auth 5.5(.202) / office 8.0(.191) / fond 5.7(.81) / host03 8.0(.83); RT НЕ с MySQL 8 (баг 7693)
- [reference_eterhost_front.md](reference_eterhost_front.md)**общий TLS-фронт** CT 102 `eterhost` на border: `ssh -p32 root@91.232.225.23` (порт 32! :22 → DNAT на gitlab-бэкенд), nginx 1.28.1 :443, certbot webroot (`/var/spool/nginx/tmp/client`), паттерн backend-CT :80 → proxy; терминирует HTTPS для gitlab/wiki/rt/sales/taiga/grafana и др.
- [reference_gitlab_eterfund.md](reference_gitlab_eterfund.md) — gitlab.eterfund.ru: source-install v11.0.0-rc12, **бэкенд** на отдельном CT 10.20.30.2 (`lav@91.232.225.23` порт 22 = DNAT, +sudo), TLS — на фронте [[reference_eterhost_front]]; БД `eter_gitlab` на mysql.dmz (.191, НЕ mariadb.dmz); фикс ошибки Rebase MR (`git worktree prune`)
- [reference_flathub_eterfund_ru.md](reference_flathub_eterfund_ru.md) — flathub.eterfund.ru: зеркало/кэш-прокси Flathub (flathub-proxy от ALT GNOME, переподпись своим GPG) в CT 341 (10.20.30.247) на border; фронт eterhost, LE до 2026-10-28; nginx-cache к dl.flathub.org + OSTree appstream + ed25519-ключ; грабли (access_log /dev/stdout, CACHE_NAME, fish-оболочка)
- [reference_ikev2_fr_tunnel.md](reference_ikev2_fr_tunnel.md) — вся система обхода claude.ai/Anthropic через Францию: route-update группа fr (pref 900, v6 unreachable) + IPsec .140↔rpi (78.193.2.190, доступ `ssh -p10338 root@anyssh.eterhost.ru`, контейнер ikev2-fr в /opt/ikev2-fr-docker); «egress=.140»=SA down; фикс `docker exec ikev2-fr swanctl --initiate --child s2s`; self-healing через autoheal
- [reference_ikev2_gr_tunnel.md](reference_ikev2_gr_tunnel.md) — Greek-эгресс gvpn: gr.egw=CT706 (.139, responder на border) ↔ parentglobal (Греция, 94.69.12.186, initiator, reverse-SSH anyssh:10337); gvpn default→.139→ipsec0(10.10.10.5/.6)→Греция; «gvpn offline»=CT706 stopped; фикс `pct start 706` + `swanctl --initiate --child s2s` с parentglobal. Параллель fr; отдельный `divserver` SA на parentglobal пока down
- [reference_pve_gefest.md](reference_pve_gefest.md) — Proxmox VE gefest: USB mapping (Guardant/HASP/Rutoken, path-based), роли PVEMappingUser, ACL для Testirovanie/HeadTester
- [reference_egress_tunnels.md](reference_egress_tunnels.md) — карта зарубежных egress-шлюзов (antifilter): azbyka.ru → igw(table antifilter-*) → next-hop **91.232.225.120** (контейнер `ikev2`, strongswan, ipsec0=10.10.20.2) ↔ hetzner.egw 135.181.95.108 (ipsec0=10.10.20.1), подсеть 10.10.20.0/30; health.json=/api/health на igw; 2026-07-31 SA к Hetzner самовосстановился
## Правила работы
......@@ -86,6 +93,7 @@
- [feedback_rewrite_preserve_full_config.md](feedback_rewrite_preserve_full_config.md) — переписывая конфиг, сохраняй ПОЛНОЕ содержимое (включая Database*/пароли); маскируй только для дисплея, не для записи; cp bak → surgical sed, не heredoc из отфильтрованного вида
- [feedback_password_request_only.md](feedback_password_request_only.md) — пароли ТОЛЬКО через lavtomate password_request
- [feedback_shared_passwords_rooter_store.md](feedback_shared_passwords_rooter_store.md) — shared-пароль → rooter store
- [feedback_no_touch_real_bugzilla_timer.md](feedback_no_touch_real_bugzilla_timer.md) — НЕ авто-паузить реальный Bugzilla-таймер (учёт времени TIME@Etersoft); оговорку #12105 c#63 оставили осознанно, наработка в ветке wip/idle-autopause
- [reference_rooter_password_store.md](reference_rooter_password_store.md) — admin pass store: `ssh rooter@server pass show <name>`
- [reference_remote_ssh_access.md](reference_remote_ssh_access.md) — reverse-SSH через anyssh.ru
- [lesson_anyssh_ru_in_91232225.md](lesson_anyssh_ru_in_91232225.md) — anyssh.ru=.8, не маршр. всю /24
......@@ -107,6 +115,7 @@
- [project_vpn_migrate_enceladus_aesni.md](project_vpn_migrate_enceladus_aesni.md) — ✅ 2026-06-26
- [project_rarus_1c_vpn_gateway.md](project_rarus_1c_vpn_gateway.md) — PPTP-шлюз к 1С-Рарус, ждём URL OData
- [project_pve_kerberos_spnego_gefest.md](project_pve_kerberos_spnego_gefest.md) — PVE на gefest: настоящий Kerberos SSO (SPNEGO); пользователь настраивает сам, мне — проверить после
- [plans/bugzilla-5.9-deps.md](plans/bugzilla-5.9-deps.md) — зависимости Bugzilla 5.9.1 на тест-стенде CT 944 (.251); процесс апгрейда вёл mimicode — см. [reference_mimicode_history.md](reference_mimicode_history.md)
## Десктоп lav
......@@ -114,64 +123,20 @@
- [reference_zclaude_glm_config.md](reference_zclaude_glm_config.md) — Claude Code+z.ai GLM: wrapper `zclaude``env-z.conf`, tiered routing glm-4.7/glm-5.2 (с 2026-07-06), почему квота тает быстрее Anthropic
- [reference_pam_limits_desktop_builder64.md](reference_pam_limits_desktop_builder64.md) — pam-limits-desktop: nproc/nofile подняты (bug 19109)
## Уроки
- [lesson_clone_container_iptables.md](lesson_clone_container_iptables.md) — клонирование LXC: SNAT-правила на хосте не копируются, L3 не работает пока не добавишь
- [lesson_lxc_etcnet_to_systemd_networkd.md](lesson_lxc_etcnet_to_systemd_networkd.md) — новый LXC из etcnet-шаблона 720: PVE пишет networkd-конфиг, ставим systemd-networkd; `disable network` НЕ enough (оживает на boot) → надо `mask`
- [reference_pantum_scanner.md](reference_pantum_scanner.md) — Pantum M6700DW: sane-airscan (eSCL), native-драйвер не работает, VM нужна ручная запись в airscan.conf
- [reference_telemt_fleet_ja4_monitoring.md](reference_telemt_fleet_ja4_monitoring.md) — telemt-флот chat.eterfund.ru (e5 ALT Sisyphus, d/s/b.chat Ubuntu); JA4/beobachten, мониторинг в InfluxDB gateways
- [lesson_eterban_redis_persistence.md](lesson_eterban_redis_persistence.md) — eterban priv: Redis, redis-py ≥3.5.0; php7-fpm обслуживает веб-UI — НЕ удалять
- [lesson_eterban_priv_two_wan_slots.md](lesson_eterban_priv_two_wan_slots.md) — eterban priv: ровно 2 WAN (i_interface/i_interface2), правила dynamic НЕ в /etc/sysconfig/iptables (ipset-риск); 3-й WAN — только live + sidecar
- [lesson_sip_etersoft_freeswitch.md](lesson_sip_etersoft_freeswitch.md) — sip FreeSWITCH: плоский диалплан, логи xz
- [lesson_etcnet_hooks.md](lesson_etcnet_hooks.md) — etcnet хуки в `/etc/net/ifaces/<iface>/`
- [lesson_divserver_telemt_mtproxy.md](lesson_divserver_telemt_mtproxy.md) — divserver telemt MTProxy через gre1
- [lesson_dhcp_8net_dynamic_range.md](lesson_dhcp_8net_dynamic_range.md) — dhcp.office динамические пулы
- [lesson_cyrus_sasl_restart.md](lesson_cyrus_sasl_restart.md) — cyrus-imapd: `systemctl restart` (не serv), SASL кэш, `Hoffice` не трогать
- [lesson_warp_oom_nft_deadlock.md](lesson_warp_oom_nft_deadlock.md) — warp.egw stale nft после OOM
- [lesson_builder_tmp_cleanup.md](lesson_builder_tmp_cleanup.md) — builder /tmp чистит systemd-tmpfiles
- [lesson_builder_robot_gear_bad_owner_group.md](lesson_builder_robot_gear_bad_owner_group.md) — builder-robot безымянная группа 5021 → TMPDIR setgid
- [lesson_roundcube_password_plugin_config.md](lesson_roundcube_password_plugin_config.md) — Roundcube password `%c``%P`
- [lesson_mail_postfix_sasl_config_path.md](lesson_mail_postfix_sasl_config_path.md) — Postfix читает `/etc/postfix/sasl/smtpd.conf`
- [lesson_mail_cert_renewal_webroot_hook.md](lesson_mail_cert_renewal_webroot_hook.md) — mail LE: cron.weekly webroot, deploy-hook
- [lesson_mail_mysql_credentials.md](lesson_mail_mysql_credentials.md) — mail DB mailro/mail@%; ротация → restart postfix
- [lesson_rt_condition_perl538.md](lesson_rt_condition_perl538.md) — RT 4.4.x на p11/Perl 5.38: `RT/Condition.pm:201` без `;` = fatal, падают все scrips (на p9/Perl 5.28 молча работало); фикс — одна точка
- [lesson_sieve_domain_split.md](lesson_sieve_domain_split.md) — sieve расщепление при symlink доменов
- [lesson_lavtomate_master_active_empty.md](lesson_lavtomate_master_active_empty.md) — Lavtomate пустой master active.script
- [lesson_chat_eterfund_telemt_oom.md](lesson_chat_eterfund_telemt_oom.md) — chat.eterfund.ru round-robin; gyle ARP-конфликт .43→.86
- [lesson_bind_dynamic_zone_freeze_thaw.md](lesson_bind_dynamic_zone_freeze_thaw.md) — DDNS: freeze→edit→reload→thaw
- [lesson_nf_conntrack_table_full.md](lesson_nf_conntrack_table_full.md) — NAT drops: `nf_conntrack_max=524288`
- [lesson_telemt_middle_proxy_egress_match.md](lesson_telemt_middle_proxy_egress_match.md) — telemt ME pool: src_ip должен совпадать с registered
- [lesson_igw_telegram_ipv6_broken.md](lesson_igw_telegram_ipv6_broken.md) — igw TG обход: IPv4 ок, IPv6 битый; socks5 не socks5h
- [reference_create_lxc_container_pve.md](reference_create_lxc_container_pve.md) — клон template-CT 720, СНАЧАЛА IP потом старт
- [lesson_pptp_rarus_chap_secrets_domain.md](lesson_pptp_rarus_chap_secrets_domain.md) — PPTP NT-домен: name без `DOMAIN\user`
- [lesson_pptp_nat_nf_conntrack_helper.md](lesson_pptp_nat_nf_conntrack_helper.md) — PPTP/FTP NAT: CT helper rule
- [lesson_evpn_ikev2_strongswan_cert.md](lesson_evpn_ikev2_strongswan_cert.md) — evpn IKEv2: `/etc/strongswan/swanctl`
- [reference_ruskru_telegram_notifier.md](reference_ruskru_telegram_notifier.md) — бот @ruskru на sites43
- [lesson_office_home_nfs_mount_fail.md](lesson_office_home_nfs_mount_fail.md) — office /home NFSv4 с aspetos, home.mount при загрузке
- [lesson_proxy_monitoring_functional_check.md](lesson_proxy_monitoring_functional_check.md) — мониторинг SOCKS5: curl через SOCKS, не порт :1080
- [lesson_ikev2_beget_cert_dns_fix.md](lesson_ikev2_beget_cert_dns_fix.md) — ikev2.beget: протух LE-серт, DNS курица-яйцо
- [lesson_traceroute_first.md](lesson_traceroute_first.md) — диагностика сети: сначала traceroute/mtr, не гадать по IP
- [lesson_matrix_etersoft_synapse_disk_telegram_bridge.md](lesson_matrix_etersoft_synapse_disk_telegram_bridge.md) — matrix Synapse media_store пухнет от TG-моста
- [lesson_rooter_home_pbs_restore.md](lesson_rooter_home_pbs_restore.md) — rooter home на NFS; restore через PBS
- [lesson_grafana_influxql_total_line.md](lesson_grafana_influxql_total_line.md) — Σ total на Grafana InfluxQL: серверный подзапрос sum(last()) (НЕ calculateField); byRegexp substring; Playwright MCP крошечный viewport → панели вне экрана не рендерятся
- [lesson_rt_mail_pickup_test.md](lesson_rt_mail_pickup_test.md) — тест забора RT: слать на name@etersoft.ru (Roundcube-Sieve "Not me" на @office.etersoft.ru кладёт прочее в подпапку); requestor проверять в БД (API MemberEmailAddresses врёт пустым); postfix-логи RT в journald, исходящие от noreply@etersoft.ru
- [lesson_rt_stale_stats_analyze.md](lesson_rt_stale_stats_analyze.md) — RT виснет на истории тикета (htmx /Helpers/TicketHistoryPage) после bulk-import дампа: устаревшая InnoDB-статистика → BNL full-scan Attachments (194k строк × Content-блобы); EXPLAIN rows=194225 type=ALL → после ANALYZE rows=2; fix `mariadb-check --analyze eter_rt` (helper 15с+ → 0.024с). Тот же root cause что прод #70334; подтверждено для RT 6.0
- [lesson_rt6_secure_cookies_http.md](lesson_rt6_secure_cookies_http.md) — RT 6.0 дефолтит WebSecureCookies=1 (4.4 — нет): на HTTP-only контуре (rt-test) браузер роняет secure-cookie → логин не прилипает (верный пароль принят, след. запрос = откат на логин; неверный — честная ошибка); фикс Set($WebSecureCookies,0). Прод за HTTPS — дефолт ок. + rt-fcgi socket-activated: поднимать сокеты, не сервисы напрямую
- [lesson_rt6_runtime_deps_missed.md](lesson_rt6_runtime_deps_missed.md) — RT 6.0: make testdeps и Requires пакета rt пропускают runtime-условные Perl-модули. Всплыли 3: CSS::Inliner (HTML+CSS), GraphViz2 (графы), DateTime::Set (calendar display-mode). Первые 2 собраны girar 426095; DateTime::Set уже в Сизифе (epm install). ⚠️ rt не Requires perl(DateTime/Set.pm) — пакетный баг
- [reference_rt_package_requires.md](reference_rt_package_requires.md) — spec rt 6.0.3-alt1 (#426033): DateTime/Set + Event/Recurrence + CSS/Inliner уже жёсткие Requires ✅; GraphViz2 пока опционален (%filter_from_requires стр.8-9, устарел т.к. #426095 опубликован в Сизиф) — RT требует его жёстко (RT/Graph/Tickets.pm:61), pending решение мейнтейнера. graphviz/dot доб. не надо (perl-GraphViz2 сам Depends: graphviz)
- [lesson_pam_system_check_localuser_uid500.md](lesson_pam_system_check_localuser_uid500.md) — ALT поднял порог system-check-localuser до uid>=1000 (даже legacy) → SSSD-доменные юзеры 500-999 отваливаются. Фикс dc-client/install-localuser-etersoft.sh + control etersoft. lav(192.168.0.55)/builder64/white=etersoft (2026-07-21). Внимание: хост `lav` (192.168.0.55) ≠ `builder64` (где идёт Claude-сессия) ≠ юзер `lav` (uid 502, sss)
- [lesson_restart_container_verify_autostart.md](lesson_restart_container_verify_autostart.md) — после настройки новой системы (cutover/миграция): перезапусти КОНТЕЙНЕР и перепроверь весь автозапуск (cron /etc/cron.d, timers, сервисы). В LXC crond (vixie-cron) не всегда перечитывает /etc/cron.d по inotify → RT fetchmail простой 9.5ч (2026-07-23). `/etc/cron.d` режим 0700 — пакетный, не «чинить»
## Уроки (сгруппированы; детали — в файлах)
- **LXC/PVE**: [lesson_clone_container_iptables](lesson_clone_container_iptables.md) (SNAT не копируется), [lesson_lxc_etcnet_to_systemd_networkd](lesson_lxc_etcnet_to_systemd_networkd.md) (mask network), [reference_create_lxc_container_pve](reference_create_lxc_container_pve.md) (CT 720: IP потом старт), [lesson_restart_container_verify_autostart](lesson_restart_container_verify_autostart.md) (перезапуск+автозапуск cron/timers), [lesson_pam_system_check_localuser_uid500](lesson_pam_system_check_localuser_uid500.md) (uid≥1000 порог; lav≠builder64≠юзер lav)
- **eterban priv**: [lesson_eterban_redis_persistence](lesson_eterban_redis_persistence.md), [lesson_eterban_priv_two_wan_slots](lesson_eterban_priv_two_wan_slots.md), [lesson_eterban_firehol_bogon](lesson_eterban_firehol_bogon.md) (firehol_level1 блочит private IP, whitelist.txt пуст → бан DMZ-хостов), [lesson_alt_fail2ban_systemd_profile](lesson_alt_fail2ban_systemd_profile.md) (ALT fail2ban не стартует: paths-overrides.local + python3-module-systemd; прим. на priv), [reference_eterban_priv_admin](reference_eterban_priv_admin.md) (ПРОД-админка, +секция fail2ban)
- **mail**: [lesson_cyrus_sasl_restart](lesson_cyrus_sasl_restart.md), [lesson_mail_postfix_sasl_config_path](lesson_mail_postfix_sasl_config_path.md), [lesson_mail_cert_renewal_webroot_hook](lesson_mail_cert_renewal_webroot_hook.md), [lesson_mail_mysql_credentials](lesson_mail_mysql_credentials.md), [lesson_sieve_domain_split](lesson_sieve_domain_split.md), [lesson_roundcube_password_plugin_config](lesson_roundcube_password_plugin_config.md)
- **RT**: [lesson_rt_condition_perl538](lesson_rt_condition_perl538.md), [lesson_rt_stale_stats_analyze](lesson_rt_stale_stats_analyze.md), [lesson_rt6_secure_cookies_http](lesson_rt6_secure_cookies_http.md), [lesson_rt6_runtime_deps_missed](lesson_rt6_runtime_deps_missed.md), [reference_rt_package_requires](reference_rt_package_requires.md), [lesson_rt_mail_pickup_test](lesson_rt_mail_pickup_test.md)
- **telemt/chat**: [reference_telemt_fleet_ja4_monitoring](reference_telemt_fleet_ja4_monitoring.md), [lesson_divserver_telemt_mtproxy](lesson_divserver_telemt_mtproxy.md), [lesson_chat_eterfund_telemt_oom](lesson_chat_eterfund_telemt_oom.md), [lesson_telemt_middle_proxy_egress_match](lesson_telemt_middle_proxy_egress_match.md)
- **VPN/IPsec**: [lesson_evpn_ikev2_strongswan_cert](lesson_evpn_ikev2_strongswan_cert.md), [lesson_ikev2_beget_cert_dns_fix](lesson_ikev2_beget_cert_dns_fix.md), [lesson_pptp_rarus_chap_secrets_domain](lesson_pptp_rarus_chap_secrets_domain.md), [lesson_pptp_nat_nf_conntrack_helper](lesson_pptp_nat_nf_conntrack_helper.md)
- **сеть/DNS**: [lesson_bind_dynamic_zone_freeze_thaw](lesson_bind_dynamic_zone_freeze_thaw.md), [lesson_nf_conntrack_table_full](lesson_nf_conntrack_table_full.md), [lesson_igw_telegram_ipv6_broken](lesson_igw_telegram_ipv6_broken.md), [lesson_traceroute_first](lesson_traceroute_first.md), [lesson_route_health_flush_hang](lesson_route_health_flush_hang.md) ( ИСПРАВЛЕНО 01.08: bulk flush + окно 3m), [lesson_vici_socket_acl_for_telegraf](lesson_vici_socket_acl_for_telegraf.md) (check-vpn-status под telegraf не читает vici → vpn_status=0 → ikev2 churn; фикс ACL на vici-сокет, sudo 4710 блокирует sudoers)
- **builder**: [lesson_builder_tmp_cleanup](lesson_builder_tmp_cleanup.md), [lesson_builder_robot_gear_bad_owner_group](lesson_builder_robot_gear_bad_owner_group.md), [lesson_office_home_nfs_mount_fail](lesson_office_home_nfs_mount_fail.md)
- **прочее**: [lesson_sip_etersoft_freeswitch](lesson_sip_etersoft_freeswitch.md), [lesson_etcnet_hooks](lesson_etcnet_hooks.md), [lesson_dhcp_8net_dynamic_range](lesson_dhcp_8net_dynamic_range.md), [lesson_warp_oom_nft_deadlock](lesson_warp_oom_nft_deadlock.md), [lesson_lavtomate_master_active_empty](lesson_lavtomate_master_active_empty.md), [reference_pantum_scanner](reference_pantum_scanner.md), [reference_ruskru_telegram_notifier](reference_ruskru_telegram_notifier.md), [lesson_proxy_monitoring_functional_check](lesson_proxy_monitoring_functional_check.md), [lesson_matrix_etersoft_synapse_disk_telegram_bridge](lesson_matrix_etersoft_synapse_disk_telegram_bridge.md), [lesson_rooter_home_pbs_restore](lesson_rooter_home_pbs_restore.md), [lesson_grafana_influxql_total_line](lesson_grafana_influxql_total_line.md)
### Короткие уроки (без отдельного файла)
- heredoc через SSH: `ssh host "cat > file" << 'EOF'` (кавычки вокруг маркера!)
- НЕ `iptables-restore` на работающей системе — сносит правила podman/docker
- Клонирование LXC в PVE: СНАЧАЛА поменять IP, ПОТОМ запускать
- `control ИМЯФАЙЛА РЕЖИМ` вместо chmod для suid/sgid на ALT
- epm: `-y` неинтерактивно, `epm ei` обновить, `epm release-upgrade --force` апгрейд ALT
- WebFetch идёт через серверы Anthropic — для внутренних хостов `curl`
- journald в LXC: `Storage=persistent` + `SystemMaxUse=16M`; border LXC `systemd-tmpfiles-setup`=73 → `systemd-tmpfiles --create`
- Cyrus autocreate: разделитель `|`, НЕ пробел
- ALT sudo: includes `/etc/sudo.d/` (НЕ `/etc/sudoers.d/`!)
- mail.etersoft.ru postfix: логи в `/var/log/mail/all` (НЕ journald) → fail2ban `backend=polling`, `logpath=/var/log/mail/all`
- eterban priv: `/usr/bin/eterban`, лог `/var/log/eterban/eterban.log`, ipset `eterban_1`/`eterban_1_ipv6`
- heredoc через SSH: `ssh host "cat > file" << 'EOF'` (кавычки вокруг маркера!); НЕ `iptables-restore` на живой системе (сносит podman/docker); клон LXC: IP потом старт; `control ФАЙЛ РЕЖИМ` вместо chmod (suid/sgid)
- epm: `-y`, `ei` обновить, `release-upgrade --force`; WebFetch через серверы Anthropic → внутр. хосты через `curl`; ALT sudo includes `/etc/sudo.d/` (НЕ sudoers.d)
- journald LXC: `Storage=persistent`+`SystemMaxUse=16M`; border `systemd-tmpfiles-setup`=73 → `systemd-tmpfiles --create`; Cyrus autocreate разделитель `|`; mail postfix логи `/var/log/mail/all` → fail2ban `backend=polling`; eterban priv: `/usr/bin/eterban`, лог `/var/log/eterban/eterban.log`, ipset `eterban_1`/`eterban_1_ipv6`
---
name: lesson_route_health_flush_hang
description: "ИСТОРИЯ (исправлено 01.08.2026): route-health.sh на igw вешал ВЕСЬ мониторинг шлюзов per-route flush 121k v6-маршрутов + окно 1m ложный dead feedback-loop. Фикс: bulk flush + окно 3m. Отдельный корень ikev2 churn см. [[lesson_vici_socket_acl_for_telegraf]]"
metadata:
node_type: memory
type: lesson
modified: 2026-08-01T19:28:55.619Z
originSessionId: c2840474-3dab-4156-9d46-6f9a238fcfe2
---
`router/route-health.sh` на igw (CT, timer `route-health.timer` OnUnitActiveSec=20s). Симптом (2026-08-01): все шлюзы в `health.json` замёржены на стейл-состоянии, gre.hetzner2 и ikev2.vdska показывают «dead» хотя оба реально здоровы. `route-health.service` висит в одной инвокации (activating 20+ мин, load avg 14+).
**Корень — три проблемы в скрипте (вместе = self-reinforcing collapse):**
1. **`flush_gw_routes()` (стр. 275) делает per-route delete**: `$ipcmd route show table "$t" | grep "via $dead_gw" | while read route; do … ip route del …`. Для шлюза с массой маршрутов (ikev2.vdska.v6 держал 121 913 v6-маршрутов в **общей** table 202) это ~20 мин тысяч netlink `RTM_DELROUTE`. Комментарий на стр. 283 сам признаёт: должно быть по per-gateway таблицам и один `ip route flush table`. На общей таблице это O(n) катастрофа.
2. **Узкое окно ping-запроса (стр. 50):** `SELECT last(percent_packet_loss) FROM ping WHERE time > now() - 1m GROUP BY gateway` + `curl --max-time 5`. Под нагрузкой (см. п.3) telegraf на egress-контейнерах недополучает CPU → ping-точки пишутся реже 1m → запрос возвращает **пусто**`get_health` для tunnel_gw: `loss=""`**«dead»** (ложный). Прямой запрос с окном 2m данные видит, с 1m — нет. 1m слишком тесно для мониторинга, который как раз нужен под нагрузкой.
3. **Feedback loop:** flush-шторм (тысячи netlock-опов) → load avg 14+ на igw/border → telegraf-агенты голодают → ping стареет >1m → ложный dead → **ещё flush** → ещё load. Перезапуск сервиса не лечит: свежий прогон тут же ловит ложный dead (stale ping) и возобновляет flush.
**Доп.:** без таймаута на per-gateway `ip`-операции одно зависшее `ip route show` (netlock contention от собственного flush'а) глушит инвокацию навсегда → `OnUnitActiveSec=20s` не перепланируется (сервис не exiting) → таймер NEXT="-".
**Что сделал 01.08.2026:** `systemctl stop route-health.timer` + `disable`, `systemctl kill -s SIGKILL route-health.service` — остановил разрушительный flush (маршруты ikev2.vdska.v6 сохранены, ~37k, и правильно — шлюз здоров). route-health оставлен **stopped+disabled** до починки скрипта. route-update (отдельный timer) продолжает работать.
**Рекомендация автору (Vitaly Lipatov):**
- `flush_gw_routes` → массовый `ip route flush table <per-gw>` (как задумано в комментарии стр. 283); per-gateway таблицы вместо общей 202.
- Окно ping-запроса 1m → 3–5m (или last-seen логика), чтобы пропуск точек под нагрузкой не давал ложный dead.
- `timeout` на все `ip`-вызовы в циклах flush.
Проверка verdict'а шлюза в обход зависшего route-health: дёрнуть точные запросы из строк 48-78 route-health.sh к InfluxDB `10.20.30.130:8086` db=gateways. Все egress-шлюзы реально здоровы (SA up, vpn=1, iperf3=success, ping rc=0). См. [[reference_egress_tunnels]], [[gre.hetzner2.egw]].
## ✅ ИСПРАВЛЕНО 01.08.2026
Оба изменения залиты в репо (коммиты `5f8a5bc` route-health + `8144abe` vici-dropin, gpush в pub.gitlab) и развёрнуты:
1. **`flush_gw_routes()` → bulk flush:** `timeout 60 $ipcmd route flush table "$t" via "$dead_gw"` вместо per-route цикла. Идиома та же, что route-update.sh:827-830. На igw: цикл 18s вместо 20+ мин, table202 v6 via vdska 127259→0 за секунды.
2. **Окно ping/vpn 1m → 3m** (запросы через `last()` — реакцию на реальное падение не задерживает, только убирает пустой результат → ложный dead).
3. **`route-health.timer` включён обратно** — циклы быстрые, зависаний нет.
**Важный дочерний корень ikev2 churn:** даже после фикса flush'а ikev2.vdska продолжал churn'ить dead↔healthy, потому что `check-vpn-status.sh` (под telegraf) не мог прочитать vici-сокет → ложный vpn_status=0. Починено отдельно — см. [[lesson_vici_socket_acl_for_telegraf]]. Развёрнуто на .131/.120/.139/.140.
Реплицировано на egw (91.232.225.14): checkout `/root/etersoft-admin-essential` был позади на 10 коммитов с локальной правкой (== upstream 08365b4) — отбросил дубликат, `git pull --ff-only``8144abe`. На egw route-health.service не запущен (нет unit), скрипт обновлён для консистентности.
---
name: lesson_vici_socket_acl_for_telegraf
description: check-vpn-status.sh под telegraf не может в swanctl (vici 770 root:root) → ложный vpn_status=0 → route-health churn ikev2.*; фикс — ACL на vici-сокет (sudo не работает: /bin/sudo 4710 root:wheel)
metadata:
node_type: memory
type: lesson
originSessionId: c2840474-3dab-4156-9d46-6f9a238fcfe2
modified: 2026-08-01T19:29:21.855Z
---
`router/check-vpn-status.sh` крутится telegraf-exec-плагином (каждые 10s) под юзером **telegraf** на egress-контейнерах ikev2.* (.120/.131/.139/.140). IKEv2-ветка сначала зовёт `swanctl --list-sas`, при неудаче падает в fallback «ipsec0 rx_bytes изменился за 10s».
**Симптом:** ikev2.vdska churn'ил в route-health dead↔healthy (12 flush+11 recover за 3 мин, load ~17, v6-маршруты table202 via vdska упорно 0) — даже после фикса flush-шторма ([[lesson_route_health_flush_hang]]).
**Корень:** swanctl под telegraf падает с *Permission denied* на vici-сокете `/run/charon.vici` (`srwxrwx--- root:root`, 770 — telegraf не в группе). → `established=0` → fallback по rx_bytes → при затишье трафика (10s без пакетов) rx_bytes не меняется → `connected=0` → route-health: `vpn=0 → dead`. Прямой прогон скрипта root'ом давал connected=1 всегда.
**Грабли с sudo (выбранный изначально путь «sudoers + sudo swanctl» НЕ сработал):** на ALT `/bin/sudo` = **4710 root:wheel** — execute только для root и группы wheel. telegraf даже НЕ МОГ запустить sudo (`/bin/sudo: Отказано в доступе`, exit 126). Добавление telegraf в wheel давало бы латентный риск (`%wheel ALL=(ALL) ALL` когда-нибудь добавят), ACL на setuid-бинарник `/bin/sudo` сбрасывается при `epm upgrade sudo`. `/etc/sudoers` на этих CT: `@includedir /etc/sudoers.d` (НЕ /etc/sudo.d — память про /etc/sudo.d на этих хостах неверна, проверять `grep @includedir`), и НЕТ правила `%wheel` (алиас WHEEL_USERS объявлен, но не использован). sudo хочет mode **0400** (не 0440) для файлов в sudoers.d.
**Фикс (чистый, без sudo):** дать telegraf чтение vici-сокета через systemd drop-in на strongSwan (Type=notify → сокет уже есть на ExecStartPost):
```
# /etc/systemd/system/strongswan.service.d/telegraf-vici.conf
[Service]
ExecStartPost=/bin/sh -c "setfacl -m u:telegraf:rwx /run/charon.vici || true"
```
Артефакт в репо: `router/strongswan-vici-telegraf.conf`. `|| true` — чтобы сбой ACL никогда не уронил IPsec-туннель (uptime туннеля важнее мониторинга). Скрипт check-vpn-status.sh править НЕ нужно — `swanctl` и так зовётся первым, просто теперь telegraf до него дотягивается (PATH telegraf включает /sbin → bare `swanctl` резолвится).
**Проверка:** `su -s /bin/sh telegraf -c "swanctl --list-sas | grep -c ESTABLISHED"` = 1. В InfluxDB `SELECT connected FROM vpn_status WHERE gateway='ikev2.vdska'` — стабильно 1, churn прекратился, маршруты table202 via vdska восстановились до 127259.
**⚠️ Перезапуск strongSwan рвёт SA:** при `systemctl restart strongswan` (чтобы применить drop-in) SA кратко падает. На .131/.120 (site-to-site, оба конца наши) переподнялся сам. На .139/.140 (ikev2.gr/fr — длинные туннели к удалённым NAT-пирам rpi/Греция) SA тоже переподнялся сам за ~35-39s (initiator реконнектится, см. [[reference_ikev2_fr_tunnel]], [[reference_ikev2_gr_tunnel]]), но проверять надо через ~40s, не сразу (в первые секунды ESTABLISHED=0 — это нормально, не признак поломки). Альтернатива без рыва SA: применить ACL вручную `setfacl -m u:telegraf:rwx /run/charon.vici` сразу + drop-in для персистентности (сработает при следующем рестарте/буте).
Развёрнуто на .131 (ikev2.vdska, чинил churn), .120 (ikev2.hetzner, латентно), .139 (ikev2.gr, pingonly — косметика health.json), .140 (ikev2.fr, pingonly). См. [[lesson_route_health_flush_hang]], [[reference_egress_tunnels]], [[gre.hetzner2.egw]].
---
name: igw
description: igw (CT на border, 91.232.225.13) — gateway health/failover (route-health.sh, route-update.sh); changelog
metadata:
node_type: memory
type: objects
originSessionId: c2840474-3dab-4156-9d46-6f9a238fcfe2
---
igw = CT на border, 91.232.225.13. Хостит `route-health.sh` (oneshot, timer `route-health.timer` OnUnitActiveSec=20s) + `route-update.sh` (timer 30min). InfluxDB `10.20.30.130:8086` db=gateways. Checkout репо `/root/etersoft-admin-essential` (origin gitlab.eterfund). См. [[reference_egress_tunnels]], [[reference_igw_route_api]].
## 2026-08-01 — починен route-health flush-шторм + ikev2 churn
**route-health.sh** зависал 20+ мин (load 14+), замораживая мониторинг ВСЕХ шлюзов и ложе помечая здоровые gre.hetzner2/ikev2.vdska dead → разрушительный flush 127k v6-маршрутов. Два корня, оба починены (коммиты `5f8a5bc`, `8144abe`, gpush):
1. `flush_gw_routes()` делал per-route `ip route del` ×127k → O(n) netlink-шторм → вис oneshot. → bulk `timeout 60 ip route flush table T via GW`.
2. Окно ping/vpn InfluxDB 1m → пустой результат под нагрузкой → ложный dead. → 3m (запросы через `last()`, реакцию не задерживает).
Дочерний корень ikev2.vdska churn: `check-vpn-status.sh` под telegraf не читал vici-сокет → vpn_status=0. Фикс — ACL на vici-сокет (drop-in на strongSwan), см. [[lesson_vici_socket_acl_for_telegraf]]. Drop-in развёрнут на egress-CT .131/.120/.139/.140 (на border, не на самом igw).
**Что сделано на igw:**
- Деплой фикса route-health.sh + `bash -n` + тест одного цикла (18s, exit 0).
- `route-health.timer` включён обратно (был stop+disable 01.08 днём). Циклы быстрые, churn прекратился, table202 v6 via vdska = 127259 (восстановлено).
- checkout `/root/etersoft-admin-essential` обновлён (там был dirty с моим фиксом в working tree; коммит ушёл через builder64 → pub.gitlab).
**egw (91.232.225.14):** checkout был позади на 10 коммитов + локальная правка route-health.sh (== upstream 08365b4 pingonly). Отбросил дубликат, `git pull --ff-only``8144abe`. На egw route-health.service НЕ запущен (нет unit) — скрипт обновлён для консистентности.
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