# My Point VPN ### Intro Предоставляет интерфейс чат бота в телеграмм посредством которого позволяет разворачивать 3x-ui на своем сервере и выпускать ключи. Базово конфигурируется 3x-ui на создание vless подключений с tls+reality маскировкой трафика. Настраивается dns, подписка и базовая безопасность сервера. Пользователь может прикрутить прокси на выход или включить cf_warp прокси. По каждому серверу дает базовую статистику у ручки управления. Если вам нужен приватный доступ в интернет, передайте сервер боту и он настроит вам его. Выглядит это так: пользователь заводит аккаунт хостинг провайдера, арендует сервер, ему выдают ip и пароль root, он передает их боту, оный настраивает сервер, теперь пользователь может выпускать ключи vless и подключаться к интернету безопасно и приватно. - статистика сервера: - сколько трафика пропустил - сколько пользователей - можно добавить пользователя - статистика по пользователю: - онлайн? - сколько трафика пропустил - можно удалить пользователя Серверу можно настроить: - прокси на выходе (cf или свои) - домен (сертификат Let's Encrypt; без домена сертификат выпускается на ip) За Cloudflare точки не работают: reality через проксирование Cloudflare невозможен, Cloudflare сам завершает TLS. Скрыть адрес панели от клиентов можно сервером маскировки. ### Окружение - Linux Mint 22 - Python 3.12.3 - PyCharm 2026.2.1 ### Интерфейс чата Переход в главное меню должен быть реализован кнопкой в клавиатуре. `/start` и кнопка "главное меню" должны выполняться одним методом. Сейчас у пользователя нет данных и это его первое сообщение, поэтому система показывает ему сообщение заглушку. ``` ---> /start <--- привет. выбери действие [ФАК][добавить сервер][помощь] ``` Пользователь нажимает на кнопку добавления сервера и переходит в меню добавления сервера. ##### Меню добавления сервера ``` ---> добавить сервер <--- Сервер: - Сервер маскировки: - Домен: - Прокси: - [домен][прокси][маскировка] [отмена][установить][сервер][помощь] ``` ``` ---> сервер/маскировка <--- отправь данные для подключения к серверу `ip:root_password` [отмена] ``` После получения данных выполняется процесс настройки сервера. Этот процесс занимает время, поэтому выполняется в фоне. ``` ---> 127.0.0.1:toor <--- Сервер: 127.0.0.1 Домен: - Прокси: - [домен][прокси][маскировка] [отмена][установить][сервер][помощь] ``` ``` ---> прокси <--- Можно указать свои или включить cf_warp. [cf_warp][отмена][удалить] ``` ``` ---> http://127.0.0.1:9050 <--- Сервер: 127.0.0.1 Домен: - Прокси: http://127.0.0.1:9050 [домен][прокси][маскировка] [отмена][установить][сервер][помощь] ``` ``` ---> установить <--- Запускаю установку сервера. Отправлю уведомление когда все будет готово. ``` А по окончании генерируется уведомление. ``` ---> <--- сервер ip - проименован как `NAME`, готов к работе. [меню сервера] ``` ##### Меню Пользователь опять отправляет /start это нормально, так он получает главное меню с перечислением его серверов. ``` ---> /start <--- point-1a2b3c активен [ФАК][добавить сервер][помощь] [управление сервером] ``` Чтобы перейти к управлению сервером нужно вот такой квест пройти, надо все эти id в копируемый pre сунуть. ``` ---> управление сервером <--- Пришлите server_name [отмена] ``` ##### Меню управления сервером ``` ---> меню сервера <--- Сервер: NAME Состояние: активен Панель: 1.2.3.4 Маскировка: - Ключи: 2 Домен: - Прокси: - [Вернуть][Переустановить] [Домен][Прокси] [Клиенты] [главное меню] ``` Возврат сервера связан с отключением его от платформы. Доступы к серверу изымаются, ставится новый пароль рута, а данные остаются как есть. Просто отдаем сервер назад. ``` ---> Вернуть <--- Сервер будет освобожден из-под моего контроля, будет установлен случайный пароль рута, мои доступы будут убраны, данные на сервере сохранены. Будет отправлено уведомление с новым паролем. Продолжить? [Да][Нет] ``` Возможно потребуется переустановка после сброса сервера. Бывает такое когда это нужно. Обычно после сброса сервера задается новый пароль. ``` ---> Переустановить <--- Будет произведена повторная установка всех компонентов. Вызывайте эту функцию, только после того, как в панеле управления сервером в аккаунте хостинг провайдера вызовите переустановку сервера. Если уверены, то пришлите новый пароль сервера. [Отмена][Использовать старый] ``` Меню управления доменом. После установки выпускаются ссл сертификаты, а если домена нет, то сертификат выпускаем на ip. ``` ---> Домен <--- Сейчас установлен: - Доменное имя лучше подходит для маскировки вашей точки доступа. [установить][отключить] ``` Прокси полезно ставить. Есть 2 варианта, когда пользователь покупает прокси и задает их тут, или когда активирует cf_warp. ``` ---> Прокси <--- Сейчас установлено: - Позволяют маскировать ip адрес вашей точки доступа от сайтов, которые посещаются. X <> MyPoint <> PROXY <- Web Сайты видят ip прокси, а не ip вашей точки доступа. [установить][отключить] ``` ``` ---> установить <--- пришли прокси в формате `protocol://username:password@host:port` или нажми кнопку. [cloudflare warp][отмена] ``` ##### Меню управления клиентами Домен и прокси меняются на горячую, в фоне: точка на это время "настраивается", по окончании приходит уведомление. Новый прокси сначала проверяется, а сертификат на новый домен сначала выпускается. Если не вышло, точка остается активной с прежними настройками, а ошибка видна в карточке. У точки с маскировкой домен можно сменить, но не убрать. Смена домена меняет ссылки подписок: ключи нужно раздать заново. Сообщение с прокси бот удаляет из чата, пароль прокси в карточке скрыт. ``` ---> Клиенты <--- Ключи point-1a2b3c mom-phone ↓ 1.2 ГБ ↑ 80.0 МБ, в сети 26.09 14:05 laptop ↓ 0 Б ↑ 0 Б, не подключался Пришли имя ключа, чтобы получить ссылку подписки. [выпустить ключ][отозвать ключ] [меню сервера] ``` ``` ---> mom-phone <--- Ключ mom-phone: ↓ 1.2 ГБ ↑ 80.0 МБ, в сети 26.09 14:05 Подписка: https://1.2.3.4:12839/9g72PmSGAQ3V/ ``` "выпустить ключ" просит имя (латиница, цифры, `-` и `_`), "отозвать ключ" - имя существующего. Клиенту выдается URL подписки, а не vless-ссылка: он переживает переустановку точки, ключи восстанавливаются с прежними uuid и subId. Ограничений на число ключей нет, выпускает их владелец точки. ### Настройка сервера Чтобы сервера были в безопасности их следует правильно настроить. От пользователя ожидается на вход девственный сервер с только что установленной операционной системой. 1. Конфигурирование ssh 2. Смена пароля рута 3. Конфигурирование nftables 4. Обновление операционной системы 5. Установка 3x-ui 6. Выпуск сертификата 7. Настройка vless+tls+reality 8. Настройка прокси ### Функционал бота **Добавление сервера** Сервер добавляется после установки ОС. Для бота требуется, чтобы ОС была debian-12 или debian-13. Свежий сервер: - открыт публично 22 порт ssh - имеет ip - рут может войти по ssh используя пароль Алгоритм действий для нового сервера, чтобы включить его в работу. 1. Заходим на сервер по паролю 2. прописываем ему свой ключ 3. меняем пароль, но сохраняем оба 4. Выполняем обновление системы `apt update -y && apt dist-upgrade -y` 5. Настраиваем ssh 1. отключаем вход по паролю 2. жестко фиксируем авторизацию только по ключам 3. меняем порт 4. сохраняем конфиг sshd, перезапускаем сервис, проверяем коннект 6. Настраиваем nftables Система общается с сервером только через авторизацию по ssh ключам. Когда пользовать захочет вернуть сервер себе, следует: 1. Откатываем настройки ssh 2. Сбросить nftables 3. Удалить файл /root/.ssh/authorized_keys 4. Отдать ip:password После базовой настройки нового сервера можно его специализировать. Этим занимается пакет serverus, который умеет готовить специализированные сервера под определенный вид задач. Пакет также занимается и настройкой серверов базово. И позволяет сделать из сервера прокси или панель 3x-ui. Для наших целей требуется оба и в интерфейсе добавления сервера есть пункт "Сервер маскировки" - это сервер из которого нужно сделать прозрачный прокси. В App заводим модель в которой объединяем эти 2 сервера в единую систему. Так как кнопка "Вернуть" вернет оба сервера и они связаны настройками маршрутизации. ### Запуск 1. `cp env_example .env` и заполнить: база, RabbitMQ, `FIELD_ENCRYPTION_KEYS`, `SERVERUS_CERTIFICATES`. 2. `docker compose up -d` - Postgres, RabbitMQ, свой Bot API сервер. 3. `make sync`, `make dj_migrate`, `make dj_superuser`. 4. Три процесса: `make dj_run` (сайт и админка), `make dj_worker` (установка и возврат серверов), `make tg_run` (бот, запускать строго один экземпляр). 5. В админке добавить бота с токеном, выбрать интерфейс MyPoint и опубликовать. Подробности: `src/App/README.md` (сценарии, секреты, ручной вход `make serve_ssh`), `src/serverus/README.md` (плейбуки, ручная проверка на сервере), `src/Telegram/README.md` (боты). Локальный стенд: `SERVERUS_CERTIFICATES=local`, сертификаты выпускает свой CA из `extra/serverus/ca`, `ca.pem` нужно добавить в доверенные на машине с клиентом. Let's Encrypt на серых адресах не работает. ### Модель данных Пользователи - приходят из телеграма, у них есть id, который уникален и проверен, его можно использовать для авторегистрации. И следует обязательно запоминать, так как боту недоступна информация о подключенных к нему пользователях, только в момент когда пользователь взаимодействует с ботом. - telegram user id - запоминаем id пользователя телеграм Точка - наша выдуманная абстракция, чтобы объединить в группу (кластер) 2 сервера. Домен. Прокси (или аккаунт cf_warp). - сервер 3x-ui - обязательно должен быть, ради него все и затевается - сервер маскировки - если пользователь хочет особый режим, то он может добавить еще один сервер купленный в своей стране - домен - если сервер маскировки указан, то домен обязательно нужно указать - ssl сертификаты - если домен не указан, то сертификаты выпускаются на IP сервера 3x-ui, а сервера маскировки нет; а если домен есть то он привязывается к серверу маскировки и на него выпускаются ssl ключи, который хранятся на сервере 3x-ui, потому что сервер маскировки лишь прозрачно проксирует. Храним и домен, и ip, по ssh ходим только по ip - ssh ключи - доступ к серверам, находящимся под нашей ведомостью, всегда осуществляется асимметричным способом (ключ-файл) - прокси - можно задать свои и с авторизацией, а можно воспользоваться cf_warp прокси, которые можно регистрировать автоматически через x-ui - ключи - клиенты панели: имя, uuid и subId, чтобы восстановить их после переустановки Сервер - реальные сервера с ip и доступом к root. Настраиваем безопасное окружение по всем канонам. Сервис - На серверах у нас живут сервисы. Поднимается или настраивается какой-то сервис, чтобы решить какую-то полезную задачу. И реализуют api для управления сервисом на сервере. Сейчас эту функцию выполняет Роль сервера, потому что подразумевается что сервис может быть 1. ### Что осталось Проверено на локальном стенде (Debian 13, свой CA): установка точки из бота с маскировкой, DoT и запасной DoH, ключи и подписка, socks5 и WARP на выходе, отказ нерабочего прокси, переустановка с восстановлением ключей, возврат серверов, `serve_ssh`, шифрование секретов в Postgres. **Функции** - [x] Кнопки "Домен" и "Прокси" у готовой точки, смена на горячую. - [ ] Скрипт маскировки (сейчас маскировка - перенаправление портов nftables). - [ ] Статистика точки в главном меню и карточке: трафик и число ключей онлайн (сейчас статистика только у ключей). - [ ] Кто может пользоваться ботом: сейчас любой, кто написал боту, может добавить сервер. Решить: белый список, инвайты или открыто. **Надежность** - [ ] Точка, зависшая в "устанавливается" или "возвращается", если воркер упал посреди задачи: в боте с ней ничего не сделать, а в админке статус только для чтения. Нужно действие в админке (сбросить в "ошибка") или проверка по времени. - [ ] Периодическая проверка точек: панель отвечает, сертификат не истекает (короткий сертификат на ip продлевается каждые несколько дней). **Проверка на настоящих серверах** - [ ] Let's Encrypt на домен и на ip, продление по cron. - [ ] Возврат серверов и Debian 12. - [ ] Точка с маскировкой и настоящим доменом. **Продакшен** - [ ] Настройки: `SECRET_KEY`, `DEBUG`, `ALLOWED_HOSTS` из `.env` (сейчас в `base.py` небезопасные значения для разработки). - [ ] Запуск на сервере: systemd юниты или контейнеры для сайта (gunicorn за nginx), воркера и `telegram_run` (строго один экземпляр), логи. - [ ] Бэкапы Postgres. `FIELD_ENCRYPTION_KEYS` хранить отдельно от бэкапов: без него база бесполезна. **Уборка** - [ ] Удалить `django-fernet-fields` (не работает на Django 6.1, заменен своим полем) и обновить `requirements.txt`. - [ ] Удалить `src/db.sqlite3` и `extra/db-before-encryption-*.sqlite3`: в бэкапе секреты открытым текстом. - [ ] Контейнер Postgres называется `shop-postgres`: переименовать. - [ ] `Key` в админке (только для чтения). - [x] Карточка точки показывает прокси вместе с логином и паролем: маскировать пароль. - [ ] Пароль root при переустановке уходит в задачу dramatiq открытым текстом (сообщения RabbitMQ лежат на диске): шифровать, как прокси.