docs: RU/DE VPS setup and verified direct VPN acceptance #21
1 changed files with 257 additions and 0 deletions
257
agents/codex/done/2026-10-23-vps-ru-de-setup.md
Normal file
257
agents/codex/done/2026-10-23-vps-ru-de-setup.md
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
# RU/DE VPS — настройка 23.10.2026
|
||||
|
||||
**База: PASS. Серверная связка: PASS внешним контролем DE и локальным клиентом через SSH. Прямой клиент из текущей сети этой машины: HOLD.** Полную приёмку этого конкретного публичного пути не объявляю. Перед переносом семьи нужен контроль с её фактической сети. Финляндия и Дания не затронуты.
|
||||
|
||||
## Основание и исходники
|
||||
|
||||
Прямое задание владельца: `kagent/agents/claude/done/2026-10-23-fixes/CODEX-vps-setup-ru-de.md`; повтор `kagent/kagent` в переданном пути исправлен. Только два адреса из разрешённых RU/DE файлов; иных SSH-хостов не проверял. Порядок: RU полностью, затем DE, затем связка.
|
||||
|
||||
Развёрнуты скрипты **main после PR19**, точный merge SHA `47d5e030dfa392a995649c0519088aae74f73935` (PR19 head `eb00e38a7515c6772535322d7b353c9c01718fcc`). Merge и main CI5/task7370 SUCCESS проверены до работы. Использован отдельный worktree существующего репозитория; скрипты переданы SCP, все SHA-256 сверены на серверах. С GitHub репозиторий на VPS не клонировался. Продуктовых прогонов KAgent/Telegram не запускал.
|
||||
|
||||
Первый парольный вход — один на каждый VPS через SSH_ASKPASS, без паролей в argv/history/логах/временных копиях. Далее — новый ключ оператора. Исходные `.env` и `.ppk` не копировались и не менялись, каталог700/файлы600 сохранены. У `.ppk` читались только заголовки и ровно Public-Lines, остановка до приватной части.
|
||||
|
||||
Host keys (Ed25519), зафиксированы при первом контакте, **TOFU**, не независимая внеполосная аттестация:
|
||||
|
||||
- RU: `SHA256:rYHjuLL2NjiHlImXA3ShWCeZBrdoGbGw0phQfxafJlE`
|
||||
- DE: `SHA256:UeebWqUQoNx4FePQGV4P14iSpzZHClFDjndLm/9k3DI`
|
||||
|
||||
Постоянный known_hosts: `~/.ssh/kagent_vps_known_hosts`; новый порт привязан к тому же ранее проверенному host key. Создан `~/.ssh/kagent_vps_ed25519` (0600). Приватный ключ не передавался на VPS. В новом admin authorized_keys обоих — публичные ключи владельца и оператора. Полный вход оператора и sudo с паролем проверены. Сервер отдельно подтвердил приём публичного ключа владельца (SSH public-key probe); end-to-end подпись его приватным ключом не выполнялась, поскольку приватную часть PPK читать запрещено.
|
||||
|
||||
## Выполненные этапы
|
||||
|
||||
| Проверка | RU | DE |
|
||||
| --- | --- | --- |
|
||||
| ОС | Ubuntu24.04 LTS: проверка24.04.4, после обновления24.04.5 | то же |
|
||||
| Часовой пояс | Europe/Moscow | Europe/Berlin |
|
||||
| Этап1 | swap2GiB, текущая локаль сохранена, необязательные программы пропущены | то же |
|
||||
| Этап2 | IPv4, выбранный SSH +443, временный22 затем удалён | то же |
|
||||
| Этап3 | новый admin, два ключа, SSH root/password/kbdinteractive no, sudo с паролем | то же |
|
||||
| Вторая независимая key-session | PASS до подтверждения удаления22 | PASS до подтверждения удаления22 |
|
||||
| Этап6 | 3x-ui v3.10.2; панель и подписки loopback; WARP off | то же |
|
||||
| Получение 3x-ui | GitHub, закреплённые SHA-256 main-helper | то же |
|
||||
| Страница входа через SSH-L | HTTP200 | HTTP200 |
|
||||
| Этап7 | initial snapshot +checksum PASS | initial snapshot +checksum PASS |
|
||||
| Состояние после связки и финальной смены секретов | consistent SQLite checkpoint +ручные daily snapshots/checksum PASS | то же |
|
||||
|
||||
Автоматические расписания не включались; первичные снимки не перезаписывались. После API-ротации логина/пароля/секретного пути выполнен финальный согласованный checkpoint БД и новый ручной снимок, чтобы восстановление соответствовало актуальным env-файлам. Настройка выполнялась без изменения глобальной сети/брандмауэра этой машины. Этапы4,5,8 не выполнялись. Telegram-узел DE не ставился. WARP не установлен.
|
||||
|
||||
На Ubuntu с socket activation после обновления пакетов отсутствовал `/run/sshd`; standalone `sshd -t` завершился ошибкой до рестарта. Обратимо создан стандартный служебный каталог root:root755, затем неизменённый main-скрипт прошёл проверку и перенос SSH. Текущая административная сессия сохранялась до новой key-session и password-sudo проверки. Этот дефект оформлен **отдельным code PR20**: https://git.ochenstarik.ru/ochenstarik/lightweight-server/pulls/20 . Head `9e8f024b896dc2dfa036318fb611fe9595811da2`; 13тестов PASS, pushCI6/task7372 и PRCI7/task7373 SUCCESS. Полный pushlog23816B без усечения проверен; SHA256 `3173f66931adff2fb1e74e61b5bd6dcaffe2429c00df1bcecb2f6eb09b682fff`. На VPS выполнялась операционная подготовка каталога; несмерженный код PR20 не разворачивался.
|
||||
|
||||
## Связка и сетевые проверки
|
||||
|
||||
Через аутентифицированный API 3x-ui по SSH-туннелям, с штатным CSRF-token/session cookie:
|
||||
|
||||
- DE: VLESS+Reality TCP на24443, inbound `codex-ru-de-link`, клиент `ru-link`; UFW разрешает этот порт **только с RU_IP**. В общий список глобально публикуемых managed ports он не добавлен, чтобы последующий рендер не расширил CIDR-правило до Anywhere.
|
||||
- RU: VLESS+Reality443, один тестовый клиент `owner-test`, inbound `family-owner-test`; outbound `vpn-de` — в DE. Private IP и geoip:ru → direct; geosite:category-ru и домены ru/su/рф → direct; остальное по умолчанию → DE. Служебные API/stats и прежние правила сохранены.
|
||||
- Native Xray из закреплённого 3x-ui:26.10.10 на обоих; временный клиент26.10.21 (SHA-256 проверен по pinned архиву). Также проверялся клиент26.10.10: наблюдение не является только различием версий.
|
||||
- Начальный camouflage target RU Microsoft сменён на доступный Cloudflare; ключи/UUID не ротировались. DE target Microsoft. После изменения выполнен штатный reload Xray. Настройки в реальном config.json сверены с API-моделью. Подмены TLS/отключения проверок сертификата нет.
|
||||
|
||||
| Путь клиента | Зарубежный запрос api.ipify.org | Российский запрос к сервису Яндекса | Статус |
|
||||
| --- | --- | --- | --- |
|
||||
| Эта машина → публичный RU443, обычный REALITY | TLS error35 | TLS error35 | HOLD |
|
||||
| Эта машина → SSH-L к тому же RU443 → REALITY | фактический IP=DE_IP | фактический IP=RU_IP | PASS, это SSH-путь |
|
||||
| Временный клиент на DE → публичный RU443 → DE | фактический IP=DE_IP | фактический IP=RU_IP | PASS, внешний контроль публичного входа |
|
||||
|
||||
Российская проверка: `https://ipv4-internet.yandex.net/api/v0/ip`; ответ сопоставлен с RU_IP в памяти, сам IP не журналировался. 2ip.ru вернул HTTP-ошибку и не использовался как положительное доказательство.
|
||||
|
||||
В прямом локальном пути REALITY получил настоящий маскирующий сертификат вместо принятой REALITY-аутентификации. UUID, SNI, short ID, private/public pair и реально загруженные настройки совпадают. Microsoft и Cloudflare на обоих VPS доступны с TLS1.3 и валидной цепочкой. Альтернативные SNI/fingerprint и очистка proxy env только у дочернего клиента не устранили наблюдение. Через SSH к тому же слушателю и с внешнего DE оно не воспроизводится. **Причина конкретного публичного пути локализована, но не установлена полностью**; утверждать доказанный MITM/DPI или полную готовность семейного входа из текущей сети нельзя. По разрешённому fallback оставлены рабочая база, панели и проверенная серверная связка; без дальнейших изменений глобальной сети хоста.
|
||||
|
||||
Тестовая ссылка: только `/home/ochenstarik/srgfd/vpn_test_link.txt` (0600). Не передавать семье как полностью принятую до проверки её фактической сети. Не переустанавливать/переносить FI до переезда семьи.
|
||||
|
||||
## Доступ к панелям
|
||||
|
||||
Актуальные значения панели сохранены в защищённых `panel_ru.env` и `panel_de.env`; в report/Git/вывод команд их нет. Одноразовые параметры upstream-установщика, который внутри использует CLI-setting, аннулированы: логин/пароль и секретный path сменены штатным API без секретов в argv. Новый вход проверен. Проверка journal показала отсутствие актуального пароля и секретного path. Сам идентификатор пользователя 3x-ui записывает в штатный authentication audit; утверждать, что username нигде на VPS не встречается, нельзя. Аудит не отключался и не удалялся. Полный набор реквизитов сохраняется только в указанных env-файлах. Подробные готовые команды с приватными адресами/именем/SSH-портом и PuTTY-параметрами — `/home/ochenstarik/srgfd/PANEL_HOWTO.txt` (0600). SSH alias config — `/home/ochenstarik/srgfd/ssh_config` (0600).
|
||||
|
||||
Готовые команды из этой машины без публикации приватных адресов и значений из env:
|
||||
|
||||
```bash
|
||||
# RU — оставить открытым в отдельном терминале:
|
||||
PANEL_PORT="$(python3 -c 'from pathlib import Path; import shlex; print(dict((k,shlex.split(v)[0]) for k,v in (s.split("=",1) for s in Path("/home/ochenstarik/srgfd/panel_ru.env").read_text().splitlines()))["port"])')"
|
||||
ssh -F /home/ochenstarik/srgfd/ssh_config -i ~/.ssh/kagent_vps_ed25519 -N -L "127.0.0.1:18053:127.0.0.1:$PANEL_PORT" ru-vpn
|
||||
# DE — в другом терминале:
|
||||
PANEL_PORT="$(python3 -c 'from pathlib import Path; import shlex; print(dict((k,shlex.split(v)[0]) for k,v in (s.split("=",1) for s in Path("/home/ochenstarik/srgfd/panel_de.env").read_text().splitlines()))["port"])')"
|
||||
ssh -F /home/ochenstarik/srgfd/ssh_config -i ~/.ssh/kagent_vps_ed25519 -N -L "127.0.0.1:18054:127.0.0.1:$PANEL_PORT" de-vpn
|
||||
```
|
||||
|
||||
PuTTY: SSH Auth → указать существующий `.ppk` владельца; Connection → SSH → Tunnels: source18053(RU)/18054(DE), destination `127.0.0.1:<PANEL_PORT из panel_*.env>`, Local, Add. Адрес браузера: `http://127.0.0.1:18053<path из panel_ru.env>` либо `http://127.0.0.1:18054<path из panel_de.env>`. В HOWTO есть команда открытия URL через чтение env без печати секретного пути. Обе страницы входа реально проверены, не только описаны.
|
||||
|
||||
## Снимки приёмки (значения доступов и panel port отредактированы)
|
||||
|
||||
### RU
|
||||
|
||||
`os_kernel`, exit=0
|
||||
|
||||
```text
|
||||
Operating System: Ubuntu 24.04.5 LTS
|
||||
Kernel: Linux 6.8.0-100-generic
|
||||
```
|
||||
|
||||
`timezone`, exit=0
|
||||
|
||||
```text
|
||||
Europe/Moscow
|
||||
```
|
||||
|
||||
`swap`, exit=0
|
||||
|
||||
```text
|
||||
NAME TYPE SIZE USED PRIO
|
||||
/swapfile file 2G 16.9M -2
|
||||
```
|
||||
|
||||
`sshd`, exit=0
|
||||
|
||||
```text
|
||||
port <SSH_PORT>
|
||||
permitrootlogin no
|
||||
passwordauthentication no
|
||||
kbdinteractiveauthentication no
|
||||
```
|
||||
|
||||
`ufw`, exit=0
|
||||
|
||||
```text
|
||||
Status: active
|
||||
Logging: on (low)
|
||||
Default: deny (incoming), allow (outgoing), disabled (routed)
|
||||
New profiles: skip
|
||||
|
||||
To Action From
|
||||
-- ------ ----
|
||||
<SSH_PORT>/tcp ALLOW IN Anywhere
|
||||
443/tcp ALLOW IN Anywhere
|
||||
```
|
||||
|
||||
`ss`, exit=0
|
||||
|
||||
```text
|
||||
127.0.0.1:62789 users:(("xray-linux-amd6",pid=29837,fd=3))
|
||||
127.0.0.54:53 users:(("systemd-resolve",pid=9926,fd=17))
|
||||
127.0.0.1:11111 users:(("xray-linux-amd6",pid=29837,fd=7))
|
||||
127.0.0.53%lo:53 users:(("systemd-resolve",pid=9926,fd=15))
|
||||
127.0.0.1:<PANEL_PORT> users:(("x-ui",pid=28434,fd=10))
|
||||
127.0.0.1:2096 users:(("x-ui",pid=28434,fd=16))
|
||||
0.0.0.0:<SSH_PORT> users:(("sshd",pid=25875,fd=3))
|
||||
*:443 users:(("xray-linux-amd6",pid=29837,fd=6))
|
||||
[::]:<SSH_PORT> users:(("sshd",pid=25875,fd=4))
|
||||
```
|
||||
|
||||
`nft_tables`, exit=0
|
||||
|
||||
```text
|
||||
table ip filter
|
||||
table ip6 filter
|
||||
```
|
||||
|
||||
`services`, exit=0
|
||||
|
||||
```text
|
||||
active
|
||||
active
|
||||
```
|
||||
|
||||
Panel DB (без path/credentials):
|
||||
|
||||
```json
|
||||
{
|
||||
"webListen": "127.0.0.1",
|
||||
"webPort": "<PANEL_PORT>",
|
||||
"subListen": "127.0.0.1",
|
||||
"subPort": "2096",
|
||||
"subEnable": "true"
|
||||
}
|
||||
```
|
||||
|
||||
### DE
|
||||
|
||||
`os_kernel`, exit=0
|
||||
|
||||
```text
|
||||
Operating System: Ubuntu 24.04.5 LTS
|
||||
Kernel: Linux 6.8.0-111-generic
|
||||
```
|
||||
|
||||
`timezone`, exit=0
|
||||
|
||||
```text
|
||||
Europe/Berlin
|
||||
```
|
||||
|
||||
`swap`, exit=0
|
||||
|
||||
```text
|
||||
NAME TYPE SIZE USED PRIO
|
||||
/swapfile file 512M 1M -2
|
||||
```
|
||||
|
||||
`sshd`, exit=0
|
||||
|
||||
```text
|
||||
port <SSH_PORT>
|
||||
permitrootlogin no
|
||||
passwordauthentication no
|
||||
kbdinteractiveauthentication no
|
||||
```
|
||||
|
||||
`ufw`, exit=0
|
||||
|
||||
```text
|
||||
Status: active
|
||||
Logging: on (low)
|
||||
Default: deny (incoming), allow (outgoing), disabled (routed)
|
||||
New profiles: skip
|
||||
|
||||
To Action From
|
||||
-- ------ ----
|
||||
<SSH_PORT>/tcp ALLOW IN Anywhere
|
||||
443/tcp ALLOW IN Anywhere
|
||||
24443/tcp ALLOW IN <RU_IP> # RU-DE Reality upstream
|
||||
```
|
||||
|
||||
`ss`, exit=0
|
||||
|
||||
```text
|
||||
127.0.0.1:11111 users:(("xray-linux-amd6",pid=151126,fd=7))
|
||||
127.0.0.1:<PANEL_PORT> users:(("x-ui",pid=149833,fd=10))
|
||||
127.0.0.1:2096 users:(("x-ui",pid=149833,fd=13))
|
||||
127.0.0.1:62789 users:(("xray-linux-amd6",pid=151126,fd=3))
|
||||
0.0.0.0:<SSH_PORT> users:(("sshd",pid=147427,fd=3))
|
||||
127.0.0.53%lo:53 users:(("systemd-resolve",pid=145942,fd=15))
|
||||
127.0.0.54:53 users:(("systemd-resolve",pid=145942,fd=17))
|
||||
*:24443 users:(("xray-linux-amd6",pid=151126,fd=6))
|
||||
[::]:<SSH_PORT> users:(("sshd",pid=147427,fd=4))
|
||||
```
|
||||
|
||||
`nft_tables`, exit=0
|
||||
|
||||
```text
|
||||
table ip filter
|
||||
table ip6 filter
|
||||
table inet f2b-table
|
||||
```
|
||||
|
||||
`services`, exit=0
|
||||
|
||||
```text
|
||||
active
|
||||
active
|
||||
```
|
||||
|
||||
Panel DB (без path/credentials):
|
||||
|
||||
```json
|
||||
{
|
||||
"webListen": "127.0.0.1",
|
||||
"webPort": "<PANEL_PORT>",
|
||||
"subListen": "127.0.0.1",
|
||||
"subPort": "2096",
|
||||
"subEnable": "true"
|
||||
}
|
||||
```
|
||||
|
||||
## Границы результата и следующая приёмка
|
||||
|
||||
- Внешний публичный контроль DE и оба egress-направления PASS; прямой клиент с текущей сети этой машины HOLD. Следующее необходимое действие — проверить owner-test из фактической сети семьи/другой клиентской сети и при необходимости разбирать именно этот публичный первый hop. Связку/ключи вслепую не ротировать.
|
||||
- Публичная панель, публичные подписки, Telegram-ноды, AI-агенты и WARP не включались. Новых дополнительных мониторов/автоматизаций нет; прежний тик30 не возобновлялся.
|
||||
- Для послеустановочного восстановления оставлены согласованные SQLite checkpoints и локальные initial/daily snapshots с проверенными checksum. Локальная копия не заменяет отдельное внешнее хранилище; offsite не включался.
|
||||
- Этот PR содержит только данный обезличенный отчёт. Code PR20 отдельный, автор не вливает. Прежний release gate для новых PR/документов без CI не обходится.
|
||||
Loading…
Reference in a new issue